From owner-svn-src-head@freebsd.org Thu Feb 6 18:04:16 2020 Return-Path: Delivered-To: svn-src-head@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id AEBBE2327A7; Thu, 6 Feb 2020 18:04:16 +0000 (UTC) (envelope-from pfg@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) server-signature RSA-PSS (4096 bits) client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 48D5sr4GnZz4MVZ; Thu, 6 Feb 2020 18:04:16 +0000 (UTC) (envelope-from pfg@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 8DE6C1F9BA; Thu, 6 Feb 2020 18:04:16 +0000 (UTC) (envelope-from pfg@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id 016I4GmA089556; Thu, 6 Feb 2020 18:04:16 GMT (envelope-from pfg@FreeBSD.org) Received: (from pfg@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id 016I4Gx8089554; Thu, 6 Feb 2020 18:04:16 GMT (envelope-from pfg@FreeBSD.org) Message-Id: <202002061804.016I4Gx8089554@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: pfg set sender to pfg@FreeBSD.org using -f From: "Pedro F. Giffuni" Date: Thu, 6 Feb 2020 18:04:16 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r357631 - head/usr.sbin/fstyp X-SVN-Group: head X-SVN-Commit-Author: pfg X-SVN-Commit-Paths: head/usr.sbin/fstyp X-SVN-Commit-Revision: 357631 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 06 Feb 2020 18:04:16 -0000 Author: pfg Date: Thu Feb 6 18:04:15 2020 New Revision: 357631 URL: https://svnweb.freebsd.org/changeset/base/357631 Log: fstyp: sync HAMMER1/2 detection support with DragonFly BSD. Submitted by: Tomohiro Kusumi PR: 243929 Modified: head/usr.sbin/fstyp/hammer.c head/usr.sbin/fstyp/hammer2.c Modified: head/usr.sbin/fstyp/hammer.c ============================================================================== --- head/usr.sbin/fstyp/hammer.c Thu Feb 6 18:02:38 2020 (r357630) +++ head/usr.sbin/fstyp/hammer.c Thu Feb 6 18:04:15 2020 (r357631) @@ -1,5 +1,6 @@ /*- - * Copyright (c) 2016 The DragonFly Project + * Copyright (c) 2016-2019 The DragonFly Project + * Copyright (c) 2016-2019 Tomohiro Kusumi * All rights reserved. * * This software was developed by Edward Tomasz Napierala under sponsorship @@ -43,7 +44,7 @@ __FBSDID("$FreeBSD$"); #include "fstyp.h" static hammer_volume_ondisk_t -__read_ondisk(FILE *fp) +read_ondisk(FILE *fp) { hammer_volume_ondisk_t ondisk; @@ -55,7 +56,7 @@ __read_ondisk(FILE *fp) } static int -__test_ondisk(const hammer_volume_ondisk_t ondisk) +test_ondisk(const hammer_volume_ondisk_t ondisk) { static int count = 0; static hammer_uuid_t fsid, fstype; @@ -97,23 +98,23 @@ fstyp_hammer(FILE *fp, char *label, size_t size) hammer_volume_ondisk_t ondisk; int error = 1; - ondisk = __read_ondisk(fp); + ondisk = read_ondisk(fp); if (ondisk->vol_no != HAMMER_ROOT_VOLNO) - goto done; + goto fail; if (ondisk->vol_count != 1) - goto done; - if (__test_ondisk(ondisk)) - goto done; + goto fail; + if (test_ondisk(ondisk)) + goto fail; strlcpy(label, ondisk->vol_label, size); error = 0; -done: +fail: free(ondisk); return (error); } static int -__test_volume(const char *volpath) +test_volume(const char *volpath) { hammer_volume_ondisk_t ondisk; FILE *fp; @@ -122,13 +123,13 @@ __test_volume(const char *volpath) if ((fp = fopen(volpath, "r")) == NULL) err(1, "failed to open %s", volpath); - ondisk = __read_ondisk(fp); + ondisk = read_ondisk(fp); fclose(fp); - if (__test_ondisk(ondisk)) - goto done; + if (test_ondisk(ondisk)) + goto fail; volno = ondisk->vol_no; -done: +fail: free(ondisk); return (volno); } @@ -136,51 +137,60 @@ done: static int __fsvtyp_hammer(const char *blkdevs, char *label, size_t size, int partial) { - hammer_volume_ondisk_t ondisk; + hammer_volume_ondisk_t ondisk = NULL; FILE *fp; char *dup, *p, *volpath, x[HAMMER_MAX_VOLUMES]; int i, volno, error = 1; + if (!blkdevs) + goto fail; + memset(x, 0, sizeof(x)); dup = strdup(blkdevs); p = dup; + volpath = NULL; + volno = -1; while (p) { volpath = p; if ((p = strchr(p, ':')) != NULL) *p++ = '\0'; - if ((volno = __test_volume(volpath)) == -1) + if ((volno = test_volume(volpath)) == -1) break; + assert(volno >= 0); + assert(volno < HAMMER_MAX_VOLUMES); x[volno]++; } + if (!volpath) + err(1, "invalid path %s", blkdevs); if ((fp = fopen(volpath, "r")) == NULL) err(1, "failed to open %s", volpath); - ondisk = __read_ondisk(fp); + ondisk = read_ondisk(fp); fclose(fp); free(dup); if (volno == -1) - goto done; + goto fail; if (partial) goto success; for (i = 0; i < HAMMER_MAX_VOLUMES; i++) if (x[i] > 1) - goto done; + goto fail; for (i = 0; i < HAMMER_MAX_VOLUMES; i++) if (x[i] == 0) break; if (ondisk->vol_count != i) - goto done; + goto fail; for (; i < HAMMER_MAX_VOLUMES; i++) if (x[i] != 0) - goto done; + goto fail; success: strlcpy(label, ondisk->vol_label, size); error = 0; -done: +fail: free(ondisk); return (error); } Modified: head/usr.sbin/fstyp/hammer2.c ============================================================================== --- head/usr.sbin/fstyp/hammer2.c Thu Feb 6 18:02:38 2020 (r357630) +++ head/usr.sbin/fstyp/hammer2.c Thu Feb 6 18:04:15 2020 (r357631) @@ -1,5 +1,6 @@ /*- * Copyright (c) 2017-2019 The DragonFly Project + * Copyright (c) 2017-2019 Tomohiro Kusumi * All rights reserved. * * This software was developed by Edward Tomasz Napierala under sponsorship @@ -32,8 +33,10 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include +#include #include @@ -42,7 +45,7 @@ __FBSDID("$FreeBSD$"); #include "fstyp.h" static hammer2_volume_data_t* -__read_voldata(FILE *fp) +read_voldata(FILE *fp) { hammer2_volume_data_t *voldata; @@ -54,7 +57,7 @@ __read_voldata(FILE *fp) } static int -__test_voldata(const hammer2_volume_data_t *voldata) +test_voldata(const hammer2_volume_data_t *voldata) { if (voldata->magic != HAMMER2_VOLUME_ID_HBO && voldata->magic != HAMMER2_VOLUME_ID_ABO) @@ -63,14 +66,152 @@ __test_voldata(const hammer2_volume_data_t *voldata) return (0); } +static hammer2_media_data_t* +read_media(FILE *fp, const hammer2_blockref_t *bref, size_t *media_bytes) +{ + hammer2_media_data_t *media; + hammer2_off_t io_off, io_base; + size_t bytes, io_bytes, boff; + + bytes = (bref->data_off & HAMMER2_OFF_MASK_RADIX); + if (bytes) + bytes = (size_t)1 << bytes; + *media_bytes = bytes; + + if (!bytes) { + warnx("blockref has no data"); + return (NULL); + } + + io_off = bref->data_off & ~HAMMER2_OFF_MASK_RADIX; + io_base = io_off & ~(hammer2_off_t)(HAMMER2_MINIOSIZE - 1); + boff = io_off - io_base; + + io_bytes = HAMMER2_MINIOSIZE; + while (io_bytes + boff < bytes) + io_bytes <<= 1; + + if (io_bytes > sizeof(hammer2_media_data_t)) { + warnx("invalid I/O bytes"); + return (NULL); + } + + if (fseek(fp, io_base, SEEK_SET) == -1) { + warnx("failed to seek media"); + return (NULL); + } + media = read_buf(fp, io_base, io_bytes); + if (media == NULL) { + warnx("failed to read media"); + return (NULL); + } + if (boff) + memcpy(media, (char *)media + boff, bytes); + + return (media); +} + static int -__read_label(FILE *fp, char *label, size_t size) +find_pfs(FILE *fp, const hammer2_blockref_t *bref, const char *pfs, bool *res) { + hammer2_media_data_t *media; + hammer2_inode_data_t ipdata; + hammer2_blockref_t *bscan; + size_t bytes; + int i, bcount; + + media = read_media(fp, bref, &bytes); + if (media == NULL) + return (-1); + + switch (bref->type) { + case HAMMER2_BREF_TYPE_INODE: + ipdata = media->ipdata; + if (ipdata.meta.pfs_type & HAMMER2_PFSTYPE_SUPROOT) { + bscan = &ipdata.u.blockset.blockref[0]; + bcount = HAMMER2_SET_COUNT; + } else { + bscan = NULL; + bcount = 0; + if (ipdata.meta.op_flags & HAMMER2_OPFLAG_PFSROOT) { + if (memchr(ipdata.filename, 0, + sizeof(ipdata.filename))) { + if (!strcmp( + (const char*)ipdata.filename, pfs)) + *res = true; + } else { + if (strlen(pfs) > 0 && + !memcmp(ipdata.filename, pfs, + strlen(pfs))) + *res = true; + } + } else + assert(0); + } + break; + case HAMMER2_BREF_TYPE_INDIRECT: + bscan = &media->npdata[0]; + bcount = bytes / sizeof(hammer2_blockref_t); + break; + default: + bscan = NULL; + bcount = 0; + break; + } + + for (i = 0; i < bcount; ++i) { + if (bscan[i].type != HAMMER2_BREF_TYPE_EMPTY) { + if (find_pfs(fp, &bscan[i], pfs, res) == -1) { + free(media); + return (-1); + } + } + } + free(media); + + return (0); +} + +static char* +extract_device_name(const char *devpath) +{ + char *p, *head; + + if (!devpath) + return NULL; + + p = strdup(devpath); + head = p; + + p = strchr(p, '@'); + if (p) + *p = 0; + + p = strrchr(head, '/'); + if (p) { + p++; + if (*p == 0) { + free(head); + return NULL; + } + p = strdup(p); + free(head); + return p; + } + + return head; +} + +static int +read_label(FILE *fp, char *label, size_t size) +{ hammer2_blockref_t broot, best, *bref; hammer2_media_data_t *vols[HAMMER2_NUM_VOLHDRS], *media; - hammer2_off_t io_off, io_base; - size_t bytes, io_bytes, boff; - int i, best_i, error = 0; + size_t bytes; + bool res = false; + int i, best_i, error = 1; + const char *pfs; + char *devname; best_i = -1; memset(&best, 0, sizeof(best)); @@ -90,40 +231,39 @@ __read_label(FILE *fp, char *label, size_t size) bref = &vols[best_i]->voldata.sroot_blockset.blockref[0]; if (bref->type != HAMMER2_BREF_TYPE_INODE) { - warnx("Superroot blockref type is not inode"); - error = 2; - goto done; + warnx("blockref type is not inode"); + goto fail; } - bytes = bref->data_off & HAMMER2_OFF_MASK_RADIX; - if (bytes) - bytes = (size_t)1 << bytes; - if (bytes != sizeof(hammer2_inode_data_t)) { - warnx("Superroot blockref size does not match inode size"); - error = 3; - goto done; + media = read_media(fp, bref, &bytes); + if (media == NULL) { + goto fail; } - io_off = bref->data_off & ~HAMMER2_OFF_MASK_RADIX; - io_base = io_off & ~(hammer2_off_t)(HAMMER2_MINIOSIZE - 1); - boff = io_off - io_base; + pfs = ""; + devname = extract_device_name(NULL); + assert(!devname); /* Currently always NULL in FreeBSD. */ - io_bytes = HAMMER2_MINIOSIZE; - while (io_bytes + boff < bytes) - io_bytes <<= 1; - if (io_bytes > sizeof(*media)) { - warnx("Invalid I/O bytes"); - error = 4; - goto done; + /* Add device name to help support multiple autofs -media mounts. */ + if (find_pfs(fp, bref, pfs, &res) == 0 && res) { + if (devname) + snprintf(label, size, "%s_%s", pfs, devname); + else + strlcpy(label, pfs, size); + } else { + memset(label, 0, size); + memcpy(label, media->ipdata.filename, + sizeof(media->ipdata.filename)); + if (devname) { + strlcat(label, "_", size); + strlcat(label, devname, size); + } } - - media = read_buf(fp, io_base, io_bytes); - if (boff) - memcpy(media, (char*)media + boff, bytes); - - strlcpy(label, (char*)media->ipdata.filename, size); + if (devname) + free(devname); free(media); -done: + error = 0; +fail: for (i = 0; i < HAMMER2_NUM_VOLHDRS; i++) free(vols[i]); @@ -136,12 +276,12 @@ fstyp_hammer2(FILE *fp, char *label, size_t size) hammer2_volume_data_t *voldata; int error = 1; - voldata = __read_voldata(fp); - if (__test_voldata(voldata)) - goto done; + voldata = read_voldata(fp); + if (test_voldata(voldata)) + goto fail; - error = __read_label(fp, label, size); -done: + error = read_label(fp, label, size); +fail: free(voldata); return (error); }