The difference between "test -a file" and "test file -ef file"

QNX (Neutrino 6.5.0) uses the open source ksh implementation as its shell. Many of the provided scripts, including system startup scripts, use constructs such as

if ! test /dev/slog -ef /dev/slog; then # do something fi 

to check if the resource manager exists or not in the file system. I searched and could find very detailed explanations that -ef checks if both options are actually the same file. Since the specified file name is the same, it just boils down to checking for the file.

I checked the behavior of test -a and test -e (both seem to check for the presence of files of any type according to the various documents I read) and they seem to work as well.

Is there a difference in checks between -ef and -a / -e ? Does -ef any attempt to protect itself from race conditions in the existence of a file?

+6
source share
2 answers

strace at strace on a Ubuntu Linux copy of ksh does not reveal significant differences. One stat call versus two.

 $ strace test /tmp/tmp.geLaoPkXXC -ef /tmp/tmp.geLaoPkXXC 

showed it:

 mmap(NULL, 7220736, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f11dc80b000 close(3) = 0 stat("/tmp/tmp.geLaoPkXXC", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0 stat("/tmp/tmp.geLaoPkXXC", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0 close(1) = 0 close(2) = 0 

... a

 $ strace test -a /tmp/tmp.geLaoPkXXC 

showed it:

 fstat(3, {st_mode=S_IFREG|0644, st_size=7220736, ...}) = 0 mmap(NULL, 7220736, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f6b49e2b000 close(3) = 0 stat("/tmp/tmp.geLaoPkXXC", {st_mode=S_IFREG|0600, st_size=0, ...}) = 0 close(1) = 0 close(2) = 0 

One stat versus two.

 $ ksh --version version sh (AT&T Research) 93u 2011-02-08 
+4
source

We do not know how the code uses statistics exactly without the code, we need to find the difference through the code.

 /* code for -ef */ return (stat (argv[op - 1], &stat_buf) == 0 && stat (argv[op + 1], &stat_spare) == 0 && stat_buf.st_dev == stat_spare.st_dev && stat_buf.st_ino == stat_spare.st_ino); /* code for -e/-a */ case 'a': /* file exists in the file system? */ case 'e': return stat (argv[pos - 1], &stat_buf) == 0; 

So, if the names match, and two stat () with the same name return the same value, test -a/-e file same as test file -ef file . We know that the first condition is true, and we know that the second condition is also true from @tinman's comments

+1
source

Source: https://habr.com/ru/post/919757/


All Articles