...
In this non-compliant code example, a file is moved using rename()
.
Code Block | ||
---|---|---|
| ||
/* program code */ char const *old = "oldfile.ext"/* ... */; char const *new = "newfile.ext" /* ... */; if (rename(old, new) != 0) { /* Handle rename failureError */ } /* program code */ |
If newfile.ext
the named by new
exists at the time of the call to rename()
, the result is implementation-defined.
...
This compliant solution checks for the existence of the new file before callling rename()
. This code contains an unavoidable race condition between the call to fopen()
and the call to rename()
. Consequently, this code can only be safely executed within a secure directory.
Code Block | ||
---|---|---|
| ||
/* program code */ char const *old = "oldfile.ext"/* ... */; char const *new = "newfile.ext" /* ... */; FILE *file = fopen(new, "r"); if (!file) { if (rename(old, new) != 0) { /* Handle rename failureError */ } } else { fclose(file); /* handle error condition Error */ } |
Unfortunately, fopen()
may fail on many file systems when the file exists but the program does not have sufficient permissions to read it.
Compliant Solution (POSIX)
Wiki Markup |
---|
A somewhat better solution involves using the POSIX {{access()}} function which can check for the existence of a file explicitly \[[Open Group 04|AA. C References#Open Group 04]\]. |
Code Block | ||
---|---|---|
| ||
char const *old = /* ... */; char const *new = /* ... */; if (access(new,F_OK) != 0) { if (rename(old, new) != 0) { /* Handle Error */ } } else { /* programHandle codeError */ } |
While the likelihood of access()
returning a false negative is lower than that of fopen()
, on file systems where the program does not have sufficient permissions in the directory to view the file, access()
may return -1
even when the file exists. In such cases, rename()
will also likely fail since the program does not have adequate permissions inside the directory.
Risk Assessment
Calling rename()
has implementation-defined behavior when the new file name refers to an existing file. Incorrect use of rename()
can result in a file being unexpectedly overwritten or other unexpected behavior.
...
Wiki Markup |
---|
\[[ISO/IEC 9899:1999|AA. C References#ISO/IEC 9899-1999]\] Section 7.9.4.2, "The {{rename}} function"
\[[Open Group 04|AA. C References#Open Group 04]\] [{{access()}}|http://www.opengroup.org/onlinepubs/009695399/functions/access.html] |
...
FIO09-A. Be careful with binary data when transferring data across systems 09. Input Output (FIO) FIO11-A. Take care when specifying the mode parameter of fopen()