On 2025-04-09 05:47, Nelson H. F. Beebe wrote:
I ran these tests in the gzip-1.13.56-e549 build directory
on DragonFlyBSD 6.4.0:
mkdir d
echo >d/f
chmod a-w d
env LC_ALL=C truss -o gzip.truss ./gzip d/f
That last command produces this output;
gzip: d/f.gz already exists; do you wish to overwrite (y or n)? y
gzip: d/f.gz: No such file or directory
The truss output on this system is not as clear as what the Solaris
truss produces:
% cat gzip.truss
mmap() = 7077888 (0x6c0000)
open("/proc/curproc/mem",0x1,0400033010400) = 4 (0x4)
fcntl(0x4,0x2,0x1) = 0 (0x0)
ioctl(4,PIOCBIS,0x21) = 0 (0x0)
ioctl(4,PIOCSFL,0x1) = 0 (0x0)
execve(<missing argument>,<missing argument>,<missing
argument>)__sysctl(0x7fffffdfc528,0x2,0x80066e4cc,0x7fffffdfc520,0x0,0x0) = 0 (0x0)
mmap() = 4624384 (0x469000)
issetugid() = 0 (0x0)
__sysctl(0x7fffffdfb808,0x2,0x7fffffdfb7fc,0x7fffffdfb800,0x0,0x0) = 0
(0x0)
__realpath(0x80045c7fe,0x80046d000,0x400) ERR#2 'No such file or
directory'
access("/usr/lib/gcc80/libc.so.8",0) ERR#2 'No such file or
directory'
access("/usr/uumath/lib/libc.so.8",0) ERR#2 'No such file or
directory'
access("/usr/local/lib/libc.so.8",0) ERR#2 'No such file or
directory'
open("/var/run/ld-elf.so.hints",0x20000,010) = 4 (0x4)
read(0x4,0x7fffffdfc290,0x80) = 128 (0x80)
lseek() = 128 (0x80)
read(0x4,0x80046b400,0x1fc) = 508 (0x1fc)
close(4) = 0 (0x0)
access("/lib/libc.so.8",0) = 0 (0x0)
open("/lib/libc.so.8",0x20000,010) = 4 (0x4)
fstat(4,0x7fffffdfc4b0) = 0 (0x0)
mmap() = 4657152 (0x471000)
mmap() = 6811648 (0x67f000)
mmap() = 6811648 (0x67f000)
mmap() = 10170368 (0x9b3000)
mmap() = 10219520 (0x9bf000)
munmap(0x800471000,0x1000) = 0 (0x0)
close(4) = 0 (0x0)
__sysctl(0x7fffffdfc5f0,0x2,0x7fffffdfc5e0,0x7fffffdfc5e8,0x0,0x0) = 0
(0x0)
munmap(0x800470000,0x1000) = 0 (0x0)
mmap() = 4653056 (0x470000)
sigprocmask(0x1,0x80066e380,0x7fffffdfc560) = 0 (0x0)
sigprocmask(0x3,0x7fffffdfc580,0x0) = 0 (0x0)
sigprocmask(0x1,0x80066e380,0x7fffffdfcdb0) = 0 (0x0)
sigprocmask(0x3,0x7fffffdfcdd0,0x0) = 0 (0x0)
set_tls_area(0x0,0x7fffffdfce90,0x10) = 0 (0x0)
sigprocmask(0x1,0x80066e380,0x7fffffdfcde0) = 0 (0x0)
sigprocmask(0x3,0x7fffffdfcdc0,0x0) = 0 (0x0)
issetugid() = 0 (0x0)
open(0,0x0,03777777767747460) = 4 (0x4)
read(0x4,0x8009c06c0,0x40) = 64 (0x40)
close(4) = 0 (0x0)
open("/dev/lpmap",0x2,00) = 4 (0x4)
mmap() = 4755456 (0x489000)
close(4) = 0 (0x0)
sigprocmask(0x1,0x80066e380,0x7fffffdfcda0) = 0 (0x0)
sigprocmask(0x3,0x7fffffdfcdc0,0x0) = 0 (0x0)
sigprocmask(0x1,0x80066e380,0x7fffffdfcda0) = 0 (0x0)
sigprocmask(0x3,0x7fffffdfce00,0x0) = 0 (0x0)
open("d/",0x8000000,00) = 4 (0x4)
openat(0x4,0x42e002,0x8104,0x0) = 5 (0x5)
fstat(5,0x42a920) = 0 (0x0)
mmap() = 4820992 (0x499000)
munmap(0x800499000,0x10000) = 0 (0x0)
mmap() = 4849664 (0x4a0000)
mmap() = 4915200 (0x4b0000)
sigaction(SIGINT,0x0,0x7fffffdfcd80) = 0 (0x0)
sigaction(SIGHUP,0x0,0x7fffffdfcd80) = 0 (0x0)
sigaction(SIGPIPE,0x0,0x7fffffdfcd80) = 0 (0x0)
sigaction(SIGTERM,0x0,0x7fffffdfcd80) = 0 (0x0)
sigaction(SIGXCPU,0x0,0x7fffffdfcd80) = 0 (0x0)
sigaction(SIGXFSZ,0x0,0x7fffffdfcd80) = 0 (0x0)
sigaction(SIGINT,0x7fffffdfcd80,0x0) = 0 (0x0)
sigaction(SIGHUP,0x7fffffdfcd80,0x0) = 0 (0x0)
sigaction(SIGPIPE,0x7fffffdfcd80,0x0) = 0 (0x0)
sigaction(SIGTERM,0x7fffffdfcd80,0x0) = 0 (0x0)
sigaction(SIGXCPU,0x7fffffdfcd80,0x0) = 0 (0x0)
sigaction(SIGXFSZ,0x7fffffdfcd80,0x0) = 0 (0x0)
sigprocmask(0x1,0x42a0e0,0x7fffffdfcdc0) = 0 (0x0)
openat(0x4,0x49f822,0xa01,0x180) ERR#17 'File exists'
Thanks for the info. This seems to be a kernel bug, one I see no easy
way for gzip to work around. To reproduce the bug, perhaps you can run
the following shell commands:
mkdir d
chmod a-w d
gcc dfly-openat-bug.c
./a.out
where dfly-openat-bug.c is attached. The a.out should succeed, but I
expect it reports a failure for d/f. This might be a basis for a bug
report to the DragonflyBSD folks.
sigprocmask(0x3,0x7fffffdfcdc0,0x0) = 0 (0x0)
write(2,0x7fffffdfc4c0,28) = 28 (0x1c)
ioctl(0,TIOCGETA,0x7fffffdfcd60) = 0 (0x0)
write(2,0x7fffffdfc4c0,36) = 36 (0x24)
fstat(0,0x7fffffdfcc50) = 0 (0x0)
ioctl(0,TIOCGETA,0x7fffffdfccb0) = 0 (0x0)
read(0x0,0x8004af000,0x1000) = 2 (0x2)
unlink(0x49f820) ERR#2 'No such file or
directory'
mmap() = 4980736 (0x4c0000)
stat("/usr/share/nls/C/libc.cat",0x7fffffdfcc10) ERR#2 'No such file or
directory'
stat("/usr/share/nls/libc/C",0x7fffffdfcc10) ERR#2 'No such file or
directory'
stat("/usr/local/share/nls/C/libc.cat",0x7fffffdfcc10) ERR#2 'No such
file or directory'
stat("/usr/local/share/nls/libc/C",0x7fffffdfcc10) ERR#2 'No such file
or directory'
mmap() = 5046272 (0x4d0000)
write(2,0x7fffffdfc4a0,40) = 40 (0x28)
close(5) = 0 (0x0)
sigprocmask(0x1,0x80066e380,0x7fffffdfccd0) = 0 (0x0)
sigprocmask(0x3,0x7fffffdfcca0,0x0) = 0 (0x0)
sigprocmask(0x1,0x80066e380,0x7fffffdfcc80) = 0 (0x0)
sigprocmask(0x3,0x7fffffdfcca0,0x0) = 0 (0x0)
sigprocmask(0x1,0x80066e380,0x7fffffdfcc80) = 0 (0x0)
sigprocmask(0x3,0x7fffffdfccf0,0x0) = 0 (0x0)
exit(0x1) process exit, rval = 256
The line
openat(0x4,0x49f822,0xa01,0x180) ERR#17 'File exists'
has 0xa01 as the "int flags" argument, and "man openat" says
The flags specified are formed by or'ing the following values
O_RDONLY open for reading only
O_WRONLY open for writing only
O_RDWR open for reading and writing
O_NONBLOCK do not block on open
O_APPEND append on each write
O_CREAT create file if it does not exist
O_TRUNC truncate size to 0
O_EXCL error if create and file exists
O_SHLOCK atomically obtain a shared lock
O_EXLOCK atomically obtain an exclusive lock
O_DIRECT eliminate or reduce cache effects
O_FSYNC synchronous writes
O_NOFOLLOW do not follow symlinks
O_DIRECTORY error if file is not a directory
O_CLOEXEC set FD_CLOEXEC upon open
In <fcntl.h>, I find these O_* flag values:
#define O_RDONLY 0x0000 /* open for reading only */
#define O_WRONLY 0x0001 /* open for writing only */
#define O_RDWR 0x0002 /* open for reading and writing */
#define O_ACCMODE 0x0003 /* mask for above modes */
#define O_NONBLOCK 0x0004 /* no delay */
#define O_APPEND 0x0008 /* set append mode */
#define O_SHLOCK 0x0010 /* open with shared file lock */
#define O_EXLOCK 0x0020 /* open with exclusive file lock */
#define O_ASYNC 0x0040 /* signal pgrp when data ready */
#define O_FSYNC 0x0080 /* synchronous writes */
#define O_SYNC 0x0080 /* Same as O_FSYNC, but POSIX */
#define O_NOFOLLOW 0x0100 /* don't follow symlinks */
#define O_CREAT 0x0200 /* create if nonexistent */
#define O_TRUNC 0x0400 /* truncate to zero length */
#define O_EXCL 0x0800 /* error if already exists */
#define O_NOCTTY 0x8000 /* don't assign controlling terminal */
#define O_DIRECT 0x00010000
#define O_CLOEXEC 0x00020000 /* atomically set FD_CLOEXEC */
#define O_FBLOCKING 0x00040000 /* force blocking I/O */
#define O_FNONBLOCKING 0x00080000 /* force non-blocking I/O */
#define O_FAPPEND 0x00100000 /* force append mode for write */
#define O_FOFFSET 0x00200000 /* force specific offset */
#define O_FSYNCWRITE 0x00400000 /* force synchronous write */
#define O_FASYNCWRITE 0x00800000 /* force asynchronous write */
#define O_UNUSED24 0x01000000
#define O_UNUSED25 0x02000000
#define O_UNUSED26 0x04000000
#define O_DIRECTORY 0x08000000 /* error if not a directory */
#define FAPPENDONLY 0x20000000 /* O_APPEND cannot be changed */
#define O_FMASK (O_FBLOCKING|O_FNONBLOCKING|O_FAPPEND|O_FOFFSET|\
#define FAPPEND O_APPEND /* kernel/compat */
#define FASYNC O_ASYNC /* kernel/compat */
#define FFSYNC O_FSYNC /* kernel */
#define FNONBLOCK O_NONBLOCK /* kernel */
#define FNDELAY O_NONBLOCK /* compat */
#define O_NDELAY O_NONBLOCK /* compat */
#define FPOSIXSHM O_NOFOLLOW
Thus, 0xa01 should mean O_EXCL | O_CREAT | O_WRONLY, the same flags
that you got in your Solaris truss report.
-------------------------------------------------------------------------------
- Nelson H. F. Beebe Tel: +1 801 581 5254 -
- University of Utah -
- Department of Mathematics, 110 LCB Internet e-mail: be...@math.utah.edu -
- 155 S 1400 E RM 233 be...@acm.org be...@computer.org -
- Salt Lake City, UT 84112-0090, USA URL: https://www.math.utah.edu/~beebe -
-------------------------------------------------------------------------------
#define _GNU_SOURCE 1
#include <fcntl.h>
#include <stdio.h>
int
main (void)
{
int dirfd = open ("d/", O_SEARCH | O_DIRECTORY);
if (dirfd < 0)
return perror ("d/"), 1;
int fd = openat (dirfd, "f", O_EXCL | O_CREAT | O_WRONLY, 0660);
if (fd < 0)
return perror ("d/f"), 1;
return 0;
}