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