Index: head/sys/geom/label/g_label.c =================================================================== --- head/sys/geom/label/g_label.c (revision 363536) +++ head/sys/geom/label/g_label.c (revision 363537) @@ -1,568 +1,580 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2004-2005 Pawel Jakub Dawidek * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_geom.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include FEATURE(geom_label, "GEOM labeling support"); SYSCTL_DECL(_kern_geom); SYSCTL_NODE(_kern_geom, OID_AUTO, label, CTLFLAG_RW | CTLFLAG_MPSAFE, 0, "GEOM_LABEL stuff"); u_int g_label_debug = 0; SYSCTL_UINT(_kern_geom_label, OID_AUTO, debug, CTLFLAG_RWTUN, &g_label_debug, 0, "Debug level"); static int g_label_destroy_geom(struct gctl_req *req, struct g_class *mp, struct g_geom *gp); static int g_label_destroy(struct g_geom *gp, boolean_t force); static struct g_geom *g_label_taste(struct g_class *mp, struct g_provider *pp, int flags __unused); +static void g_label_generic_taste(struct g_consumer *, char *, size_t); static void g_label_config(struct gctl_req *req, struct g_class *mp, const char *verb); +#define G_LABEL_DIRPREFIX "label/" + struct g_class g_label_class = { .name = G_LABEL_CLASS_NAME, .version = G_VERSION, .ctlreq = g_label_config, .taste = g_label_taste, .destroy_geom = g_label_destroy_geom }; +static struct g_label_desc g_label_generic = { + .ld_taste = g_label_generic_taste, + .ld_dirprefix = G_LABEL_DIRPREFIX, + .ld_enabled = 1 +}; + /* * To add a new file system where you want to look for volume labels, * you have to: * 1. Add a file g_label_.c which implements labels recognition. * 2. Add an 'extern const struct g_label_desc g_label_;' into * g_label.h file. * 3. Add an element to the table below '&g_label_,'. * 4. Add your file to sys/conf/files. * 5. Add your file to sys/modules/geom/geom_label/Makefile. * 6. Add your file system to manual page sbin/geom/class/label/glabel.8. */ const struct g_label_desc *g_labels[] = { &g_label_gpt, &g_label_gpt_uuid, #ifdef GEOM_LABEL &g_label_ufs_id, &g_label_ufs_volume, &g_label_iso9660, &g_label_msdosfs, &g_label_ext2fs, &g_label_reiserfs, &g_label_ntfs, &g_label_disk_ident, &g_label_flashmap, #endif + &g_label_generic, NULL }; void g_label_rtrim(char *label, size_t size) { ptrdiff_t i; for (i = size - 1; i >= 0; i--) { if (label[i] == '\0') continue; else if (label[i] == ' ') label[i] = '\0'; else break; } } static int g_label_destroy_geom(struct gctl_req *req __unused, struct g_class *mp, struct g_geom *gp __unused) { /* * XXX: Unloading a class which is using geom_slice:1.56 is currently * XXX: broken, so we deny unloading when we have geoms. */ return (EOPNOTSUPP); } static void g_label_orphan(struct g_consumer *cp) { G_LABEL_DEBUG(1, "Label %s removed.", LIST_FIRST(&cp->geom->provider)->name); g_slice_orphan(cp); } static void g_label_spoiled(struct g_consumer *cp) { G_LABEL_DEBUG(1, "Label %s removed.", LIST_FIRST(&cp->geom->provider)->name); g_slice_spoiled(cp); } static void g_label_resize(struct g_consumer *cp) { G_LABEL_DEBUG(1, "Label %s resized.", LIST_FIRST(&cp->geom->provider)->name); g_slice_config(cp->geom, 0, G_SLICE_CONFIG_FORCE, (off_t)0, cp->provider->mediasize, cp->provider->sectorsize, "notused"); } static int g_label_is_name_ok(const char *label) { const char *s; /* Check if the label starts from ../ */ if (strncmp(label, "../", 3) == 0) return (0); /* Check if the label contains /../ */ if (strstr(label, "/../") != NULL) return (0); /* Check if the label ends at ../ */ if ((s = strstr(label, "/..")) != NULL && s[3] == '\0') return (0); return (1); } static void g_label_mangle_name(char *label, size_t size) { struct sbuf *sb; const u_char *c; size_t len, i; /* Trim trailing whitespace. */ len = strlen(label); for (i = len; i > 0; i--) { if (isspace(label[i - 1])) label[i - 1] = '\0'; else break; } if (*label == '\0') return; sb = sbuf_new(NULL, NULL, size, SBUF_FIXEDLEN); for (c = label; *c != '\0'; c++) { /* Trim leading whitespace. */ if (isspace(*c) && sbuf_len(sb) == 0) continue; if (!isprint(*c) || isspace(*c) || *c =='"' || *c == '%') sbuf_printf(sb, "%%%02X", *c); else sbuf_putc(sb, *c); } if (sbuf_finish(sb) != 0) label[0] = '\0'; else strlcpy(label, sbuf_data(sb), size); sbuf_delete(sb); } static struct g_geom * g_label_create(struct gctl_req *req, struct g_class *mp, struct g_provider *pp, - const char *label, const char *dir, off_t mediasize) + const char *label, const char *dirprefix, off_t mediasize) { struct g_geom *gp; struct g_provider *pp2; struct g_consumer *cp; char name[64]; g_topology_assert(); if (!g_label_is_name_ok(label)) { G_LABEL_DEBUG(0, "%s contains suspicious label, skipping.", pp->name); G_LABEL_DEBUG(1, "%s suspicious label is: %s", pp->name, label); if (req != NULL) gctl_error(req, "Label name %s is invalid.", label); return (NULL); } gp = NULL; cp = NULL; - if (snprintf(name, sizeof(name), "%s/%s", dir, label) >= sizeof(name)) { + if (snprintf(name, sizeof(name), "%s%s", dirprefix, label) >= sizeof(name)) { if (req != NULL) gctl_error(req, "Label name %s is too long.", label); return (NULL); } LIST_FOREACH(gp, &mp->geom, geom) { pp2 = LIST_FIRST(&gp->provider); if (pp2 == NULL) continue; if ((pp2->flags & G_PF_ORPHAN) != 0) continue; if (strcmp(pp2->name, name) == 0) { G_LABEL_DEBUG(1, "Label %s(%s) already exists (%s).", label, name, pp->name); if (req != NULL) { gctl_error(req, "Provider %s already exists.", name); } return (NULL); } } gp = g_slice_new(mp, 1, pp, &cp, NULL, 0, NULL); if (gp == NULL) { G_LABEL_DEBUG(0, "Cannot create slice %s.", label); if (req != NULL) gctl_error(req, "Cannot create slice %s.", label); return (NULL); } gp->orphan = g_label_orphan; gp->spoiled = g_label_spoiled; gp->resize = g_label_resize; g_access(cp, -1, 0, 0); g_slice_config(gp, 0, G_SLICE_CONFIG_SET, (off_t)0, mediasize, pp->sectorsize, "%s", name); G_LABEL_DEBUG(1, "Label for provider %s is %s.", pp->name, name); return (gp); } static int g_label_destroy(struct g_geom *gp, boolean_t force) { struct g_provider *pp; g_topology_assert(); pp = LIST_FIRST(&gp->provider); if (pp != NULL && (pp->acr != 0 || pp->acw != 0 || pp->ace != 0)) { if (force) { G_LABEL_DEBUG(0, "Provider %s is still open, so it " "can't be definitely removed.", pp->name); } else { G_LABEL_DEBUG(1, "Provider %s is still open (r%dw%de%d).", pp->name, pp->acr, pp->acw, pp->ace); return (EBUSY); } } else if (pp != NULL) G_LABEL_DEBUG(1, "Label %s removed.", pp->name); g_slice_spoiled(LIST_FIRST(&gp->consumer)); return (0); } static int g_label_read_metadata(struct g_consumer *cp, struct g_label_metadata *md) { struct g_provider *pp; u_char *buf; int error; - g_topology_assert(); - pp = cp->provider; - g_topology_unlock(); buf = g_read_data(cp, pp->mediasize - pp->sectorsize, pp->sectorsize, &error); - g_topology_lock(); if (buf == NULL) return (error); /* Decode metadata. */ label_metadata_decode(buf, md); g_free(buf); return (0); } static void g_label_orphan_taste(struct g_consumer *cp __unused) { KASSERT(1 == 0, ("%s called?", __func__)); } static void g_label_start_taste(struct bio *bp __unused) { KASSERT(1 == 0, ("%s called?", __func__)); } static int g_label_access_taste(struct g_provider *pp __unused, int dr __unused, int dw __unused, int de __unused) { KASSERT(1 == 0, ("%s called", __func__)); return (EOPNOTSUPP); } +static void +g_label_generic_taste(struct g_consumer *cp, char *label, size_t size) +{ + struct g_provider *pp; + struct g_label_metadata md; + + g_topology_assert_not(); + label[0] = '\0'; + pp = cp->provider; + + if (g_label_read_metadata(cp, &md) != 0) + return; + + if (strcmp(md.md_magic, G_LABEL_MAGIC) != 0) + return; + + if (md.md_version > G_LABEL_VERSION) { + printf("geom_label.ko module is too old to handle %s.\n", + pp->name); + return; + } + /* + * Backward compatibility: there was no md_provsize field in + * earlier versions of metadata, so only check if we have it. + */ + if (md.md_version >= 2 && md.md_provsize != pp->mediasize) + return; + + strlcpy(label, md.md_label, size); +} + static struct g_geom * g_label_taste(struct g_class *mp, struct g_provider *pp, int flags __unused) { - struct g_label_metadata md; struct g_consumer *cp; struct g_geom *gp; + off_t mediasize; int i; g_trace(G_T_TOPOLOGY, "%s(%s, %s)", __func__, mp->name, pp->name); g_topology_assert(); G_LABEL_DEBUG(2, "Tasting %s.", pp->name); /* Skip providers that are already open for writing. */ if (pp->acw > 0) return (NULL); if (strcmp(pp->geom->class->name, mp->name) == 0) return (NULL); gp = g_new_geomf(mp, "label:taste"); gp->start = g_label_start_taste; gp->access = g_label_access_taste; gp->orphan = g_label_orphan_taste; cp = g_new_consumer(gp); g_attach(cp, pp); if (g_access(cp, 1, 0, 0) != 0) goto end; - do { - if (g_label_read_metadata(cp, &md) != 0) - break; - if (strcmp(md.md_magic, G_LABEL_MAGIC) != 0) - break; - if (md.md_version > G_LABEL_VERSION) { - printf("geom_label.ko module is too old to handle %s.\n", - pp->name); - break; - } - - /* - * Backward compatibility: - */ - /* - * There was no md_provsize field in earlier versions of - * metadata. - */ - if (md.md_version < 2) - md.md_provsize = pp->mediasize; - - if (md.md_provsize != pp->mediasize) - break; - - g_label_create(NULL, mp, pp, md.md_label, G_LABEL_DIR, - pp->mediasize - pp->sectorsize); - } while (0); for (i = 0; g_labels[i] != NULL; i++) { char label[128]; if (g_labels[i]->ld_enabled == 0) continue; g_topology_unlock(); g_labels[i]->ld_taste(cp, label, sizeof(label)); g_label_mangle_name(label, sizeof(label)); g_topology_lock(); if (label[0] == '\0') continue; - g_label_create(NULL, mp, pp, label, g_labels[i]->ld_dir, - pp->mediasize); + if (g_labels[i] != &g_label_generic) { + mediasize = pp->mediasize; + } else { + mediasize = pp->mediasize - pp->sectorsize; + } + g_label_create(NULL, mp, pp, label, + g_labels[i]->ld_dirprefix, mediasize); } g_access(cp, -1, 0, 0); end: g_detach(cp); g_destroy_consumer(cp); g_destroy_geom(gp); return (NULL); } static void g_label_ctl_create(struct gctl_req *req, struct g_class *mp) { struct g_provider *pp; const char *name; int *nargs; g_topology_assert(); nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); if (nargs == NULL) { gctl_error(req, "No '%s' argument", "nargs"); return; } if (*nargs != 2) { gctl_error(req, "Invalid number of arguments."); return; } /* * arg1 is the name of provider. */ pp = gctl_get_provider(req, "arg1"); if (pp == NULL) return; /* * arg0 is the label. */ name = gctl_get_asciiparam(req, "arg0"); if (name == NULL) { gctl_error(req, "No 'arg%d' argument", 0); return; } - g_label_create(req, mp, pp, name, G_LABEL_DIR, pp->mediasize); + g_label_create(req, mp, pp, name, G_LABEL_DIRPREFIX, pp->mediasize); } static const char * g_label_skip_dir(const char *name) { - char path[64]; u_int i; if (strncmp(name, _PATH_DEV, strlen(_PATH_DEV)) == 0) name += strlen(_PATH_DEV); - if (strncmp(name, G_LABEL_DIR "/", strlen(G_LABEL_DIR "/")) == 0) - name += strlen(G_LABEL_DIR "/"); for (i = 0; g_labels[i] != NULL; i++) { - snprintf(path, sizeof(path), "%s/", g_labels[i]->ld_dir); - if (strncmp(name, path, strlen(path)) == 0) { - name += strlen(path); + if (strncmp(name, g_labels[i]->ld_dirprefix, + strlen(g_labels[i]->ld_dirprefix)) == 0) { + name += strlen(g_labels[i]->ld_dirprefix); break; } } return (name); } static struct g_geom * g_label_find_geom(struct g_class *mp, const char *name) { struct g_geom *gp; struct g_provider *pp; const char *pname; name = g_label_skip_dir(name); LIST_FOREACH(gp, &mp->geom, geom) { pp = LIST_FIRST(&gp->provider); pname = g_label_skip_dir(pp->name); if (strcmp(pname, name) == 0) return (gp); } return (NULL); } static void g_label_ctl_destroy(struct gctl_req *req, struct g_class *mp) { int *nargs, *force, error, i; struct g_geom *gp; const char *name; char param[16]; g_topology_assert(); nargs = gctl_get_paraml(req, "nargs", sizeof(*nargs)); if (nargs == NULL) { gctl_error(req, "No '%s' argument", "nargs"); return; } if (*nargs <= 0) { gctl_error(req, "Missing device(s)."); return; } force = gctl_get_paraml(req, "force", sizeof(*force)); if (force == NULL) { gctl_error(req, "No 'force' argument"); return; } for (i = 0; i < *nargs; i++) { snprintf(param, sizeof(param), "arg%d", i); name = gctl_get_asciiparam(req, param); if (name == NULL) { gctl_error(req, "No 'arg%d' argument", i); return; } gp = g_label_find_geom(mp, name); if (gp == NULL) { G_LABEL_DEBUG(1, "Label %s is invalid.", name); gctl_error(req, "Label %s is invalid.", name); return; } error = g_label_destroy(gp, *force); if (error != 0) { gctl_error(req, "Cannot destroy label %s (error=%d).", LIST_FIRST(&gp->provider)->name, error); return; } } } static void g_label_config(struct gctl_req *req, struct g_class *mp, const char *verb) { uint32_t *version; g_topology_assert(); version = gctl_get_paraml(req, "version", sizeof(*version)); if (version == NULL) { gctl_error(req, "No '%s' argument.", "version"); return; } if (*version != G_LABEL_VERSION) { gctl_error(req, "Userland and kernel parts are out of sync."); return; } if (strcmp(verb, "create") == 0) { g_label_ctl_create(req, mp); return; } else if (strcmp(verb, "destroy") == 0 || strcmp(verb, "stop") == 0) { g_label_ctl_destroy(req, mp); return; } gctl_error(req, "Unknown verb."); } DECLARE_GEOM_CLASS(g_label_class, g_label); MODULE_VERSION(geom_label, 0); Index: head/sys/geom/label/g_label.h =================================================================== --- head/sys/geom/label/g_label.h (revision 363536) +++ head/sys/geom/label/g_label.h (revision 363537) @@ -1,113 +1,112 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2004-2005 Pawel Jakub Dawidek * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef _G_LABEL_H_ #define _G_LABEL_H_ #include #ifdef _KERNEL #include #endif #define G_LABEL_CLASS_NAME "LABEL" #define G_LABEL_MAGIC "GEOM::LABEL" /* * Version history: * 1 - Initial version number. * 2 - Added md_provsize field to metadata. */ #define G_LABEL_VERSION 2 -#define G_LABEL_DIR "label" #ifdef _KERNEL extern u_int g_label_debug; #define G_LABEL_DEBUG(lvl, ...) \ _GEOM_DEBUG("GEOM_LABEL", g_label_debug, (lvl), NULL, __VA_ARGS__) SYSCTL_DECL(_kern_geom_label); #define G_LABEL_INIT(kind, label, descr) \ SYSCTL_NODE(_kern_geom_label, OID_AUTO, kind, \ CTLFLAG_RD | CTLFLAG_MPSAFE, \ NULL, ""); \ SYSCTL_INT(_kern_geom_label_##kind, OID_AUTO, enable, \ CTLFLAG_RWTUN, &label.ld_enabled, 1, descr) typedef void g_label_taste_t (struct g_consumer *cp, char *label, size_t size); struct g_label_desc { g_label_taste_t *ld_taste; - char *ld_dir; + char *ld_dirprefix; int ld_enabled; }; /* Supported labels. */ extern struct g_label_desc g_label_ufs_id; extern struct g_label_desc g_label_ufs_volume; extern struct g_label_desc g_label_iso9660; extern struct g_label_desc g_label_msdosfs; extern struct g_label_desc g_label_ext2fs; extern struct g_label_desc g_label_reiserfs; extern struct g_label_desc g_label_ntfs; extern struct g_label_desc g_label_gpt; extern struct g_label_desc g_label_gpt_uuid; extern struct g_label_desc g_label_disk_ident; extern struct g_label_desc g_label_flashmap; extern void g_label_rtrim(char *label, size_t size); #endif /* _KERNEL */ struct g_label_metadata { char md_magic[16]; /* Magic value. */ uint32_t md_version; /* Version number. */ char md_label[16]; /* Label. */ uint64_t md_provsize; /* Provider's size. */ }; static __inline void label_metadata_encode(const struct g_label_metadata *md, u_char *data) { bcopy(md->md_magic, data, sizeof(md->md_magic)); le32enc(data + 16, md->md_version); bcopy(md->md_label, data + 20, sizeof(md->md_label)); le64enc(data + 36, md->md_provsize); } static __inline void label_metadata_decode(const u_char *data, struct g_label_metadata *md) { bcopy(data, md->md_magic, sizeof(md->md_magic)); md->md_version = le32dec(data + 16); bcopy(data + 20, md->md_label, sizeof(md->md_label)); md->md_provsize = le64dec(data + 36); } #endif /* _G_LABEL_H_ */ Index: head/sys/geom/label/g_label_disk_ident.c =================================================================== --- head/sys/geom/label/g_label_disk_ident.c (revision 363536) +++ head/sys/geom/label/g_label_disk_ident.c (revision 363537) @@ -1,90 +1,88 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2012 Ivan Voras * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include -#define G_LABEL_DISK_IDENT_DIR "diskid" - static char* classes_pass[] = { G_DISK_CLASS_NAME, G_MULTIPATH_CLASS_NAME, NULL }; static void g_label_disk_ident_taste(struct g_consumer *cp, char *label, size_t size) { struct g_class *cls; char ident[DISK_IDENT_SIZE]; int ident_len, found, i; g_topology_assert_not(); label[0] = '\0'; cls = cp->provider->geom->class; /* * Get the GEOM::ident string, and construct a label in the format * "CLASS_NAME-ident" */ ident_len = sizeof(ident); if (g_io_getattr("GEOM::ident", cp, &ident_len, ident) == 0) { if (ident_len == 0 || ident[0] == '\0') return; for (i = 0, found = 0; classes_pass[i] != NULL; i++) if (strcmp(classes_pass[i], cls->name) == 0) { found = 1; break; } if (!found) return; /* * We can safely ignore the result of snprintf(): the label * will simply be truncated, which at most is only annoying. */ (void)snprintf(label, size, "%s-%s", cls->name, ident); } } struct g_label_desc g_label_disk_ident = { .ld_taste = g_label_disk_ident_taste, - .ld_dir = G_LABEL_DISK_IDENT_DIR, + .ld_dirprefix = "diskid/", .ld_enabled = 1 }; G_LABEL_INIT(disk_ident, g_label_disk_ident, "Create device nodes for drives " "which export a disk identification string"); Index: head/sys/geom/label/g_label_ext2fs.c =================================================================== --- head/sys/geom/label/g_label_ext2fs.c (revision 363536) +++ head/sys/geom/label/g_label_ext2fs.c (revision 363537) @@ -1,104 +1,104 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2005 Stanislav Sedov * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #define EXT2FS_SB_OFFSET 1024 #define EXT2_SUPER_MAGIC 0xef53 #define EXT2_DYNAMIC_REV 1 typedef struct e2sb { uint8_t fake1[56]; uint16_t s_magic; uint8_t fake2[18]; uint32_t s_rev_level; uint8_t fake3[40]; char s_volume_name[16]; } e2sb_t; static void g_label_ext2fs_taste(struct g_consumer *cp, char *label, size_t size) { struct g_provider *pp; e2sb_t *fs; char *s_volume_name; g_topology_assert_not(); pp = cp->provider; label[0] = '\0'; if ((EXT2FS_SB_OFFSET % pp->sectorsize) != 0) return; fs = (e2sb_t *)g_read_data(cp, EXT2FS_SB_OFFSET, pp->sectorsize, NULL); if (fs == NULL) return; /* Check for magic and versio n*/ if (fs->s_magic == EXT2_SUPER_MAGIC && fs->s_rev_level == EXT2_DYNAMIC_REV) { G_LABEL_DEBUG(1, "ext2fs file system detected on %s.", pp->name); } else { goto exit_free; } s_volume_name = fs->s_volume_name; /* Terminate label */ s_volume_name[sizeof(fs->s_volume_name) - 1] = '\0'; if (s_volume_name[0] == '/') s_volume_name += 1; /* Check for volume label */ if (s_volume_name[0] == '\0') goto exit_free; strlcpy(label, s_volume_name, size); exit_free: g_free(fs); } struct g_label_desc g_label_ext2fs = { .ld_taste = g_label_ext2fs_taste, - .ld_dir = "ext2fs", + .ld_dirprefix = "ext2fs/", .ld_enabled = 1 }; G_LABEL_INIT(ext2fs, g_label_ext2fs, "Create device nodes for EXT2FS volumes"); Index: head/sys/geom/label/g_label_flashmap.c =================================================================== --- head/sys/geom/label/g_label_flashmap.c (revision 363536) +++ head/sys/geom/label/g_label_flashmap.c (revision 363537) @@ -1,77 +1,75 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2019 Ian Lepore * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include -#define G_LABEL_FLASHMAP_SLICE_DIR "flash" - static void g_label_flashmap_taste(struct g_consumer *cp, char *label, size_t size) { struct g_flashmap *gfp; struct g_slicer *gsp; struct g_provider *pp; g_topology_assert_not(); pp = cp->provider; label[0] = '\0'; /* We taste only partitions handled by flashmap */ if (strncmp(pp->geom->class->name, FLASHMAP_CLASS_NAME, sizeof(FLASHMAP_CLASS_NAME)) != 0) return; gsp = (struct g_slicer *)pp->geom->softc; gfp = (struct g_flashmap *)gsp->softc; /* If it's handled by flashmap it should have a label, but be safe. */ if (gfp->labels[pp->index] == NULL) return; strlcpy(label, gfp->labels[pp->index], size); } struct g_label_desc g_label_flashmap = { .ld_taste = g_label_flashmap_taste, - .ld_dir = G_LABEL_FLASHMAP_SLICE_DIR, + .ld_dirprefix = "flash/", .ld_enabled = 1 }; G_LABEL_INIT(flashmap, g_label_flashmap, "Create device nodes for Flashmap labels"); Index: head/sys/geom/label/g_label_gpt.c =================================================================== --- head/sys/geom/label/g_label_gpt.c (revision 363536) +++ head/sys/geom/label/g_label_gpt.c (revision 363537) @@ -1,172 +1,169 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2008 Marius Nuennerich * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #define PART_CLASS_NAME "PART" #define SCHEME_NAME "GPT" -#define G_LABEL_GPT_VOLUME_DIR "gpt" -#define G_LABEL_GPT_ID_DIR "gptid" - /* XXX: Also defined in geom/part/g_part_gpt.c */ struct g_part_gpt_entry { struct g_part_entry base; struct gpt_ent ent; }; /* XXX: Shamelessly stolen from g_part_gpt.c */ static void sbuf_nprintf_utf16(struct sbuf *sb, uint16_t *str, size_t len) { u_int bo; uint32_t ch; uint16_t c; bo = LITTLE_ENDIAN; /* GPT is little-endian */ while (len > 0 && *str != 0) { ch = (bo == BIG_ENDIAN) ? be16toh(*str) : le16toh(*str); str++, len--; if ((ch & 0xf800) == 0xd800) { if (len > 0) { c = (bo == BIG_ENDIAN) ? be16toh(*str) : le16toh(*str); str++, len--; } else c = 0xfffd; if ((ch & 0x400) == 0 && (c & 0xfc00) == 0xdc00) { ch = ((ch & 0x3ff) << 10) + (c & 0x3ff); ch += 0x10000; } else ch = 0xfffd; } else if (ch == 0xfffe) { /* BOM (U+FEFF) swapped. */ bo = (bo == BIG_ENDIAN) ? LITTLE_ENDIAN : BIG_ENDIAN; continue; } else if (ch == 0xfeff) /* BOM (U+FEFF) unswapped. */ continue; /* Write the Unicode character in UTF-8 */ if (ch < 0x80) sbuf_printf(sb, "%c", ch); else if (ch < 0x800) sbuf_printf(sb, "%c%c", 0xc0 | (ch >> 6), 0x80 | (ch & 0x3f)); else if (ch < 0x10000) sbuf_printf(sb, "%c%c%c", 0xe0 | (ch >> 12), 0x80 | ((ch >> 6) & 0x3f), 0x80 | (ch & 0x3f)); else if (ch < 0x200000) sbuf_printf(sb, "%c%c%c%c", 0xf0 | (ch >> 18), 0x80 | ((ch >> 12) & 0x3f), 0x80 | ((ch >> 6) & 0x3f), 0x80 | (ch & 0x3f)); } } static void g_label_gpt_taste(struct g_consumer *cp, char *label, size_t size) { struct g_provider *pp; struct g_part_table *tp; struct g_part_gpt_entry *part_gpt_entry; struct sbuf *lbl; g_topology_assert_not(); pp = cp->provider; tp = (struct g_part_table *)pp->geom->softc; label[0] = '\0'; /* We taste only partitions handled by GPART */ if (strncmp(pp->geom->class->name, PART_CLASS_NAME, sizeof(PART_CLASS_NAME))) return; /* and only GPT */ if (strncmp(tp->gpt_scheme->name, SCHEME_NAME, sizeof(SCHEME_NAME))) return; part_gpt_entry = (struct g_part_gpt_entry *)pp->private; /* * Create sbuf with biggest possible size. * We need max. 4 bytes for every 2-byte utf16 char. */ lbl = sbuf_new(NULL, NULL, sizeof(part_gpt_entry->ent.ent_name) << 1, SBUF_FIXEDLEN); /* Size is the number of characters, not bytes */ sbuf_nprintf_utf16(lbl, part_gpt_entry->ent.ent_name, sizeof(part_gpt_entry->ent.ent_name) >> 1); sbuf_finish(lbl); strlcpy(label, sbuf_data(lbl), size); sbuf_delete(lbl); } static void g_label_gpt_uuid_taste(struct g_consumer *cp, char *label, size_t size) { struct g_provider *pp; struct g_part_table *tp; struct g_part_gpt_entry *part_gpt_entry; g_topology_assert_not(); pp = cp->provider; tp = (struct g_part_table *)pp->geom->softc; label[0] = '\0'; /* We taste only partitions handled by GPART */ if (strncmp(pp->geom->class->name, PART_CLASS_NAME, sizeof(PART_CLASS_NAME))) return; /* and only GPT */ if (strncmp(tp->gpt_scheme->name, SCHEME_NAME, sizeof(SCHEME_NAME))) return; part_gpt_entry = (struct g_part_gpt_entry *)pp->private; snprintf_uuid(label, size, &part_gpt_entry->ent.ent_uuid); } struct g_label_desc g_label_gpt = { .ld_taste = g_label_gpt_taste, - .ld_dir = G_LABEL_GPT_VOLUME_DIR, + .ld_dirprefix = "gpt/", .ld_enabled = 1 }; struct g_label_desc g_label_gpt_uuid = { .ld_taste = g_label_gpt_uuid_taste, - .ld_dir = G_LABEL_GPT_ID_DIR, + .ld_dirprefix = "gptid/", .ld_enabled = 1 }; G_LABEL_INIT(gpt, g_label_gpt, "Create device nodes for GPT labels"); G_LABEL_INIT(gptid, g_label_gpt_uuid, "Create device nodes for GPT UUIDs"); Index: head/sys/geom/label/g_label_iso9660.c =================================================================== --- head/sys/geom/label/g_label_iso9660.c (revision 363536) +++ head/sys/geom/label/g_label_iso9660.c (revision 363537) @@ -1,82 +1,80 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2004 Pawel Jakub Dawidek * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include -#define G_LABEL_ISO9660_DIR "iso9660" - #define ISO9660_MAGIC "\x01" "CD001" "\x01\x00" #define ISO9660_OFFSET 0x8000 #define VOLUME_LEN 32 static void g_label_iso9660_taste(struct g_consumer *cp, char *label, size_t size) { struct g_provider *pp; char *sector, *volume; g_topology_assert_not(); pp = cp->provider; label[0] = '\0'; if ((ISO9660_OFFSET % pp->sectorsize) != 0) return; sector = (char *)g_read_data(cp, ISO9660_OFFSET, pp->sectorsize, NULL); if (sector == NULL) return; if (bcmp(sector, ISO9660_MAGIC, sizeof(ISO9660_MAGIC) - 1) != 0) { g_free(sector); return; } G_LABEL_DEBUG(1, "ISO9660 file system detected on %s.", pp->name); volume = sector + 0x28; bzero(label, size); strlcpy(label, volume, MIN(size, VOLUME_LEN)); g_free(sector); g_label_rtrim(label, size); } struct g_label_desc g_label_iso9660 = { .ld_taste = g_label_iso9660_taste, - .ld_dir = G_LABEL_ISO9660_DIR, + .ld_dirprefix = "iso9660/", .ld_enabled = 1 }; G_LABEL_INIT(iso9660, g_label_iso9660, "Create device nodes for ISO9660 volume names"); Index: head/sys/geom/label/g_label_msdosfs.c =================================================================== --- head/sys/geom/label/g_label_msdosfs.c (revision 363536) +++ head/sys/geom/label/g_label_msdosfs.c (revision 363537) @@ -1,220 +1,219 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2004 Pawel Jakub Dawidek * Copyright (c) 2006 Tobias Reifenberger * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include -#define G_LABEL_MSDOSFS_DIR "msdosfs" #define LABEL_NO_NAME "NO NAME " static void g_label_msdosfs_taste(struct g_consumer *cp, char *label, size_t size) { struct g_provider *pp; FAT_BSBPB *pfat_bsbpb; FAT32_BSBPB *pfat32_bsbpb; FAT_DES *pfat_entry; uint8_t *sector0, *sector; g_topology_assert_not(); pp = cp->provider; sector0 = NULL; sector = NULL; bzero(label, size); /* Check if the sector size of the medium is a valid FAT sector size. */ switch(pp->sectorsize) { case 512: case 1024: case 2048: case 4096: break; default: G_LABEL_DEBUG(1, "MSDOSFS: %s: sector size %d not compatible.", pp->name, pp->sectorsize); return; } /* Load 1st sector with boot sector and boot parameter block. */ sector0 = (uint8_t *)g_read_data(cp, 0, pp->sectorsize, NULL); if (sector0 == NULL) return; /* Check for the FAT boot sector signature. */ if (sector0[510] != 0x55 || sector0[511] != 0xaa) { G_LABEL_DEBUG(1, "MSDOSFS: %s: no FAT signature found.", pp->name); goto error; } /* * Test if this is really a FAT volume and determine the FAT type. */ pfat_bsbpb = (FAT_BSBPB *)sector0; pfat32_bsbpb = (FAT32_BSBPB *)sector0; if (UINT16BYTES(pfat_bsbpb->BPB_FATSz16) != 0) { /* * If the BPB_FATSz16 field is not zero and the string "FAT" is * at the right place, this should be a FAT12 or FAT16 volume. */ if (strncmp(pfat_bsbpb->BS_FilSysType, "FAT", 3) != 0) { G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT12/16 volume not valid.", pp->name); goto error; } G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT12/FAT16 volume detected.", pp->name); /* A volume with no name should have "NO NAME " as label. */ if (strncmp(pfat_bsbpb->BS_VolLab, LABEL_NO_NAME, sizeof(pfat_bsbpb->BS_VolLab)) == 0) { G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT12/16 volume has no name.", pp->name); goto error; } strlcpy(label, pfat_bsbpb->BS_VolLab, MIN(size, sizeof(pfat_bsbpb->BS_VolLab) + 1)); } else if (UINT32BYTES(pfat32_bsbpb->BPB_FATSz32) != 0) { uint32_t fat_FirstDataSector, fat_BytesPerSector, offset; /* * If the BPB_FATSz32 field is not zero and the string "FAT" is * at the right place, this should be a FAT32 volume. */ if (strncmp(pfat32_bsbpb->BS_FilSysType, "FAT", 3) != 0) { G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT32 volume not valid.", pp->name); goto error; } G_LABEL_DEBUG(1, "MSDOSFS: %s: FAT32 volume detected.", pp->name); /* * If the volume label is not "NO NAME " we're done. */ if (strncmp(pfat32_bsbpb->BS_VolLab, LABEL_NO_NAME, sizeof(pfat32_bsbpb->BS_VolLab)) != 0) { strlcpy(label, pfat32_bsbpb->BS_VolLab, MIN(size, sizeof(pfat32_bsbpb->BS_VolLab) + 1)); goto endofchecks; } /* * If the volume label "NO NAME " is in the boot sector, the * label of FAT32 volumes may be stored as a special entry in * the root directory. */ fat_FirstDataSector = UINT16BYTES(pfat32_bsbpb->BPB_RsvdSecCnt) + (pfat32_bsbpb->BPB_NumFATs * UINT32BYTES(pfat32_bsbpb->BPB_FATSz32)); fat_BytesPerSector = UINT16BYTES(pfat32_bsbpb->BPB_BytsPerSec); G_LABEL_DEBUG(2, "MSDOSFS: FAT_FirstDataSector=0x%x, FAT_BytesPerSector=%d", fat_FirstDataSector, fat_BytesPerSector); for (offset = fat_BytesPerSector * fat_FirstDataSector;; offset += fat_BytesPerSector) { sector = (uint8_t *)g_read_data(cp, offset, fat_BytesPerSector, NULL); if (sector == NULL) goto error; pfat_entry = (FAT_DES *)sector; do { /* No more entries available. */ if (pfat_entry->DIR_Name[0] == 0) { G_LABEL_DEBUG(1, "MSDOSFS: %s: " "FAT32 volume has no name.", pp->name); goto error; } /* Skip empty or long name entries. */ if (pfat_entry->DIR_Name[0] == 0xe5 || (pfat_entry->DIR_Attr & FAT_DES_ATTR_LONG_NAME) == FAT_DES_ATTR_LONG_NAME) { continue; } /* * The name of the entry is the volume label if * ATTR_VOLUME_ID is set. */ if (pfat_entry->DIR_Attr & FAT_DES_ATTR_VOLUME_ID) { strlcpy(label, pfat_entry->DIR_Name, MIN(size, sizeof(pfat_entry->DIR_Name) + 1)); goto endofchecks; } } while((uint8_t *)(++pfat_entry) < (uint8_t *)(sector + fat_BytesPerSector)); g_free(sector); } } else { G_LABEL_DEBUG(1, "MSDOSFS: %s: no FAT volume detected.", pp->name); goto error; } endofchecks: g_label_rtrim(label, size); error: if (sector0 != NULL) g_free(sector0); if (sector != NULL) g_free(sector); } struct g_label_desc g_label_msdosfs = { .ld_taste = g_label_msdosfs_taste, - .ld_dir = G_LABEL_MSDOSFS_DIR, + .ld_dirprefix = "msdosfs/", .ld_enabled = 1 }; G_LABEL_INIT(msdosfs, g_label_msdosfs, "Create device nodes for MSDOSFS volumes"); Index: head/sys/geom/label/g_label_ntfs.c =================================================================== --- head/sys/geom/label/g_label_ntfs.c (revision 363536) +++ head/sys/geom/label/g_label_ntfs.c (revision 363537) @@ -1,177 +1,175 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2005 Takanori Watanabe * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #define NTFS_A_VOLUMENAME 0x60 #define NTFS_FILEMAGIC ((uint32_t)(0x454C4946)) #define NTFS_VOLUMEINO 3 -#define G_LABEL_NTFS_DIR "ntfs" - struct ntfs_attr { uint32_t a_type; uint32_t reclen; uint8_t a_flag; uint8_t a_namelen; uint8_t a_nameoff; uint8_t reserved1; uint8_t a_compression; uint8_t reserved2; uint16_t a_index; uint16_t a_datalen; uint16_t reserved3; uint16_t a_dataoff; uint16_t a_indexed; } __packed; struct ntfs_filerec { uint32_t fr_hdrmagic; uint16_t fr_hdrfoff; uint16_t fr_hdrfnum; uint8_t reserved[8]; uint16_t fr_seqnum; uint16_t fr_nlink; uint16_t fr_attroff; uint16_t fr_flags; uint32_t fr_size; uint32_t fr_allocated; uint64_t fr_mainrec; uint16_t fr_attrnum; } __packed; struct ntfs_bootfile { uint8_t reserved1[3]; uint8_t bf_sysid[8]; uint16_t bf_bps; uint8_t bf_spc; uint8_t reserved2[7]; uint8_t bf_media; uint8_t reserved3[2]; uint16_t bf_spt; uint16_t bf_heads; uint8_t reserver4[12]; uint64_t bf_spv; uint64_t bf_mftcn; uint64_t bf_mftmirrcn; int8_t bf_mftrecsz; uint32_t bf_ibsz; uint32_t bf_volsn; } __packed; static void g_label_ntfs_taste(struct g_consumer *cp, char *label, size_t size) { struct g_provider *pp; struct ntfs_bootfile *bf; struct ntfs_filerec *fr; struct ntfs_attr *atr; off_t voloff; char *filerecp, *ap; int8_t mftrecsz; char vnchar; int recsize, j; g_topology_assert_not(); label[0] = '\0'; pp = cp->provider; filerecp = NULL; bf = (struct ntfs_bootfile *)g_read_data(cp, 0, pp->sectorsize, NULL); if (bf == NULL || strncmp(bf->bf_sysid, "NTFS ", 8) != 0) goto done; mftrecsz = bf->bf_mftrecsz; recsize = (mftrecsz > 0) ? (mftrecsz * bf->bf_bps * bf->bf_spc) : (1 << -mftrecsz); if (recsize == 0 || recsize % pp->sectorsize != 0) goto done; voloff = bf->bf_mftcn * bf->bf_spc * bf->bf_bps + recsize * NTFS_VOLUMEINO; if (voloff % pp->sectorsize != 0) goto done; filerecp = g_read_data(cp, voloff, recsize, NULL); if (filerecp == NULL) goto done; fr = (struct ntfs_filerec *)filerecp; if (fr->fr_hdrmagic != NTFS_FILEMAGIC) goto done; for (ap = filerecp + fr->fr_attroff; atr = (struct ntfs_attr *)ap, atr->a_type != -1; ap += atr->reclen) { if (atr->a_type == NTFS_A_VOLUMENAME) { if(atr->a_datalen >= size *2){ label[0] = 0; goto done; } /* *UNICODE to ASCII. * Should we need to use iconv(9)? */ for (j = 0; j < atr->a_datalen; j++) { vnchar = *(ap + atr->a_dataoff + j); if (j & 1) { if (vnchar) { label[0] = 0; goto done; } } else { label[j / 2] = vnchar; } } label[j / 2] = 0; break; } } done: if (bf != NULL) g_free(bf); if (filerecp != NULL) g_free(filerecp); } struct g_label_desc g_label_ntfs = { .ld_taste = g_label_ntfs_taste, - .ld_dir = G_LABEL_NTFS_DIR, + .ld_dirprefix = "ntfs/", .ld_enabled = 1 }; G_LABEL_INIT(ntfs, g_label_ntfs, "Create device nodes for NTFS volumes"); Index: head/sys/geom/label/g_label_reiserfs.c =================================================================== --- head/sys/geom/label/g_label_reiserfs.c (revision 363536) +++ head/sys/geom/label/g_label_reiserfs.c (revision 363537) @@ -1,123 +1,123 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2005 Stanislav Sedov * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #define REISERFS_NEW_DISK_OFFSET 64 * 1024 #define REISERFS_OLD_DISK_OFFSET 8 * 1024 #define REISERFS_SUPER_MAGIC "ReIsEr" typedef struct reiserfs_sb { uint8_t fake1[52]; char s_magic[10]; uint8_t fake2[10]; uint16_t s_version; uint8_t fake3[26]; char s_volume_name[16]; } reiserfs_sb_t; static reiserfs_sb_t * g_label_reiserfs_read_super(struct g_consumer *cp, off_t offset) { reiserfs_sb_t *fs; u_int secsize; secsize = cp->provider->sectorsize; if ((offset % secsize) != 0) return (NULL); fs = (reiserfs_sb_t *)g_read_data(cp, offset, secsize, NULL); if (fs == NULL) return (NULL); if (strncmp(fs->s_magic, REISERFS_SUPER_MAGIC, strlen(REISERFS_SUPER_MAGIC)) != 0) { g_free(fs); return (NULL); } return (fs); } static void g_label_reiserfs_taste(struct g_consumer *cp, char *label, size_t size) { struct g_provider *pp; reiserfs_sb_t *fs; g_topology_assert_not(); pp = cp->provider; label[0] = '\0'; /* Try old format */ fs = g_label_reiserfs_read_super(cp, REISERFS_OLD_DISK_OFFSET); if (fs == NULL) { /* Try new format */ fs = g_label_reiserfs_read_super(cp, REISERFS_NEW_DISK_OFFSET); } if (fs == NULL) return; /* Check version */ if (fs->s_version == 2) { G_LABEL_DEBUG(1, "reiserfs file system detected on %s.", pp->name); } else { goto exit_free; } /* Check for volume label */ if (fs->s_volume_name[0] == '\0') goto exit_free; /* Terminate label */ fs->s_volume_name[sizeof(fs->s_volume_name) - 1] = '\0'; strlcpy(label, fs->s_volume_name, size); exit_free: g_free(fs); } struct g_label_desc g_label_reiserfs = { .ld_taste = g_label_reiserfs_taste, - .ld_dir = "reiserfs", + .ld_dirprefix = "reiserfs/", .ld_enabled = 1 }; G_LABEL_INIT(reiserfs, g_label_reiserfs, "Create device nodes for REISERFS volumes"); Index: head/sys/geom/label/g_label_ufs.c =================================================================== --- head/sys/geom/label/g_label_ufs.c (revision 363536) +++ head/sys/geom/label/g_label_ufs.c (revision 363537) @@ -1,158 +1,155 @@ /*- * SPDX-License-Identifier: BSD-2-Clause-FreeBSD * * Copyright (c) 2002, 2003 Gordon Tetlow * Copyright (c) 2006 Pawel Jakub Dawidek * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include -#define G_LABEL_UFS_VOLUME_DIR "ufs" -#define G_LABEL_UFS_ID_DIR "ufsid" - #define G_LABEL_UFS_VOLUME 0 #define G_LABEL_UFS_ID 1 /* * G_LABEL_UFS_CMP returns true if difference between provider mediasize * and filesystem size is less than G_LABEL_UFS_MAXDIFF sectors */ #define G_LABEL_UFS_CMP(prov, fsys, size) \ ( abs( ((fsys)->size) - ( (prov)->mediasize / (fsys)->fs_fsize )) \ < G_LABEL_UFS_MAXDIFF ) #define G_LABEL_UFS_MAXDIFF 0x100 /* * Try to find a superblock on the provider. If successful, then * check that the size in the superblock corresponds to the size * of the underlying provider. Finally, look for a volume label * and create an appropriate provider based on that. */ static void g_label_ufs_taste_common(struct g_consumer *cp, char *label, size_t size, int what) { struct g_provider *pp; struct fs *fs; g_topology_assert_not(); pp = cp->provider; label[0] = '\0'; fs = NULL; if (SBLOCKSIZE % pp->sectorsize != 0 || ffs_sbget(cp, &fs, STDSB_NOHASHFAIL, M_GEOM, g_use_g_read_data) != 0) { KASSERT(fs == NULL, ("g_label_ufs_taste_common: non-NULL fs %p\n", fs)); return; } /* * Check for magic. We also need to check if file system size * is almost equal to providers size, because sysinstall(8) * used to bogusly put first partition at offset 0 * instead of 16, and glabel/ufs would find file system on slice * instead of partition. * * In addition, media size can be a bit bigger than file system * size. For instance, mkuzip can append bytes to align data * to large sector size (it improves compression rates). */ if (fs->fs_magic == FS_UFS1_MAGIC && fs->fs_fsize > 0 && ( G_LABEL_UFS_CMP(pp, fs, fs_old_size) || G_LABEL_UFS_CMP(pp, fs, fs_providersize))) { /* Valid UFS1. */ } else if (fs->fs_magic == FS_UFS2_MAGIC && fs->fs_fsize > 0 && ( G_LABEL_UFS_CMP(pp, fs, fs_size) || G_LABEL_UFS_CMP(pp, fs, fs_providersize))) { /* Valid UFS2. */ } else { goto out; } G_LABEL_DEBUG(1, "%s file system detected on %s.", fs->fs_magic == FS_UFS1_MAGIC ? "UFS1" : "UFS2", pp->name); switch (what) { case G_LABEL_UFS_VOLUME: /* Check for volume label */ if (fs->fs_volname[0] != '\0') strlcpy(label, fs->fs_volname, size); break; case G_LABEL_UFS_ID: if (fs->fs_id[0] != 0 || fs->fs_id[1] != 0) snprintf(label, size, "%08x%08x", fs->fs_id[0], fs->fs_id[1]); break; } out: g_free(fs->fs_csp); g_free(fs->fs_si); g_free(fs); } static void g_label_ufs_volume_taste(struct g_consumer *cp, char *label, size_t size) { g_label_ufs_taste_common(cp, label, size, G_LABEL_UFS_VOLUME); } static void g_label_ufs_id_taste(struct g_consumer *cp, char *label, size_t size) { g_label_ufs_taste_common(cp, label, size, G_LABEL_UFS_ID); } struct g_label_desc g_label_ufs_volume = { .ld_taste = g_label_ufs_volume_taste, - .ld_dir = G_LABEL_UFS_VOLUME_DIR, + .ld_dirprefix = "ufs/", .ld_enabled = 1 }; struct g_label_desc g_label_ufs_id = { .ld_taste = g_label_ufs_id_taste, - .ld_dir = G_LABEL_UFS_ID_DIR, + .ld_dirprefix = "ufsid/", .ld_enabled = 1 }; G_LABEL_INIT(ufsid, g_label_ufs_id, "Create device nodes for UFS file system IDs"); G_LABEL_INIT(ufs, g_label_ufs_volume, "Create device nodes for UFS volume names"); MODULE_DEPEND(g_label, ufs, 1, 1, 1);