diff options
Diffstat (limited to 'guts/unlinkat.c')
-rw-r--r-- | guts/unlinkat.c | 23 |
1 files changed, 19 insertions, 4 deletions
diff --git a/guts/unlinkat.c b/guts/unlinkat.c index b146602..13fdc82 100644 --- a/guts/unlinkat.c +++ b/guts/unlinkat.c @@ -6,6 +6,10 @@ * wrap_unlinkat(int dirfd, const char *path, int rflags) { * int rc = -1; */ + pseudo_msg_t *old_file; + int save_errno; + struct stat64 buf; + #ifdef PSEUDO_NO_REAL_AT_FUNCTIONS if (dirfd != AT_FDCWD) { errno = ENOSYS; @@ -22,7 +26,6 @@ return -1; } #endif - struct stat64 buf; #ifdef PSEUDO_NO_REAL_AT_FUNCTIONS rc = real___lxstat64(_STAT_VER, path, &buf); @@ -32,15 +35,27 @@ if (rc == -1) { return rc; } + old_file = pseudo_client_op(OP_UNLINK, 0, -1, dirfd, path, &buf); #ifdef PSEUDO_NO_REAL_AT_FUNCTIONS rc = real_unlink(path); #else rc = real_unlinkat(dirfd, path, rflags); #endif - if (rc != -1) { - pseudo_client_op(OP_UNLINK, 0, -1, dirfd, path, &buf); + if (rc == -1) { + save_errno = errno; + if (old_file && old_file->result == RESULT_SUCCEED) { + pseudo_debug(1, "unlink failed, trying to relink...\n"); + buf.st_uid = old_file->uid; + buf.st_gid = old_file->uid; + buf.st_mode = old_file->mode; + buf.st_dev = old_file->dev; + buf.st_ino = old_file->ino; + pseudo_client_op(OP_LINK, 0, -1, dirfd, path, &buf); + } else { + pseudo_debug(1, "unlink failed, but found no database entry, ignoring.\n"); + } + errno = save_errno; } - /* return rc; * } */ |