xref: /plan9/sys/src/cmd/test.c (revision 728c92e567f21a49f3c62100b4a1865b6c377f7d)
13e12c5d1SDavid du Colombier /*
23e12c5d1SDavid du Colombier  * POSIX standard
33e12c5d1SDavid du Colombier  *	test expression
43e12c5d1SDavid du Colombier  *	[ expression ]
59a747e4fSDavid du Colombier  *
69a747e4fSDavid du Colombier  * Plan 9 additions:
79a747e4fSDavid du Colombier  *	-A file exists and is append-only
89a747e4fSDavid du Colombier  *	-L file exists and is exclusive-use
9b7327ca2SDavid du Colombier  *	-T file exists and is temporary
103e12c5d1SDavid du Colombier  */
113e12c5d1SDavid du Colombier 
123e12c5d1SDavid du Colombier #include <u.h>
133e12c5d1SDavid du Colombier #include <libc.h>
144cffb70cSDavid du Colombier 
153e12c5d1SDavid du Colombier #define EQ(a,b)	((tmp=a)==0?0:(strcmp(tmp,b)==0))
163e12c5d1SDavid du Colombier 
173e12c5d1SDavid du Colombier int	ap;
183e12c5d1SDavid du Colombier int	ac;
193e12c5d1SDavid du Colombier char	**av;
203e12c5d1SDavid du Colombier char	*tmp;
213e12c5d1SDavid du Colombier 
223e12c5d1SDavid du Colombier void	synbad(char *, char *);
233e12c5d1SDavid du Colombier int	fsizep(char *);
243e12c5d1SDavid du Colombier int	isdir(char *);
253e12c5d1SDavid du Colombier int	isreg(char *);
263e12c5d1SDavid du Colombier int	isatty(int);
273e12c5d1SDavid du Colombier int	isint(char *, int *);
28cd1a0026SDavid du Colombier int	isolder(char *, char *);
2980b7488dSDavid du Colombier int	isolderthan(char *, char *);
3080b7488dSDavid du Colombier int	isnewerthan(char *, char *);
319a747e4fSDavid du Colombier int	hasmode(char *, ulong);
323e12c5d1SDavid du Colombier int	tio(char *, int);
333e12c5d1SDavid du Colombier int	e(void), e1(void), e2(void), e3(void);
341066d6deSDavid du Colombier char	*nxtarg(int);
353e12c5d1SDavid du Colombier 
363e12c5d1SDavid du Colombier void
main(int argc,char * argv[])373e12c5d1SDavid du Colombier main(int argc, char *argv[])
383e12c5d1SDavid du Colombier {
391066d6deSDavid du Colombier 	int r;
401066d6deSDavid du Colombier 	char *c;
413e12c5d1SDavid du Colombier 
423e12c5d1SDavid du Colombier 	ac = argc; av = argv; ap = 1;
433e12c5d1SDavid du Colombier 	if(EQ(argv[0],"[")) {
443e12c5d1SDavid du Colombier 		if(!EQ(argv[--ac],"]"))
453e12c5d1SDavid du Colombier 			synbad("] missing","");
463e12c5d1SDavid du Colombier 	}
473e12c5d1SDavid du Colombier 	argv[ac] = 0;
484cffb70cSDavid du Colombier 	if (ac<=1)
494cffb70cSDavid du Colombier 		exits("usage");
501066d6deSDavid du Colombier 	r = e();
514cffb70cSDavid du Colombier 	/*
524cffb70cSDavid du Colombier 	 * nice idea but short-circuit -o and -a operators may have
534cffb70cSDavid du Colombier 	 * not consumed their right-hand sides.
544cffb70cSDavid du Colombier 	 */
554cffb70cSDavid du Colombier 	if(0 && (c = nxtarg(1)) != nil)
561066d6deSDavid du Colombier 		synbad("unexpected operator/operand: ", c);
571066d6deSDavid du Colombier 	exits(r?0:"false");
583e12c5d1SDavid du Colombier }
593e12c5d1SDavid du Colombier 
603e12c5d1SDavid du Colombier char *
nxtarg(int mt)613e12c5d1SDavid du Colombier nxtarg(int mt)
623e12c5d1SDavid du Colombier {
633e12c5d1SDavid du Colombier 	if(ap>=ac){
643e12c5d1SDavid du Colombier 		if(mt){
653e12c5d1SDavid du Colombier 			ap++;
663e12c5d1SDavid du Colombier 			return(0);
673e12c5d1SDavid du Colombier 		}
683e12c5d1SDavid du Colombier 		synbad("argument expected","");
693e12c5d1SDavid du Colombier 	}
703e12c5d1SDavid du Colombier 	return(av[ap++]);
713e12c5d1SDavid du Colombier }
723e12c5d1SDavid du Colombier 
733e12c5d1SDavid du Colombier int
nxtintarg(int * pans)743e12c5d1SDavid du Colombier nxtintarg(int *pans)
753e12c5d1SDavid du Colombier {
763e12c5d1SDavid du Colombier 	if(ap<ac && isint(av[ap], pans)){
773e12c5d1SDavid du Colombier 		ap++;
783e12c5d1SDavid du Colombier 		return 1;
793e12c5d1SDavid du Colombier 	}
803e12c5d1SDavid du Colombier 	return 0;
813e12c5d1SDavid du Colombier }
823e12c5d1SDavid du Colombier 
833e12c5d1SDavid du Colombier int
e(void)844cffb70cSDavid du Colombier e(void)
854cffb70cSDavid du Colombier {
863e12c5d1SDavid du Colombier 	int p1;
873e12c5d1SDavid du Colombier 
883e12c5d1SDavid du Colombier 	p1 = e1();
894cffb70cSDavid du Colombier 	if (EQ(nxtarg(1), "-o"))
904cffb70cSDavid du Colombier 		return(p1 || e());
913e12c5d1SDavid du Colombier 	ap--;
923e12c5d1SDavid du Colombier 	return(p1);
933e12c5d1SDavid du Colombier }
943e12c5d1SDavid du Colombier 
953e12c5d1SDavid du Colombier int
e1(void)964cffb70cSDavid du Colombier e1(void)
974cffb70cSDavid du Colombier {
983e12c5d1SDavid du Colombier 	int p1;
993e12c5d1SDavid du Colombier 
1003e12c5d1SDavid du Colombier 	p1 = e2();
1014cffb70cSDavid du Colombier 	if (EQ(nxtarg(1), "-a"))
1024cffb70cSDavid du Colombier 		return (p1 && e1());
1033e12c5d1SDavid du Colombier 	ap--;
1043e12c5d1SDavid du Colombier 	return(p1);
1053e12c5d1SDavid du Colombier }
1063e12c5d1SDavid du Colombier 
1073e12c5d1SDavid du Colombier int
e2(void)1084cffb70cSDavid du Colombier e2(void)
1094cffb70cSDavid du Colombier {
1103e12c5d1SDavid du Colombier 	if (EQ(nxtarg(0), "!"))
1117dd7cddfSDavid du Colombier 		return(!e2());
1123e12c5d1SDavid du Colombier 	ap--;
1133e12c5d1SDavid du Colombier 	return(e3());
1143e12c5d1SDavid du Colombier }
1153e12c5d1SDavid du Colombier 
1163e12c5d1SDavid du Colombier int
e3(void)1174cffb70cSDavid du Colombier e3(void)
1184cffb70cSDavid du Colombier {
1194cffb70cSDavid du Colombier 	int p1, int1, int2;
1204cffb70cSDavid du Colombier 	char *a, *p2;
1213e12c5d1SDavid du Colombier 
1223e12c5d1SDavid du Colombier 	a = nxtarg(0);
1233e12c5d1SDavid du Colombier 	if(EQ(a, "(")) {
1243e12c5d1SDavid du Colombier 		p1 = e();
1254cffb70cSDavid du Colombier 		if(!EQ(nxtarg(0), ")"))
1264cffb70cSDavid du Colombier 			synbad(") expected","");
1273e12c5d1SDavid du Colombier 		return(p1);
1283e12c5d1SDavid du Colombier 	}
1293e12c5d1SDavid du Colombier 
1309a747e4fSDavid du Colombier 	if(EQ(a, "-A"))
1319a747e4fSDavid du Colombier 		return(hasmode(nxtarg(0), DMAPPEND));
1329a747e4fSDavid du Colombier 
1339a747e4fSDavid du Colombier 	if(EQ(a, "-L"))
1349a747e4fSDavid du Colombier 		return(hasmode(nxtarg(0), DMEXCL));
1359a747e4fSDavid du Colombier 
136b7327ca2SDavid du Colombier 	if(EQ(a, "-T"))
137b7327ca2SDavid du Colombier 		return(hasmode(nxtarg(0), DMTMP));
138b7327ca2SDavid du Colombier 
1393e12c5d1SDavid du Colombier 	if(EQ(a, "-f"))
1403e12c5d1SDavid du Colombier 		return(isreg(nxtarg(0)));
1413e12c5d1SDavid du Colombier 
1423e12c5d1SDavid du Colombier 	if(EQ(a, "-d"))
1433e12c5d1SDavid du Colombier 		return(isdir(nxtarg(0)));
1443e12c5d1SDavid du Colombier 
1453e12c5d1SDavid du Colombier 	if(EQ(a, "-r"))
1463e12c5d1SDavid du Colombier 		return(tio(nxtarg(0), 4));
1473e12c5d1SDavid du Colombier 
1483e12c5d1SDavid du Colombier 	if(EQ(a, "-w"))
1493e12c5d1SDavid du Colombier 		return(tio(nxtarg(0), 2));
1503e12c5d1SDavid du Colombier 
1513e12c5d1SDavid du Colombier 	if(EQ(a, "-x"))
1523e12c5d1SDavid du Colombier 		return(tio(nxtarg(0), 1));
1533e12c5d1SDavid du Colombier 
1543e12c5d1SDavid du Colombier 	if(EQ(a, "-e"))
1553e12c5d1SDavid du Colombier 		return(tio(nxtarg(0), 0));
1563e12c5d1SDavid du Colombier 
1573e12c5d1SDavid du Colombier 	if(EQ(a, "-c"))
1583e12c5d1SDavid du Colombier 		return(0);
1593e12c5d1SDavid du Colombier 
1603e12c5d1SDavid du Colombier 	if(EQ(a, "-b"))
1613e12c5d1SDavid du Colombier 		return(0);
1623e12c5d1SDavid du Colombier 
1633e12c5d1SDavid du Colombier 	if(EQ(a, "-u"))
1643e12c5d1SDavid du Colombier 		return(0);
1653e12c5d1SDavid du Colombier 
1663e12c5d1SDavid du Colombier 	if(EQ(a, "-g"))
1673e12c5d1SDavid du Colombier 		return(0);
1683e12c5d1SDavid du Colombier 
1693e12c5d1SDavid du Colombier 	if(EQ(a, "-s"))
1703e12c5d1SDavid du Colombier 		return(fsizep(nxtarg(0)));
1713e12c5d1SDavid du Colombier 
1723e12c5d1SDavid du Colombier 	if(EQ(a, "-t"))
1731066d6deSDavid du Colombier 		if(ap>=ac)
1743e12c5d1SDavid du Colombier 			return(isatty(1));
1751066d6deSDavid du Colombier 		else if(nxtintarg(&int1))
1763e12c5d1SDavid du Colombier 			return(isatty(int1));
1771066d6deSDavid du Colombier 		else
1781066d6deSDavid du Colombier 			synbad("not a valid file descriptor number ", "");
1793e12c5d1SDavid du Colombier 
1803e12c5d1SDavid du Colombier 	if(EQ(a, "-n"))
1813e12c5d1SDavid du Colombier 		return(!EQ(nxtarg(0), ""));
1823e12c5d1SDavid du Colombier 	if(EQ(a, "-z"))
1833e12c5d1SDavid du Colombier 		return(EQ(nxtarg(0), ""));
1843e12c5d1SDavid du Colombier 
1853e12c5d1SDavid du Colombier 	p2 = nxtarg(1);
1863e12c5d1SDavid du Colombier 	if (p2==0)
1873e12c5d1SDavid du Colombier 		return(!EQ(a,""));
1883e12c5d1SDavid du Colombier 	if(EQ(p2, "="))
1893e12c5d1SDavid du Colombier 		return(EQ(nxtarg(0), a));
1903e12c5d1SDavid du Colombier 
1913e12c5d1SDavid du Colombier 	if(EQ(p2, "!="))
1923e12c5d1SDavid du Colombier 		return(!EQ(nxtarg(0), a));
1933e12c5d1SDavid du Colombier 
194cd1a0026SDavid du Colombier 	if(EQ(p2, "-older"))
195cd1a0026SDavid du Colombier 		return(isolder(nxtarg(0), a));
196cd1a0026SDavid du Colombier 
19780b7488dSDavid du Colombier 	if(EQ(p2, "-ot"))
19880b7488dSDavid du Colombier 		return(isolderthan(nxtarg(0), a));
19980b7488dSDavid du Colombier 
20080b7488dSDavid du Colombier 	if(EQ(p2, "-nt"))
20180b7488dSDavid du Colombier 		return(isnewerthan(nxtarg(0), a));
20280b7488dSDavid du Colombier 
2033e12c5d1SDavid du Colombier 	if(!isint(a, &int1))
2041066d6deSDavid du Colombier 		synbad("unexpected operator/operand: ", p2);
2053e12c5d1SDavid du Colombier 
2063e12c5d1SDavid du Colombier 	if(nxtintarg(&int2)){
2073e12c5d1SDavid du Colombier 		if(EQ(p2, "-eq"))
2083e12c5d1SDavid du Colombier 			return(int1==int2);
2093e12c5d1SDavid du Colombier 		if(EQ(p2, "-ne"))
2103e12c5d1SDavid du Colombier 			return(int1!=int2);
2113e12c5d1SDavid du Colombier 		if(EQ(p2, "-gt"))
2123e12c5d1SDavid du Colombier 			return(int1>int2);
2133e12c5d1SDavid du Colombier 		if(EQ(p2, "-lt"))
2143e12c5d1SDavid du Colombier 			return(int1<int2);
2153e12c5d1SDavid du Colombier 		if(EQ(p2, "-ge"))
2163e12c5d1SDavid du Colombier 			return(int1>=int2);
2173e12c5d1SDavid du Colombier 		if(EQ(p2, "-le"))
2183e12c5d1SDavid du Colombier 			return(int1<=int2);
2193e12c5d1SDavid du Colombier 	}
2203e12c5d1SDavid du Colombier 
2213e12c5d1SDavid du Colombier 	synbad("unknown operator ",p2);
2223e12c5d1SDavid du Colombier 	return 0;		/* to shut ken up */
2233e12c5d1SDavid du Colombier }
2243e12c5d1SDavid du Colombier 
2253e12c5d1SDavid du Colombier int
tio(char * a,int f)2263e12c5d1SDavid du Colombier tio(char *a, int f)
2273e12c5d1SDavid du Colombier {
2283e12c5d1SDavid du Colombier 	return access (a, f) >= 0;
2293e12c5d1SDavid du Colombier }
2303e12c5d1SDavid du Colombier 
231055c7668SDavid du Colombier /*
232055c7668SDavid du Colombier  * note that the name strings pointed to by Dir members are
233055c7668SDavid du Colombier  * allocated with the Dir itself (by the same call to malloc),
234055c7668SDavid du Colombier  * but are not included in sizeof(Dir), so copying a Dir won't
235055c7668SDavid du Colombier  * copy the strings it points to.
236055c7668SDavid du Colombier  */
2379a747e4fSDavid du Colombier 
2389a747e4fSDavid du Colombier int
hasmode(char * f,ulong m)2399a747e4fSDavid du Colombier hasmode(char *f, ulong m)
2409a747e4fSDavid du Colombier {
241055c7668SDavid du Colombier 	int r;
242055c7668SDavid du Colombier 	Dir *dir;
2439a747e4fSDavid du Colombier 
244055c7668SDavid du Colombier 	dir = dirstat(f);
245055c7668SDavid du Colombier 	if (dir == nil)
246055c7668SDavid du Colombier 		return 0;
247055c7668SDavid du Colombier 	r = (dir->mode & m) != 0;
248055c7668SDavid du Colombier 	free(dir);
249055c7668SDavid du Colombier 	return r;
2509a747e4fSDavid du Colombier }
2519a747e4fSDavid du Colombier 
2523e12c5d1SDavid du Colombier int
isdir(char * f)2533e12c5d1SDavid du Colombier isdir(char *f)
2543e12c5d1SDavid du Colombier {
255055c7668SDavid du Colombier 	return hasmode(f, DMDIR);
2563e12c5d1SDavid du Colombier }
2573e12c5d1SDavid du Colombier 
2583e12c5d1SDavid du Colombier int
isreg(char * f)2593e12c5d1SDavid du Colombier isreg(char *f)
2603e12c5d1SDavid du Colombier {
261014ad43fSDavid du Colombier 	int r;
262014ad43fSDavid du Colombier 	Dir *dir;
263014ad43fSDavid du Colombier 
264014ad43fSDavid du Colombier 	dir = dirstat(f);
265014ad43fSDavid du Colombier 	if (dir == nil)
266014ad43fSDavid du Colombier 		return 0;
267014ad43fSDavid du Colombier 	r = (dir->mode & DMDIR) == 0;
268014ad43fSDavid du Colombier 	free(dir);
269014ad43fSDavid du Colombier 	return r;
2703e12c5d1SDavid du Colombier }
2713e12c5d1SDavid du Colombier 
2723e12c5d1SDavid du Colombier int
isatty(int fd)2733e12c5d1SDavid du Colombier isatty(int fd)
2743e12c5d1SDavid du Colombier {
275055c7668SDavid du Colombier 	int r;
276055c7668SDavid du Colombier 	Dir *d1, *d2;
2773e12c5d1SDavid du Colombier 
278055c7668SDavid du Colombier 	d1 = dirfstat(fd);
279055c7668SDavid du Colombier 	d2 = dirstat("/dev/cons");
280055c7668SDavid du Colombier 	if (d1 == nil || d2 == nil)
281055c7668SDavid du Colombier 		r = 0;
282055c7668SDavid du Colombier 	else
283055c7668SDavid du Colombier 		r = d1->type == d2->type && d1->dev == d2->dev &&
284055c7668SDavid du Colombier 			d1->qid.path == d2->qid.path;
285055c7668SDavid du Colombier 	free(d1);
286055c7668SDavid du Colombier 	free(d2);
287055c7668SDavid du Colombier 	return r;
2883e12c5d1SDavid du Colombier }
2893e12c5d1SDavid du Colombier 
2903e12c5d1SDavid du Colombier int
fsizep(char * f)2913e12c5d1SDavid du Colombier fsizep(char *f)
2923e12c5d1SDavid du Colombier {
293055c7668SDavid du Colombier 	int r;
294055c7668SDavid du Colombier 	Dir *dir;
2959a747e4fSDavid du Colombier 
296055c7668SDavid du Colombier 	dir = dirstat(f);
297055c7668SDavid du Colombier 	if (dir == nil)
298055c7668SDavid du Colombier 		return 0;
299055c7668SDavid du Colombier 	r = dir->length > 0;
300055c7668SDavid du Colombier 	free(dir);
301055c7668SDavid du Colombier 	return r;
3023e12c5d1SDavid du Colombier }
3033e12c5d1SDavid du Colombier 
3043e12c5d1SDavid du Colombier void
synbad(char * s1,char * s2)3053e12c5d1SDavid du Colombier synbad(char *s1, char *s2)
3063e12c5d1SDavid du Colombier {
3073e12c5d1SDavid du Colombier 	int len;
3083e12c5d1SDavid du Colombier 
3093e12c5d1SDavid du Colombier 	write(2, "test: ", 6);
3103e12c5d1SDavid du Colombier 	if ((len = strlen(s1)) != 0)
3113e12c5d1SDavid du Colombier 		write(2, s1, len);
3123e12c5d1SDavid du Colombier 	if ((len = strlen(s2)) != 0)
3133e12c5d1SDavid du Colombier 		write(2, s2, len);
3143e12c5d1SDavid du Colombier 	write(2, "\n", 1);
3153e12c5d1SDavid du Colombier 	exits("bad syntax");
3163e12c5d1SDavid du Colombier }
3173e12c5d1SDavid du Colombier 
3183e12c5d1SDavid du Colombier int
isint(char * s,int * pans)3193e12c5d1SDavid du Colombier isint(char *s, int *pans)
3203e12c5d1SDavid du Colombier {
3213e12c5d1SDavid du Colombier 	char *ep;
3223e12c5d1SDavid du Colombier 
3233e12c5d1SDavid du Colombier 	*pans = strtol(s, &ep, 0);
3243e12c5d1SDavid du Colombier 	return (*ep == 0);
3253e12c5d1SDavid du Colombier }
326cd1a0026SDavid du Colombier 
327cd1a0026SDavid du Colombier int
isolder(char * pin,char * f)328cd1a0026SDavid du Colombier isolder(char *pin, char *f)
329cd1a0026SDavid du Colombier {
330*728c92e5SDavid du Colombier 	int r, rel;
331cd1a0026SDavid du Colombier 	ulong n, m;
332055c7668SDavid du Colombier 	char *p = pin;
333055c7668SDavid du Colombier 	Dir *dir;
334cd1a0026SDavid du Colombier 
335055c7668SDavid du Colombier 	dir = dirstat(f);
336055c7668SDavid du Colombier 	if (dir == nil)
337055c7668SDavid du Colombier 		return 0;
338cd1a0026SDavid du Colombier 
339cd1a0026SDavid du Colombier 	/* parse time */
340cd1a0026SDavid du Colombier 	n = 0;
341*728c92e5SDavid du Colombier 	rel = 0;
342cd1a0026SDavid du Colombier 	while(*p){
343cd1a0026SDavid du Colombier 		m = strtoul(p, &p, 0);
344cd1a0026SDavid du Colombier 		switch(*p){
345cd1a0026SDavid du Colombier 		case 0:
346cd1a0026SDavid du Colombier 			n = m;
347cd1a0026SDavid du Colombier 			break;
348cd1a0026SDavid du Colombier 		case 'y':
349cd1a0026SDavid du Colombier 			m *= 12;
350cd1a0026SDavid du Colombier 			/* fall through */
351cd1a0026SDavid du Colombier 		case 'M':
352cd1a0026SDavid du Colombier 			m *= 30;
353cd1a0026SDavid du Colombier 			/* fall through */
354cd1a0026SDavid du Colombier 		case 'd':
355cd1a0026SDavid du Colombier 			m *= 24;
356cd1a0026SDavid du Colombier 			/* fall through */
357cd1a0026SDavid du Colombier 		case 'h':
358cd1a0026SDavid du Colombier 			m *= 60;
359cd1a0026SDavid du Colombier 			/* fall through */
360cd1a0026SDavid du Colombier 		case 'm':
361cd1a0026SDavid du Colombier 			m *= 60;
362cd1a0026SDavid du Colombier 			/* fall through */
363cd1a0026SDavid du Colombier 		case 's':
364cd1a0026SDavid du Colombier 			n += m;
365cd1a0026SDavid du Colombier 			p++;
366*728c92e5SDavid du Colombier 			rel = 1;
367cd1a0026SDavid du Colombier 			break;
368cd1a0026SDavid du Colombier 		default:
369cd1a0026SDavid du Colombier 			synbad("bad time syntax, ", pin);
370cd1a0026SDavid du Colombier 		}
371cd1a0026SDavid du Colombier 	}
372*728c92e5SDavid du Colombier 	if (!rel)
373*728c92e5SDavid du Colombier 		m = n;
374*728c92e5SDavid du Colombier 	else{
375*728c92e5SDavid du Colombier 		m = time(0);
376*728c92e5SDavid du Colombier 		if (n > m)		/* before epoch? */
377*728c92e5SDavid du Colombier 			m = 0;
378*728c92e5SDavid du Colombier 		else
379*728c92e5SDavid du Colombier 			m -= n;
380*728c92e5SDavid du Colombier 	}
381*728c92e5SDavid du Colombier 	r = dir->mtime < m;
382055c7668SDavid du Colombier 	free(dir);
383055c7668SDavid du Colombier 	return r;
384cd1a0026SDavid du Colombier }
38580b7488dSDavid du Colombier 
38680b7488dSDavid du Colombier int
isolderthan(char * a,char * b)38780b7488dSDavid du Colombier isolderthan(char *a, char *b)
38880b7488dSDavid du Colombier {
389055c7668SDavid du Colombier 	int r;
390055c7668SDavid du Colombier 	Dir *ad, *bd;
39180b7488dSDavid du Colombier 
392055c7668SDavid du Colombier 	ad = dirstat(a);
393055c7668SDavid du Colombier 	bd = dirstat(b);
394055c7668SDavid du Colombier 	if (ad == nil || bd == nil)
395055c7668SDavid du Colombier 		r = 0;
396055c7668SDavid du Colombier 	else
397055c7668SDavid du Colombier 		r = ad->mtime > bd->mtime;
398055c7668SDavid du Colombier 	free(ad);
399055c7668SDavid du Colombier 	free(bd);
400055c7668SDavid du Colombier 	return r;
40180b7488dSDavid du Colombier }
40280b7488dSDavid du Colombier 
40380b7488dSDavid du Colombier int
isnewerthan(char * a,char * b)40480b7488dSDavid du Colombier isnewerthan(char *a, char *b)
40580b7488dSDavid du Colombier {
406055c7668SDavid du Colombier 	int r;
407055c7668SDavid du Colombier 	Dir *ad, *bd;
40880b7488dSDavid du Colombier 
409055c7668SDavid du Colombier 	ad = dirstat(a);
410055c7668SDavid du Colombier 	bd = dirstat(b);
411055c7668SDavid du Colombier 	if (ad == nil || bd == nil)
412055c7668SDavid du Colombier 		r = 0;
413055c7668SDavid du Colombier 	else
414055c7668SDavid du Colombier 		r = ad->mtime < bd->mtime;
415055c7668SDavid du Colombier 	free(ad);
416055c7668SDavid du Colombier 	free(bd);
417055c7668SDavid du Colombier 	return r;
41880b7488dSDavid du Colombier }
419