9

I have a program that accepts two file names as arguments: it reads the first file in order to create the second file. How can I ensure that the program won't overwrite the first file?

Restrictions:

  • The method must keep working when the file system supports (soft or hard) links
  • File permissions are fixed and it is only required that the first file is readable and the second file writeable
  • It should preferably be platform-neutral (although Linux is the primary target)
1
  • 8
    In the UNIX and Linux philosophy, such a program is called a filter. It usually reads from the standard input (STDIN) and writes to the standard output (STDOUT). This eases writing such programs as it defers the responsibility of such verifications to the caller. Your program can concentrate on doing its job. Commented Jan 11, 2010 at 14:09

6 Answers 6

14

On linux, open both files, and use fstat to check if st_ino (edit:) and st_dev are the same. open will follow symbolic links. Don't use stat directly, to prevent race conditions.

2
  • 4
    The race condition means that the file status might change between stat(2) and open(2). You do stat, and then some user unlinks the file you've just stated and links your second file to the one you're just about to open(2). Just a clarification. Commented Jan 11, 2010 at 13:49
  • 8
    Also make sure the st_dev fields match. There's nothing preventing different files on two different volumes from having the same inode number. Commented Jan 11, 2010 at 14:32
9

The best bet is not to use filenames as identities. Instead, when you open the file for reading, lock it, using whatever mechanism your OS supports. When you then also open the file for writing, also lock it - if the lock fails, report an error.

1
3

If possible, open the first file read-only, (O_RDONLY) in LINUX. Then, if you try to open it again to write to it, you will get an error.

1
  • 1
    You will get false positives if the second file is already open read-only by another process. I'm not even sure the universal solution is possible (you have to resort to file-system-specific features like getting file IDs).
    – Costique
    Commented Jan 11, 2010 at 13:37
1

If you mean the same inode, in bash, you could do

[ FILE1 -ef FILE2 ] && echo equal || echo difference

Combined with realpath/readlink, that should handle the soft-links as well.

0

You can use stat to get the file status, and check if the inode numbers are the same.

0

Maybe you could use the system() function in order to invoke some shell commands?

In bash, you would simply call:

stat -c %i filename

This displays the inode number of a file. You can compare two files this way and if their inodes are identical, it means they are hard links. The following call:

stat -c %N filename

will display the file's name and if it's a symbolic link, it'll print the file name it links to as well. It prints out only one name, even if the file it points to has hard links, so checking the symbolic link would require comparing inode numbers for the 2nd file and the file the symbolic links links to in order to make sure.

You could redirect stat output to a text file and then parse the file in your program.

3
  • 2
    Not my downvote, but there is rarely a point in shelling out to run a command to convert data to text and then parsing the text. On unix systems the SEE ALSO section of the man page will generally tell you what function the command line utilities are calling to achieve their work. In this case man 1 stat tells me about lstat(2) and stat(2) which share a man page with fstat(2), so you can get to the optimal answer pretty easily. Commented Jan 11, 2010 at 14:21
  • In general, I thing calling system() is a Bad Thing (tm). Just suggested a possibility, although I recognise it's suboptimal.
    – mingos
    Commented Jan 11, 2010 at 22:41
  • +1. Sure, for C program such practice is questionable at least, so technically this answer is bad. On the other hand, if someone needs to test inodes in shell script - this answer is great. In that case, writing and building small C utility would be reinvention of the wheel. OP asked specifically for C solution, but remember, someone else (like myself) can still google up this question.
    – Przemek
    Commented Oct 25, 2020 at 8:51

Not the answer you're looking for? Browse other questions tagged or ask your own question.