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