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 182