Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I check if two FILE* or file descriptor numbers refer to the same file?

Tags:

c

I have a program that reads from a file and writes to a file. I'd like to prevent the user from specifying the same file for both (for obvious reasons). Lets say the first path is in char* path1 and the second path is in char* path2. can I fopen() both paths, call fileno() on each and get the same number?

To explain more clearly:

char* path1 = "/asdf"
char* path2 = "/asdf"

FILE* f1 = fopen(path1, "r");
FILE* f2 = fopen(path2, "w");

int fd1 = fileno(f1);
int fd2 = fileno(f2);

if(fd1 == fd2) {
  printf("These are the same file, you really shouldn't do this\n");
}

EDIT:

I do not want to compare filenames because one could easily defeat that with paths like /asdf/./asdf or by using symlinks. Ultimately, I do not want to write my output into the file that I'm reading from (could cause serious issues).

like image 228
Huckle Avatar asked Sep 19 '12 20:09

Huckle


People also ask

Can two file descriptors point to the same file?

Pointers to the Open File Table: One process can have multiple file descriptors point to the same entry (e.g., as a result of a call to dup() ) Multiple processes (e.g., a parent and child) can have file descriptors that point to the same entry.

What's the relationship between a file * and a file descriptor?

A FILE pointer is a C standard library-level construct, used to represent a file. The FILE wraps the file descriptor, and adds buffering and other features to make I/O easier.

How do I check if a file descriptor exists?

fcntl(fd, F_GETFD) is the canonical cheapest way to check that fd is a valid open file descriptor. If you need to batch-check a lot, using poll with a zero timeout and the events member set to 0 and checking for POLLNVAL in revents after it returns is more efficient.


1 Answers

Yes - compare the file device ID and inode. Per the <sys/stat.h> specification:

The st_ino and st_dev fields taken together uniquely identify the file within the system.

Use

int same_file(int fd1, int fd2) {
    struct stat stat1, stat2;
    if(fstat(fd1, &stat1) < 0) return -1;
    if(fstat(fd2, &stat2) < 0) return -1;
    return (stat1.st_dev == stat2.st_dev) && (stat1.st_ino == stat2.st_ino);
}
like image 145
nneonneo Avatar answered Sep 24 '22 20:09

nneonneo