1509798eaSPedro F. Giffuni /*-
29d529ed8SPedro F. Giffuni * Copyright (c) 2016-2019 The DragonFly Project
39d529ed8SPedro F. Giffuni * Copyright (c) 2016-2019 Tomohiro Kusumi <tkusumi@netbsd.org>
4509798eaSPedro F. Giffuni * All rights reserved.
5509798eaSPedro F. Giffuni *
6509798eaSPedro F. Giffuni * This software was developed by Edward Tomasz Napierala under sponsorship
7509798eaSPedro F. Giffuni * from the FreeBSD Foundation.
8509798eaSPedro F. Giffuni *
9509798eaSPedro F. Giffuni * Redistribution and use in source and binary forms, with or without
10509798eaSPedro F. Giffuni * modification, are permitted provided that the following conditions
11509798eaSPedro F. Giffuni * are met:
12509798eaSPedro F. Giffuni * 1. Redistributions of source code must retain the above copyright
13509798eaSPedro F. Giffuni * notice, this list of conditions and the following disclaimer.
14509798eaSPedro F. Giffuni * 2. Redistributions in binary form must reproduce the above copyright
15509798eaSPedro F. Giffuni * notice, this list of conditions and the following disclaimer in the
16509798eaSPedro F. Giffuni * documentation and/or other materials provided with the distribution.
17509798eaSPedro F. Giffuni *
18509798eaSPedro F. Giffuni * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
19509798eaSPedro F. Giffuni * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20509798eaSPedro F. Giffuni * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21509798eaSPedro F. Giffuni * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
22509798eaSPedro F. Giffuni * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23509798eaSPedro F. Giffuni * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24509798eaSPedro F. Giffuni * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25509798eaSPedro F. Giffuni * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26509798eaSPedro F. Giffuni * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27509798eaSPedro F. Giffuni * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28509798eaSPedro F. Giffuni * SUCH DAMAGE.
29509798eaSPedro F. Giffuni */
30509798eaSPedro F. Giffuni
31509798eaSPedro F. Giffuni #include <sys/cdefs.h>
32509798eaSPedro F. Giffuni #include <stdio.h>
33509798eaSPedro F. Giffuni #include <stdlib.h>
34509798eaSPedro F. Giffuni #include <string.h>
35509798eaSPedro F. Giffuni #include <err.h>
36509798eaSPedro F. Giffuni #include <assert.h>
37509798eaSPedro F. Giffuni
38509798eaSPedro F. Giffuni #include <sys/types.h>
39509798eaSPedro F. Giffuni
40509798eaSPedro F. Giffuni #include "hammer_disk.h"
41509798eaSPedro F. Giffuni
42509798eaSPedro F. Giffuni #include "fstyp.h"
43509798eaSPedro F. Giffuni
44*da0c0e01SPiotr Pawel Stefaniak extern int fsvtyp_hammer(const char *blkdevs, char *label, size_t size);
45*da0c0e01SPiotr Pawel Stefaniak extern int fsvtyp_hammer_partial(const char *blkdevs, char *label, size_t size);
46*da0c0e01SPiotr Pawel Stefaniak
47509798eaSPedro F. Giffuni static hammer_volume_ondisk_t
read_ondisk(FILE * fp)489d529ed8SPedro F. Giffuni read_ondisk(FILE *fp)
49509798eaSPedro F. Giffuni {
50509798eaSPedro F. Giffuni hammer_volume_ondisk_t ondisk;
51509798eaSPedro F. Giffuni
52509798eaSPedro F. Giffuni ondisk = read_buf(fp, 0, sizeof(*ondisk));
53509798eaSPedro F. Giffuni if (ondisk == NULL)
54509798eaSPedro F. Giffuni err(1, "failed to read ondisk");
55509798eaSPedro F. Giffuni
56509798eaSPedro F. Giffuni return (ondisk);
57509798eaSPedro F. Giffuni }
58509798eaSPedro F. Giffuni
59509798eaSPedro F. Giffuni static int
test_ondisk(const hammer_volume_ondisk_t ondisk)609d529ed8SPedro F. Giffuni test_ondisk(const hammer_volume_ondisk_t ondisk)
61509798eaSPedro F. Giffuni {
62509798eaSPedro F. Giffuni static int count = 0;
63509798eaSPedro F. Giffuni static hammer_uuid_t fsid, fstype;
64509798eaSPedro F. Giffuni static char label[64];
65509798eaSPedro F. Giffuni
66509798eaSPedro F. Giffuni if (ondisk->vol_signature != HAMMER_FSBUF_VOLUME &&
67509798eaSPedro F. Giffuni ondisk->vol_signature != HAMMER_FSBUF_VOLUME_REV)
68509798eaSPedro F. Giffuni return (1);
69509798eaSPedro F. Giffuni if (ondisk->vol_rootvol != HAMMER_ROOT_VOLNO)
70509798eaSPedro F. Giffuni return (2);
71509798eaSPedro F. Giffuni if (ondisk->vol_no < 0 || ondisk->vol_no > HAMMER_MAX_VOLUMES - 1)
72509798eaSPedro F. Giffuni return (3);
73509798eaSPedro F. Giffuni if (ondisk->vol_count < 1 || ondisk->vol_count > HAMMER_MAX_VOLUMES)
74509798eaSPedro F. Giffuni return (4);
75509798eaSPedro F. Giffuni
76509798eaSPedro F. Giffuni if (count == 0) {
77509798eaSPedro F. Giffuni count = ondisk->vol_count;
78509798eaSPedro F. Giffuni assert(count != 0);
79509798eaSPedro F. Giffuni memcpy(&fsid, &ondisk->vol_fsid, sizeof(fsid));
80509798eaSPedro F. Giffuni memcpy(&fstype, &ondisk->vol_fstype, sizeof(fstype));
810ab52bd3SEric van Gyzen strlcpy(label, ondisk->vol_label, sizeof(label));
82509798eaSPedro F. Giffuni } else {
83509798eaSPedro F. Giffuni if (ondisk->vol_count != count)
84509798eaSPedro F. Giffuni return (5);
85509798eaSPedro F. Giffuni if (memcmp(&ondisk->vol_fsid, &fsid, sizeof(fsid)))
86509798eaSPedro F. Giffuni return (6);
87509798eaSPedro F. Giffuni if (memcmp(&ondisk->vol_fstype, &fstype, sizeof(fstype)))
88509798eaSPedro F. Giffuni return (7);
890ab52bd3SEric van Gyzen if (strcmp(ondisk->vol_label, label))
90509798eaSPedro F. Giffuni return (8);
91509798eaSPedro F. Giffuni }
92509798eaSPedro F. Giffuni
93509798eaSPedro F. Giffuni return (0);
94509798eaSPedro F. Giffuni }
95509798eaSPedro F. Giffuni
96509798eaSPedro F. Giffuni int
fstyp_hammer(FILE * fp,char * label,size_t size)97509798eaSPedro F. Giffuni fstyp_hammer(FILE *fp, char *label, size_t size)
98509798eaSPedro F. Giffuni {
99509798eaSPedro F. Giffuni hammer_volume_ondisk_t ondisk;
100509798eaSPedro F. Giffuni int error = 1;
101509798eaSPedro F. Giffuni
1029d529ed8SPedro F. Giffuni ondisk = read_ondisk(fp);
103509798eaSPedro F. Giffuni if (ondisk->vol_no != HAMMER_ROOT_VOLNO)
1049d529ed8SPedro F. Giffuni goto fail;
105509798eaSPedro F. Giffuni if (ondisk->vol_count != 1)
1069d529ed8SPedro F. Giffuni goto fail;
1079d529ed8SPedro F. Giffuni if (test_ondisk(ondisk))
1089d529ed8SPedro F. Giffuni goto fail;
109509798eaSPedro F. Giffuni
110509798eaSPedro F. Giffuni strlcpy(label, ondisk->vol_label, size);
111509798eaSPedro F. Giffuni error = 0;
1129d529ed8SPedro F. Giffuni fail:
113509798eaSPedro F. Giffuni free(ondisk);
114509798eaSPedro F. Giffuni return (error);
115509798eaSPedro F. Giffuni }
116509798eaSPedro F. Giffuni
117509798eaSPedro F. Giffuni static int
test_volume(const char * volpath)1189d529ed8SPedro F. Giffuni test_volume(const char *volpath)
119509798eaSPedro F. Giffuni {
120509798eaSPedro F. Giffuni hammer_volume_ondisk_t ondisk;
121509798eaSPedro F. Giffuni FILE *fp;
122509798eaSPedro F. Giffuni int volno = -1;
123509798eaSPedro F. Giffuni
124509798eaSPedro F. Giffuni if ((fp = fopen(volpath, "r")) == NULL)
125509798eaSPedro F. Giffuni err(1, "failed to open %s", volpath);
126509798eaSPedro F. Giffuni
1279d529ed8SPedro F. Giffuni ondisk = read_ondisk(fp);
128509798eaSPedro F. Giffuni fclose(fp);
1299d529ed8SPedro F. Giffuni if (test_ondisk(ondisk))
1309d529ed8SPedro F. Giffuni goto fail;
131509798eaSPedro F. Giffuni
132509798eaSPedro F. Giffuni volno = ondisk->vol_no;
1339d529ed8SPedro F. Giffuni fail:
134509798eaSPedro F. Giffuni free(ondisk);
135509798eaSPedro F. Giffuni return (volno);
136509798eaSPedro F. Giffuni }
137509798eaSPedro F. Giffuni
138509798eaSPedro F. Giffuni static int
__fsvtyp_hammer(const char * blkdevs,char * label,size_t size,int partial)139509798eaSPedro F. Giffuni __fsvtyp_hammer(const char *blkdevs, char *label, size_t size, int partial)
140509798eaSPedro F. Giffuni {
1419d529ed8SPedro F. Giffuni hammer_volume_ondisk_t ondisk = NULL;
142509798eaSPedro F. Giffuni FILE *fp;
143509798eaSPedro F. Giffuni char *dup, *p, *volpath, x[HAMMER_MAX_VOLUMES];
144509798eaSPedro F. Giffuni int i, volno, error = 1;
145509798eaSPedro F. Giffuni
1469d529ed8SPedro F. Giffuni if (!blkdevs)
1479d529ed8SPedro F. Giffuni goto fail;
1489d529ed8SPedro F. Giffuni
149509798eaSPedro F. Giffuni memset(x, 0, sizeof(x));
150509798eaSPedro F. Giffuni dup = strdup(blkdevs);
151509798eaSPedro F. Giffuni p = dup;
152509798eaSPedro F. Giffuni
1539d529ed8SPedro F. Giffuni volpath = NULL;
1549d529ed8SPedro F. Giffuni volno = -1;
155509798eaSPedro F. Giffuni while (p) {
156509798eaSPedro F. Giffuni volpath = p;
157509798eaSPedro F. Giffuni if ((p = strchr(p, ':')) != NULL)
158509798eaSPedro F. Giffuni *p++ = '\0';
1599d529ed8SPedro F. Giffuni if ((volno = test_volume(volpath)) == -1)
160509798eaSPedro F. Giffuni break;
1619d529ed8SPedro F. Giffuni assert(volno >= 0);
1629d529ed8SPedro F. Giffuni assert(volno < HAMMER_MAX_VOLUMES);
163509798eaSPedro F. Giffuni x[volno]++;
164509798eaSPedro F. Giffuni }
165509798eaSPedro F. Giffuni
1669d529ed8SPedro F. Giffuni if (!volpath)
1679d529ed8SPedro F. Giffuni err(1, "invalid path %s", blkdevs);
168509798eaSPedro F. Giffuni if ((fp = fopen(volpath, "r")) == NULL)
169509798eaSPedro F. Giffuni err(1, "failed to open %s", volpath);
1709d529ed8SPedro F. Giffuni ondisk = read_ondisk(fp);
171509798eaSPedro F. Giffuni fclose(fp);
172509798eaSPedro F. Giffuni
173509798eaSPedro F. Giffuni free(dup);
174509798eaSPedro F. Giffuni
175509798eaSPedro F. Giffuni if (volno == -1)
1769d529ed8SPedro F. Giffuni goto fail;
177509798eaSPedro F. Giffuni if (partial)
178509798eaSPedro F. Giffuni goto success;
179509798eaSPedro F. Giffuni
180509798eaSPedro F. Giffuni for (i = 0; i < HAMMER_MAX_VOLUMES; i++)
181509798eaSPedro F. Giffuni if (x[i] > 1)
1829d529ed8SPedro F. Giffuni goto fail;
183509798eaSPedro F. Giffuni for (i = 0; i < HAMMER_MAX_VOLUMES; i++)
184509798eaSPedro F. Giffuni if (x[i] == 0)
185509798eaSPedro F. Giffuni break;
186509798eaSPedro F. Giffuni if (ondisk->vol_count != i)
1879d529ed8SPedro F. Giffuni goto fail;
188509798eaSPedro F. Giffuni for (; i < HAMMER_MAX_VOLUMES; i++)
189509798eaSPedro F. Giffuni if (x[i] != 0)
1909d529ed8SPedro F. Giffuni goto fail;
191509798eaSPedro F. Giffuni success:
192509798eaSPedro F. Giffuni strlcpy(label, ondisk->vol_label, size);
193509798eaSPedro F. Giffuni error = 0;
1949d529ed8SPedro F. Giffuni fail:
195509798eaSPedro F. Giffuni free(ondisk);
196509798eaSPedro F. Giffuni return (error);
197509798eaSPedro F. Giffuni }
198509798eaSPedro F. Giffuni
199509798eaSPedro F. Giffuni int
fsvtyp_hammer(const char * blkdevs,char * label,size_t size)200509798eaSPedro F. Giffuni fsvtyp_hammer(const char *blkdevs, char *label, size_t size)
201509798eaSPedro F. Giffuni {
202509798eaSPedro F. Giffuni return (__fsvtyp_hammer(blkdevs, label, size, 0));
203509798eaSPedro F. Giffuni }
204509798eaSPedro F. Giffuni
205509798eaSPedro F. Giffuni int
fsvtyp_hammer_partial(const char * blkdevs,char * label,size_t size)206509798eaSPedro F. Giffuni fsvtyp_hammer_partial(const char *blkdevs, char *label, size_t size)
207509798eaSPedro F. Giffuni {
208509798eaSPedro F. Giffuni return (__fsvtyp_hammer(blkdevs, label, size, 1));
209509798eaSPedro F. Giffuni }
210