From b9ad6f1e954a68640d01176e597af03ec9281e35 Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Fri, 9 Jan 2015 01:26:41 -0600 Subject: 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 --- src/libr-bfd.c | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'src') 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 #include #include +#include /* * 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); -- cgit v1.2.3