Module Name: src
Committed By: pooka
Date: Thu Dec 3 14:23:49 UTC 2009
Modified Files:
src/lib/libukfs: ukfs.c ukfs.h ukfs_disklabel.c ukfs_int_disklabel.h
Log Message:
Improve the ukfs magicpath interface a bit:
* rename PART to DISKLABEL
* allow to take an OFFSET range to make it possible to access an image
where there is no disklabel present
* make future extensions easier and less intrusive for the callers
To generate a diff of this commit:
cvs rdiff -u -r1.42 -r1.43 src/lib/libukfs/ukfs.c
cvs rdiff -u -r1.12 -r1.13 src/lib/libukfs/ukfs.h
cvs rdiff -u -r1.1 -r1.2 src/lib/libukfs/ukfs_disklabel.c \
src/lib/libukfs/ukfs_int_disklabel.h
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/lib/libukfs/ukfs.c
diff -u src/lib/libukfs/ukfs.c:1.42 src/lib/libukfs/ukfs.c:1.43
--- src/lib/libukfs/ukfs.c:1.42 Mon Nov 16 17:21:26 2009
+++ src/lib/libukfs/ukfs.c Thu Dec 3 14:23:49 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: ukfs.c,v 1.42 2009/11/16 17:21:26 njoly Exp $ */
+/* $NetBSD: ukfs.c,v 1.43 2009/12/03 14:23:49 pooka Exp $ */
/*
* Copyright (c) 2007, 2008, 2009 Antti Kantee. All Rights Reserved.
@@ -62,6 +62,7 @@
#include <rump/rump.h>
#include <rump/rump_syscalls.h>
+#include <rump/rumpuser.h>
#include "ukfs_int_disklabel.h"
@@ -161,6 +162,32 @@
rump_pub_lwp_release(rump_pub_lwp_curlwp());
}
+struct ukfs_part {
+ int part_type;
+ char part_labelchar;
+ off_t part_devoff;
+ off_t part_devsize;
+};
+
+enum ukfs_parttype { UKFS_PART_NONE, UKFS_PART_DISKLABEL, UKFS_PART_OFFSET };
+
+static struct ukfs_part ukfs__part_none = {
+ .part_type = UKFS_PART_NONE,
+ .part_devoff = 0,
+ .part_devsize = RUMP_ETFS_SIZE_ENDOFF,
+};
+static struct ukfs_part ukfs__part_na;
+struct ukfs_part *ukfs_part_none;
+struct ukfs_part *ukfs_part_na;
+
+static void
+ukfs_initparts(void)
+{
+
+ ukfs_part_none = &ukfs__part_none;
+ ukfs_part_na = &ukfs__part_na;
+}
+
int
_ukfs_init(int version)
{
@@ -173,6 +200,7 @@
return -1;
}
+ ukfs_initparts();
if ((rv = rump_init()) != 0) {
errno = rv;
return -1;
@@ -190,28 +218,180 @@
}
int
-ukfs_partition_probe(char *devpath, int *partition)
+ukfs_part_probe(char *devpath, struct ukfs_part **partp)
{
+ struct ukfs_part *part;
char *p;
- int rv = 0;
+ int error = 0;
+ int devfd = -1;
+
+ ukfs_initparts();
+ if ((p = strstr(devpath, UKFS_PARTITION_SCANMAGIC)) != NULL) {
+ fprintf(stderr, "ukfs: %%PART is deprecated. use "
+ "%%DISKLABEL instead\n");
+ errno = ENODEV;
+ return -1;
+ }
+
+ part = malloc(sizeof(*part));
+ if (part == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ part->part_type = UKFS_PART_NONE;
/*
- * Check for disklabel magic in pathname:
- * /regularpath%PART:<char>%\0
+ * Check for magic in pathname:
+ * disklabel: /regularpath%DISKLABEL:labelchar%\0
+ * offsets: /regularpath%OFFSET:start,end%\0
*/
-#define MAGICADJ(p, n) (p+sizeof(UKFS_PARTITION_SCANMAGIC)-1+n)
- if ((p = strstr(devpath, UKFS_PARTITION_SCANMAGIC)) != NULL
- && strlen(p) == UKFS_PARTITION_MAGICLEN
- && *(MAGICADJ(p,1)) == '%') {
- if (*(MAGICADJ(p,0)) >= 'a' &&
- *(MAGICADJ(p,0)) < 'a' + UKFS_MAXPARTITIONS) {
- *partition = *(MAGICADJ(p,0)) - 'a';
+#define MAGICADJ_DISKLABEL(p, n) (p+sizeof(UKFS_DISKLABEL_SCANMAGIC)-1+n)
+ if ((p = strstr(devpath, UKFS_DISKLABEL_SCANMAGIC)) != NULL
+ && strlen(p) == UKFS_DISKLABEL_MAGICLEN
+ && *(MAGICADJ_DISKLABEL(p,1)) == '%') {
+ if (*(MAGICADJ_DISKLABEL(p,0)) >= 'a' &&
+ *(MAGICADJ_DISKLABEL(p,0)) < 'a' + UKFS_MAXPARTITIONS) {
+ struct ukfs__disklabel dl;
+ struct ukfs__partition *pp;
+ char buf[65536];
+ char labelchar = *(MAGICADJ_DISKLABEL(p,0));
+ int partition = labelchar - 'a';
+
*p = '\0';
+ devfd = open(devpath, O_RDONLY);
+ if (devfd == -1) {
+ error = errno;
+ goto out;
+ }
+
+ /* Locate the disklabel and find the partition. */
+ if (pread(devfd, buf, sizeof(buf), 0) == -1) {
+ error = errno;
+ goto out;
+ }
+
+ if (ukfs__disklabel_scan(&dl, buf, sizeof(buf)) != 0) {
+ error = ENOENT;
+ goto out;
+ }
+
+ if (dl.d_npartitions < partition) {
+ error = ENOENT;
+ goto out;
+ }
+
+ pp = &dl.d_partitions[partition];
+ part->part_type = UKFS_PART_DISKLABEL;
+ part->part_labelchar = labelchar;
+ part->part_devoff = pp->p_offset << DEV_BSHIFT;
+ part->part_devsize = pp->p_size << DEV_BSHIFT;
} else {
- rv = EINVAL;
+ error = EINVAL;
+ }
+#define MAGICADJ_OFFSET(p, n) (p+sizeof(UKFS_OFFSET_SCANMAGIC)-1+n)
+ } else if (((p = strstr(devpath, UKFS_OFFSET_SCANMAGIC)) != NULL)
+ && (strlen(p) >= UKFS_OFFSET_MINLEN)) {
+ char *comma, *pers, *ep, *nptr;
+ u_quad_t val;
+
+ comma = strchr(p, ',');
+ if (comma == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ pers = strchr(comma, '%');
+ if (pers == NULL) {
+ error = EINVAL;
+ goto out;
+ }
+ *comma = '\0';
+ *pers = '\0';
+ *p = '\0';
+
+ nptr = MAGICADJ_OFFSET(p,0);
+ /* check if string is negative */
+ if (*nptr == '-') {
+ error = ERANGE;
+ goto out;
+ }
+ val = strtouq(nptr, &ep, 10);
+ if (val == UQUAD_MAX) {
+ error = ERANGE;
+ goto out;
+ }
+ if (*ep != '\0') {
+ error = EADDRNOTAVAIL; /* creative ;) */
+ goto out;
+ }
+ part->part_devoff = val;
+
+ /* omstart */
+
+ nptr = comma+1;
+ /* check if string is negative */
+ if (*nptr == '-') {
+ error = ERANGE;
+ goto out;
+ }
+ val = strtouq(nptr, &ep, 10);
+ if (val == UQUAD_MAX) {
+ error = ERANGE;
+ goto out;
+ }
+ if (*ep != '\0') {
+ error = EADDRNOTAVAIL; /* creative ;) */
+ goto out;
}
+ part->part_devsize = val;
+ part->part_type = UKFS_PART_OFFSET;
} else {
- *partition = UKFS_PARTITION_NONE;
+ free(part);
+ part = ukfs_part_none;
+ }
+
+ out:
+ if (devfd != -1)
+ close(devfd);
+ if (error) {
+ free(part);
+ errno = error;
+ } else {
+ *partp = part;
+ }
+
+ return error ? -1 : 0;
+}
+
+int
+ukfs_part_tostring(struct ukfs_part *part, char *str, size_t strsize)
+{
+ int rv;
+
+ *str = '\0';
+ /* "pseudo" values */
+ if (part == ukfs_part_na) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (part == ukfs_part_none)
+ return 0;
+
+ rv = 0;
+ switch (part->part_type) {
+ case UKFS_PART_NONE:
+ break;
+
+ case UKFS_PART_DISKLABEL:
+ snprintf(str, strsize, "%%DISKLABEL:%c%%",part->part_labelchar);
+ rv = 1;
+ break;
+
+ case UKFS_PART_OFFSET:
+ snprintf(str, strsize, "[%llu,%llu]",
+ (unsigned long long)part->part_devoff,
+ (unsigned long long)(part->part_devoff+part->part_devsize));
+ rv = 1;
+ break;
}
return rv;
@@ -239,51 +419,21 @@
* n device is open
*/
static int
-process_diskdevice(const char *devpath, int partition, int rdonly,
- int *dfdp, uint64_t *devoff, uint64_t *devsize)
+process_diskdevice(const char *devpath, struct ukfs_part *part, int rdonly,
+ int *dfdp)
{
- char buf[65536];
struct stat sb;
- struct ukfs_disklabel dl;
- struct ukfs_partition *pp;
int rv = 0, devfd;
/* defaults */
- *devoff = 0;
- *devsize = RUMP_ETFS_SIZE_ENDOFF;
*dfdp = -1;
devfd = open(devpath, rdonly ? O_RDONLY : O_RDWR);
if (devfd == -1) {
- if (UKFS_USEPARTITION(partition))
- rv = errno;
+ rv = errno;
goto out;
}
- /*
- * Locate the disklabel and find the partition in question.
- */
- if (UKFS_USEPARTITION(partition)) {
- if (pread(devfd, buf, sizeof(buf), 0) == -1) {
- rv = errno;
- goto out;
- }
-
- if (ukfs_disklabel_scan(&dl, buf, sizeof(buf)) != 0) {
- rv = ENOENT;
- goto out;
- }
-
- if (dl.d_npartitions < partition) {
- rv = ENOENT;
- goto out;
- }
-
- pp = &dl.d_partitions[partition];
- *devoff = pp->p_offset << DEV_BSHIFT;
- *devsize = pp->p_size << DEV_BSHIFT;
- }
-
if (fstat(devfd, &sb) == -1) {
rv = errno;
goto out;
@@ -311,30 +461,25 @@
if (rv) {
if (devfd != -1)
close(devfd);
- errno = rv;
- rv = -1;
}
return rv;
}
static struct ukfs *
-doukfsmount(const char *vfsname, const char *devpath, int partition,
+doukfsmount(const char *vfsname, const char *devpath, struct ukfs_part *part,
const char *mountpath, int mntflags, void *arg, size_t alen)
{
struct ukfs *fs = NULL;
int rv = 0, devfd = -1;
- uint64_t devoff, devsize;
int mounted = 0;
int regged = 0;
- /* XXX: gcc whine */
- devoff = 0;
- devsize = 0;
-
- if (partition != UKFS_PARTITION_NA)
- process_diskdevice(devpath, partition, mntflags & MNT_RDONLY,
- &devfd, &devoff, &devsize);
+ if (part != ukfs_part_na) {
+ if ((rv = process_diskdevice(devpath, part,
+ mntflags & MNT_RDONLY, &devfd)) != 0)
+ goto out;
+ }
fs = malloc(sizeof(struct ukfs));
if (fs == NULL) {
@@ -351,9 +496,10 @@
}
}
- if (partition != UKFS_PARTITION_NA) {
+ if (part != ukfs_part_na) {
+ /* LINTED */
rv = rump_pub_etfs_register_withsize(devpath, devpath,
- RUMP_ETFS_BLK, devoff, devsize);
+ RUMP_ETFS_BLK, part->part_devoff, part->part_devsize);
if (rv) {
goto out;
}
@@ -385,6 +531,7 @@
assert(rv == 0);
out:
+ ukfs_part_release(part);
if (rv) {
if (fs) {
if (fs->ukfs_rvp)
@@ -411,16 +558,17 @@
const char *mountpath, int mntflags, void *arg, size_t alen)
{
- return doukfsmount(vfsname, devpath, UKFS_PARTITION_NA,
+ return doukfsmount(vfsname, devpath, ukfs_part_na,
mountpath, mntflags, arg, alen);
}
struct ukfs *
-ukfs_mount_disk(const char *vfsname, const char *devpath, int partition,
- const char *mountpath, int mntflags, void *arg, size_t alen)
+ukfs_mount_disk(const char *vfsname, const char *devpath,
+ struct ukfs_part *part, const char *mountpath, int mntflags,
+ void *arg, size_t alen)
{
- return doukfsmount(vfsname, devpath, partition,
+ return doukfsmount(vfsname, devpath, part,
mountpath, mntflags, arg, alen);
}
@@ -466,6 +614,14 @@
return 0;
}
+void
+ukfs_part_release(struct ukfs_part *part)
+{
+
+ if (part != ukfs_part_none && part != ukfs_part_na)
+ free(part);
+}
+
#define STDCALL(ukfs, thecall) \
int rv = 0; \
\
Index: src/lib/libukfs/ukfs.h
diff -u src/lib/libukfs/ukfs.h:1.12 src/lib/libukfs/ukfs.h:1.13
--- src/lib/libukfs/ukfs.h:1.12 Thu Nov 5 14:22:54 2009
+++ src/lib/libukfs/ukfs.h Thu Dec 3 14:23:49 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: ukfs.h,v 1.12 2009/11/05 14:22:54 pooka Exp $ */
+/* $NetBSD: ukfs.h,v 1.13 2009/12/03 14:23:49 pooka Exp $ */
/*
* Copyright (c) 2007, 2008, 2009 Antti Kantee. All Rights Reserved.
@@ -42,6 +42,7 @@
struct ukfs;
struct ukfs_dircookie;
+struct ukfs_part;
#define UKFS_DEFAULTMP "/ukfs"
@@ -56,7 +57,7 @@
int _ukfs_init(int);
struct ukfs *ukfs_mount(const char *, const char *, const char *,
int, void *, size_t);
-struct ukfs *ukfs_mount_disk(const char *, const char *, int,
+struct ukfs *ukfs_mount_disk(const char *, const char *, struct ukfs_part *,
const char *, int, void *, size_t);
int ukfs_release(struct ukfs *, int);
@@ -114,21 +115,29 @@
void * ukfs_getspecific(struct ukfs *);
/* partition magic in device names */
-#define UKFS_PARTITION_SCANMAGIC "%PART:"
-#define UKFS_PARTITION_MAGICLEN (sizeof(UKFS_PARTITION_SCANMAGIC "a%")-1)
-#define UKFS_PARTITION_MAXPATHLEN (MAXPATHLEN+UKFS_PARTITION_MAGICLEN)
-#define UKFS_PARTITION_NONE (-1)
-#define UKFS_PARTITION_NA (-2)
-#define UKFS_USEPARTITION(a) \
- ((a) != UKFS_PARTITION_NONE && (a) != UKFS_PARTITION_NA)
-#define UKFS_PARTITION_ARGVPROBE(part) \
+extern struct ukfs_part *ukfs_part_none;
+extern struct ukfs_part *ukfs_part_na;
+#define UKFS_PARTITION_SCANMAGIC "%PART:" /* deprecated */
+
+#define UKFS_DISKLABEL_SCANMAGIC "%DISKLABEL:"
+#define UKFS_DISKLABEL_MAGICLEN (sizeof(UKFS_DISKLABEL_SCANMAGIC "a%")-1)
+
+#define UKFS_OFFSET_SCANMAGIC "%OFFSET:"
+#define UKFS_OFFSET_MINLEN (sizeof(UKFS_OFFSET_SCANMAGIC "512,512%")-1)
+
+#define UKFS_DEVICE_MAXSTR 128 /* unexact science ... */
+#define UKFS_DEVICE_MAXPATHLEN (MAXPATHLEN+UKFS_DEVICE_MAXSTR)
+
+#define UKFS_DEVICE_ARGVPROBE(part) \
do { \
- part = UKFS_PARTITION_NONE; \
if (argc >= 3) \
- ukfs_partition_probe(argv[argc-2], &part); \
+ if (ukfs_part_probe(argv[argc-2], part) == -1) \
+ err(1, "ukfs_part_probe"); \
} while (/*CONSTCOND*/0)
-int ukfs_partition_probe(char *, int *);
+int ukfs_part_probe(char *, struct ukfs_part **);
+void ukfs_part_release(struct ukfs_part *);
+int ukfs_part_tostring(struct ukfs_part *, char *, size_t);
/* dynamic loading of library modules */
int ukfs_modload(const char *);
Index: src/lib/libukfs/ukfs_disklabel.c
diff -u src/lib/libukfs/ukfs_disklabel.c:1.1 src/lib/libukfs/ukfs_disklabel.c:1.2
--- src/lib/libukfs/ukfs_disklabel.c:1.1 Wed Oct 7 20:51:00 2009
+++ src/lib/libukfs/ukfs_disklabel.c Thu Dec 3 14:23:49 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: ukfs_disklabel.c,v 1.1 2009/10/07 20:51:00 pooka Exp $ */
+/* $NetBSD: ukfs_disklabel.c,v 1.2 2009/12/03 14:23:49 pooka Exp $ */
/*
* Local copies of libutil disklabel routines. This uncouples libukfs
@@ -50,7 +50,7 @@
#define SCAN_INCR 4
int
-ukfs_disklabel_scan(struct ukfs_disklabel *lp, char *buf, size_t buflen)
+ukfs__disklabel_scan(struct ukfs__disklabel *lp, char *buf, size_t buflen)
{
size_t i;
@@ -68,7 +68,7 @@
sanity:
/* we've found something, let's sanity check it */
if (lp->d_npartitions > UKFS_MAXPARTITIONS
- || ukfs_disklabel_dkcksum(lp))
+ || ukfs__disklabel_dkcksum(lp))
return 1;
return 0;
@@ -110,7 +110,7 @@
*/
uint16_t
-ukfs_disklabel_dkcksum(struct ukfs_disklabel *lp)
+ukfs__disklabel_dkcksum(struct ukfs__disklabel *lp)
{
uint16_t *start, *end;
uint16_t sum;
Index: src/lib/libukfs/ukfs_int_disklabel.h
diff -u src/lib/libukfs/ukfs_int_disklabel.h:1.1 src/lib/libukfs/ukfs_int_disklabel.h:1.2
--- src/lib/libukfs/ukfs_int_disklabel.h:1.1 Wed Oct 7 20:51:00 2009
+++ src/lib/libukfs/ukfs_int_disklabel.h Thu Dec 3 14:23:49 2009
@@ -1,4 +1,4 @@
-/* $NetBSD: ukfs_int_disklabel.h,v 1.1 2009/10/07 20:51:00 pooka Exp $ */
+/* $NetBSD: ukfs_int_disklabel.h,v 1.2 2009/12/03 14:23:49 pooka Exp $ */
/*
* Modified copy of disklabel.h so that ukfs doesn't have to depend
@@ -48,7 +48,7 @@
#define UKFS_MAXPARTITIONS 22
#define UKFS_DISKMAGIC ((uint32_t)0x82564557) /* The disk magic number */
-struct ukfs_disklabel {
+struct ukfs__disklabel {
uint32_t d_magic; /* the magic number */
uint16_t d_type; /* drive type */
uint16_t d_subtype; /* controller/d_type specific */
@@ -130,7 +130,7 @@
uint16_t d_npartitions; /* number of partitions in following */
uint32_t d_bbsize; /* size of boot area at sn0, bytes */
uint32_t d_sbsize; /* max size of fs superblock, bytes */
- struct ukfs_partition { /* the partition table */
+ struct ukfs__partition { /* the partition table */
uint32_t p_size; /* number of sectors in partition */
uint32_t p_offset; /* starting sector */
union {
@@ -151,7 +151,7 @@
} d_partitions[UKFS_MAXPARTITIONS]; /* actually may be more */
};
-uint16_t ukfs_disklabel_dkcksum(struct ukfs_disklabel *);
-int ukfs_disklabel_scan(struct ukfs_disklabel *, char *, size_t);
+uint16_t ukfs__disklabel_dkcksum(struct ukfs__disklabel *);
+int ukfs__disklabel_scan(struct ukfs__disklabel *, char *, size_t);
#endif /* !LIB_UKFS_DISKLABEL_H_ */