Opened 4 years ago

Closed 3 years ago

#16506 closed bug (fixed)

write() doesn't properly update file offset if opened with O_APPEND

Reported by: mike.dld Owned by: korli
Priority: normal Milestone: R1/beta3
Component: System/POSIX Version: R1/Development
Keywords: Cc:
Blocked By: Blocking:
Platform: All

Description

When opening file (via open()) in append mode (with O_APPEND flag), subsequent write operations (via write()) update current file offset (retrieved via lseek()) as if they were issued on an empty file, i.e. current file offset does not take pre-existing file size into account. Note that data being written does it fact end up at the end of the file.

Environment:

~> uname -a
Haiku shredder 1 hrev54538 Sep  1 2020 06:01:43 x86_64 x86_64 Haiku

~> df -a
 Mount             Type      Total     Free      Flags   Device
----------------- --------- --------- --------- ------- ------------------------
/                 rootfs            0         0 ------W 
/dev              devfs             0         0 ------W 
/boot             bfs        40.0 GiB  33.7 GiB QAM-P-W /dev/disk/ata/0/master/raw
/boot/system      packagefs   4.0 KiB   4.0 KiB QAM-P-- 
/boot/home/config packagefs   4.0 KiB   4.0 KiB QAM-P--

Repro code:

#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>

int main(int argc, char** argv)
{
    const char* const data = argc == 2 ? argv[1] : "?";
    const int fd = open("a.dat", O_RDWR | O_APPEND | O_CREAT, 0644);
    if (fd != -1) {
        write(fd, data, strlen(data));
        printf("pos1: %d\n", (int)lseek(fd, 0, SEEK_CUR));
        write(fd, "\n", 1);
        printf("pos2: %d\n", (int)lseek(fd, 0, SEEK_CUR));
        close(fd);
    }
}

Expected result:

~> ./a.out 
pos1: 1
pos2: 2
~> ./a.out foo
pos1: 5
pos2: 6
~> ./a.out barbaz
pos1: 12
pos2: 13
~> cat a.dat 
?
foo
barbaz

Actual result:

~> ./a.out
pos1: 1
pos2: 2
~> ./a.out foo
pos1: 3
pos2: 4
~> ./a.out barbaz
pos1: 6
pos2: 7
~> cat a.dat
?
foo
barbaz

Related docs:

  1. https://pubs.opengroup.org/onlinepubs/9699919799/functions/open.html

    O_APPEND
    If set, the file offset shall be set to the end of the file prior to each write.

  2. https://pubs.opengroup.org/onlinepubs/9699919799/functions/write.html

    If the O_APPEND flag of the file status flags is set, the file offset shall be set to the end of the file prior to each write and no intervening file modification operation shall occur between changing the file offset and the write operation.

  3. https://pubs.opengroup.org/onlinepubs/9699919799/functions/lseek.html

    If whence is SEEK_CUR, the file offset shall be set to its current location plus offset.

    RETURN VALUE
    Upon successful completion, the resulting offset, as measured in bytes from the beginning of the file, shall be returned.

Change History (4)

comment:2 by korli, 3 years ago

Owner: changed from nobody to korli
Status: newassigned

comment:3 by korli, 3 years ago

Milestone: UnscheduledR1/beta3

comment:4 by korli, 3 years ago

Resolution: fixed
Status: assignedclosed

Applied in hrev54697 kernel write is still pending.

Note: See TracTickets for help on using tickets.