Re: current directory and openat() et al Marc Feeley 23 Apr 2020 13:56 UTC

> On Apr 23, 2020, at 7:27 AM, Lassi Kortela <xxxxxx@lassi.io> wrote:
>
>>> I suspect that if the current working directory is specified in terms
>>> of parameter-like semantics then it should be possible to make use of
>>> openat() etc behind the scenes
>> Gambit does some of this; I suggest grepping the source code
>
> All of the calls are in os_files.c:
>
> $ grep -nF 'at (' lib/os_files.c
> 542:          new_dir = openat (dir, start, O_DIRECTORY);
> 587:      fd = openat (dir, path2, flags, mode);
> 621:      result = mkfifoat (dir, path2, mode);
> 655:      result = mkdirat (dir, path2, mode);
> 686:      result = unlinkat (dir, path2, 0);
> 724:          result = linkat (olddir, oldpath2, newdir, newpath2, 0);
> 760:      result = symlinkat (target, dir, path2);
> 797:      result = readlinkat (dir, path2, buf, bufsize);
> 893:                result = linkat (olddir, oldpath2, newdir, newpath2, 0);
> 900:                    result = unlinkat (olddir, oldpath2, 0);
> 911:                result = renameat (olddir, oldpath2, newdir, newpath2);
> 962:      int fd = openat (dir, path2, O_DIRECTORY);
> 1001:      result = fstatat (dir, path2, statbuf, follow ? 0 : AT_SYMLINK_NOFOLLOW);

Interestingly the use of the “at” system calls was added to Gambit to handle filenames that are longer than PATH_MAX.  It allows accessing files that are very deeply nested.  It uses openat() on successive chunks of the path <= PATH_MAX to reach deeply nested files.

In the following example Gambit handles a path of length 10009 on linux (well beyond the typical 1024 character limit) whereas most other Scheme implementations give an error (I tested Chicken, Chez and Guile):

% cat long.scm
(define deep-dir
  (string-append "/tmp"
                 (apply string-append
                        (vector->list (make-vector 5000 "/x")))))

(define path (string-append deep-dir "/file"))

(write (list (string-length path) (read (open-input-file path))))
(newline)
% gsi long.scm
(10009 hello!)
% csi -quiet long.scm

Error: (open-input-file) cannot open file - File name too long: "/tmp/.../x/x/x/x/file"
...
% scheme --quiet --script long.scm
Exception in open-input-file: failed for /tmp/.../x/x/x/x/file: file name too long
% guile long.scm
...
ERROR: In procedure open-file:
ERROR: In procedure open-file: File name too long: "/tmp/.../x/x/x/x/file"

Marc