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;
}

Reply via email to