diff options
author | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2015-01-09 01:26:41 -0600 |
---|---|---|
committer | Timothy Pearson <kb9vqf@pearsoncomputing.net> | 2015-01-09 01:26:41 -0600 |
commit | b9ad6f1e954a68640d01176e597af03ec9281e35 (patch) | |
tree | 2428dd8869a2754e3ade86aff5d64f462b6f67c6 | |
parent | ff4002f7a42db78228975b1c492cd8afa22df886 (diff) | |
download | libr-b9ad6f1e954a68640d01176e597af03ec9281e35.tar.gz libr-b9ad6f1e954a68640d01176e597af03ec9281e35.zip |
Alter safe_rename behaviour to more closely match that of rename()
This resolves bus errors on tdelibs build when using cross-device /tmp due to truncating libraries that tdelfeditor relies on when updating their metadata
-rw-r--r-- | src/libr-bfd.c | 25 |
1 files changed, 21 insertions, 4 deletions
diff --git a/src/libr-bfd.c b/src/libr-bfd.c index 338cd81..9d6d263 100644 --- a/src/libr-bfd.c +++ b/src/libr-bfd.c @@ -43,6 +43,7 @@ #include <unistd.h> #include <stdlib.h> #include <stdio.h> +#include <limits.h> /* * Build the libr_file handle for processing with libbfd @@ -324,12 +325,28 @@ int safe_rename(const char *old, const char *new) size_t read; int status_in; int status_out; - + char linkdest[PATH_MAX]; + char linkdest_test[PATH_MAX]; + int ret; + int is_symlink = 0; + ret = readlink(new, linkdest_test, PATH_MAX); + while (ret >= 0) { + // Symlink encountered + is_symlink = 1; + linkdest_test[ret] = 0; + char* cwd = getcwd(NULL, 0); + snprintf(linkdest, PATH_MAX, "%s/%s", cwd, linkdest_test); + free(cwd); + ret = readlink(linkdest, linkdest_test, PATH_MAX); + } + in = fopen(old, "r"); if(!in) { return -1; } - out = fopen(new, "w"); + // Avoid bus error if modifying a library we are currently using + unlink((is_symlink)?linkdest:new); + out = fopen((is_symlink)?linkdest:new, "w"); if(!out) { fclose(in); return -1; @@ -342,7 +359,7 @@ int safe_rename(const char *old, const char *new) if (ferror(in) || ferror(out)) { fclose(in); fclose(out); - remove(new); + remove((is_symlink)?linkdest:new); return -1; } } @@ -351,7 +368,7 @@ int safe_rename(const char *old, const char *new) fclose(in); fclose(out); if(status_in || status_out) { - remove(new); + remove((is_symlink)?linkdest:new); return -1; } return remove(old); |