hist.c (5027B)
1 #include <u.h> 2 #include <libc.h> 3 #include <ctype.h> 4 5 #define MINUTE(x) ((long)(x)*60L) 6 #define HOUR(x) (MINUTE(x)*60L) 7 #define YEAR(x) (HOUR(x)*24L*360L) 8 9 int verb; 10 int uflag; 11 int force; 12 int diff; 13 int diffb; 14 char* sflag; 15 char *sys; 16 17 void ysearch(char*); 18 long starttime(char*); 19 void lastbefore(ulong, char*, char*, char*); 20 char* prtime(ulong); 21 22 int 23 main(int argc, char *argv[]) 24 { 25 int i; 26 27 sys = sysname(); 28 if(strncmp(sys, "amsterdam", 9) == 0) /* BUG */ 29 sys = "am"; 30 31 ARGBEGIN { 32 default: 33 goto usage; 34 case 'v': 35 verb = 1; 36 break; 37 case 'f': 38 force = 1; 39 break; 40 case 'd': 41 diff = 1; 42 break; 43 case 'b': 44 diffb = 1; 45 break; 46 case 's': 47 sflag = ARGF(); 48 break; 49 case 'u': 50 uflag = 1; 51 break; 52 } ARGEND 53 54 if(argc == 0) { 55 usage: 56 fprint(2, "usage: hist [-bdfuv] [-s yyyymmdd] files\n"); 57 exits(0); 58 } 59 60 for(i=0; i<argc; i++) 61 ysearch(argv[i]); 62 exits(0); 63 return 0; 64 } 65 66 int 67 strprefix(char *a, char *aa) 68 { 69 return memcmp(a, aa, strlen(a)) == 0; 70 } 71 72 void 73 ysearch(char *file) 74 { 75 char *ndump; 76 char fil[400], buf[500], nbuf[100], pair[2][500]; 77 Tm *tm; 78 Dir *dir, *d; 79 ulong otime, dt; 80 int toggle, started, missing; 81 82 started = 0; 83 dir = dirstat(file); 84 if(dir == nil) 85 fprint(2, "history: warning: %s does not exist\n", file); 86 else{ 87 print("%s %s %lld\n", prtime(dir->mtime), file, dir->length); 88 started = 1; 89 strcpy(pair[1], file); 90 } 91 free(dir); 92 fil[0] = 0; 93 if(file[0] != '/') { 94 getwd(strchr(fil, 0), 100); 95 strcat(fil, "/"); 96 } 97 strcat(fil, file); 98 cleanname(fil); 99 100 sprint(nbuf, "/dump/%s", sys); 101 ndump = nbuf; 102 103 tm = localtime(time(0)); 104 sprint(buf, "%s/%.4d/", ndump, tm->year+1900); 105 if(access(buf, AREAD) < 0){ 106 print("cannot access %s\n", buf); 107 return; 108 } 109 110 otime = starttime(sflag); 111 toggle = 0; 112 for(;;) { 113 lastbefore(otime, fil, buf, ndump); 114 dir = dirstat(buf); 115 if(dir == nil) { 116 if(!force) 117 return; 118 dir = malloc(sizeof(Dir)); 119 nulldir(dir); 120 dir->mtime = otime + 1; 121 } 122 dt = HOUR(12); 123 missing = 0; 124 while(otime <= dir->mtime){ 125 if(verb) 126 print("backup %ld, %ld\n", dir->mtime, otime-dt); 127 lastbefore(otime-dt, fil, buf, ndump); 128 d = dirstat(buf); 129 if(d == nil){ 130 if(!force) 131 return; 132 if(!missing) 133 print("removed %s\n", buf); 134 missing = 1; 135 }else{ 136 free(dir); 137 dir = d; 138 } 139 dt += HOUR(12); 140 } 141 strcpy(pair[toggle], buf); 142 if(diff && started){ 143 if(verb) 144 print("diff %s %s\n", pair[toggle^1], pair[toggle]); 145 switch(rfork(RFFDG|RFPROC)){ 146 case 0: 147 execlp("diff", "diff", diffb ? "-cb" : "-c", pair[toggle], pair[toggle ^ 1], (char*)0); 148 fprint(2, "can't exec diff: %r\n"); 149 exits(0); 150 case -1: 151 fprint(2, "can't fork diff: %r\n"); 152 break; 153 default: 154 while(waitpid() != -1) 155 ; 156 break; 157 } 158 } 159 print("%s %s %lld\n", prtime(dir->mtime), buf, dir->length); 160 toggle ^= 1; 161 started = 1; 162 otime = dir->mtime; 163 free(dir); 164 } 165 } 166 167 void 168 lastbefore(ulong t, char *f, char *b, char *ndump) 169 { 170 Tm *tm; 171 Dir *dir; 172 int vers, try; 173 ulong t0, mtime; 174 175 t0 = t; 176 if(verb) 177 print("%ld lastbefore %s\n", t0, f); 178 mtime = 0; 179 for(try=0; try<10; try++) { 180 tm = localtime(t); 181 sprint(b, "%s/%.4d/%.2d%.2d", ndump, 182 tm->year+1900, tm->mon+1, tm->mday); 183 dir = dirstat(b); 184 if(dir){ 185 mtime = dir->mtime; 186 free(dir); 187 } 188 if(dir==nil || mtime > t0) { 189 if(verb) 190 print("%ld earlier %s\n", mtime, b); 191 t -= HOUR(24); 192 continue; 193 } 194 for(vers=0;; vers++) { 195 sprint(b, "%s/%.4d/%.2d%.2d%d", ndump, 196 tm->year+1900, tm->mon+1, tm->mday, vers+1); 197 dir = dirstat(b); 198 if(dir){ 199 mtime = dir->mtime; 200 free(dir); 201 } 202 if(dir==nil || mtime > t0) 203 break; 204 if(verb) 205 print("%ld later %s\n", mtime, b); 206 } 207 sprint(b, "%s/%.4d/%.2d%.2d%s", ndump, 208 tm->year+1900, tm->mon+1, tm->mday, f); 209 if(vers) 210 sprint(b, "%s/%.4d/%.2d%.2d%d%s", ndump, 211 tm->year+1900, tm->mon+1, tm->mday, vers, f); 212 return; 213 } 214 strcpy(b, "XXX"); /* error */ 215 } 216 217 char* 218 prtime(ulong t) 219 { 220 static char buf[100]; 221 char *b; 222 Tm *tm; 223 224 if(uflag) 225 tm = gmtime(t); 226 else 227 tm = localtime(t); 228 b = asctime(tm); 229 memcpy(buf, b+4, 24); 230 buf[24] = 0; 231 return buf; 232 } 233 234 long 235 starttime(char *s) 236 { 237 Tm *tm; 238 long t, dt; 239 int i, yr, mo, da; 240 241 t = time(0); 242 if(s == 0) 243 return t; 244 for(i=0; s[i]; i++) 245 if(s[i] < '0' || s[i] > '9') { 246 fprint(2, "bad start time: %s\n", s); 247 return t; 248 } 249 if(strlen(s)==6){ 250 yr = (s[0]-'0')*10 + s[1]-'0'; 251 mo = (s[2]-'0')*10 + s[3]-'0' - 1; 252 da = (s[4]-'0')*10 + s[5]-'0'; 253 if(yr < 70) 254 yr += 100; 255 }else if(strlen(s)==8){ 256 yr = (((s[0]-'0')*10 + s[1]-'0')*10 + s[2]-'0')*10 + s[3]-'0'; 257 yr -= 1900; 258 mo = (s[4]-'0')*10 + s[5]-'0' - 1; 259 da = (s[6]-'0')*10 + s[7]-'0'; 260 }else{ 261 fprint(2, "bad start time: %s\n", s); 262 return t; 263 } 264 t = 0; 265 dt = YEAR(10); 266 for(i=0; i<50; i++) { 267 tm = localtime(t+dt); 268 if(yr > tm->year || 269 (yr == tm->year && mo > tm->mon) || 270 (yr == tm->year && mo == tm->mon) && da > tm->mday) { 271 t += dt; 272 continue; 273 } 274 dt /= 2; 275 if(dt == 0) 276 break; 277 } 278 t += HOUR(12); /* .5 day to get to noon of argument */ 279 return t; 280 }