Merge from vendor branch FILE:
[dragonfly.git] / sbin / mount_hammer / mount_hammer.c
1 /*
2  * Copyright (c) 2007 The DragonFly Project.  All rights reserved.
3  * 
4  * This code is derived from software contributed to The DragonFly Project
5  * by Matthew Dillon <dillon@backplane.com>
6  * 
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 
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.
20  * 
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.
33  * 
34  * $DragonFly: src/sbin/mount_hammer/mount_hammer.c,v 1.3 2007/12/12 23:47:57 dillon Exp $
35  */
36
37 #include <sys/types.h>
38 #include <sys/diskslice.h>
39 #include <sys/diskmbr.h>
40 #include <sys/stat.h>
41 #include <sys/time.h>
42 #include <vfs/hammer/hammer_mount.h>
43
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <stdarg.h>
47 #include <stddef.h>
48 #include <unistd.h>
49 #include <string.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <uuid.h>
53 #include <err.h>
54 #include <assert.h>
55 #include <ctype.h>
56
57 #include "mntopts.h"
58
59 static void hammer_parsetime(u_int64_t *tidp, const char *timestr);
60
61 #define MOPT_HAMMEROPTS         \
62         { "history", 1, HMNT_NOHISTORY, 1 }
63
64 static struct mntopt mopts[] = { MOPT_STDOPTS, MOPT_HAMMEROPTS, MOPT_NULL };
65
66 static void usage(void);
67
68 int
69 main(int ac, char **av)
70 {
71         struct hammer_mount_info info;
72         struct vfsconf vfc;
73         int mount_flags;
74         int error;
75         int ch;
76         char *mountpt;
77
78         bzero(&info, sizeof(info));
79         info.asof = 0;
80         mount_flags = 0;
81         info.hflags = 0;
82
83         while ((ch = getopt(ac, av, "o:T:")) != -1) {
84                 switch(ch) {
85                 case 'T':
86                         hammer_parsetime(&info.asof, optarg);
87                         break;
88                 case 'o':
89                         getmntopts(optarg, mopts, &mount_flags, &info.hflags);
90                         break;
91                 default:
92                         usage();
93                         /* not reached */
94                 }
95         }
96         ac -= optind;
97         av += optind;
98
99         if (ac < 2) {
100                 usage();
101                 /* not reached */
102         }
103
104         /*
105          * Mount arguments: vol [vol...] mountpt
106          */
107         info.volumes = (const char **)av;
108         info.nvolumes = ac - 1;
109         mountpt = av[ac - 1];
110
111         /*
112          * Load the hammer module if necessary (this bit stolen from
113          * mount_null).
114          */
115         error = getvfsbyname("hammer", &vfc);
116         if (error && vfsisloadable("hammer")) {
117                 if (vfsload("hammer") != 0)
118                         err(1, "vfsload(hammer)");
119                 endvfsent();
120                 error = getvfsbyname("hammer", &vfc);
121         }
122         if (error)
123                 errx(1, "hammer filesystem is not available");
124
125         if (mount(vfc.vfc_name, mountpt, mount_flags, &info))
126                 err(1, NULL);
127         exit(0);
128 }
129
130 /*
131  * Parse a timestamp for the mount point
132  *
133  * yyyymmddhhmmss
134  * -N[s/h/d/m/y]
135  */
136 static
137 void
138 hammer_parsetime(u_int64_t *tidp, const char *timestr)
139 {
140         struct tm tm;
141         time_t t;
142         int32_t n;
143         char c;
144         double seconds = 0;
145
146         t = time(NULL);
147
148         if (*timestr == 0)
149                 usage();
150
151         if (isalpha(timestr[strlen(timestr)-1])) {
152                 if (sscanf(timestr, "%d%c", &n, &c) != 2)
153                         usage();
154                 switch(c) {
155                 case 'Y':
156                         n *= 365;
157                         goto days;
158                 case 'M':
159                         n *= 30;
160                         /* fall through */
161                 case 'D':
162                 days:
163                         n *= 24;
164                         /* fall through */
165                 case 'h':
166                         n *= 60;
167                         /* fall through */
168                 case 'm':
169                         n *= 60;
170                         /* fall through */
171                 case 's':
172                         t -= n;
173                         break;
174                 default:
175                         usage();
176                 }
177         } else {
178                 localtime_r(&t, &tm);
179                 seconds = (double)tm.tm_sec;
180                 tm.tm_year -= 1900;
181                 tm.tm_mon -= 1;
182                 n = sscanf(timestr, "%4d%2d%2d:%2d%2d%lf",
183                            &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
184                            &tm.tm_hour, &tm.tm_min, &seconds);
185                 tm.tm_mon += 1;
186                 tm.tm_year += 1900;
187                 tm.tm_sec = (int)seconds;
188                 t = mktime(&tm);
189         }
190         localtime_r(&t, &tm);
191         printf("mount_hammer as-of %s", asctime(&tm));
192         *tidp = (u_int64_t)t * 1000000000 + 
193                 (seconds - (int)seconds) * 1000000000;
194 }
195
196 static
197 void
198 usage(void)
199 {
200         fprintf(stderr, "mount_hammer [-T time] [-o options] "
201                         "volume [volume...] mount_pt");
202         fprintf(stderr, "    time: +n[s/m/h/D/M/Y]\n"
203                         "    time: yyyymmdd[:hhmmss]\n");
204         exit(1);
205 }