HAMMER 15/many - user utility infrastructure, refactor alists, misc
[dragonfly.git] / sbin / hammer / 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/hammer/hammer.c,v 1.2 2008/01/03 06:48:45 dillon Exp $
35  */
36
37 #include "hammer.h"
38
39 static void hammer_parsetime(u_int64_t *tidp, const char *timestr);
40 static void usage(int exit_code);
41
42 int
43 main(int ac, char **av)
44 {
45         u_int64_t tid;
46         int ch;
47         int status;
48
49         while ((ch = getopt(ac, av, "h")) != -1) {
50                 switch(ch) {
51                 case 'h':
52                         usage(0);
53                         /* not reached */
54                 default:
55                         usage(1);
56                         /* not reached */
57                 }
58         }
59         ac -= optind;
60         av += optind;
61         if (ac < 1) {
62                 usage(1);
63                 /* not reached */
64         }
65
66         if (strcmp(av[0], "now") == 0) {
67                 hammer_parsetime(&tid, "0s");
68                 printf("0x%08x\n", (int)(tid / 1000000000LL));
69                 exit(0);
70         }
71         if (strcmp(av[0], "stamp") == 0) {
72                 if (av[1] == NULL)
73                         usage(1);
74                 hammer_parsetime(&tid, av[1]);
75                 printf("0x%08x\n", (int)(tid / 1000000000LL));
76                 exit(0);
77         }
78
79         uuid_name_lookup(&Hammer_FSType, "DragonFly HAMMER", &status);
80         if (status != uuid_s_ok) {
81                 errx(1, "uuids file does not have the DragonFly "
82                         "HAMMER filesystem type");
83         }
84         init_alist_templates();
85
86         /*
87          * Additional commands
88          */
89
90         usage(1);
91         /* not reached */
92         return(0);
93 }
94
95 /*
96  * Parse a timestamp for the mount point
97  *
98  * yyyymmddhhmmss
99  * -N[s/h/d/m/y]
100  */
101 static
102 void
103 hammer_parsetime(u_int64_t *tidp, const char *timestr)
104 {
105         struct tm tm;
106         time_t t;
107         int32_t n;
108         char c;
109         double seconds = 0;
110
111         t = time(NULL);
112
113         if (*timestr == 0)
114                 usage(1);
115
116         if (isalpha(timestr[strlen(timestr)-1])) {
117                 if (sscanf(timestr, "%d%c", &n, &c) != 2)
118                         usage(1);
119                 switch(c) {
120                 case 'Y':
121                         n *= 365;
122                         goto days;
123                 case 'M':
124                         n *= 30;
125                         /* fall through */
126                 case 'D':
127                 days:
128                         n *= 24;
129                         /* fall through */
130                 case 'h':
131                         n *= 60;
132                         /* fall through */
133                 case 'm':
134                         n *= 60;
135                         /* fall through */
136                 case 's':
137                         t -= n;
138                         break;
139                 default:
140                         usage(1);
141                 }
142         } else {
143                 localtime_r(&t, &tm);
144                 seconds = (double)tm.tm_sec;
145                 tm.tm_year -= 1900;
146                 tm.tm_mon -= 1;
147                 n = sscanf(timestr, "%4d%2d%2d:%2d%2d%lf",
148                            &tm.tm_year, &tm.tm_mon, &tm.tm_mday,
149                            &tm.tm_hour, &tm.tm_min, &seconds);
150                 tm.tm_mon += 1;
151                 tm.tm_year += 1900;
152                 tm.tm_sec = (int)seconds;
153                 t = mktime(&tm);
154         }
155         localtime_r(&t, &tm);
156         *tidp = (u_int64_t)t * 1000000000 + 
157                 (seconds - (int)seconds) * 1000000000;
158 }
159
160 static
161 void
162 usage(int exit_code)
163 {
164         fprintf(stderr, 
165                 "hammer -h\n"
166                 "hammer now\n"
167                 "hammer stamp <time>\n"
168         );
169         fprintf(stderr, "    time: +n[s/m/h/D/M/Y]\n"
170                         "    time: yyyymmdd[:hhmmss]\n");
171         exit(exit_code);
172 }