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 <stdio.h> 31 #include <stdlib.h> 32 #include <string.h> 33 #include <err.h> 34 #include <assert.h> 35 #include <vfs/hammer/hammer_disk.h> 36 37 #include "fstyp.h" 38 39 static hammer_volume_ondisk_t 40 __read_ondisk(FILE *fp) 41 { 42 hammer_volume_ondisk_t ondisk; 43 44 ondisk = read_buf(fp, 0, sizeof(*ondisk)); 45 if (ondisk == NULL) 46 err(1, "failed to read ondisk"); 47 48 return (ondisk); 49 } 50 51 static int 52 __test_ondisk(const hammer_volume_ondisk_t ondisk) 53 { 54 static int count = 0; 55 static uuid_t fsid, fstype; 56 static char label[64]; 57 58 if (ondisk->vol_signature != HAMMER_FSBUF_VOLUME && 59 ondisk->vol_signature != HAMMER_FSBUF_VOLUME_REV) 60 return (1); 61 if (ondisk->vol_rootvol != HAMMER_ROOT_VOLNO) 62 return (2); 63 if (ondisk->vol_no < 0 || ondisk->vol_no > HAMMER_MAX_VOLUMES - 1) 64 return (3); 65 if (ondisk->vol_count < 1 || ondisk->vol_count > HAMMER_MAX_VOLUMES) 66 return (4); 67 68 if (count == 0) { 69 count = ondisk->vol_count; 70 assert(count != 0); 71 memcpy(&fsid, &ondisk->vol_fsid, sizeof(fsid)); 72 memcpy(&fstype, &ondisk->vol_fstype, sizeof(fstype)); 73 strncpy(label, ondisk->vol_label, sizeof(label)); 74 } else { 75 if (ondisk->vol_count != count) 76 return (5); 77 if (memcmp(&ondisk->vol_fsid, &fsid, sizeof(fsid))) 78 return (6); 79 if (memcmp(&ondisk->vol_fstype, &fstype, sizeof(fstype))) 80 return (7); 81 if (strncmp(ondisk->vol_label, label, sizeof(label))) 82 return (8); 83 } 84 85 return (0); 86 } 87 88 int 89 fstyp_hammer(FILE *fp, char *label, size_t size) 90 { 91 hammer_volume_ondisk_t ondisk; 92 int error = 1; 93 94 ondisk = __read_ondisk(fp); 95 if (ondisk->vol_no != HAMMER_ROOT_VOLNO) 96 goto done; 97 if (ondisk->vol_count != 1) 98 goto done; 99 if (__test_ondisk(ondisk)) 100 goto done; 101 102 strlcpy(label, ondisk->vol_label, size); 103 error = 0; 104 done: 105 free(ondisk); 106 return (error); 107 } 108 109 static int 110 __test_volume(const char *volpath) 111 { 112 hammer_volume_ondisk_t ondisk; 113 FILE *fp; 114 int volno = -1; 115 116 if ((fp = fopen(volpath, "r")) == NULL) 117 err(1, "failed to open %s", volpath); 118 119 ondisk = __read_ondisk(fp); 120 fclose(fp); 121 if (__test_ondisk(ondisk)) 122 goto done; 123 124 volno = ondisk->vol_no; 125 done: 126 free(ondisk); 127 return (volno); 128 } 129 130 static int 131 __fsvtyp_hammer(const char *blkdevs, char *label, size_t size, int partial) 132 { 133 hammer_volume_ondisk_t ondisk; 134 FILE *fp; 135 char *dup, *p, *volpath, x[HAMMER_MAX_VOLUMES]; 136 int i, volno, error = 1; 137 138 memset(x, 0, sizeof(x)); 139 dup = strdup(blkdevs); 140 p = dup; 141 142 while (p) { 143 volpath = p; 144 if ((p = strchr(p, ':')) != NULL) 145 *p++ = '\0'; 146 if ((volno = __test_volume(volpath)) == -1) 147 break; 148 x[volno]++; 149 } 150 151 if ((fp = fopen(volpath, "r")) == NULL) 152 err(1, "failed to open %s", volpath); 153 ondisk = __read_ondisk(fp); 154 fclose(fp); 155 156 free(dup); 157 158 if (volno == -1) 159 goto done; 160 if (partial) 161 goto success; 162 163 for (i = 0; i < HAMMER_MAX_VOLUMES; i++) 164 if (x[i] > 1) 165 goto done; 166 for (i = 0; i < HAMMER_MAX_VOLUMES; i++) 167 if (x[i] == 0) 168 break; 169 if (ondisk->vol_count != i) 170 goto done; 171 for (; i < HAMMER_MAX_VOLUMES; i++) 172 if (x[i] != 0) 173 goto done; 174 success: 175 strlcpy(label, ondisk->vol_label, size); 176 error = 0; 177 done: 178 free(ondisk); 179 return (error); 180 } 181 182 int 183 fsvtyp_hammer(const char *blkdevs, char *label, size_t size) 184 { 185 return (__fsvtyp_hammer(blkdevs, label, size, 0)); 186 } 187 188 int 189 fsvtyp_hammer_partial(const char *blkdevs, char *label, size_t size) 190 { 191 return (__fsvtyp_hammer(blkdevs, label, size, 1)); 192 } 193