Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <ctype.h>
5 #define MINUTE(x) ((long)(x)*60L)
6 #define HOUR(x) (MINUTE(x)*60L)
7 #define YEAR(x) (HOUR(x)*24L*360L)
9 int verb;
10 int uflag;
11 int force;
12 int diff;
13 int diffb;
14 char* sflag;
15 char *sys;
17 void ysearch(char*);
18 long starttime(char*);
19 void lastbefore(ulong, char*, char*, char*);
20 char* prtime(ulong);
22 int
23 main(int argc, char *argv[])
24 {
25 int i;
27 sys = sysname();
28 if(strncmp(sys, "amsterdam", 9) == 0) /* BUG */
29 sys = "am";
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
54 if(argc == 0) {
55 usage:
56 fprint(2, "usage: hist [-bdfuv] [-s yyyymmdd] files\n");
57 exits(0);
58 }
60 for(i=0; i<argc; i++)
61 ysearch(argv[i]);
62 exits(0);
63 return 0;
64 }
66 int
67 strprefix(char *a, char *aa)
68 {
69 return memcmp(a, aa, strlen(a)) == 0;
70 }
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;
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);
100 sprint(nbuf, "/dump/%s", sys);
101 ndump = nbuf;
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;
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;
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;
139 dt += HOUR(12);
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)
156 break;
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);
167 void
168 lastbefore(ulong t, char *f, char *b, char *ndump)
170 Tm *tm;
171 Dir *dir;
172 int vers, try;
173 ulong t0, mtime;
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);
188 if(dir==nil || mtime > t0) {
189 if(verb)
190 print("%ld earlier %s\n", mtime, b);
191 t -= HOUR(24);
192 continue;
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);
202 if(dir==nil || mtime > t0)
203 break;
204 if(verb)
205 print("%ld later %s\n", mtime, b);
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;
214 strcpy(b, "XXX"); /* error */
217 char*
218 prtime(ulong t)
220 static char buf[100];
221 char *b;
222 Tm *tm;
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;
234 long
235 starttime(char *s)
237 Tm *tm;
238 long t, dt;
239 int i, yr, mo, da;
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;
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;
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;
274 dt /= 2;
275 if(dt == 0)
276 break;
278 t += HOUR(12); /* .5 day to get to noon of argument */
279 return t;