...
This code example is noncompliant because any existing destination file is removed by rename()
.:
Code Block | ||||
---|---|---|---|---|
| ||||
const char *src_file = /* ... */; const char *dest_file = /* ... */; if (rename(src_file, dest_file) != 0) { /* Handle Error */ } |
...
If the programmer's intent is not to remove an existing destination file, the POSIX access()
function can be used to check for the existence of a file [Open Group 2004]. This compliant solution renames the source file only if the destination file does not exist.:
Code Block | ||||
---|---|---|---|---|
| ||||
const char *src_file = /* ... */; const char *dest_file = /* ... */; if (access(dest_file, F_OK) != 0) { if (rename(src_file, dest_file) != 0) { /* Handle error condition */ } } else { /* Handle file-exists condition */ } |
...
If the intent of the programmer is to remove the file referenced by dest_file
if it exists prior to calling rename()
, this code example is noncompliant on Windows platforms because rename()
will fail.:
Code Block | ||||
---|---|---|---|---|
| ||||
const char *src_file = /* ... */; const char *dest_file = /* ... */; if (rename(src_file, dest_file) != 0) { /* Handle error */ } |
...
On Windows systems, it is necessary to explicitly remove the destination file before calling rename()
if you want the file to be overwritten and the rename()
operation to succeed.:
Code Block | ||||
---|---|---|---|---|
| ||||
const char *src_file = /* ... */; const char *dest_file = /* ... */; if (_access_s(dest_file, 0) == 0) { if (remove(dest_file) != 0) { /* Handle error condition */ } } if (rename(src_file, dest_file) != 0) { /* Handle error condition */ } |
This code contains unavoidable race conditions between the calls to _access_s()
, remove()
, and rename()
and can consequently be safely executed only within a secure directory. (See FIO15-C. Ensure that file operations are performed in a secure directory.) Another option would be to use the MoveFileEx API, and pass in the MOVEFILE_REPLACE_EXISTING
flag.:
Code Block | ||||
---|---|---|---|---|
| ||||
const char *src_file = /* ... */; const char *dest_file = /* ... */; if (!MoveFileEx(src_file, dest_file, MOVEFILE_REPLACE_EXISTING)) { /* Handle error condition */ } |
...
On POSIX systems, if the destination file exists prior to calling rename()
, the file is automatically removed.:
Code Block | ||||
---|---|---|---|---|
| ||||
const char *src_file = /* ... */; const char *dest_file = /* ... */; if (rename(src_file, dest_file) != 0) { /* Handle error condition */ } |
...
This compliant solution ensures that any destination file is portably removed.:
Code Block | ||||
---|---|---|---|---|
| ||||
const char *src_file = /* ... */; const char *dest_file = /* ... */; (void)remove(dest_file); if (rename(src_file, dest_file) != 0) { /* Handle error condition */ } |
...
This compliant solution renames the source file only if the destination file does not exist.:
Code Block | ||||
---|---|---|---|---|
| ||||
const char *src_file = /* ... */; const char *dest_file = /* ... */; if (!file_exists(dest_file)) { if (rename(src_file, dest_file) != 0) { /* Handle error condition */ } } else { /* Handle file-exists condition */ } |
...