HAMMER utilities: Add the 'prune' and 'history' commands.
[dragonfly/netmp.git] / sbin / hammer / cmd_history.c
blob264e560104ca2a7d9238ab38fced8b53ba1177eb
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:
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.
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.
34 * $DragonFly: src/sbin/hammer/cmd_history.c,v 1.1 2008/02/04 08:34:22 dillon Exp $
37 #include "hammer.h"
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);
43 * history <file1> ... <fileN>
45 void
46 hammer_cmd_history(const char *offset_str, char **av, int ac)
48 off_t off;
49 int i;
50 int len;
51 char *rptr;
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;
62 for (i = 0; i < ac; ++i)
63 hammer_do_history(av[i], off, len);
66 static void
67 hammer_do_history(const char *path, off_t off, int len)
69 struct hammer_ioc_history hist;
70 const char *status;
71 int fd;
72 int i;
74 printf("%s\t", path);
75 fd = open(path, O_RDONLY);
76 if (fd < 0) {
77 printf("%s\n", strerror(errno));
78 return;
80 bzero(&hist, sizeof(hist));
81 hist.beg_tid = HAMMER_MIN_TID;
82 hist.end_tid = HAMMER_MAX_TID;
84 if (off >= 0) {
85 hist.flags |= HAMMER_IOC_HISTORY_ATKEY;
86 hist.key = off;
87 hist.nxt_key = off + 1;
91 if (ioctl(fd, HAMMERIOC_GETHISTORY, &hist) < 0) {
92 printf("%s\n", strerror(errno));
93 close(fd);
94 return;
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;
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);
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), "?");
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("'");
136 printf("\n");
137 free(hist_path);
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;
151 printf("}\n");
152 close(fd);
155 static void
156 dumpat(const char *path, off_t off, int len)
158 char buf[1024];
159 int fd;
160 int n;
161 int r;
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);