Merge branch 'vendor/OPENSSH'
[dragonfly.git] / usr.sbin / fstyp / hammer.c
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 }