1*509798eaSPedro F. Giffuni /*- 2*509798eaSPedro F. Giffuni * Copyright (c) 2016 The DragonFly Project 3*509798eaSPedro F. Giffuni * All rights reserved. 4*509798eaSPedro F. Giffuni * 5*509798eaSPedro F. Giffuni * This software was developed by Edward Tomasz Napierala under sponsorship 6*509798eaSPedro F. Giffuni * from the FreeBSD Foundation. 7*509798eaSPedro F. Giffuni * 8*509798eaSPedro F. Giffuni * Redistribution and use in source and binary forms, with or without 9*509798eaSPedro F. Giffuni * modification, are permitted provided that the following conditions 10*509798eaSPedro F. Giffuni * are met: 11*509798eaSPedro F. Giffuni * 1. Redistributions of source code must retain the above copyright 12*509798eaSPedro F. Giffuni * notice, this list of conditions and the following disclaimer. 13*509798eaSPedro F. Giffuni * 2. Redistributions in binary form must reproduce the above copyright 14*509798eaSPedro F. Giffuni * notice, this list of conditions and the following disclaimer in the 15*509798eaSPedro F. Giffuni * documentation and/or other materials provided with the distribution. 16*509798eaSPedro F. Giffuni * 17*509798eaSPedro F. Giffuni * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND 18*509798eaSPedro F. Giffuni * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*509798eaSPedro F. Giffuni * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*509798eaSPedro F. Giffuni * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE 21*509798eaSPedro F. Giffuni * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*509798eaSPedro F. Giffuni * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23*509798eaSPedro F. Giffuni * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24*509798eaSPedro F. Giffuni * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25*509798eaSPedro F. Giffuni * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26*509798eaSPedro F. Giffuni * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27*509798eaSPedro F. Giffuni * SUCH DAMAGE. 28*509798eaSPedro F. Giffuni */ 29*509798eaSPedro F. Giffuni 30*509798eaSPedro F. Giffuni #include <sys/cdefs.h> 31*509798eaSPedro F. Giffuni __FBSDID("$FreeBSD$"); 32*509798eaSPedro F. Giffuni 33*509798eaSPedro F. Giffuni #include <stdio.h> 34*509798eaSPedro F. Giffuni #include <stdlib.h> 35*509798eaSPedro F. Giffuni #include <string.h> 36*509798eaSPedro F. Giffuni #include <err.h> 37*509798eaSPedro F. Giffuni #include <assert.h> 38*509798eaSPedro F. Giffuni 39*509798eaSPedro F. Giffuni #include <sys/types.h> 40*509798eaSPedro F. Giffuni 41*509798eaSPedro F. Giffuni #include "hammer_disk.h" 42*509798eaSPedro F. Giffuni 43*509798eaSPedro F. Giffuni #include "fstyp.h" 44*509798eaSPedro F. Giffuni 45*509798eaSPedro F. Giffuni static hammer_volume_ondisk_t 46*509798eaSPedro F. Giffuni __read_ondisk(FILE *fp) 47*509798eaSPedro F. Giffuni { 48*509798eaSPedro F. Giffuni hammer_volume_ondisk_t ondisk; 49*509798eaSPedro F. Giffuni 50*509798eaSPedro F. Giffuni ondisk = read_buf(fp, 0, sizeof(*ondisk)); 51*509798eaSPedro F. Giffuni if (ondisk == NULL) 52*509798eaSPedro F. Giffuni err(1, "failed to read ondisk"); 53*509798eaSPedro F. Giffuni 54*509798eaSPedro F. Giffuni return (ondisk); 55*509798eaSPedro F. Giffuni } 56*509798eaSPedro F. Giffuni 57*509798eaSPedro F. Giffuni static int 58*509798eaSPedro F. Giffuni __test_ondisk(const hammer_volume_ondisk_t ondisk) 59*509798eaSPedro F. Giffuni { 60*509798eaSPedro F. Giffuni static int count = 0; 61*509798eaSPedro F. Giffuni static hammer_uuid_t fsid, fstype; 62*509798eaSPedro F. Giffuni static char label[64]; 63*509798eaSPedro F. Giffuni 64*509798eaSPedro F. Giffuni if (ondisk->vol_signature != HAMMER_FSBUF_VOLUME && 65*509798eaSPedro F. Giffuni ondisk->vol_signature != HAMMER_FSBUF_VOLUME_REV) 66*509798eaSPedro F. Giffuni return (1); 67*509798eaSPedro F. Giffuni if (ondisk->vol_rootvol != HAMMER_ROOT_VOLNO) 68*509798eaSPedro F. Giffuni return (2); 69*509798eaSPedro F. Giffuni if (ondisk->vol_no < 0 || ondisk->vol_no > HAMMER_MAX_VOLUMES - 1) 70*509798eaSPedro F. Giffuni return (3); 71*509798eaSPedro F. Giffuni if (ondisk->vol_count < 1 || ondisk->vol_count > HAMMER_MAX_VOLUMES) 72*509798eaSPedro F. Giffuni return (4); 73*509798eaSPedro F. Giffuni 74*509798eaSPedro F. Giffuni if (count == 0) { 75*509798eaSPedro F. Giffuni count = ondisk->vol_count; 76*509798eaSPedro F. Giffuni assert(count != 0); 77*509798eaSPedro F. Giffuni memcpy(&fsid, &ondisk->vol_fsid, sizeof(fsid)); 78*509798eaSPedro F. Giffuni memcpy(&fstype, &ondisk->vol_fstype, sizeof(fstype)); 79*509798eaSPedro F. Giffuni strncpy(label, ondisk->vol_label, sizeof(label)); 80*509798eaSPedro F. Giffuni } else { 81*509798eaSPedro F. Giffuni if (ondisk->vol_count != count) 82*509798eaSPedro F. Giffuni return (5); 83*509798eaSPedro F. Giffuni if (memcmp(&ondisk->vol_fsid, &fsid, sizeof(fsid))) 84*509798eaSPedro F. Giffuni return (6); 85*509798eaSPedro F. Giffuni if (memcmp(&ondisk->vol_fstype, &fstype, sizeof(fstype))) 86*509798eaSPedro F. Giffuni return (7); 87*509798eaSPedro F. Giffuni if (strncmp(ondisk->vol_label, label, sizeof(label))) 88*509798eaSPedro F. Giffuni return (8); 89*509798eaSPedro F. Giffuni } 90*509798eaSPedro F. Giffuni 91*509798eaSPedro F. Giffuni return (0); 92*509798eaSPedro F. Giffuni } 93*509798eaSPedro F. Giffuni 94*509798eaSPedro F. Giffuni int 95*509798eaSPedro F. Giffuni fstyp_hammer(FILE *fp, char *label, size_t size) 96*509798eaSPedro F. Giffuni { 97*509798eaSPedro F. Giffuni hammer_volume_ondisk_t ondisk; 98*509798eaSPedro F. Giffuni int error = 1; 99*509798eaSPedro F. Giffuni 100*509798eaSPedro F. Giffuni ondisk = __read_ondisk(fp); 101*509798eaSPedro F. Giffuni if (ondisk->vol_no != HAMMER_ROOT_VOLNO) 102*509798eaSPedro F. Giffuni goto done; 103*509798eaSPedro F. Giffuni if (ondisk->vol_count != 1) 104*509798eaSPedro F. Giffuni goto done; 105*509798eaSPedro F. Giffuni if (__test_ondisk(ondisk)) 106*509798eaSPedro F. Giffuni goto done; 107*509798eaSPedro F. Giffuni 108*509798eaSPedro F. Giffuni strlcpy(label, ondisk->vol_label, size); 109*509798eaSPedro F. Giffuni error = 0; 110*509798eaSPedro F. Giffuni done: 111*509798eaSPedro F. Giffuni free(ondisk); 112*509798eaSPedro F. Giffuni return (error); 113*509798eaSPedro F. Giffuni } 114*509798eaSPedro F. Giffuni 115*509798eaSPedro F. Giffuni static int 116*509798eaSPedro F. Giffuni __test_volume(const char *volpath) 117*509798eaSPedro F. Giffuni { 118*509798eaSPedro F. Giffuni hammer_volume_ondisk_t ondisk; 119*509798eaSPedro F. Giffuni FILE *fp; 120*509798eaSPedro F. Giffuni int volno = -1; 121*509798eaSPedro F. Giffuni 122*509798eaSPedro F. Giffuni if ((fp = fopen(volpath, "r")) == NULL) 123*509798eaSPedro F. Giffuni err(1, "failed to open %s", volpath); 124*509798eaSPedro F. Giffuni 125*509798eaSPedro F. Giffuni ondisk = __read_ondisk(fp); 126*509798eaSPedro F. Giffuni fclose(fp); 127*509798eaSPedro F. Giffuni if (__test_ondisk(ondisk)) 128*509798eaSPedro F. Giffuni goto done; 129*509798eaSPedro F. Giffuni 130*509798eaSPedro F. Giffuni volno = ondisk->vol_no; 131*509798eaSPedro F. Giffuni done: 132*509798eaSPedro F. Giffuni free(ondisk); 133*509798eaSPedro F. Giffuni return (volno); 134*509798eaSPedro F. Giffuni } 135*509798eaSPedro F. Giffuni 136*509798eaSPedro F. Giffuni static int 137*509798eaSPedro F. Giffuni __fsvtyp_hammer(const char *blkdevs, char *label, size_t size, int partial) 138*509798eaSPedro F. Giffuni { 139*509798eaSPedro F. Giffuni hammer_volume_ondisk_t ondisk; 140*509798eaSPedro F. Giffuni FILE *fp; 141*509798eaSPedro F. Giffuni char *dup, *p, *volpath, x[HAMMER_MAX_VOLUMES]; 142*509798eaSPedro F. Giffuni int i, volno, error = 1; 143*509798eaSPedro F. Giffuni 144*509798eaSPedro F. Giffuni memset(x, 0, sizeof(x)); 145*509798eaSPedro F. Giffuni dup = strdup(blkdevs); 146*509798eaSPedro F. Giffuni p = dup; 147*509798eaSPedro F. Giffuni 148*509798eaSPedro F. Giffuni while (p) { 149*509798eaSPedro F. Giffuni volpath = p; 150*509798eaSPedro F. Giffuni if ((p = strchr(p, ':')) != NULL) 151*509798eaSPedro F. Giffuni *p++ = '\0'; 152*509798eaSPedro F. Giffuni if ((volno = __test_volume(volpath)) == -1) 153*509798eaSPedro F. Giffuni break; 154*509798eaSPedro F. Giffuni x[volno]++; 155*509798eaSPedro F. Giffuni } 156*509798eaSPedro F. Giffuni 157*509798eaSPedro F. Giffuni if ((fp = fopen(volpath, "r")) == NULL) 158*509798eaSPedro F. Giffuni err(1, "failed to open %s", volpath); 159*509798eaSPedro F. Giffuni ondisk = __read_ondisk(fp); 160*509798eaSPedro F. Giffuni fclose(fp); 161*509798eaSPedro F. Giffuni 162*509798eaSPedro F. Giffuni free(dup); 163*509798eaSPedro F. Giffuni 164*509798eaSPedro F. Giffuni if (volno == -1) 165*509798eaSPedro F. Giffuni goto done; 166*509798eaSPedro F. Giffuni if (partial) 167*509798eaSPedro F. Giffuni goto success; 168*509798eaSPedro F. Giffuni 169*509798eaSPedro F. Giffuni for (i = 0; i < HAMMER_MAX_VOLUMES; i++) 170*509798eaSPedro F. Giffuni if (x[i] > 1) 171*509798eaSPedro F. Giffuni goto done; 172*509798eaSPedro F. Giffuni for (i = 0; i < HAMMER_MAX_VOLUMES; i++) 173*509798eaSPedro F. Giffuni if (x[i] == 0) 174*509798eaSPedro F. Giffuni break; 175*509798eaSPedro F. Giffuni if (ondisk->vol_count != i) 176*509798eaSPedro F. Giffuni goto done; 177*509798eaSPedro F. Giffuni for (; i < HAMMER_MAX_VOLUMES; i++) 178*509798eaSPedro F. Giffuni if (x[i] != 0) 179*509798eaSPedro F. Giffuni goto done; 180*509798eaSPedro F. Giffuni success: 181*509798eaSPedro F. Giffuni strlcpy(label, ondisk->vol_label, size); 182*509798eaSPedro F. Giffuni error = 0; 183*509798eaSPedro F. Giffuni done: 184*509798eaSPedro F. Giffuni free(ondisk); 185*509798eaSPedro F. Giffuni return (error); 186*509798eaSPedro F. Giffuni } 187*509798eaSPedro F. Giffuni 188*509798eaSPedro F. Giffuni int 189*509798eaSPedro F. Giffuni fsvtyp_hammer(const char *blkdevs, char *label, size_t size) 190*509798eaSPedro F. Giffuni { 191*509798eaSPedro F. Giffuni return (__fsvtyp_hammer(blkdevs, label, size, 0)); 192*509798eaSPedro F. Giffuni } 193*509798eaSPedro F. Giffuni 194*509798eaSPedro F. Giffuni int 195*509798eaSPedro F. Giffuni fsvtyp_hammer_partial(const char *blkdevs, char *label, size_t size) 196*509798eaSPedro F. Giffuni { 197*509798eaSPedro F. Giffuni return (__fsvtyp_hammer(blkdevs, label, size, 1)); 198*509798eaSPedro F. Giffuni } 199