hammer.c revision 1.4 1 1.4 tkusumi /* $NetBSD: hammer.c,v 1.4 2021/01/10 12:38:40 tkusumi Exp $ */
2 1.1 tkusumi
3 1.1 tkusumi /*-
4 1.1 tkusumi * Copyright (c) 2016-2019 The DragonFly Project
5 1.1 tkusumi * Copyright (c) 2016-2019 Tomohiro Kusumi <tkusumi (at) netbsd.org>
6 1.1 tkusumi * All rights reserved.
7 1.1 tkusumi *
8 1.1 tkusumi * Redistribution and use in source and binary forms, with or without
9 1.1 tkusumi * modification, are permitted provided that the following conditions
10 1.1 tkusumi * are met:
11 1.1 tkusumi * 1. Redistributions of source code must retain the above copyright
12 1.1 tkusumi * notice, this list of conditions and the following disclaimer.
13 1.1 tkusumi * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 tkusumi * notice, this list of conditions and the following disclaimer in the
15 1.1 tkusumi * documentation and/or other materials provided with the distribution.
16 1.1 tkusumi *
17 1.1 tkusumi * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
18 1.1 tkusumi * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 1.1 tkusumi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 1.1 tkusumi * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
21 1.1 tkusumi * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 1.1 tkusumi * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 1.1 tkusumi * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 1.1 tkusumi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 1.1 tkusumi * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 1.1 tkusumi * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 1.1 tkusumi * SUCH DAMAGE.
28 1.1 tkusumi */
29 1.1 tkusumi #include <sys/cdefs.h>
30 1.4 tkusumi __KERNEL_RCSID(0, "$NetBSD: hammer.c,v 1.4 2021/01/10 12:38:40 tkusumi Exp $");
31 1.1 tkusumi
32 1.1 tkusumi #include <stdio.h>
33 1.1 tkusumi #include <stdlib.h>
34 1.1 tkusumi #include <string.h>
35 1.1 tkusumi #include <err.h>
36 1.4 tkusumi #include <uuid.h>
37 1.1 tkusumi
38 1.1 tkusumi #include "fstyp.h"
39 1.1 tkusumi #include "hammer_disk.h"
40 1.1 tkusumi
41 1.1 tkusumi static hammer_volume_ondisk_t
42 1.1 tkusumi read_ondisk(FILE *fp)
43 1.1 tkusumi {
44 1.4 tkusumi return (read_buf(fp, 0, sizeof(struct hammer_volume_ondisk)));
45 1.1 tkusumi }
46 1.1 tkusumi
47 1.1 tkusumi static int
48 1.1 tkusumi test_ondisk(const hammer_volume_ondisk_t ondisk)
49 1.1 tkusumi {
50 1.1 tkusumi static int count = 0;
51 1.1 tkusumi static hammer_uuid_t fsid, fstype;
52 1.1 tkusumi static char label[64];
53 1.1 tkusumi
54 1.1 tkusumi if (ondisk->vol_signature != HAMMER_FSBUF_VOLUME &&
55 1.1 tkusumi ondisk->vol_signature != HAMMER_FSBUF_VOLUME_REV)
56 1.1 tkusumi return (1);
57 1.1 tkusumi if (ondisk->vol_rootvol != HAMMER_ROOT_VOLNO)
58 1.4 tkusumi return (1);
59 1.1 tkusumi if (ondisk->vol_no < 0 || ondisk->vol_no > HAMMER_MAX_VOLUMES - 1)
60 1.4 tkusumi return (1);
61 1.1 tkusumi if (ondisk->vol_count < 1 || ondisk->vol_count > HAMMER_MAX_VOLUMES)
62 1.4 tkusumi return (1);
63 1.1 tkusumi
64 1.1 tkusumi if (count == 0) {
65 1.1 tkusumi count = ondisk->vol_count;
66 1.4 tkusumi if (count == 0)
67 1.4 tkusumi return (1);
68 1.1 tkusumi memcpy(&fsid, &ondisk->vol_fsid, sizeof(fsid));
69 1.1 tkusumi memcpy(&fstype, &ondisk->vol_fstype, sizeof(fstype));
70 1.3 tkusumi strlcpy(label, ondisk->vol_label, sizeof(label));
71 1.1 tkusumi } else {
72 1.1 tkusumi if (ondisk->vol_count != count)
73 1.4 tkusumi return (1);
74 1.4 tkusumi if (!uuid_equal(&ondisk->vol_fsid, &fsid, NULL))
75 1.4 tkusumi return (1);
76 1.4 tkusumi if (!uuid_equal(&ondisk->vol_fstype, &fstype, NULL))
77 1.4 tkusumi return (1);
78 1.3 tkusumi if (strcmp(ondisk->vol_label, label))
79 1.4 tkusumi return (1);
80 1.1 tkusumi }
81 1.1 tkusumi
82 1.1 tkusumi return (0);
83 1.1 tkusumi }
84 1.1 tkusumi
85 1.4 tkusumi static const char*
86 1.4 tkusumi extract_device_name(const char *devpath)
87 1.4 tkusumi {
88 1.4 tkusumi const char *p;
89 1.4 tkusumi
90 1.4 tkusumi p = strrchr(devpath, '/');
91 1.4 tkusumi if (p) {
92 1.4 tkusumi p++;
93 1.4 tkusumi if (*p == 0)
94 1.4 tkusumi p = NULL;
95 1.4 tkusumi } else {
96 1.4 tkusumi p = devpath;
97 1.4 tkusumi }
98 1.4 tkusumi return (p);
99 1.4 tkusumi }
100 1.4 tkusumi
101 1.1 tkusumi int
102 1.1 tkusumi fstyp_hammer(FILE *fp, char *label, size_t size)
103 1.1 tkusumi {
104 1.1 tkusumi hammer_volume_ondisk_t ondisk;
105 1.1 tkusumi int error = 1;
106 1.1 tkusumi #ifdef HAS_DEVPATH
107 1.1 tkusumi const char *p;
108 1.1 tkusumi #endif
109 1.1 tkusumi ondisk = read_ondisk(fp);
110 1.4 tkusumi if (!ondisk)
111 1.4 tkusumi goto fail;
112 1.1 tkusumi if (ondisk->vol_no != HAMMER_ROOT_VOLNO)
113 1.2 tkusumi goto fail;
114 1.1 tkusumi if (ondisk->vol_count != 1)
115 1.2 tkusumi goto fail;
116 1.1 tkusumi if (test_ondisk(ondisk))
117 1.2 tkusumi goto fail;
118 1.1 tkusumi
119 1.1 tkusumi /*
120 1.1 tkusumi * fstyp_function in DragonFly takes an additional devpath argument
121 1.1 tkusumi * which doesn't exist in FreeBSD and NetBSD.
122 1.1 tkusumi */
123 1.1 tkusumi #ifdef HAS_DEVPATH
124 1.1 tkusumi /* Add device name to help support multiple autofs -media mounts. */
125 1.4 tkusumi p = extract_device_name(devpath);
126 1.4 tkusumi if (p)
127 1.4 tkusumi snprintf(label, size, "%s_%s", ondisk->vol_label, p);
128 1.4 tkusumi else
129 1.4 tkusumi strlcpy(label, ondisk->vol_label, size);
130 1.1 tkusumi #else
131 1.1 tkusumi strlcpy(label, ondisk->vol_label, size);
132 1.1 tkusumi #endif
133 1.1 tkusumi error = 0;
134 1.2 tkusumi fail:
135 1.1 tkusumi free(ondisk);
136 1.1 tkusumi return (error);
137 1.1 tkusumi }
138 1.1 tkusumi
139 1.1 tkusumi static int
140 1.1 tkusumi test_volume(const char *volpath)
141 1.1 tkusumi {
142 1.4 tkusumi hammer_volume_ondisk_t ondisk = NULL;
143 1.1 tkusumi FILE *fp;
144 1.1 tkusumi int volno = -1;
145 1.1 tkusumi
146 1.1 tkusumi if ((fp = fopen(volpath, "r")) == NULL)
147 1.4 tkusumi goto fail;
148 1.1 tkusumi
149 1.1 tkusumi ondisk = read_ondisk(fp);
150 1.4 tkusumi if (!ondisk)
151 1.4 tkusumi goto fail;
152 1.1 tkusumi if (test_ondisk(ondisk))
153 1.2 tkusumi goto fail;
154 1.1 tkusumi
155 1.1 tkusumi volno = ondisk->vol_no;
156 1.2 tkusumi fail:
157 1.4 tkusumi if (fp)
158 1.4 tkusumi fclose(fp);
159 1.1 tkusumi free(ondisk);
160 1.1 tkusumi return (volno);
161 1.1 tkusumi }
162 1.1 tkusumi
163 1.1 tkusumi static int
164 1.1 tkusumi __fsvtyp_hammer(const char *blkdevs, char *label, size_t size, int partial)
165 1.1 tkusumi {
166 1.2 tkusumi hammer_volume_ondisk_t ondisk = NULL;
167 1.4 tkusumi FILE *fp = NULL;
168 1.4 tkusumi char *dup = NULL, *p, *volpath, *rootvolpath, x[HAMMER_MAX_VOLUMES];
169 1.1 tkusumi int i, volno, error = 1;
170 1.1 tkusumi
171 1.2 tkusumi if (!blkdevs)
172 1.2 tkusumi goto fail;
173 1.2 tkusumi
174 1.1 tkusumi memset(x, 0, sizeof(x));
175 1.1 tkusumi dup = strdup(blkdevs);
176 1.1 tkusumi p = dup;
177 1.1 tkusumi
178 1.1 tkusumi volpath = NULL;
179 1.4 tkusumi rootvolpath = NULL;
180 1.2 tkusumi volno = -1;
181 1.1 tkusumi while (p) {
182 1.1 tkusumi volpath = p;
183 1.1 tkusumi if ((p = strchr(p, ':')) != NULL)
184 1.1 tkusumi *p++ = '\0';
185 1.1 tkusumi if ((volno = test_volume(volpath)) == -1)
186 1.1 tkusumi break;
187 1.4 tkusumi if (volno < 0 || volno >= HAMMER_MAX_VOLUMES)
188 1.4 tkusumi goto fail;
189 1.1 tkusumi x[volno]++;
190 1.4 tkusumi if (volno == HAMMER_ROOT_VOLNO)
191 1.4 tkusumi rootvolpath = volpath;
192 1.1 tkusumi }
193 1.1 tkusumi
194 1.4 tkusumi /* If no rootvolpath, proceed only if partial mode with volpath. */
195 1.4 tkusumi if (rootvolpath)
196 1.4 tkusumi volpath = rootvolpath;
197 1.4 tkusumi else if (!partial || !volpath)
198 1.4 tkusumi goto fail;
199 1.1 tkusumi if ((fp = fopen(volpath, "r")) == NULL)
200 1.4 tkusumi goto fail;
201 1.1 tkusumi ondisk = read_ondisk(fp);
202 1.4 tkusumi if (!ondisk)
203 1.4 tkusumi goto fail;
204 1.1 tkusumi
205 1.1 tkusumi if (volno == -1)
206 1.2 tkusumi goto fail;
207 1.1 tkusumi if (partial)
208 1.1 tkusumi goto success;
209 1.1 tkusumi
210 1.1 tkusumi for (i = 0; i < HAMMER_MAX_VOLUMES; i++)
211 1.1 tkusumi if (x[i] > 1)
212 1.2 tkusumi goto fail;
213 1.1 tkusumi for (i = 0; i < HAMMER_MAX_VOLUMES; i++)
214 1.1 tkusumi if (x[i] == 0)
215 1.1 tkusumi break;
216 1.1 tkusumi if (ondisk->vol_count != i)
217 1.2 tkusumi goto fail;
218 1.1 tkusumi for (; i < HAMMER_MAX_VOLUMES; i++)
219 1.1 tkusumi if (x[i] != 0)
220 1.2 tkusumi goto fail;
221 1.1 tkusumi success:
222 1.4 tkusumi /* Add device name to help support multiple autofs -media mounts. */
223 1.4 tkusumi p = __UNCONST(extract_device_name(volpath));
224 1.4 tkusumi if (p)
225 1.4 tkusumi snprintf(label, size, "%s_%s", ondisk->vol_label, p);
226 1.4 tkusumi else
227 1.4 tkusumi strlcpy(label, ondisk->vol_label, size);
228 1.1 tkusumi error = 0;
229 1.2 tkusumi fail:
230 1.4 tkusumi if (fp)
231 1.4 tkusumi fclose(fp);
232 1.1 tkusumi free(ondisk);
233 1.4 tkusumi free(dup);
234 1.1 tkusumi return (error);
235 1.1 tkusumi }
236 1.1 tkusumi
237 1.1 tkusumi int
238 1.1 tkusumi fsvtyp_hammer(const char *blkdevs, char *label, size_t size)
239 1.1 tkusumi {
240 1.1 tkusumi return (__fsvtyp_hammer(blkdevs, label, size, 0));
241 1.1 tkusumi }
242 1.1 tkusumi
243 1.1 tkusumi int
244 1.1 tkusumi fsvtyp_hammer_partial(const char *blkdevs, char *label, size_t size)
245 1.1 tkusumi {
246 1.1 tkusumi return (__fsvtyp_hammer(blkdevs, label, size, 1));
247 1.1 tkusumi }
248