user1011471
user1011471

Reputation: 1130

How to test existence of 'file' that cannot be accessed?

I have a full path stored in char full_path[1000] and I'd like to know whether anything exists at that location.

(The next thing my code would do after this check is create something at that location, but I want it to count as an error if there is already something there instead of clearing the spot with the equivalent of rm -rf)

The spot might be occupied by a file or a directory or even a link to some no-longer-existing-target e.g.:

lrwxrwxrwx 1 user grp 4 Jun 16 20:02 a-link -> non-existent-thing

With an invalid link, access(full_path, F_OK) is going to tell me I can't access full_path and that could be because (1) nothing exists there or because (2) the link is invalid.

Given that, what's the best way to determine if anything exists at full_path?

Upvotes: 0

Views: 96

Answers (2)

user1011471
user1011471

Reputation: 1130

Since the next thing we plan to do is create something at that location, and since we want to treat it as an error if something already exists there, then let's not bother checking. Just attempt the create and exit with an error if it fails. The create step uses symlink so if it fails we can use strerror(errno) for the explanation of any failure.

To create a file in general (vs just a symlink), EOF points out in comments that open(path, O_CREAT|O_EXCL, mode) will return failure (-1) if the file already exists, and create the file otherwise. This is atomic and safe (unlike trying to stat) and guaranteed to work atomically on POSIX (with the possible exception of NFS).

Upvotes: 0

Zach P
Zach P

Reputation: 1791

You simply cannot do that in a cross-platform obvious way. stat() and fopen() would not work. You can, though, use the OS API, for example, on windows you could use WinAPI with the example code:

int doesFileExist(TCHAR* path)
{
   WIN32_FIND_DATA FindFileData;
   HANDLE handle = FindFirstFile(path, &FindFileData) ;
   int found = (handle != INVALID_HANDLE_VALUE);
   if(found) 
   {
       FindClose(handle);
   }
   return found;
}

If you just want to check if anything exists, finding any file (again, using Windows API) would also work, you could just go directory by directory to check if it exists, if one doesn't - return an error. Keep going until you got to the directory then check for the certain file in the way mentioned above.

Say you have C:/Dir1/Dir2/Dir3/file.txt then you'd go to C: first, then check if Dir1 exists, if it does - go to it, if it doesn't return an error. Same for Dir2 and so on up until you get to the last directory and check for the file OR if you don't check for a certain file and for any item - just try using the functions mentioned in MSDN for finding first file or first directory.

Upvotes: 1

Related Questions