Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Intercept calls that change file timestamps #183

Closed
bmwiedemann opened this issue Jan 30, 2019 · 14 comments
Closed

Intercept calls that change file timestamps #183

bmwiedemann opened this issue Jan 30, 2019 · 14 comments

Comments

@bmwiedemann
Copy link

I am working on reproducible builds for openSUSE and there I would like to use libfaketime to make software behave exactly as if date+time were

  • in the future
  • deterministic (this is why I use the i1 param)

e.g. I would like to use faketime -f '@2020-01-01 01:01:01 i1'

But one problem with stat is visible when you compare

cmd='echo $SECONDS;touch /tmp/x ; stat /tmp/x ; echo $SECONDS; sleep 1 ; stat /tmp/x ; echo $SECONDS;echo $SECONDS'
bash -c "$cmd"
faketime -f '+0y i1' bash -c "$cmd"

That produces

> bash -c "$cmd"
0
  File: /tmp/x
  Size: 7               Blocks: 8          IO Block: 4096   regular file
Device: 803h/2051d      Inode: 531866      Links: 1
Access: (0644/-rw-r--r--)  Uid: (16894/bwiedemann)   Gid: (   50/    suse)
Access: 2019-01-30 15:26:01.572086689 +0100
Modify: 2019-01-30 15:26:01.572086689 +0100
Change: 2019-01-30 15:26:01.572086689 +0100
 Birth: -
0

  File: /tmp/x
  Size: 7               Blocks: 8          IO Block: 4096   regular file
Device: 803h/2051d      Inode: 531866      Links: 1
Access: (0644/-rw-r--r--)  Uid: (16894/bwiedemann)   Gid: (   50/    suse)
Access: 2019-01-30 15:26:01.572086689 +0100
Modify: 2019-01-30 15:26:01.572086689 +0100
Change: 2019-01-30 15:26:01.572086689 +0100
 Birth: -
1
1


> faketime -f '+0y i1' bash -c "$cmd"
32
  File: /tmp/x
  Size: 7               Blocks: 8          IO Block: 4096   regular file
Device: 803h/2051d      Inode: 531866      Links: 1
Access: (0644/-rw-r--r--)  Uid: (16894/bwiedemann)   Gid: (   50/    suse)
Access: 2019-01-30 15:27:02.605862595 +0100
Modify: 2019-01-30 15:27:03.605862595 +0100
Change: 2019-01-30 15:27:01.605862595 +0100
 Birth: -
62
  File: /tmp/x
  Size: 7               Blocks: 8          IO Block: 4096   regular file
Device: 803h/2051d      Inode: 531866      Links: 1
Access: (0644/-rw-r--r--)  Uid: (16894/bwiedemann)   Gid: (   50/    suse)
Access: 2019-01-30 15:27:15.605862595 +0100
Modify: 2019-01-30 15:27:16.605862595 +0100
Change: 2019-01-30 15:27:14.605862595 +0100
 Birth: -
75
76

With faketime, the stat results are shifting, when nothing touched the file, which can confuse programs like make.

@wolfcw
Copy link
Owner

wolfcw commented Jan 30, 2019

Yes, I can reproduce that problem.

Could you please try LD_PRELOAD'ing libfaketime.so.1 directly instead of using the faketime wrapper?

LD_PRELOAD=/path/to/libfaketime.so.1 FAKETIME='+0y i1' bash -c "$cmd"

produces the desired output here, and using libfaketime[MT].so.1 directly instead of the wrapper is generally recommended for more advanced use cases.

@bmwiedemann
Copy link
Author

Using plain LD_PRELOAD lacks the other variable for shared memory required for the synchronized counter, so the two echo $SECONDS at the end print the same value

@wolfcw
Copy link
Owner

wolfcw commented Aug 21, 2019

With 0c8905f, the following should work as expected:

FAKETIME_DONT_RESET=1 faketime -f '@2020-02-29 10:20:30 i1' bash -c "$cmd"
FAKETIME_DONT_RESET=1 faketime -f '+1y i1' bash -c "$cmd"

bmwiedemann added a commit to bmwiedemann/reproducible-faketools that referenced this issue Aug 21, 2019
to make the time jump +1 second each time it is queried

Use the fix from wolfcw/libfaketime#183
bmwiedemann added a commit to bmwiedemann/reproducible-faketools that referenced this issue Aug 21, 2019
to make the time jump +1 second each time it is queried

Use the fix from wolfcw/libfaketime#183
bmwiedemann added a commit to bmwiedemann/reproducible-faketools that referenced this issue Aug 21, 2019
to make the time jump +1 second each time it is queried

Use the fix from wolfcw/libfaketime#183
@bmwiedemann
Copy link
Author

