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
pull/2/head
Timothy Pearson 10 years ago
parent ff4002f7a4
commit b9ad6f1e95

@ -43,6 +43,7 @@
#include <unistd.h> #include <unistd.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <limits.h>
/* /*
* Build the libr_file handle for processing with libbfd * 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; size_t read;
int status_in; int status_in;
int status_out; 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"); in = fopen(old, "r");
if(!in) { if(!in) {
return -1; 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) { if(!out) {
fclose(in); fclose(in);
return -1; return -1;
@ -342,7 +359,7 @@ int safe_rename(const char *old, const char *new)
if (ferror(in) || ferror(out)) { if (ferror(in) || ferror(out)) {
fclose(in); fclose(in);
fclose(out); fclose(out);
remove(new); remove((is_symlink)?linkdest:new);
return -1; return -1;
} }
} }
@ -351,7 +368,7 @@ int safe_rename(const char *old, const char *new)
fclose(in); fclose(in);
fclose(out); fclose(out);
if(status_in || status_out) { if(status_in || status_out) {
remove(new); remove((is_symlink)?linkdest:new);
return -1; return -1;
} }
return remove(old); return remove(old);

Loading…
Cancel
Save