Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

In this non-compliant code example, a file is moved using rename().

Code Block
bgColor#ffcccc
/* 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
bgColor#ccccff

/* 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
bgColor#ccccff

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()