This looks good to me. In my tests, stat output remains stable, except for slight sub-second variations (probably because the real clock is used for the touch call so it matters when that is done)

Now I'm wondering, when the 0.9.8 release is planned.

@wolfcw
Copy link
Owner

wolfcw commented Aug 21, 2019

Thanks for testing!

If everything else works out fine, the v0.9.8 release should be out before end of this month.

@wolfcw wolfcw closed this as completed Aug 21, 2019
@bmwiedemann
Copy link
Author

I just discovered one downside: files that have constant time (e.g. extracted from a tarball) change time with different fake time date values.
e.g. do once touch -d@1000000000 /tmp/y
and include it in stat calls.

@wolfcw
Copy link
Owner

wolfcw commented Aug 21, 2019

Yes, I see what you mean. But that's a somewhat fundamental problem... with -DFAKE_STAT, we can either fake the file timestamps for all files or none at all. There practically is no way to keep track of which files have been created/touched during libfaketime run-time and only fake timestamps for those, while reporting the original timestamp for every other file.

Eventually we could add black-/whitelists of filenames for which the stats should be faked (similar to what is already implemented for process names) in a later version, but this wouldn't solve the problem for stat-before-touch files (unless we also have some "reverse limited stat faking" in analogy to the existing "limiting per process").

The basic goal here is some sort of repeatability / determinism. When it also should be "good looking", it might be worth the effort to "touch" the files to the right timestamp within the libfaketime environment before starting their processing.

@bmwiedemann
Copy link
Author

I could imagine, that one way would be to intercept write/close/utimensat/futimens calls and touch files in the filesystem to the faked time, so you do not have to track them yourself.
This could also get rid of the sub-second variations in the original reproducer.

@wolfcw
Copy link
Owner

wolfcw commented Aug 21, 2019

Agreed - although pushing the faked time through to the file system will leave the "read only" characteristic (= all the faked times are limited to the one process running with libfaketime), which libfaketime has so far, behind.

There's quite a queue of additional system calls that libfaketime should intercept, so I can't make any promises when this will be done. If you're interested in contributing or know someone, I'd be happy for any assistance.

@wolfcw wolfcw reopened this Aug 21, 2019
@wolfcw wolfcw changed the title stat results are faked incorrectly Intercept calls that change file timestamps Sep 3, 2019
@wolfcw
Copy link
Owner

wolfcw commented Sep 3, 2019

Apparently a lot more system calls trigger updates of the file's atime and must be considered when implementing this.

Also, while atime and mtime can be set rather easily, faking the ctime seems to be challenging.

Contributors wanted. :-)

@speq
Copy link

speq commented Nov 6, 2019

I've made a simple and dirty patch on utime() and utimes(), just for a simple application i used.
You may need also preload utimensat() and futimens() for program like touch.

utimes.patch.gz

@sdettmer
Copy link

@bmwiedemann I considered a similar situation for embedded builds but I think it won't work this way, because of concurrency:

I am working on reproducible builds for openSUSE and there I would like to use libfaketime to make software behave exactly as if date+time were

  • in the future
  • deterministic (this is why I use the i1 param)

e.g. I would like to use faketime -f '@2020-01-01 01:01:01 i1'

I think this won't work well in practice, because the build process may create parallel processes and these may race for who calls some gettime first; depending on many aspects like number of cores, performance, load and who knows what else...

@bmwiedemann Do you have an idea how to work around this? Binding everything on single core and avoid parallelism somehow?

@paexlegends
Copy link

@bmwiedemann hello dear sorry for interpreting the convo ,i'm newbie ,i need little help i'm running opensuse tumbleweed under virtual machine i would like to know how I can manage to intercept time in firefox with libfaketime library would please list all commands to achieve that ,i struggled many time during a month with no result

bmwiedemann added a commit to bmwiedemann/reproducible-faketools that referenced this issue Jan 28, 2022
to make the time jump +1 second each time it is queried

Use the fix from wolfcw/libfaketime#183
bmwiedemann added a commit to bmwiedemann/reproducible-faketools that referenced this issue Jan 28, 2022
to make the time jump +1 second each time it is queried

Use the fix from wolfcw/libfaketime#183
bmwiedemann added a commit to bmwiedemann/reproducible-faketools that referenced this issue Jan 28, 2022
to make the time jump +1 second each time it is queried

Use the fix from wolfcw/libfaketime#183
@wolfcw
Copy link
Owner

wolfcw commented Feb 20, 2022

I'm afraid we haven't found anyone wanting to help on this within more than 3 years, so I'm closing this issue. Feel free to reopen if you can contribute.

@wolfcw wolfcw closed this as completed Feb 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants