find(1) mishandles multiple -newer options - fix included

John P. Linderman jpl at allegra.UUCP
Tue Oct 22 00:30:31 AEST 1985


Index: usr.bin/find.c 4.2BSD

Description:
	Only one -newer option will be correctly processed on a find.
Repeat-By:
	# The following script demonstrates the problem (which also
	# exists on System V and Version 8) and the effect of the fix.
	# The fix also adds the ability to compare on access and
	# inode modification times as well as file modification time,
	# as is also demonstrated in the script.
	$ touch 1
	$ touch 2
	$ touch 3
	$ find . \( -newer 2 -o -newer 3 \) -print
	.
	$ /usr/5bin/find . \( -newer 2 -o -newer 3 \) -print
	.
	$ find . \( -newer 3 -o -newer 2 \) -print
	.
	./3
	$ ./find . \( -newer 2 -o -newer 3 \) -print
	.
	./3
	$ mv 1 4
	$ find . -newer 2 -print
	.
	./3
	$ ./find . -newer 2 -print
	.
	./3
	$ ./find . -newerc 2 -print
	.
	./3
	./4
	$
Fix:
	The following diffs to the BSD 4.2 source correct the problem,
	and add a dozen options.  (Only a few options are genuinely
	useful, but it was cleaner to add them all than to prune out
	the useless ones.)  -newer can be followed by one or two
	occurrences of the letters [acm] to specify which time from the
	stat structure (st_atime, st_ctime or st_mtime -- see stat(2))
	will be used in the comparison.  The first letter, if any,
	determines the time used for the files the find command is
	searching.  The second, if any, determines the time from the
	file that follows the -newer option.  Both default to m, so
	-newer foo, -newerm foo, and -newermm foo are identical.  Note
	that -newerc causes the INODE modification time of the found
	files to be compared to the FILE (not inode) modification time
	of the specified target.  This was done deliberately, because
	it works correctly with the following incremental backup scheme

	touch startstamp
	find ... -newerc laststamp ...
	mv startstamp laststamp

	If the dump dies midstream, laststamp is not changed, so the
	next dump will get all the files this dump would have.  If the
	dump does run to completion, the mv changes the inode
	modification time of startstamp but not the file modification
	time, so the next incremental dump will pick up all the files
	changed after OR DURING this dump, including those whose modes
	or owners were changed or those renamed.

	I don't know if the System V and Version 8 sources are
	identical, but (except for the MAXPATHLEN change), the
	changes appear to be analogous.  The new features are
	particularly useful in conjunction with the System V
	touch command, which allows one to set the modification
	dates of a file to an arbitrary time.  These give
	greater precision and cleaner semantics than the -mtime
	and -atime options (one day since when??).

	John P. Linderman  Department of find bug finders  allegra!jpl

11c11
< char	Pathname[200];
---
> char	Pathname[MAXPATHLEN + 1];
30c30,32
< long	Newer;
---
> #define	NNEW	50
> int	Nnewer;
> time_t	Newer[NNEW];
230c232,234
< 	else if(EQ(a, "-newer")) {
---
> 	else if(strncmp(a, "-newer", 6) == 0) {
> 		char *p =        a + 6;
> 		time_t *t1p, *t2p;
235,236c239,278
< 		Newer = Statb.st_mtime;
< 		return mk(newer, (struct anode *)0, (struct anode *)0);
---
> 		if(Nnewer >= NNEW) {
> 			fprintf(stderr, "find: too many -newer constructs\n");
> 			exit(1);
> 		}
> 		t1p = t2p = &(Statb.st_mtime);
> 		switch (*p) {
> 		case 'm':
> 		    p++;
> 		    break;
> 		case '\0':
> 		    break;
> 		case 'a':
> 		    t1p = &(Statb.st_atime);
> 		    p++;
> 		    break;
> 		case 'c':
> 		    t1p = &(Statb.st_ctime);
> 		    p++;
> 		    break;
> 		}
> 		switch (*p) {
> 		case 'm':
> 		    p++;
> 		    break;
> 		case '\0':
> 		    break;
> 		case 'a':
> 		    t2p = &(Statb.st_atime);
> 		    p++;
> 		    break;
> 		case 'c':
> 		    t2p = &(Statb.st_ctime);
> 		    p++;
> 		    break;
> 		}
> 		if (*p == '\0') {
> 		    Newer[Nnewer] = *t2p;
> 		    return mk(newer, (struct anode *)t1p,
> 				     (struct anode *)(&Newer[Nnewer++]));
> 		}
428c470,471
< newer()
---
> newer(p)
> register struct { int f; time_t *t1, *t2; } *p;
430c473
< 	return Statb.st_mtime > Newer;
---
> 	return *(p->t1) > *(p->t2);



More information about the Comp.unix.wizards mailing list