aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/hist.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2005-07-13 14:03:30 +0000
committerrsc <devnull@localhost>2005-07-13 14:03:30 +0000
commite3769d22f79c3f33c4b4223a833d087d7620a491 (patch)
treebf0984f6a96097f60f241cb3d5e78b3d41366ac4 /src/cmd/hist.c
parent2e3b80968606dfa31a6b8981764e0f79d35068c6 (diff)
downloadplan9port-e3769d22f79c3f33c4b4223a833d087d7620a491.tar.gz
plan9port-e3769d22f79c3f33c4b4223a833d087d7620a491.tar.bz2
plan9port-e3769d22f79c3f33c4b4223a833d087d7620a491.zip
move hist
Diffstat (limited to 'src/cmd/hist.c')
-rw-r--r--src/cmd/hist.c280
1 files changed, 280 insertions, 0 deletions
diff --git a/src/cmd/hist.c b/src/cmd/hist.c
new file mode 100644
index 00000000..18e66909
--- /dev/null
+++ b/src/cmd/hist.c
@@ -0,0 +1,280 @@
+#include <u.h>
+#include <libc.h>
+#include <ctype.h>
+
+#define MINUTE(x) ((long)(x)*60L)
+#define HOUR(x) (MINUTE(x)*60L)
+#define YEAR(x) (HOUR(x)*24L*360L)
+
+int verb;
+int uflag;
+int force;
+int diff;
+int diffb;
+char* sflag;
+char *sys;
+
+void ysearch(char*);
+long starttime(char*);
+void lastbefore(ulong, char*, char*, char*);
+char* prtime(ulong);
+
+int
+main(int argc, char *argv[])
+{
+ int i;
+
+ sys = sysname();
+ if(strncmp(sys, "amsterdam", 9) == 0) /* BUG */
+ sys = "am";
+
+ ARGBEGIN {
+ default:
+ goto usage;
+ case 'v':
+ verb = 1;
+ break;
+ case 'f':
+ force = 1;
+ break;
+ case 'd':
+ diff = 1;
+ break;
+ case 'b':
+ diffb = 1;
+ break;
+ case 's':
+ sflag = ARGF();
+ break;
+ case 'u':
+ uflag = 1;
+ break;
+ } ARGEND
+
+ if(argc == 0) {
+ usage:
+ fprint(2, "usage: hist [-bdfuv] [-s yyyymmdd] files\n");
+ exits(0);
+ }
+
+ for(i=0; i<argc; i++)
+ ysearch(argv[i]);
+ exits(0);
+ return 0;
+}
+
+int
+strprefix(char *a, char *aa)
+{
+ return memcmp(a, aa, strlen(a)) == 0;
+}
+
+void
+ysearch(char *file)
+{
+ char *ndump;
+ char fil[400], buf[500], nbuf[100], pair[2][500], *p;
+ Tm *tm;
+ Dir *dir, *d;
+ ulong otime, dt;
+ int toggle, started, missing;
+
+ started = 0;
+ dir = dirstat(file);
+ if(dir == nil)
+ fprint(2, "history: warning: %s does not exist\n", file);
+ else{
+ print("%s %s %lld\n", prtime(dir->mtime), file, dir->length);
+ started = 1;
+ strcpy(pair[1], file);
+ }
+ free(dir);
+ fil[0] = 0;
+ if(file[0] != '/') {
+ getwd(strchr(fil, 0), 100);
+ strcat(fil, "/");
+ }
+ strcat(fil, file);
+ cleanname(fil);
+
+ sprint(nbuf, "/dump/%s", sys);
+ ndump = nbuf;
+
+ tm = localtime(time(0));
+ sprint(buf, "%s/%.4d/", ndump, tm->year+1900);
+ if(access(buf, AREAD) < 0){
+ print("cannot access %s\n", buf);
+ return;
+ }
+
+ otime = starttime(sflag);
+ toggle = 0;
+ for(;;) {
+ lastbefore(otime, fil, buf, ndump);
+ dir = dirstat(buf);
+ if(dir == nil) {
+ if(!force)
+ return;
+ dir = malloc(sizeof(Dir));
+ nulldir(dir);
+ dir->mtime = otime + 1;
+ }
+ dt = HOUR(12);
+ missing = 0;
+ while(otime <= dir->mtime){
+ if(verb)
+ print("backup %ld, %ld\n", dir->mtime, otime-dt);
+ lastbefore(otime-dt, fil, buf, ndump);
+ d = dirstat(buf);
+ if(d == nil){
+ if(!force)
+ return;
+ if(!missing)
+ print("removed %s\n", buf);
+ missing = 1;
+ }else{
+ free(dir);
+ dir = d;
+ }
+ dt += HOUR(12);
+ }
+ strcpy(pair[toggle], buf);
+ if(diff && started){
+ if(verb)
+ print("diff %s %s\n", pair[toggle^1], pair[toggle]);
+ switch(rfork(RFFDG|RFPROC)){
+ case 0:
+ execlp("diff", "diff", diffb ? "-cb" : "-c", pair[toggle], pair[toggle ^ 1], 0);
+ fprint(2, "can't exec diff: %r\n");
+ exits(0);
+ case -1:
+ fprint(2, "can't fork diff: %r\n");
+ break;
+ default:
+ while(waitpid() != -1)
+ ;
+ break;
+ }
+ }
+ print("%s %s %lld\n", prtime(dir->mtime), buf, dir->length);
+ toggle ^= 1;
+ started = 1;
+ otime = dir->mtime;
+ free(dir);
+ }
+}
+
+void
+lastbefore(ulong t, char *f, char *b, char *ndump)
+{
+ Tm *tm;
+ Dir *dir;
+ int vers, try;
+ ulong t0, mtime;
+
+ t0 = t;
+ if(verb)
+ print("%ld lastbefore %s\n", t0, f);
+ mtime = 0;
+ for(try=0; try<10; try++) {
+ tm = localtime(t);
+ sprint(b, "%s/%.4d/%.2d%.2d", ndump,
+ tm->year+1900, tm->mon+1, tm->mday);
+ dir = dirstat(b);
+ if(dir){
+ mtime = dir->mtime;
+ free(dir);
+ }
+ if(dir==nil || mtime > t0) {
+ if(verb)
+ print("%ld earlier %s\n", mtime, b);
+ t -= HOUR(24);
+ continue;
+ }
+ for(vers=0;; vers++) {
+ sprint(b, "%s/%.4d/%.2d%.2d%d", ndump,
+ tm->year+1900, tm->mon+1, tm->mday, vers+1);
+ dir = dirstat(b);
+ if(dir){
+ mtime = dir->mtime;
+ free(dir);
+ }
+ if(dir==nil || mtime > t0)
+ break;
+ if(verb)
+ print("%ld later %s\n", mtime, b);
+ }
+ sprint(b, "%s/%.4d/%.2d%.2d%s", ndump,
+ tm->year+1900, tm->mon+1, tm->mday, f);
+ if(vers)
+ sprint(b, "%s/%.4d/%.2d%.2d%d%s", ndump,
+ tm->year+1900, tm->mon+1, tm->mday, vers, f);
+ return;
+ }
+ strcpy(b, "XXX"); /* error */
+}
+
+char*
+prtime(ulong t)
+{
+ static char buf[100];
+ char *b;
+ Tm *tm;
+
+ if(uflag)
+ tm = gmtime(t);
+ else
+ tm = localtime(t);
+ b = asctime(tm);
+ memcpy(buf, b+4, 24);
+ buf[24] = 0;
+ return buf;
+}
+
+long
+starttime(char *s)
+{
+ Tm *tm;
+ long t, dt;
+ int i, yr, mo, da;
+
+ t = time(0);
+ if(s == 0)
+ return t;
+ for(i=0; s[i]; i++)
+ if(s[i] < '0' || s[i] > '9') {
+ fprint(2, "bad start time: %s\n", s);
+ return t;
+ }
+ if(strlen(s)==6){
+ yr = (s[0]-'0')*10 + s[1]-'0';
+ mo = (s[2]-'0')*10 + s[3]-'0' - 1;
+ da = (s[4]-'0')*10 + s[5]-'0';
+ if(yr < 70)
+ yr += 100;
+ }else if(strlen(s)==8){
+ yr = (((s[0]-'0')*10 + s[1]-'0')*10 + s[2]-'0')*10 + s[3]-'0';
+ yr -= 1900;
+ mo = (s[4]-'0')*10 + s[5]-'0' - 1;
+ da = (s[6]-'0')*10 + s[7]-'0';
+ }else{
+ fprint(2, "bad start time: %s\n", s);
+ return t;
+ }
+ t = 0;
+ dt = YEAR(10);
+ for(i=0; i<50; i++) {
+ tm = localtime(t+dt);
+ if(yr > tm->year ||
+ (yr == tm->year && mo > tm->mon) ||
+ (yr == tm->year && mo == tm->mon) && da > tm->mday) {
+ t += dt;
+ continue;
+ }
+ dt /= 2;
+ if(dt == 0)
+ break;
+ }
+ t += HOUR(12); /* .5 day to get to noon of argument */
+ return t;
+}