Commit | Line | Data |
---|---|---|
a89ff8c8 MD |
1 | /* |
2 | * Copyright (c) 2007 The DragonFly Project. All rights reserved. | |
745703c7 | 3 | * |
a89ff8c8 MD |
4 | * This code is derived from software contributed to The DragonFly Project |
5 | * by Matthew Dillon <dillon@backplane.com> | |
745703c7 | 6 | * |
a89ff8c8 MD |
7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | |
9 | * are met: | |
745703c7 | 10 | * |
a89ff8c8 MD |
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 | |
15 | * the documentation and/or other materials provided with the | |
16 | * distribution. | |
17 | * 3. Neither the name of The DragonFly Project nor the names of its | |
18 | * contributors may be used to endorse or promote products derived | |
19 | * from this software without specific, prior written permission. | |
745703c7 | 20 | * |
a89ff8c8 MD |
21 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
22 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
23 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
24 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
25 | * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, | |
26 | * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, | |
27 | * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | |
28 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED | |
29 | * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | |
30 | * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT | |
31 | * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
32 | * SUCH DAMAGE. | |
a89ff8c8 MD |
33 | */ |
34 | ||
35 | #include <sys/types.h> | |
a89ff8c8 | 36 | #include <sys/stat.h> |
a89ff8c8 MD |
37 | #include <vfs/hammer/hammer_mount.h> |
38 | ||
39 | #include <stdio.h> | |
40 | #include <stdlib.h> | |
41 | #include <stdarg.h> | |
42 | #include <stddef.h> | |
43 | #include <unistd.h> | |
44 | #include <string.h> | |
a89ff8c8 | 45 | #include <fcntl.h> |
a89ff8c8 | 46 | #include <err.h> |
2dc55a02 | 47 | #include <mntopts.h> |
a89ff8c8 | 48 | |
25abdf3e | 49 | static void test_master_id(int master_id); |
aeb72a17 TK |
50 | static void extract_volumes(struct hammer_mount_info *info, char **av, int ac); |
51 | static void free_volumes(struct hammer_mount_info *info); | |
b519f4e8 | 52 | static void usage(void); |
4adc29ed | 53 | |
25abdf3e TK |
54 | #define hwarnx(format, args...) warnx("WARNING: "format,## args) |
55 | ||
195c19a1 | 56 | #define MOPT_HAMMEROPTS \ |
da44aa75 MD |
57 | { "history", 1, HMNT_NOHISTORY, 1 }, \ |
58 | { "master=", 0, HMNT_MASTERID, 1 }, \ | |
87b8f936 | 59 | { "mirror", 1, HMNT_NOMIRROR, 1 } |
195c19a1 | 60 | |
4adc29ed MD |
61 | static struct mntopt mopts[] = { MOPT_STDOPTS, MOPT_HAMMEROPTS, |
62 | MOPT_UPDATE, MOPT_NULL }; | |
a89ff8c8 | 63 | |
a89ff8c8 MD |
64 | int |
65 | main(int ac, char **av) | |
66 | { | |
67 | struct hammer_mount_info info; | |
68 | struct vfsconf vfc; | |
4adc29ed | 69 | int mount_flags = 0; |
b519f4e8 | 70 | int init_flags = 0; |
a89ff8c8 MD |
71 | int error; |
72 | int ch; | |
73 | char *mountpt; | |
da44aa75 | 74 | char *ptr; |
a89ff8c8 | 75 | |
195c19a1 | 76 | bzero(&info, sizeof(info)); |
195c19a1 | 77 | |
4adc29ed | 78 | while ((ch = getopt(ac, av, "o:T:u")) != -1) { |
a89ff8c8 MD |
79 | switch(ch) { |
80 | case 'T': | |
b5aaba7f | 81 | info.asof = strtoull(optarg, NULL, 0); |
a89ff8c8 MD |
82 | break; |
83 | case 'o': | |
195c19a1 | 84 | getmntopts(optarg, mopts, &mount_flags, &info.hflags); |
da44aa75 | 85 | |
da44aa75 MD |
86 | /* |
87 | * Handle extended flags with parameters. | |
88 | */ | |
89 | if (info.hflags & HMNT_MASTERID) { | |
90 | ptr = strstr(optarg, "master="); | |
91 | if (ptr) { | |
92 | info.master_id = strtol(ptr + 7, NULL, 0); | |
25abdf3e | 93 | test_master_id(info.master_id); |
da44aa75 | 94 | } |
87b8f936 TK |
95 | } |
96 | if (info.hflags & HMNT_NOMIRROR) { | |
da44aa75 MD |
97 | ptr = strstr(optarg, "nomirror"); |
98 | if (ptr) | |
99 | info.master_id = -1; | |
100 | } | |
a89ff8c8 | 101 | break; |
4adc29ed MD |
102 | case 'u': |
103 | init_flags |= MNT_UPDATE; | |
104 | break; | |
a89ff8c8 MD |
105 | default: |
106 | usage(); | |
107 | /* not reached */ | |
88356ed4 | 108 | break; |
a89ff8c8 MD |
109 | } |
110 | } | |
111 | ac -= optind; | |
112 | av += optind; | |
4adc29ed MD |
113 | mount_flags |= init_flags; |
114 | ||
115 | /* | |
116 | * Only the mount point need be specified in update mode. | |
117 | */ | |
118 | if (init_flags & MNT_UPDATE) { | |
119 | if (ac != 1) { | |
120 | usage(); | |
121 | /* not reached */ | |
122 | } | |
123 | mountpt = av[0]; | |
9db06424 | 124 | if (mount(vfc.vfc_name, mountpt, mount_flags, &info)) { |
1a607e3e | 125 | err(1, "mountpoint %s", mountpt); |
9db06424 TK |
126 | /* not reached */ |
127 | } | |
4adc29ed MD |
128 | exit(0); |
129 | } | |
a89ff8c8 MD |
130 | |
131 | if (ac < 2) { | |
132 | usage(); | |
133 | /* not reached */ | |
134 | } | |
135 | ||
136 | /* | |
137 | * Mount arguments: vol [vol...] mountpt | |
138 | */ | |
aeb72a17 | 139 | extract_volumes(&info, av, ac - 1); |
a89ff8c8 MD |
140 | mountpt = av[ac - 1]; |
141 | ||
142 | /* | |
143 | * Load the hammer module if necessary (this bit stolen from | |
144 | * mount_null). | |
145 | */ | |
146 | error = getvfsbyname("hammer", &vfc); | |
147 | if (error && vfsisloadable("hammer")) { | |
9db06424 | 148 | if (vfsload("hammer") != 0) { |
a89ff8c8 | 149 | err(1, "vfsload(hammer)"); |
9db06424 TK |
150 | /* not reached */ |
151 | } | |
a89ff8c8 MD |
152 | endvfsent(); |
153 | error = getvfsbyname("hammer", &vfc); | |
154 | } | |
9db06424 | 155 | if (error) { |
a89ff8c8 | 156 | errx(1, "hammer filesystem is not available"); |
9db06424 TK |
157 | /* not reached */ |
158 | } | |
a89ff8c8 | 159 | |
1a607e3e | 160 | if (mount(vfc.vfc_name, mountpt, mount_flags, &info)) { |
586b3d29 | 161 | perror("mount"); |
586b3d29 | 162 | exit(1); |
1a607e3e | 163 | } |
aeb72a17 | 164 | free_volumes(&info); |
bac217f3 TK |
165 | |
166 | return(0); | |
a89ff8c8 MD |
167 | } |
168 | ||
005a4da7 TK |
169 | static |
170 | void | |
171 | test_master_id(int master_id) | |
bab16452 TK |
172 | { |
173 | switch (master_id) { | |
174 | case 0: | |
25abdf3e TK |
175 | hwarnx("A master id of 0 is the default, " |
176 | "explicit settings should use 1-15"); | |
bab16452 TK |
177 | break; |
178 | case -1: | |
25abdf3e TK |
179 | hwarnx("A master id of -1 is nomirror mode, " |
180 | "equivalent to -o nomirror option"); | |
bab16452 | 181 | break; |
2998e5e0 TK |
182 | case 1 ... 15: /* gcc */ |
183 | /* Expected values via -o master= option */ | |
184 | break; | |
bab16452 TK |
185 | default: |
186 | /* This will eventually fail in hammer_vfs_mount() */ | |
25abdf3e | 187 | hwarnx("A master id of %d is not supported", master_id); |
bab16452 TK |
188 | break; |
189 | } | |
190 | } | |
191 | ||
4adc29ed MD |
192 | /* |
193 | * Extract a volume list | |
194 | */ | |
aeb72a17 TK |
195 | static |
196 | void | |
197 | extract_volumes(struct hammer_mount_info *info, char **av, int ac) | |
4adc29ed MD |
198 | { |
199 | int idx = 0; | |
200 | int arymax = 32; | |
688e7182 TK |
201 | char **ary, *ptr, *next, *orig; |
202 | ||
203 | #define _extend_ary(ary, arymax) ({ \ | |
204 | (arymax) += 32; \ | |
205 | realloc(ary, (arymax) * sizeof(char *)); \ | |
206 | }) | |
207 | ary = calloc(arymax, sizeof(char *)); | |
4adc29ed MD |
208 | |
209 | while (ac) { | |
688e7182 TK |
210 | if (idx == arymax) |
211 | ary = _extend_ary(ary, arymax); | |
4adc29ed | 212 | if (strchr(*av, ':') == NULL) { |
aeb72a17 | 213 | ary[idx++] = strdup(*av); |
4adc29ed | 214 | } else { |
aeb72a17 | 215 | orig = next = strdup(*av); |
4adc29ed | 216 | while ((ptr = next) != NULL) { |
688e7182 TK |
217 | if (idx == arymax) |
218 | ary = _extend_ary(ary, arymax); | |
4adc29ed MD |
219 | if ((next = strchr(ptr, ':')) != NULL) |
220 | *next++ = 0; | |
aeb72a17 | 221 | ary[idx++] = strdup(ptr); |
4adc29ed | 222 | } |
aeb72a17 | 223 | free(orig); |
4adc29ed MD |
224 | } |
225 | --ac; | |
226 | ++av; | |
4adc29ed | 227 | } |
aeb72a17 TK |
228 | info->nvolumes = idx; |
229 | info->volumes = ary; | |
230 | } | |
231 | ||
232 | static | |
233 | void | |
234 | free_volumes(struct hammer_mount_info *info) | |
235 | { | |
236 | int i; | |
237 | ||
238 | for (i = 0; i < info->nvolumes; i++) | |
e73c3403 | 239 | free(info->volumes[i]); |
aeb72a17 | 240 | free(info->volumes); |
4adc29ed MD |
241 | } |
242 | ||
a89ff8c8 MD |
243 | static |
244 | void | |
245 | usage(void) | |
246 | { | |
28ffd1b3 TN |
247 | fprintf(stderr, "usage: mount_hammer [-o options] [-T transaction-id] " |
248 | "special ... node\n"); | |
249 | fprintf(stderr, " mount_hammer [-o options] [-T transaction-id] " | |
250 | "special[:special]* node\n"); | |
251 | fprintf(stderr, " mount_hammer -u [-o options] node\n"); | |
195c19a1 | 252 | exit(1); |
a89ff8c8 | 253 | } |