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_ */