plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

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 }