* Use str_eq() instead of strcmp() when testing for string (in)equality.
* Consider using str_startswith() instead of strncmp().
* Use bool, true and false for boolean values.
+* Use tmp_unlink() or x_unlink() instead of unlink().
+* Use x_rename() instead of rename().
Other
-----
/* delete intermediate pre-processor file if needed */
if (i_tmpfile) {
if (!direct_i_file) {
- unlink(i_tmpfile);
+ tmp_unlink(i_tmpfile);
}
free(i_tmpfile);
i_tmpfile = NULL;
/* delete the cpp stderr file if necessary */
if (cpp_stderr) {
- unlink(cpp_stderr);
+ tmp_unlink(cpp_stderr);
free(cpp_stderr);
cpp_stderr = NULL;
}
if (stat(tmp_stdout, &st) != 0 || st.st_size != 0) {
cc_log("Compiler produced stdout");
stats_update(STATS_STDOUT);
- unlink(tmp_stdout);
- unlink(tmp_stderr);
- unlink(tmp_obj);
+ tmp_unlink(tmp_stdout);
+ tmp_unlink(tmp_stderr);
+ tmp_unlink(tmp_obj);
failed();
}
- unlink(tmp_stdout);
+ tmp_unlink(tmp_stdout);
/*
* Merge stderr from the preprocessor (if any) and stderr from the real
close(fd_cpp_stderr);
close(fd_real_stderr);
close(fd_result);
- unlink(tmp_stderr2);
+ tmp_unlink(tmp_stderr2);
free(tmp_stderr2);
}
/* we can use a quick method of getting the failed output */
copy_fd(fd, 2);
close(fd);
- unlink(tmp_stderr);
+ tmp_unlink(tmp_stderr);
exit(status);
}
}
- unlink(tmp_stderr);
- unlink(tmp_obj);
+ tmp_unlink(tmp_stderr);
+ tmp_unlink(tmp_obj);
failed();
}
added_bytes += file_size(&st);
added_files += 1;
} else {
- unlink(tmp_stderr);
+ tmp_unlink(tmp_stderr);
}
if (move_uncompressed_file(tmp_obj, cached_obj, enable_compression) != 0) {
cc_log("Failed to move %s to %s", tmp_obj, cached_obj);
if (status != 0) {
if (!direct_i_file) {
- unlink(path_stdout);
+ tmp_unlink(path_stdout);
}
- unlink(path_stderr);
+ tmp_unlink(path_stderr);
cc_log("Preprocessor gave exit status %d", status);
stats_update(STATS_PREPROCESSOR);
failed();
hash_delimiter(hash, "unifycpp");
if (unify_hash(hash, path_stdout) != 0) {
stats_update(STATS_ERROR);
- unlink(path_stderr);
+ tmp_unlink(path_stderr);
cc_log("Failed to unify %s", path_stdout);
failed();
}
hash_delimiter(hash, "cpp");
if (!process_preprocessed_file(hash, path_stdout)) {
stats_update(STATS_ERROR);
- unlink(path_stderr);
+ tmp_unlink(path_stderr);
failed();
}
}
*/
cpp_stderr = path_stderr;
} else {
- unlink(path_stderr);
+ tmp_unlink(path_stderr);
free(path_stderr);
}
if (str_eq(output_obj, "/dev/null")) {
ret = 0;
} else {
- unlink(output_obj);
+ x_unlink(output_obj);
/* only make a hardlink if the cache file is uncompressed */
if (getenv("CCACHE_HARDLINK") && !file_is_compressed(cached_obj)) {
ret = link(cached_obj, output_obj);
stats_update(STATS_ERROR);
failed();
}
- unlink(output_obj);
- unlink(cached_stderr);
- unlink(cached_obj);
- unlink(cached_dep);
+ x_unlink(output_obj);
+ x_unlink(cached_stderr);
+ x_unlink(cached_obj);
+ x_unlink(cached_dep);
return;
} else {
cc_log("Created %s from %s", output_obj, cached_obj);
}
if (produce_dep_file) {
- unlink(output_dep);
+ x_unlink(output_dep);
/* only make a hardlink if the cache file is uncompressed */
if (getenv("CCACHE_HARDLINK") && !file_is_compressed(cached_dep)) {
ret = link(cached_dep, output_dep);
stats_update(STATS_ERROR);
failed();
}
- unlink(output_obj);
- unlink(output_dep);
- unlink(cached_stderr);
- unlink(cached_obj);
- unlink(cached_dep);
+ x_unlink(output_obj);
+ x_unlink(output_dep);
+ x_unlink(cached_stderr);
+ x_unlink(cached_obj);
+ x_unlink(cached_dep);
return;
} else {
cc_log("Created %s from %s", output_dep, cached_dep);
cc_log("Hash from manifest doesn't match preprocessor output");
cc_log("Likely reason: different CCACHE_BASEDIRs used");
cc_log("Removing manifest as a safety measure");
- unlink(manifest_path);
+ x_unlink(manifest_path);
put_object_in_manifest = true;
}
bool is_full_path(const char *path);
void update_mtime(const char *path);
int x_rename(const char *oldpath, const char *newpath);
+int x_unlink(const char *path);
+int tmp_unlink(const char *path);
char *x_readlink(const char *path);
char *read_text_file(const char *path);
bool read_file(const char *path, size_t size_hint, char **data, size_t *size);
if (strstr(p, ".tmp.") != NULL) {
/* delete any tmp files older than 1 hour */
if (st->st_mtime + 3600 < time(NULL)) {
- unlink(fname);
+ x_unlink(fname);
goto out;
}
}
static void
delete_file(const char *path, size_t size)
{
- if (unlink(path) == 0) {
+ if (x_unlink(path) == 0) {
cache_size -= size;
files_in_cache--;
} else if (errno != ENOENT) {
}
free(p);
- unlink(fname);
+ x_unlink(fname);
}
/* wipe all cached files in all subdirs */
if (pid == 0) {
int fd;
- unlink(path_stdout);
+ tmp_unlink(path_stdout);
fd = open(path_stdout, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666);
if (fd == -1) {
exit(1);
dup2(fd, 1);
close(fd);
- unlink(path_stderr);
+ tmp_unlink(path_stderr);
fd = open(path_stderr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666);
if (fd == -1) {
exit(1);
if (write(fd, my_content, strlen(my_content)) == -1) {
cc_log("lockfile_acquire: write %s: %s", lockfile, strerror(errno));
close(fd);
- unlink(lockfile);
+ x_unlink(lockfile);
goto out;
}
close(fd);
{
char *lockfile = format("%s.lock", path);
cc_log("Releasing lock %s", lockfile);
- unlink(lockfile);
+ tmp_unlink(lockfile);
free(lockfile);
}
char *fname;
fname = format("%s/stats", cache_dir);
- unlink(fname);
+ x_unlink(fname);
free(fname);
for (dir = 0; dir <= 0xF; dir++) {
gzclose(gz_out);
}
close(fd_out);
- unlink(tmp_name);
+ tmp_unlink(tmp_name);
free(tmp_name);
return -1;
}
if (fd_out != -1) {
close(fd_out);
}
- unlink(tmp_name);
+ tmp_unlink(tmp_name);
free(tmp_name);
return -1;
}
ret = copy_file(src, dest, compress_dest);
if (ret != -1) {
- unlink(src);
+ x_unlink(src);
}
return ret;
}
{
#ifdef _WIN32
/* Windows' rename() refuses to overwrite an existing file. */
- unlink(newpath);
+ unlink(newpath); /* not x_unlink, as x_unlink calls x_rename */
#endif
return rename(oldpath, newpath);
}
+/*
+ * Remove path, NFS hazardous, for temporary files that will not exist
+ * on other systems only. IE the "path" should include tmp_string().
+ */
+int
+tmp_unlink(const char *path)
+{
+ cc_log("Unlink %s (as-tmp)", path);
+ return (unlink(path));
+}
+
+/*
+ * Remove path, safely for NFS
+ */
+int
+x_unlink(const char *path)
+{
+ /* If path is on an NFS share, unlink isn't atomic, so we rename to a temp file */
+ /* We don't care if tempfile is trashed, so it's always safe to unlink it first */
+ const char* tmp_name = format("%s.%s.rmXXXXXX", path, tmp_string());
+ cc_log("Unlink %s via %s", path, tmp_name);
+ if (x_rename(path, tmp_name) == -1) {
+ /* let caller report the error, or not */
+ return -1;
+ }
+ if (unlink(tmp_name) == -1) {
+ /* let caller report the error, or not */
+ return -1;
+ }
+ return 0;
+}
+
#ifndef _WIN32
/* Like readlink() but returns the string or NULL on failure. Caller frees. */
char *