Versions Compared

Key

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

...

Occasionally, a programmer might want to implements implement a behavior other than the implementation-defined behavior for rename() on that platform. If the desired behavior is to ensure that any file referenced by new_file is removed, Windows programmers must write additional code.

...

Code Block
bgColor#ccccff
char const *old_file = /* ... */;
char const *new_file = /* ... */;

if (_access_s(new_file,0) == 0) {
  if (remove(new_file) != 0) {
    /* Handle error condition */
  }
}

if (rename(old_file, new_file) != 0) {
  /* Handle error condition */
}

This code contains an unavoidable race conditions between the calls to _access_s(), remove() and rename() and can consequently only be safely executed within a secure directory (see FIO17-A. Ensure that file operations are performed in a secure directory).

...

Wiki Markup
If the intent of the programmer is to not remove the file referenced by {{new_file}} if it exists prior to calling {{rename()}}, the POSIX {{access()}} function can be whichused canto check for the existence of a file explicitly \[[Open Group 04|AA. C References#Open Group 04]\]. This compliant solution only renames the file referenced by {{old_file}} if the file referenced by {{new_file}} does not exist.

Code Block
bgColor#ccccff
char const *old_file = /* ... */;
char const *new_file = /* ... */;

if (access(new_file, F_OK) != 0) {
  if (rename(old_file, new_file) != 0) {
    /* Handle error condition */
  }
} 
else {
  /* Handle errorfile-exists condition */
}

This code contains an unavoidable race condition between the call to access() and the call to rename() and can consequently only be safely executed within a secure directory (see FIO17-A. Ensure that file operations are performed in a secure directory).

While the likelihood of access() returning a false negative is lower than that of fopen(), on 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() would also fail because the program lacks adequate permissions to perform the operation.

...

Portable Behavior

A programmer that wants to an application to behave the same on any C99 implementation must first determine what behavior to implement.

...

Code Block
bgColor#ccccff
char const *old_file = /* ... */;
char const *new_file = /* ... */;

if(void) (remove(new_file) != 0) {
  /* Handle error condition */
}

;

if (rename(old_file, new_file) != 0) {
  /* Handle error condition */
}

This code contains an unavoidable race condition between the call to remove() and the call to rename() and can consequently only be safely executed within a secure directory (see FIO17-A. Ensure that file operations are performed in a secure directory).

The return value of remove() is deliberately not checked, because it is expected to fail in the case where the file does not exist. If the file exists but cannot be removed, the rename() call will also fail and the error will be detected at that point.

Compliant Solution (New File Not Removed)

...

Code Block
bgColor#ccccff
char const *old_file = /* ... */;
char const *new_file = /* ... */;

if (access!file_exists(new_file, F_OK) != 0) {
  if (rename(old_file, new_file) != 0) {
    /* Handle error condition */
  }
} 
else {
  /* Handle errorfile-exists condition */
}

This code contains an unavoidable race condition between the call to removefile_exists() and the call to rename() and can consequently only be safely executed within a secure directory (see FIO17-A. Ensure that file operations are performed in a secure directory).

The file_exists() function is provided by the application, and is not shown here as it needs to be implemented differently on different platforms. (On POSIX systems it would use access(), on Windows _access_s(), and on other platforms whatever function is available to test file existence.)

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.

...