Skip to content

Instantly share code, notes, and snippets.

@makotom
Created January 29, 2019 12:32
Show Gist options
  • Save makotom/02cc431bef274fad657907798a9595b3 to your computer and use it in GitHub Desktop.
Save makotom/02cc431bef274fad657907798a9595b3 to your computer and use it in GitHub Desktop.
Let's learn about open(2) (called by fopen(3))
#include <stdio.h>
#include <unistd.h>
#define TEST_TXT "test.txt"
void phase1(void) {
FILE * fp = fopen(TEST_TXT, "w");
fprintf(fp, "hoge\n");
fclose(fp);
sleep(10); // During this, try `$ cat test.txt`
}
void phase2(void) {
FILE * fp = fopen(TEST_TXT, "w");
fprintf(fp, "fuga\n");
sleep(10); // During this, try `$ cat test.txt`
fclose(fp);
}
int main(void) {
phase1();
phase2();
return 0;
}
@makotom
Copy link
Author

makotom commented Jan 29, 2019

$ cat test.txt twice as instructed.
You should find that

  1. you get hoge on the first attempt, and
  2. you get nothing (neither hoge nor fuga) on the second attempt.

In this code fopen(3) is called with w option. This calls syscall open(2) with O_TRUNC set. On Linux, open(2) calls do_truncate, as a result of calling do_sys_open, do_filp_open, path_openat, do_last, and handle_truncate. Since do_truncate instantly updates inode upon call, the target file becomes empty immediately. Changes made by fprintf(3) in this code would not be flushed until fclose(3) called.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment