Activity log for bug #2089439

Date Who What changed Old value New value Message
2024-11-23 12:00:17 Guilherme Janczak bug added bug
2024-11-23 12:02:58 Guilherme Janczak description On Unix, if I have a file inside a directory and I have no execute permission to that directory, the file exists, but sbcl's probe-file returns nil. Internally, it gets an access denied error from the OS and still returns nil. You can create such a directory as follows: ```sh mkdir /tmp/no-exec-dir touch /tmp/no-exec-dir/file chmod a-x /tmp/no-exec-dir ``` Example sbcl run after setting up ("*" is the sbcl REPL): ``` * (probe-file "/tmp/no-exec-dir/file") NIL ``` Here's a C program that sets up a directory with no execute permission and does the C equivalent of probe-file (access/faccessat in POSIX C): ```c #define _POSIX_C_SOURCE 200809L #include <sys/stat.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <unistd.h> int main(void) { const char dir_path[] = "/tmp/no-exec-dir", file_path[] = "file"; int dir = -1, file = -1, ret; if ((ret = mkdir(dir_path, 0777)) == -1) goto err; dir = open(dir_path, O_CREAT|O_RDONLY|O_DIRECTORY, (mode_t)0777); if (dir == -1) goto err; file = openat(dir, file_path, O_CREAT|O_TRUNC|O_WRONLY, (mode_t)0777); if (file == -1) goto err; if (fchmod(dir, 0666 /* Remove exec permission. */) == -1) goto err; ret = faccessat(dir, file_path, F_OK, 0); printf("access to existing file returned %d\nerrno = %d: %s\n\n", ret, errno, strerror(errno)); ret = faccessat(dir, "some-non-existing-file", F_OK, 0); printf("access to non-existing file returned %d\nerrno = %d: %s\n", ret, errno, strerror(errno)); err: fchmod(dir, 0777 /* Restore exec permission. */); unlinkat(dir, file_path, 0); rmdir(dir_path); return 1; } ``` Example run: ```console $ ./a.out access to existing file returned -1 errno = 13: Permission denied access to non-existing file returned -1 errno = 13: Permission denied ``` Whether the file exists or not, the OS returns an error, and it's impossible for the program to tell the difference. sbcl's probe-file claims the file doesn't exist in such a case which might be untrue, it should raise a file-error instead. On Unix, if I have a file inside a directory and I have no execute permission to that directory, the file exists, but sbcl's probe-file returns nil. Internally, it gets an access denied error from the OS and still returns nil. You can create such a directory as follows: ```sh mkdir /tmp/no-exec-dir touch /tmp/no-exec-dir/file chmod a-x /tmp/no-exec-dir ``` Example sbcl run after setting up ("*" is the sbcl REPL): ``` * (probe-file "/tmp/no-exec-dir/file") NIL ``` Here's a C program that sets up a directory with no execute permission and does the C equivalent of probe-file (access/faccessat in POSIX C): ```c #define _POSIX_C_SOURCE 200809L #include <sys/stat.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> #include <string.h> #include <unistd.h> int main(void) { const char dir_path[] = "/tmp/no-exec-dir", file_path[] = "file"; int dir = -1, file = -1, ret; if ((ret = mkdir(dir_path, 0777)) == -1) goto err; dir = open(dir_path, O_CREAT|O_RDONLY|O_DIRECTORY, (mode_t)0777); if (dir == -1) goto err; file = openat(dir, file_path, O_CREAT|O_TRUNC|O_WRONLY, (mode_t)0777); if (file == -1) goto err; if (fchmod(dir, 0666 /* Remove exec permission. */) == -1) goto err; ret = faccessat(dir, file_path, F_OK, 0); printf("access to existing file returned %d\nerrno = %d: %s\n\n", ret, errno, strerror(errno)); ret = faccessat(dir, file_path, F_OK, 0); printf("access to non-existing file returned %d\nerrno = %d: %s\n", ret, errno, strerror(errno)); return 0; err: fchmod(dir, 0777 /* Restore exec permission. */); unlinkat(dir, file_path, 0); rmdir(dir_path); return 1; } ``` Example run: ```console $ ./a.out access to existing file returned -1 errno = 13: Permission denied access to non-existing file returned -1 errno = 13: Permission denied ``` Whether the file exists or not, the OS returns an error, and it's impossible for the program to tell the difference. sbcl's probe-file claims the file doesn't exist in such a case which might be untrue, it should raise a file-error instead.