Opened 7 months ago

Last modified 6 months ago

#15102 new bug

stat() modifies the access time of an existing file.

Reported by: return_0e Owned by: nobody
Priority: low Milestone: Unscheduled
Component: System/POSIX Version: R1/Development
Keywords: Cc:
Blocked By: Blocking:
Has a Patch: no Platform: All

Description

I've encountered this behaviour when running a test failure in libuv which occurs when the access time doesn't match the expected one. It turns out that Haiku's stat() implementation always modifies the st_atim field with the current timestamp when calling stat on a file that already exists.

This behaviour does not occur in macOS or Linux when running the libuv test. The test should match the given last accessed timestamp with the calculated timestamp with the file 'test_file'. Running this in Haiku has the access timestamp set as the current timestamp instead, thus fails this test.

MacOS
 
ok 1 - fs_utime
# Access time parameter: 400497753.000000
# Modification time parameter: 400497753.000000
# Path: test_file
# Calculated access time: 400497753.000000
# Calculated mod time: 400497753.000000

Linux
 
ok 1 - fs_utime
# Access time parameter: 400497753.000000
# Modification time parameter: 400497753.000000
# Path: test_file
# Calculated access time: 400497753.000000
# Calculated mod time: 400497753.000000

Haiku
 
not ok 104 - fs_utime
# exit code 5376
# Output from process `fs_utime`:
# Access time parameter: 400497753.000000
# Modification time parameter: 400497753.000000
# Path: test_file
# Calculated access time: 1559347965.842396 <----------- Incorrect access time, should be 400497753.000000
# Calculated mod time: 400497753.032244
# Assertion failed in test/test-fs.c on line 758: s->st_atim.tv_sec + (s->st_atim.tv_nsec / 1000000000.0) == atime
# Abort

To observe this behaviour:

  1. Create a new file 'touch test-file'
  2. Copy and paste this into a script file in Haiku.
    while true; do
    	stat test-file
    	sleep 1
    	clear
    done
    
  3. Run the script and the last accessed time field will be changed to the current timestamp.

Change History (2)

comment:1 by bga, 6 months ago

This is a BFS issue. It does not store access time anywhere and , instead, simple use the local time whenever stat is called on a file.

Form the Linux stat man page:

The field st_atime is changed by file accesses, for example, by execve(2), mknod(2), pipe(2), utime(2) and read(2) (of more than zero bytes). Other routines, like mmap(2), may or may not update st_atime.

it does not explicitly say that but it is implied that stat should not change atime. Maybe BFS should be changed to match this behavior? Returning simply the time stat happened is a neat trick but also a bit useless.

comment:2 by pulkomandy, 6 months ago

Let's dig into POSIX!

http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap04.html#tag_04_09

Each function or utility in POSIX.1-2017 that reads or writes data (even if the data does not change) or performs an operation to change file status (even if the file status does not change) indicates which of the appropriate timestamps shall be marked for update. If an implementation of such a function or utility marks for update one of these timestamps in a place or time not specified by POSIX.1-2017, this shall be documented, except that any changes caused by pathname resolution need not be documented. For the other functions or utilities in POSIX.1-2017 (those that are not explicitly required to read or write file data or change file status, but that in some implementations happen to do so), the effect is unspecified.

So, our implementation of stat seems to fit into this? Tricky and not very useful, indeed, but at least it's not wrong.

The root problem is here:

The resolution of timestamps of files in a file system is implementation-defined, but shall be no coarser than one-second resolution. The three timestamps shall always have values that are supported by the file system.

So, whatever we do, BFS will never really be POSIX compliant in that aspect. Unless we store the access time as an extended attribute, but that would likely create more problems than it solves.

I think we could just use the modification time instead? We should check what Linux does when the FS is mounted with noatime option, I think that would be less surprising behavior?

Note: See TracTickets for help on using tickets.