Fix various typos in our manual pages.
[dragonfly.git] / sbin / hammer / cmd_history.c
1 /*
2  * Copyright (c) 2008 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/cmd_history.c,v 1.1 2008/02/04 08:34:22 dillon Exp $
35  */
36
37 #include "hammer.h"
38
39 static void hammer_do_history(const char *path, off_t off, int len);
40 static void dumpat(const char *path, off_t off, int len);
41
42 /*
43  * history <file1> ... <fileN>
44  */
45 void
46 hammer_cmd_history(const char *offset_str, char **av, int ac)
47 {
48         off_t off;
49         int i;
50         int len;
51         char *rptr;
52
53         len = 32;
54         if (*offset_str == '@') {
55                 off = strtoll(offset_str + 1, &rptr, 0);
56                 if (*rptr == ',')
57                         len = strtol(rptr + 1, NULL, 0);
58         } else {
59                 off = -1;
60         }
61
62         for (i = 0; i < ac; ++i)
63                 hammer_do_history(av[i], off, len);
64 }
65
66 static void
67 hammer_do_history(const char *path, off_t off, int len)
68 {
69         struct hammer_ioc_history hist;
70         const char *status;
71         int fd;
72         int i;
73
74         printf("%s\t", path);
75         fd = open(path, O_RDONLY);
76         if (fd < 0) {
77                 printf("%s\n", strerror(errno));
78                 return;
79         }
80         bzero(&hist, sizeof(hist));
81         hist.beg_tid = HAMMER_MIN_TID;
82         hist.end_tid = HAMMER_MAX_TID;
83
84         if (off >= 0) {
85                 hist.flags |= HAMMER_IOC_HISTORY_ATKEY;
86                 hist.key = off;
87                 hist.nxt_key = off + 1;
88         }
89
90
91         if (ioctl(fd, HAMMERIOC_GETHISTORY, &hist) < 0) {
92                 printf("%s\n", strerror(errno));
93                 close(fd);
94                 return;
95         }
96         status = ((hist.flags & HAMMER_IOC_HISTORY_UNSYNCED) ?
97                  "dirty" : "clean");
98         printf("%016llx %s {\n", hist.obj_id, status);
99         for (;;) {
100                 for (i = 0; i < hist.count; ++i) {
101                         struct stat st;
102                         struct tm tp;
103                         time_t t;
104                         char timebuf1[64];
105                         char timebuf2[64];
106                         char *hist_path = NULL;
107
108                         t = (int64_t)hist.tid_ary[i] / 1000000000LL;
109                         localtime_r(&t, &tp);
110                         strftime(timebuf1, sizeof(timebuf1),
111                                  "%e-%b-%Y %H:%M:%S", &tp);
112
113                         asprintf(&hist_path, "%s@@0x%016llx",
114                                  path, hist.tid_ary[i]);
115                         if (off < 0 && stat(hist_path, &st) == 0) {
116                                 localtime_r(&st.st_mtime, &tp);
117                                 strftime(timebuf2, sizeof(timebuf2),
118                                          "%e-%b-%Y %H:%M:%S %Z", &tp);
119                         } else {
120                                 snprintf(timebuf2, sizeof(timebuf2), "?");
121                         }
122                         if (off < 0) {
123                                 printf("    %016llx %s contents-to %s",
124                                        hist.tid_ary[i],
125                                        timebuf1, timebuf2);
126                         } else {
127                                 printf("    %016llx %s",
128                                        hist.tid_ary[i],
129                                        timebuf1);
130                                 if (VerboseOpt) {
131                                         printf(" '");
132                                         dumpat(hist_path, off, len);
133                                         printf("'");
134                                 }
135                         }
136                         printf("\n");
137                         free(hist_path);
138                 }
139                 if (hist.flags & HAMMER_IOC_HISTORY_EOF)
140                         break;
141                 if (hist.flags & HAMMER_IOC_HISTORY_NEXT_KEY)
142                         break;
143                 if ((hist.flags & HAMMER_IOC_HISTORY_NEXT_TID) == 0)
144                         break;
145                 hist.beg_tid = hist.nxt_tid;
146                 if (ioctl(fd, HAMMERIOC_GETHISTORY, &hist) < 0) {
147                         printf("    error: %s\n", strerror(errno));
148                         break;
149                 }
150         }
151         printf("}\n");
152         close(fd);
153 }
154
155 static void
156 dumpat(const char *path, off_t off, int len)
157 {
158         char buf[1024];
159         int fd;
160         int n;
161         int r;
162
163         fd = open(path, O_RDONLY);
164         if (fd < 0)
165                 return;
166         lseek(fd, off, 0);
167         while (len) {
168                 n = (len > (int)sizeof(buf)) ? (int)sizeof(buf) : len;
169                 r = read(fd, buf, n);
170                 if (r <= 0)
171                         break;
172                 len -= r;
173                 for (n = 0; n < r; ++n) {
174                         if (isprint(buf[n]))
175                                 putc(buf[n], stdout);
176                         else
177                                 putc('.', stdout);
178                 }
179         }
180 }
181