1 /* $NetBSD: hammer.c,v 1.3 2020/01/15 15:30:46 tkusumi Exp $ */ 2 3 /*- 4 * Copyright (c) 2016-2019 The DragonFly Project 5 * Copyright (c) 2016-2019 Tomohiro Kusumi <tkusumi@netbsd.org> 6 * All rights reserved. 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 #include <sys/cdefs.h> 30 __KERNEL_RCSID(0, "$NetBSD: hammer.c,v 1.3 2020/01/15 15:30:46 tkusumi Exp $"); 31 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <err.h> 36 #include <assert.h> 37 38 #include "fstyp.h" 39 #include "hammer_disk.h" 40 41 static hammer_volume_ondisk_t 42 read_ondisk(FILE *fp) 43 { 44 hammer_volume_ondisk_t ondisk; 45 46 ondisk = read_buf(fp, 0, sizeof(*ondisk)); 47 if (ondisk == NULL) 48 err(1, "failed to read ondisk"); 49 50 return (ondisk); 51 } 52 53 static int 54 test_ondisk(const hammer_volume_ondisk_t ondisk) 55 { 56 static int count = 0; 57 static hammer_uuid_t fsid, fstype; 58 static char label[64]; 59 60 if (ondisk->vol_signature != HAMMER_FSBUF_VOLUME && 61 ondisk->vol_signature != HAMMER_FSBUF_VOLUME_REV) 62 return (1); 63 if (ondisk->vol_rootvol != HAMMER_ROOT_VOLNO) 64 return (2); 65 if (ondisk->vol_no < 0 || ondisk->vol_no > HAMMER_MAX_VOLUMES - 1) 66 return (3); 67 if (ondisk->vol_count < 1 || ondisk->vol_count > HAMMER_MAX_VOLUMES) 68 return (4); 69 70 if (count == 0) { 71 count = ondisk->vol_count; 72 assert(count != 0); 73 memcpy(&fsid, &ondisk->vol_fsid, sizeof(fsid)); 74 memcpy(&fstype, &ondisk->vol_fstype, sizeof(fstype)); 75 strlcpy(label, ondisk->vol_label, sizeof(label)); 76 } else { 77 if (ondisk->vol_count != count) 78 return (5); 79 if (memcmp(&ondisk->vol_fsid, &fsid, sizeof(fsid))) 80 return (6); 81 if (memcmp(&ondisk->vol_fstype, &fstype, sizeof(fstype))) 82 return (7); 83 if (strcmp(ondisk->vol_label, label)) 84 return (8); 85 } 86 87 return (0); 88 } 89 90 int 91 fstyp_hammer(FILE *fp, char *label, size_t size) 92 { 93 hammer_volume_ondisk_t ondisk; 94 int error = 1; 95 #ifdef HAS_DEVPATH 96 const char *p; 97 #endif 98 ondisk = read_ondisk(fp); 99 if (ondisk->vol_no != HAMMER_ROOT_VOLNO) 100 goto fail; 101 if (ondisk->vol_count != 1) 102 goto fail; 103 if (test_ondisk(ondisk)) 104 goto fail; 105 106 /* 107 * fstyp_function in DragonFly takes an additional devpath argument 108 * which doesn't exist in FreeBSD and NetBSD. 109 */ 110 #ifdef HAS_DEVPATH 111 /* Add device name to help support multiple autofs -media mounts. */ 112 p = strrchr(devpath, '/'); 113 if (p) { 114 p++; 115 if (*p == 0) 116 strlcpy(label, ondisk->vol_label, size); 117 else 118 snprintf(label, size, "%s_%s", ondisk->vol_label, p); 119 } else 120 snprintf(label, size, "%s_%s", ondisk->vol_label, devpath); 121 #else 122 strlcpy(label, ondisk->vol_label, size); 123 #endif 124 error = 0; 125 fail: 126 free(ondisk); 127 return (error); 128 } 129 130 static int 131 test_volume(const char *volpath) 132 { 133 hammer_volume_ondisk_t ondisk; 134 FILE *fp; 135 int volno = -1; 136 137 if ((fp = fopen(volpath, "r")) == NULL) 138 err(1, "failed to open %s", volpath); 139 140 ondisk = read_ondisk(fp); 141 fclose(fp); 142 if (test_ondisk(ondisk)) 143 goto fail; 144 145 volno = ondisk->vol_no; 146 fail: 147 free(ondisk); 148 return (volno); 149 } 150 151 static int 152 __fsvtyp_hammer(const char *blkdevs, char *label, size_t size, int partial) 153 { 154 hammer_volume_ondisk_t ondisk = NULL; 155 FILE *fp; 156 char *dup, *p, *volpath, x[HAMMER_MAX_VOLUMES]; 157 int i, volno, error = 1; 158 159 if (!blkdevs) 160 goto fail; 161 162 memset(x, 0, sizeof(x)); 163 dup = strdup(blkdevs); 164 p = dup; 165 166 volpath = NULL; 167 volno = -1; 168 while (p) { 169 volpath = p; 170 if ((p = strchr(p, ':')) != NULL) 171 *p++ = '\0'; 172 if ((volno = test_volume(volpath)) == -1) 173 break; 174 assert(volno >= 0); 175 assert(volno < HAMMER_MAX_VOLUMES); 176 x[volno]++; 177 } 178 179 if (!volpath) 180 err(1, "invalid path %s", blkdevs); 181 if ((fp = fopen(volpath, "r")) == NULL) 182 err(1, "failed to open %s", volpath); 183 ondisk = read_ondisk(fp); 184 fclose(fp); 185 186 free(dup); 187 188 if (volno == -1) 189 goto fail; 190 if (partial) 191 goto success; 192 193 for (i = 0; i < HAMMER_MAX_VOLUMES; i++) 194 if (x[i] > 1) 195 goto fail; 196 for (i = 0; i < HAMMER_MAX_VOLUMES; i++) 197 if (x[i] == 0) 198 break; 199 if (ondisk->vol_count != i) 200 goto fail; 201 for (; i < HAMMER_MAX_VOLUMES; i++) 202 if (x[i] != 0) 203 goto fail; 204 success: 205 /* XXX autofs -media mount can't handle multiple mounts */ 206 strlcpy(label, ondisk->vol_label, size); 207 error = 0; 208 fail: 209 free(ondisk); 210 return (error); 211 } 212 213 int 214 fsvtyp_hammer(const char *blkdevs, char *label, size_t size) 215 { 216 return (__fsvtyp_hammer(blkdevs, label, size, 0)); 217 } 218 219 int 220 fsvtyp_hammer_partial(const char *blkdevs, char *label, size_t size) 221 { 222 return (__fsvtyp_hammer(blkdevs, label, size, 1)); 223 } 224