4 #define MINUTE(x) ((long)(x)*60L)
5 #define HOUR(x) (MINUTE(x)*60L)
6 #define YEAR(x) (HOUR(x)*24L*360L)
19 void ysearch(char*, char*);
20 long starttime(char*);
21 void lastbefore(ulong, char*, char*, char*);
26 main(int argc, char *argv[])
80 ysearch(argv[i], ndump);
87 if(ndargv >= nelem(dargv)-3)
95 fprint(2, "usage: history [-bDfuv] [-d dumpfilesystem] [-s yyyymmdd] files\n");
100 ysearch(char *file, char *ndump)
102 char fil[400], buf[500], nbuf[100], pair[2][500], *p;
107 int toggle, started, missing;
111 getwd(strchr(fil, 0), 100);
115 if(memcmp(fil, "/n/", 3) == 0){
116 p = strchr(fil+3, '/');
120 if(p-fil >= sizeof nbuf-10){
121 fprint(2, "%s: dump name too long", fil);
124 memmove(nbuf, fil+3, p-(fil+3));
126 strcat(nbuf, "dump");
129 memmove(fil, p, strlen(p)+1);
134 tm = localtime(time(0));
135 snprint(buf, sizeof buf, "/n/%s/%.4d/", ndump, tm->year+1900);
136 if(access(buf, AREAD) < 0) {
138 print("mounting dump %s\n", ndump);
139 if(rfork(RFFDG|RFPROC) == 0) {
140 execl("/bin/rc", "rc", "9fs", ndump, nil);
145 fprint(2, "history: wait error: %r\n");
148 if(w->msg[0] != '\0'){
149 fprint(2, "9fs failed: %s\n", w->msg);
158 fprint(2, "history: warning: %s does not exist\n", file);
160 print("%s %s %lld [%s]\n", prtime(dir->mtime), file, dir->length, dir->muid);
162 strecpy(pair[1], pair[1]+sizeof pair[1], file);
165 otime = starttime(sflag);
168 lastbefore(otime, fil, buf, ndump);
173 dir = malloc(sizeof(Dir));
175 dir->mtime = otime + 1;
179 while(otime <= dir->mtime){
181 print("backup %ld, %ld\n", dir->mtime, otime-dt);
182 lastbefore(otime-dt, fil, buf, ndump);
188 print("removed %s\n", buf);
196 strcpy(pair[toggle], buf);
198 switch(rfork(RFFDG|RFPROC)){
200 dargv[ndargv] = pair[toggle];
201 dargv[ndargv+1] = pair[toggle ^ 1];
202 exec("/bin/diff", dargv);
203 fprint(2, "can't exec diff: %r\n");
206 fprint(2, "can't fork diff: %r\n");
209 while(waitpid() != -1)
214 print("%s %s %lld [%s]\n", prtime(dir->mtime), buf, dir->length, dir->muid);
223 lastbefore(ulong t, char *f, char *b, char *ndump)
233 print("%ld lastbefore %s\n", t0, f);
235 for(try=0; try<30; try++) {
237 sprint(b, "/n/%s/%.4d/%.2d%.2d", ndump,
238 tm->year+1900, tm->mon+1, tm->mday);
244 if(dir==nil || mtime > t0) {
246 print("%ld earlier %s\n", mtime, b);
250 if(strstr(ndump, "snap")){
254 n = dirreadall(fd, &dir);
258 for(i = n-1; i > 0; i--){
259 if(dir[i].mtime > t0)
262 sprint(b, "/n/%s/%.4d/%.2d%.2d/%s%s", ndump,
263 tm->year+1900, tm->mon+1, tm->mday, dir[i].name, f);
266 for(vers=0;; vers++) {
267 sprint(b, "/n/%s/%.4d/%.2d%.2d%d", ndump,
268 tm->year+1900, tm->mon+1, tm->mday, vers+1);
274 if(dir==nil || mtime > t0)
277 print("%ld later %s\n", mtime, b);
279 sprint(b, "/n/%s/%.4d/%.2d%.2d%s", ndump,
280 tm->year+1900, tm->mon+1, tm->mday, f);
282 sprint(b, "/n/%s/%.4d/%.2d%.2d%d%s", ndump,
283 tm->year+1900, tm->mon+1, tm->mday, vers, f);
287 strcpy(b, "XXX"); /* error */
293 static char buf[100];
302 memcpy(buf, b+4, 24);
318 if(s[i] < '0' || s[i] > '9') {
319 fprint(2, "bad start time: %s\n", s);
323 yr = (s[0]-'0')*10 + s[1]-'0';
324 mo = (s[2]-'0')*10 + s[3]-'0' - 1;
325 da = (s[4]-'0')*10 + s[5]-'0';
328 }else if(strlen(s)==8){
329 yr = (((s[0]-'0')*10 + s[1]-'0')*10 + s[2]-'0')*10 + s[3]-'0';
331 mo = (s[4]-'0')*10 + s[5]-'0' - 1;
332 da = (s[6]-'0')*10 + s[7]-'0';
334 fprint(2, "bad start time: %s\n", s);
339 for(i=0; i<50; i++) {
340 tm = localtime(t+dt);
342 (yr == tm->year && mo > tm->mon) ||
343 (yr == tm->year && mo == tm->mon) && da > tm->mday) {
351 t += HOUR(12); /* .5 day to get to noon of argument */