1509798eaSPedro F. Giffuni /*- 29d529ed8SPedro F. Giffuni * Copyright (c) 2016-2019 The DragonFly Project 39d529ed8SPedro F. Giffuni * Copyright (c) 2016-2019 Tomohiro Kusumi <tkusumi@netbsd.org> 4509798eaSPedro F. Giffuni * All rights reserved. 5509798eaSPedro F. Giffuni * 6509798eaSPedro F. Giffuni * This software was developed by Edward Tomasz Napierala under sponsorship 7509798eaSPedro F. Giffuni * from the FreeBSD Foundation. 8509798eaSPedro F. Giffuni * 9509798eaSPedro F. Giffuni * Redistribution and use in source and binary forms, with or without 10509798eaSPedro F. Giffuni * modification, are permitted provided that the following conditions 11509798eaSPedro F. Giffuni * are met: 12509798eaSPedro F. Giffuni * 1. Redistributions of source code must retain the above copyright 13509798eaSPedro F. Giffuni * notice, this list of conditions and the following disclaimer. 14509798eaSPedro F. Giffuni * 2. Redistributions in binary form must reproduce the above copyright 15509798eaSPedro F. Giffuni * notice, this list of conditions and the following disclaimer in the 16509798eaSPedro F. Giffuni * documentation and/or other materials provided with the distribution. 17509798eaSPedro F. Giffuni * 18509798eaSPedro F. Giffuni * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 19509798eaSPedro F. Giffuni * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20509798eaSPedro F. Giffuni * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21509798eaSPedro F. Giffuni * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 22509798eaSPedro F. Giffuni * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23509798eaSPedro F. Giffuni * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24509798eaSPedro F. Giffuni * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25509798eaSPedro F. Giffuni * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26509798eaSPedro F. Giffuni * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27509798eaSPedro F. Giffuni * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28509798eaSPedro F. Giffuni * SUCH DAMAGE. 29509798eaSPedro F. Giffuni */ 30509798eaSPedro F. Giffuni 31509798eaSPedro F. Giffuni #include <sys/cdefs.h> 32509798eaSPedro F. Giffuni __FBSDID("$FreeBSD$"); 33509798eaSPedro F. Giffuni 34509798eaSPedro F. Giffuni #include <stdio.h> 35509798eaSPedro F. Giffuni #include <stdlib.h> 36509798eaSPedro F. Giffuni #include <string.h> 37509798eaSPedro F. Giffuni #include <err.h> 38509798eaSPedro F. Giffuni #include <assert.h> 39509798eaSPedro F. Giffuni 40509798eaSPedro F. Giffuni #include <sys/types.h> 41509798eaSPedro F. Giffuni 42509798eaSPedro F. Giffuni #include "hammer_disk.h" 43509798eaSPedro F. Giffuni 44509798eaSPedro F. Giffuni #include "fstyp.h" 45509798eaSPedro F. Giffuni 46*da0c0e01SPiotr Pawel Stefaniak extern int fsvtyp_hammer(const char *blkdevs, char *label, size_t size); 47*da0c0e01SPiotr Pawel Stefaniak extern int fsvtyp_hammer_partial(const char *blkdevs, char *label, size_t size); 48*da0c0e01SPiotr Pawel Stefaniak 49509798eaSPedro F. Giffuni static hammer_volume_ondisk_t 509d529ed8SPedro F. Giffuni read_ondisk(FILE *fp) 51509798eaSPedro F. Giffuni { 52509798eaSPedro F. Giffuni hammer_volume_ondisk_t ondisk; 53509798eaSPedro F. Giffuni 54509798eaSPedro F. Giffuni ondisk = read_buf(fp, 0, sizeof(*ondisk)); 55509798eaSPedro F. Giffuni if (ondisk == NULL) 56509798eaSPedro F. Giffuni err(1, "failed to read ondisk"); 57509798eaSPedro F. Giffuni 58509798eaSPedro F. Giffuni return (ondisk); 59509798eaSPedro F. Giffuni } 60509798eaSPedro F. Giffuni 61509798eaSPedro F. Giffuni static int 629d529ed8SPedro F. Giffuni test_ondisk(const hammer_volume_ondisk_t ondisk) 63509798eaSPedro F. Giffuni { 64509798eaSPedro F. Giffuni static int count = 0; 65509798eaSPedro F. Giffuni static hammer_uuid_t fsid, fstype; 66509798eaSPedro F. Giffuni static char label[64]; 67509798eaSPedro F. Giffuni 68509798eaSPedro F. Giffuni if (ondisk->vol_signature != HAMMER_FSBUF_VOLUME && 69509798eaSPedro F. Giffuni ondisk->vol_signature != HAMMER_FSBUF_VOLUME_REV) 70509798eaSPedro F. Giffuni return (1); 71509798eaSPedro F. Giffuni if (ondisk->vol_rootvol != HAMMER_ROOT_VOLNO) 72509798eaSPedro F. Giffuni return (2); 73509798eaSPedro F. Giffuni if (ondisk->vol_no < 0 || ondisk->vol_no > HAMMER_MAX_VOLUMES - 1) 74509798eaSPedro F. Giffuni return (3); 75509798eaSPedro F. Giffuni if (ondisk->vol_count < 1 || ondisk->vol_count > HAMMER_MAX_VOLUMES) 76509798eaSPedro F. Giffuni return (4); 77509798eaSPedro F. Giffuni 78509798eaSPedro F. Giffuni if (count == 0) { 79509798eaSPedro F. Giffuni count = ondisk->vol_count; 80509798eaSPedro F. Giffuni assert(count != 0); 81509798eaSPedro F. Giffuni memcpy(&fsid, &ondisk->vol_fsid, sizeof(fsid)); 82509798eaSPedro F. Giffuni memcpy(&fstype, &ondisk->vol_fstype, sizeof(fstype)); 830ab52bd3SEric van Gyzen strlcpy(label, ondisk->vol_label, sizeof(label)); 84509798eaSPedro F. Giffuni } else { 85509798eaSPedro F. Giffuni if (ondisk->vol_count != count) 86509798eaSPedro F. Giffuni return (5); 87509798eaSPedro F. Giffuni if (memcmp(&ondisk->vol_fsid, &fsid, sizeof(fsid))) 88509798eaSPedro F. Giffuni return (6); 89509798eaSPedro F. Giffuni if (memcmp(&ondisk->vol_fstype, &fstype, sizeof(fstype))) 90509798eaSPedro F. Giffuni return (7); 910ab52bd3SEric van Gyzen if (strcmp(ondisk->vol_label, label)) 92509798eaSPedro F. Giffuni return (8); 93509798eaSPedro F. Giffuni } 94509798eaSPedro F. Giffuni 95509798eaSPedro F. Giffuni return (0); 96509798eaSPedro F. Giffuni } 97509798eaSPedro F. Giffuni 98509798eaSPedro F. Giffuni int 99509798eaSPedro F. Giffuni fstyp_hammer(FILE *fp, char *label, size_t size) 100509798eaSPedro F. Giffuni { 101509798eaSPedro F. Giffuni hammer_volume_ondisk_t ondisk; 102509798eaSPedro F. Giffuni int error = 1; 103509798eaSPedro F. Giffuni 1049d529ed8SPedro F. Giffuni ondisk = read_ondisk(fp); 105509798eaSPedro F. Giffuni if (ondisk->vol_no != HAMMER_ROOT_VOLNO) 1069d529ed8SPedro F. Giffuni goto fail; 107509798eaSPedro F. Giffuni if (ondisk->vol_count != 1) 1089d529ed8SPedro F. Giffuni goto fail; 1099d529ed8SPedro F. Giffuni if (test_ondisk(ondisk)) 1109d529ed8SPedro F. Giffuni goto fail; 111509798eaSPedro F. Giffuni 112509798eaSPedro F. Giffuni strlcpy(label, ondisk->vol_label, size); 113509798eaSPedro F. Giffuni error = 0; 1149d529ed8SPedro F. Giffuni fail: 115509798eaSPedro F. Giffuni free(ondisk); 116509798eaSPedro F. Giffuni return (error); 117509798eaSPedro F. Giffuni } 118509798eaSPedro F. Giffuni 119509798eaSPedro F. Giffuni static int 1209d529ed8SPedro F. Giffuni test_volume(const char *volpath) 121509798eaSPedro F. Giffuni { 122509798eaSPedro F. Giffuni hammer_volume_ondisk_t ondisk; 123509798eaSPedro F. Giffuni FILE *fp; 124509798eaSPedro F. Giffuni int volno = -1; 125509798eaSPedro F. Giffuni 126509798eaSPedro F. Giffuni if ((fp = fopen(volpath, "r")) == NULL) 127509798eaSPedro F. Giffuni err(1, "failed to open %s", volpath); 128509798eaSPedro F. Giffuni 1299d529ed8SPedro F. Giffuni ondisk = read_ondisk(fp); 130509798eaSPedro F. Giffuni fclose(fp); 1319d529ed8SPedro F. Giffuni if (test_ondisk(ondisk)) 1329d529ed8SPedro F. Giffuni goto fail; 133509798eaSPedro F. Giffuni 134509798eaSPedro F. Giffuni volno = ondisk->vol_no; 1359d529ed8SPedro F. Giffuni fail: 136509798eaSPedro F. Giffuni free(ondisk); 137509798eaSPedro F. Giffuni return (volno); 138509798eaSPedro F. Giffuni } 139509798eaSPedro F. Giffuni 140509798eaSPedro F. Giffuni static int 141509798eaSPedro F. Giffuni __fsvtyp_hammer(const char *blkdevs, char *label, size_t size, int partial) 142509798eaSPedro F. Giffuni { 1439d529ed8SPedro F. Giffuni hammer_volume_ondisk_t ondisk = NULL; 144509798eaSPedro F. Giffuni FILE *fp; 145509798eaSPedro F. Giffuni char *dup, *p, *volpath, x[HAMMER_MAX_VOLUMES]; 146509798eaSPedro F. Giffuni int i, volno, error = 1; 147509798eaSPedro F. Giffuni 1489d529ed8SPedro F. Giffuni if (!blkdevs) 1499d529ed8SPedro F. Giffuni goto fail; 1509d529ed8SPedro F. Giffuni 151509798eaSPedro F. Giffuni memset(x, 0, sizeof(x)); 152509798eaSPedro F. Giffuni dup = strdup(blkdevs); 153509798eaSPedro F. Giffuni p = dup; 154509798eaSPedro F. Giffuni 1559d529ed8SPedro F. Giffuni volpath = NULL; 1569d529ed8SPedro F. Giffuni volno = -1; 157509798eaSPedro F. Giffuni while (p) { 158509798eaSPedro F. Giffuni volpath = p; 159509798eaSPedro F. Giffuni if ((p = strchr(p, ':')) != NULL) 160509798eaSPedro F. Giffuni *p++ = '\0'; 1619d529ed8SPedro F. Giffuni if ((volno = test_volume(volpath)) == -1) 162509798eaSPedro F. Giffuni break; 1639d529ed8SPedro F. Giffuni assert(volno >= 0); 1649d529ed8SPedro F. Giffuni assert(volno < HAMMER_MAX_VOLUMES); 165509798eaSPedro F. Giffuni x[volno]++; 166509798eaSPedro F. Giffuni } 167509798eaSPedro F. Giffuni 1689d529ed8SPedro F. Giffuni if (!volpath) 1699d529ed8SPedro F. Giffuni err(1, "invalid path %s", blkdevs); 170509798eaSPedro F. Giffuni if ((fp = fopen(volpath, "r")) == NULL) 171509798eaSPedro F. Giffuni err(1, "failed to open %s", volpath); 1729d529ed8SPedro F. Giffuni ondisk = read_ondisk(fp); 173509798eaSPedro F. Giffuni fclose(fp); 174509798eaSPedro F. Giffuni 175509798eaSPedro F. Giffuni free(dup); 176509798eaSPedro F. Giffuni 177509798eaSPedro F. Giffuni if (volno == -1) 1789d529ed8SPedro F. Giffuni goto fail; 179509798eaSPedro F. Giffuni if (partial) 180509798eaSPedro F. Giffuni goto success; 181509798eaSPedro F. Giffuni 182509798eaSPedro F. Giffuni for (i = 0; i < HAMMER_MAX_VOLUMES; i++) 183509798eaSPedro F. Giffuni if (x[i] > 1) 1849d529ed8SPedro F. Giffuni goto fail; 185509798eaSPedro F. Giffuni for (i = 0; i < HAMMER_MAX_VOLUMES; i++) 186509798eaSPedro F. Giffuni if (x[i] == 0) 187509798eaSPedro F. Giffuni break; 188509798eaSPedro F. Giffuni if (ondisk->vol_count != i) 1899d529ed8SPedro F. Giffuni goto fail; 190509798eaSPedro F. Giffuni for (; i < HAMMER_MAX_VOLUMES; i++) 191509798eaSPedro F. Giffuni if (x[i] != 0) 1929d529ed8SPedro F. Giffuni goto fail; 193509798eaSPedro F. Giffuni success: 194509798eaSPedro F. Giffuni strlcpy(label, ondisk->vol_label, size); 195509798eaSPedro F. Giffuni error = 0; 1969d529ed8SPedro F. Giffuni fail: 197509798eaSPedro F. Giffuni free(ondisk); 198509798eaSPedro F. Giffuni return (error); 199509798eaSPedro F. Giffuni } 200509798eaSPedro F. Giffuni 201509798eaSPedro F. Giffuni int 202509798eaSPedro F. Giffuni fsvtyp_hammer(const char *blkdevs, char *label, size_t size) 203509798eaSPedro F. Giffuni { 204509798eaSPedro F. Giffuni return (__fsvtyp_hammer(blkdevs, label, size, 0)); 205509798eaSPedro F. Giffuni } 206509798eaSPedro F. Giffuni 207509798eaSPedro F. Giffuni int 208509798eaSPedro F. Giffuni fsvtyp_hammer_partial(const char *blkdevs, char *label, size_t size) 209509798eaSPedro F. Giffuni { 210509798eaSPedro F. Giffuni return (__fsvtyp_hammer(blkdevs, label, size, 1)); 211509798eaSPedro F. Giffuni } 212