thist.c - plan9port - [fork] Plan 9 from user space
 (HTM) git clone git://src.adamsgaard.dk/plan9port
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
       thist.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 }