Bug#143111: [OpenAFS-devel] Testing GNU findutils on AFS.... please!
pod
pod@herald.ox.ac.uk
Wed, 07 May 2008 17:55:20 +0100
--=-=-=
>>>>> "JY" == James Youngman <jay@gnu.org> writes:
JY> It occurs to me to ask something else though. Is possible for
JY> there to be any kind of infinite cycle in an AFS directory
JY> hierarchy?
Yes, this is certainly possible by mounting a volume somewhere within its
own hierarchy.
JY> With regular Unix filesystems we rely on the uniqueness of the
JY> {st_dev,st_ino} combination; if we see the same value pair twice
JY> under one startpoint, we conclude there is a loop. Will this
JY> method work for AFS?
The limited testing I've done implies that this method does work.
shell$ cd /afs/some.where/interesting
shell$ fs mkmount -dir test -vol test
shell$ cd test
shell$ echo a > a
shell$ fs mkmount -dir test -vol test
shell$ pwd
/afs/some.where/interesting/test
shell$ ls -F
a test/
shell$ ls -F test
a test/
shell$ stat -c "%d %i" a test/a test/test/a
14 214761474
14 214761474
14 214761474
shell$ find . -print
.
./a
find: File system loop detected; `./test' is part of the same file system loop as `.'.
shell$ find --version
Copyright (C) 2007 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Written by Eric B. Decker, James Youngman, and Kevin Dalley.
Built using GNU gnulib version e5573b1bad88bfabcda181b9e0125fb0c52b7d3b
Features enabled: D_TYPE O_NOFOLLOW(enabled) LEAF_OPTIMISATION FTS() CBO(level=0)
shell$
As regards dirent entries I've used the following small piece of C
--=-=-=
Content-Type: text/x-csrc
Content-Disposition: inline; filename=dirent.c
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>
int
main(int argc, char *argv[])
{
while(argv && *++argv) {
DIR *d;
struct dirent *de;
d=opendir(*argv);
if(d==NULL) {
fprintf(stderr, "opendir \"%s\" failed: %s\n", *argv, strerror(errno));
continue;
}
while((de=readdir(d))!=NULL) {
printf("%llu %hhu %s\n",
(unsigned long long)de->d_ino, de->d_type, de->d_name);
}
if(closedir(d)!=0) {
fprintf(stderr, "closedir \"%s\" failed: %s\n", *argv, strerror(errno));
}
}
return EXIT_SUCCESS;
}
--=-=-=
with which I get the following output
shell$ ln -s a b
shell$ gcc -o dirent -std=c99 -pedantic -Wall ~/tmp/t/dirent.c
shell$ ./dirent .
214761473 4 .
214761473 4 ..
214761474 8 a
214761476 4 test
214761478 0 b
214761482 8 dirent
shell$
So it would appear, at least on my system, that files get DT_REG, dirs get
DT_DIR but symlinks get DT_UNKNOWN.
shell$ mkdir d
shell$ echo c > d/c
shell$ fs setacl -dir d -acl pod l
shell$ fs listacl -path d
Access list for d is
Normal rights:
system:administrators rlidwka
pod l
shell$ ./dirent d
214761475 4 .
214761473 4 ..
214761480 8 c
shell$ ls -li d
total 1
214761480 -rw-r--r-- 1 pod users 2 May 7 17:27 c
shell$ cat d/c
cat: d/c: Permission denied
shell$ fs flushvolume -path .
shell$ ./dirent d
214761475 4 .
214761473 4 ..
214761480 0 c
shell$ ls -li d
ls: cannot access d/c: Permission denied
total 0
214761480 ?????????? ? ? ? ? ? c
shell$ cat d/c
cat: d/c: Permission denied
shell$
So the "readdir(3) returns an entry but lstat(2) on that entry fails" case
appears to be possible (note the fs flushvolume appears to be necessary to
get things into this state) and d_type appears to be DT_UNKNOWN in that
case.
I'm afraid I can't easily test for non-Linux systems that support AFS and
d_type and I apologise that the above is all rather empirical and is
informed neither by careful inspection of the relevant OpenAFS source nor
by deep knowledge of the AFS protocol.
--=-=-=--