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 }
206