mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-12-03 14:48:57 +00:00
Enhance test(1) by adding provision to compare any combination of the
access, birth, change and modify times of two files, instead of only being able to compare modify times. The builtin test in sh(1) will automagically acquire the same expansion. Approved by: grog MFC after: 2 weeks
This commit is contained in:
parent
ed88bcd300
commit
293beebc46
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=247274
@ -169,15 +169,65 @@ True if
|
||||
.Ar file
|
||||
exists and is a socket.
|
||||
.It Ar file1 Fl nt Ar file2
|
||||
True if
|
||||
True if both
|
||||
.Ar file1
|
||||
exists and is newer than
|
||||
and
|
||||
.Ar file2
|
||||
exist and
|
||||
.Ar file1
|
||||
is newer than
|
||||
.Ar file2 .
|
||||
.It Ar file1 Fl nt Ns Ar X Ns Ar Y Ar file2
|
||||
True if both
|
||||
.Ar file1
|
||||
and
|
||||
.Ar file2
|
||||
exist and
|
||||
.Ar file1
|
||||
has a more recent last access time
|
||||
.Pq Ar X Ns = Ns Cm a ,
|
||||
inode creation time
|
||||
.Pq Ar X Ns = Ns Cm b ,
|
||||
change time
|
||||
.Pq Ar X Ns = Ns Cm c ,
|
||||
or modification time
|
||||
.Pq Ar X Ns = Ns Cm m
|
||||
than the last access time
|
||||
.Pq Ar Y Ns = Ns Cm a ,
|
||||
inode creation time
|
||||
.Pq Ar Y Ns = Ns Cm b ,
|
||||
change time
|
||||
.Pq Ar Y Ns = Ns Cm c ,
|
||||
or modification time
|
||||
.Pq Ar Y Ns = Ns Cm m
|
||||
of
|
||||
.Ar file2 .
|
||||
Note that
|
||||
.Ic -ntmm
|
||||
is equivalent to
|
||||
.Ic -nt .
|
||||
.It Ar file1 Fl ot Ar file2
|
||||
True if
|
||||
True if both
|
||||
.Ar file1
|
||||
exists and is older than
|
||||
and
|
||||
.Ar file2
|
||||
exist and
|
||||
.Ar file1
|
||||
is older than
|
||||
.Ar file2 .
|
||||
Note that
|
||||
.Ar file1
|
||||
.Ic -ot
|
||||
.Ar file2
|
||||
is equivalent to
|
||||
.Ar file2
|
||||
.Ic -nt
|
||||
.Ar file1
|
||||
.It Ar file1 Fl ot Ns Ar X Ns Ar Y Ar file2
|
||||
Equivalent to
|
||||
.Ar file2
|
||||
.Ic -nt Ns Ar Y Ns Ar X
|
||||
.Ar file1 .
|
||||
.It Ar file1 Fl ef Ar file2
|
||||
True if
|
||||
.Ar file1
|
||||
|
184
bin/test/test.c
184
bin/test/test.c
@ -63,7 +63,7 @@ error(const char *msg, ...)
|
||||
"-u"|"-g"|"-k"|"-s"|"-t"|"-z"|"-n"|"-o"|"-O"|"-G"|"-L"|"-S";
|
||||
|
||||
binary-operator ::= "="|"!="|"-eq"|"-ne"|"-ge"|"-gt"|"-le"|"-lt"|
|
||||
"-nt"|"-ot"|"-ef";
|
||||
"-nt"|"-nt[abcm][abcm]"|"-ot"|"-ot[abcm][abcm])"|"-ef";
|
||||
operand ::= <any legal UNIX file name>
|
||||
*/
|
||||
|
||||
@ -85,8 +85,38 @@ enum token {
|
||||
FILSUID,
|
||||
FILSGID,
|
||||
FILSTCK,
|
||||
FILNT,
|
||||
FILOT,
|
||||
FILNTAA,
|
||||
FILNTAB,
|
||||
FILNTAC,
|
||||
FILNTAM,
|
||||
FILNTBA,
|
||||
FILNTBB,
|
||||
FILNTBC,
|
||||
FILNTBM,
|
||||
FILNTCA,
|
||||
FILNTCB,
|
||||
FILNTCC,
|
||||
FILNTCM,
|
||||
FILNTMA,
|
||||
FILNTMB,
|
||||
FILNTMC,
|
||||
FILNTMM,
|
||||
FILOTAA,
|
||||
FILOTAB,
|
||||
FILOTAC,
|
||||
FILOTAM,
|
||||
FILOTBA,
|
||||
FILOTBB,
|
||||
FILOTBC,
|
||||
FILOTBM,
|
||||
FILOTCA,
|
||||
FILOTCB,
|
||||
FILOTCC,
|
||||
FILOTCM,
|
||||
FILOTMA,
|
||||
FILOTMB,
|
||||
FILOTMC,
|
||||
FILOTMM,
|
||||
FILEQ,
|
||||
FILUID,
|
||||
FILGID,
|
||||
@ -118,9 +148,16 @@ enum token_types {
|
||||
PAREN
|
||||
};
|
||||
|
||||
enum time_types {
|
||||
ATIME,
|
||||
BTIME,
|
||||
CTIME,
|
||||
MTIME
|
||||
};
|
||||
|
||||
static struct t_op {
|
||||
char op_text[4];
|
||||
short op_num, op_type;
|
||||
char op_text[6];
|
||||
char op_num, op_type;
|
||||
} const ops [] = {
|
||||
{"-r", FILRD, UNOP},
|
||||
{"-w", FILWR, UNOP},
|
||||
@ -154,8 +191,40 @@ static struct t_op {
|
||||
{"-gt", INTGT, BINOP},
|
||||
{"-le", INTLE, BINOP},
|
||||
{"-lt", INTLT, BINOP},
|
||||
{"-nt", FILNT, BINOP},
|
||||
{"-ot", FILOT, BINOP},
|
||||
{"-nt", FILNTMM, BINOP},
|
||||
{"-ntaa", FILNTAA, BINOP},
|
||||
{"-ntab", FILNTAB, BINOP},
|
||||
{"-ntac", FILNTAC, BINOP},
|
||||
{"-ntam", FILNTAM, BINOP},
|
||||
{"-ntba", FILNTBA, BINOP},
|
||||
{"-ntbb", FILNTBB, BINOP},
|
||||
{"-ntbc", FILNTBC, BINOP},
|
||||
{"-ntbm", FILNTBM, BINOP},
|
||||
{"-ntca", FILNTCA, BINOP},
|
||||
{"-ntcb", FILNTCB, BINOP},
|
||||
{"-ntcc", FILNTCC, BINOP},
|
||||
{"-ntcm", FILNTCM, BINOP},
|
||||
{"-ntma", FILNTMA, BINOP},
|
||||
{"-ntmb", FILNTMB, BINOP},
|
||||
{"-ntmc", FILNTMC, BINOP},
|
||||
{"-ntmm", FILNTMM, BINOP},
|
||||
{"-ot", FILOTMM, BINOP},
|
||||
{"-otaa", FILOTAA, BINOP},
|
||||
{"-otab", FILOTBB, BINOP},
|
||||
{"-otac", FILOTAC, BINOP},
|
||||
{"-otam", FILOTAM, BINOP},
|
||||
{"-otba", FILOTBA, BINOP},
|
||||
{"-otbb", FILOTBB, BINOP},
|
||||
{"-otbc", FILOTBC, BINOP},
|
||||
{"-otbm", FILOTBM, BINOP},
|
||||
{"-otca", FILOTCA, BINOP},
|
||||
{"-otcb", FILOTCB, BINOP},
|
||||
{"-otcc", FILOTCC, BINOP},
|
||||
{"-otcm", FILOTCM, BINOP},
|
||||
{"-otma", FILOTMA, BINOP},
|
||||
{"-otmb", FILOTMB, BINOP},
|
||||
{"-otmc", FILOTMC, BINOP},
|
||||
{"-otmm", FILOTMM, BINOP},
|
||||
{"-ef", FILEQ, BINOP},
|
||||
{"!", UNOT, BUNOP},
|
||||
{"-a", BAND, BBINOP},
|
||||
@ -180,10 +249,10 @@ static int intcmp(const char *, const char *);
|
||||
static int isunopoperand(void);
|
||||
static int islparenoperand(void);
|
||||
static int isrparenoperand(void);
|
||||
static int newerf(const char *, const char *);
|
||||
static int newerf(const char *, const char *, enum time_types,
|
||||
enum time_types);
|
||||
static int nexpr(enum token);
|
||||
static int oexpr(enum token);
|
||||
static int olderf(const char *, const char *);
|
||||
static int primary(enum token);
|
||||
static void syntax(const char *, const char *);
|
||||
static enum token t_lex(char *);
|
||||
@ -353,10 +422,70 @@ binop(void)
|
||||
return intcmp(opnd1, opnd2) <= 0;
|
||||
case INTLT:
|
||||
return intcmp(opnd1, opnd2) < 0;
|
||||
case FILNT:
|
||||
return newerf (opnd1, opnd2);
|
||||
case FILOT:
|
||||
return olderf (opnd1, opnd2);
|
||||
case FILNTAA:
|
||||
return newerf(opnd1, opnd2, ATIME, ATIME);
|
||||
case FILNTAB:
|
||||
return newerf(opnd1, opnd2, ATIME, BTIME);
|
||||
case FILNTAC:
|
||||
return newerf(opnd1, opnd2, ATIME, CTIME);
|
||||
case FILNTAM:
|
||||
return newerf(opnd1, opnd2, ATIME, MTIME);
|
||||
case FILNTBA:
|
||||
return newerf(opnd1, opnd2, BTIME, ATIME);
|
||||
case FILNTBB:
|
||||
return newerf(opnd1, opnd2, BTIME, BTIME);
|
||||
case FILNTBC:
|
||||
return newerf(opnd1, opnd2, BTIME, CTIME);
|
||||
case FILNTBM:
|
||||
return newerf(opnd1, opnd2, BTIME, MTIME);
|
||||
case FILNTCA:
|
||||
return newerf(opnd1, opnd2, CTIME, ATIME);
|
||||
case FILNTCB:
|
||||
return newerf(opnd1, opnd2, CTIME, BTIME);
|
||||
case FILNTCC:
|
||||
return newerf(opnd1, opnd2, CTIME, CTIME);
|
||||
case FILNTCM:
|
||||
return newerf(opnd1, opnd2, CTIME, MTIME);
|
||||
case FILNTMA:
|
||||
return newerf(opnd1, opnd2, MTIME, ATIME);
|
||||
case FILNTMB:
|
||||
return newerf(opnd1, opnd2, MTIME, BTIME);
|
||||
case FILNTMC:
|
||||
return newerf(opnd1, opnd2, MTIME, CTIME);
|
||||
case FILNTMM:
|
||||
return newerf(opnd1, opnd2, MTIME, MTIME);
|
||||
case FILOTAA:
|
||||
return newerf(opnd2, opnd1, ATIME, ATIME);
|
||||
case FILOTAB:
|
||||
return newerf(opnd2, opnd1, BTIME, ATIME);
|
||||
case FILOTAC:
|
||||
return newerf(opnd2, opnd1, CTIME, ATIME);
|
||||
case FILOTAM:
|
||||
return newerf(opnd2, opnd1, MTIME, ATIME);
|
||||
case FILOTBA:
|
||||
return newerf(opnd2, opnd1, ATIME, BTIME);
|
||||
case FILOTBB:
|
||||
return newerf(opnd2, opnd1, BTIME, BTIME);
|
||||
case FILOTBC:
|
||||
return newerf(opnd2, opnd1, CTIME, BTIME);
|
||||
case FILOTBM:
|
||||
return newerf(opnd2, opnd1, MTIME, BTIME);
|
||||
case FILOTCA:
|
||||
return newerf(opnd2, opnd1, ATIME, CTIME);
|
||||
case FILOTCB:
|
||||
return newerf(opnd2, opnd1, BTIME, CTIME);
|
||||
case FILOTCC:
|
||||
return newerf(opnd2, opnd1, CTIME, CTIME);
|
||||
case FILOTCM:
|
||||
return newerf(opnd2, opnd1, MTIME, CTIME);
|
||||
case FILOTMA:
|
||||
return newerf(opnd2, opnd1, ATIME, MTIME);
|
||||
case FILOTMB:
|
||||
return newerf(opnd2, opnd1, BTIME, MTIME);
|
||||
case FILOTMC:
|
||||
return newerf(opnd2, opnd1, CTIME, MTIME);
|
||||
case FILOTMM:
|
||||
return newerf(opnd2, opnd1, MTIME, MTIME);
|
||||
case FILEQ:
|
||||
return equalf (opnd1, opnd2);
|
||||
default:
|
||||
@ -570,25 +699,34 @@ intcmp (const char *s1, const char *s2)
|
||||
}
|
||||
|
||||
static int
|
||||
newerf (const char *f1, const char *f2)
|
||||
newerf (const char *f1, const char *f2, enum time_types t1, enum time_types t2)
|
||||
{
|
||||
struct stat b1, b2;
|
||||
struct timespec *ts1, *ts2;
|
||||
|
||||
if (stat(f1, &b1) != 0 || stat(f2, &b2) != 0)
|
||||
return 0;
|
||||
|
||||
if (b1.st_mtim.tv_sec > b2.st_mtim.tv_sec)
|
||||
switch (t1) {
|
||||
case ATIME: ts1 = &b1.st_atim; break;
|
||||
case BTIME: ts1 = &b1.st_birthtim; break;
|
||||
case CTIME: ts1 = &b1.st_ctim; break;
|
||||
default: ts1 = &b1.st_mtim; break;
|
||||
}
|
||||
|
||||
switch (t2) {
|
||||
case ATIME: ts2 = &b2.st_atim; break;
|
||||
case BTIME: ts2 = &b2.st_birthtim; break;
|
||||
case CTIME: ts2 = &b2.st_ctim; break;
|
||||
default: ts2 = &b2.st_mtim; break;
|
||||
}
|
||||
|
||||
if (ts1->tv_sec > ts2->tv_sec)
|
||||
return 1;
|
||||
if (b1.st_mtim.tv_sec < b2.st_mtim.tv_sec)
|
||||
if (ts1->tv_sec < ts2->tv_sec)
|
||||
return 0;
|
||||
|
||||
return (b1.st_mtim.tv_nsec > b2.st_mtim.tv_nsec);
|
||||
}
|
||||
|
||||
static int
|
||||
olderf (const char *f1, const char *f2)
|
||||
{
|
||||
return (newerf(f2, f1));
|
||||
return (ts1->tv_nsec > ts2->tv_nsec);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -52,7 +52,7 @@ t ()
|
||||
}
|
||||
|
||||
count=0
|
||||
echo "1..130"
|
||||
echo "1..266"
|
||||
|
||||
t 0 'b = b'
|
||||
t 0 'b == b'
|
||||
@ -194,3 +194,66 @@ t 1 '\( ! -a \)'
|
||||
t 0 '\( -n -o \)'
|
||||
t 1 '\( -z -o \)'
|
||||
t 1 '\( ! -o \)'
|
||||
|
||||
# Test all file timestamp comparison operators
|
||||
s() {
|
||||
t ${1} "${35} -nt ${36}"
|
||||
t ${2} "${35} -ntaa ${36}"
|
||||
t ${3} "${35} -ntab ${36}"
|
||||
t ${4} "${35} -ntac ${36}"
|
||||
t ${5} "${35} -ntam ${36}"
|
||||
t ${6} "${35} -ntba ${36}"
|
||||
t ${7} "${35} -ntbb ${36}"
|
||||
t ${8} "${35} -ntbc ${36}"
|
||||
t ${9} "${35} -ntbm ${36}"
|
||||
t ${10} "${35} -ntca ${36}"
|
||||
t ${11} "${35} -ntcb ${36}"
|
||||
t ${12} "${35} -ntcc ${36}"
|
||||
t ${13} "${35} -ntcm ${36}"
|
||||
t ${14} "${35} -ntma ${36}"
|
||||
t ${15} "${35} -ntmb ${36}"
|
||||
t ${16} "${35} -ntmc ${36}"
|
||||
t ${17} "${35} -ntmm ${36}"
|
||||
t ${18} "${35} -ot ${36}"
|
||||
t ${19} "${35} -otaa ${36}"
|
||||
t ${20} "${35} -otab ${36}"
|
||||
t ${21} "${35} -otac ${36}"
|
||||
t ${22} "${35} -otam ${36}"
|
||||
t ${23} "${35} -otba ${36}"
|
||||
t ${24} "${35} -otbb ${36}"
|
||||
t ${25} "${35} -otbc ${36}"
|
||||
t ${26} "${35} -otbm ${36}"
|
||||
t ${27} "${35} -otca ${36}"
|
||||
t ${28} "${35} -otcb ${36}"
|
||||
t ${29} "${35} -otcc ${36}"
|
||||
t ${30} "${35} -otcm ${36}"
|
||||
t ${31} "${35} -otma ${36}"
|
||||
t ${32} "${35} -otmb ${36}"
|
||||
t ${33} "${35} -otmc ${36}"
|
||||
t ${34} "${35} -otmm ${36}"
|
||||
}
|
||||
|
||||
a=/tmp/test$$.1
|
||||
b=/tmp/test$$.2
|
||||
trap "rm -f $a $b" EXIT
|
||||
|
||||
# Tests 131-164
|
||||
s 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 $a $b
|
||||
|
||||
touch $a
|
||||
# Tests 165-198
|
||||
s 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 $a $b
|
||||
|
||||
sleep 2 # Ensure $b is newer than $a
|
||||
touch $b
|
||||
# Tests 199-232
|
||||
s 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 $a $b
|
||||
|
||||
sleep 2
|
||||
echo >$b # Updates mtime & ctime
|
||||
sleep 2
|
||||
touch -A 01 -a $b
|
||||
|
||||
# $b now has ctime > mtime > atime > btime
|
||||
# Tests 233-266
|
||||
s 1 1 0 1 1 1 1 1 1 0 0 1 0 0 0 1 1 1 1 1 0 0 0 1 0 0 1 1 1 1 1 1 0 1 $b $b
|
||||
|
Loading…
Reference in New Issue
Block a user