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.

--=-=-=--