| From 17d57a2a923a4af53c8910a9999aebeab3f5d83a Mon Sep 17 00:00:00 2001 |
| From: Robert Yang <liezhi.yang@windriver.com> |
| Date: Tue, 17 Feb 2015 21:08:07 -0800 |
| Subject: [PATCH] Act as the "mv" command when rotate log |
| |
| Act as the "mv" command when rotate log, first rename, if failed, then |
| read and write. |
| |
| Upstream-Status: Pending |
| |
| Signed-off-by: Robert Yang <liezhi.yang@windriver.com> |
| |
| --- |
| logrotate.c | 71 ++++++++++++++++++++++++++++++++++++++++++++--------- |
| 1 file changed, 59 insertions(+), 12 deletions(-) |
| |
| diff --git a/logrotate.c b/logrotate.c |
| index 45b3eb6..231371a 100644 |
| --- a/logrotate.c |
| +++ b/logrotate.c |
| @@ -1463,6 +1463,53 @@ static int findNeedRotating(const struct logInfo *log, unsigned logNum, int forc |
| return 0; |
| } |
| |
| +/* Act as the "mv" command, if rename failed, then read the old file and |
| + * write to new file. The function which invokes the mvFile will use |
| + * the strerror(errorno) to handle the error message, so we don't have |
| + * to print the error message here */ |
| + |
| +int mvFile (char *oldName, char *newName, struct logInfo *log, acl_type acl) |
| +{ |
| + struct stat sbprev; |
| + int fd_old, fd_new, n; |
| + char buf[BUFSIZ]; |
| + |
| + /* Do the rename first */ |
| + if (!rename(oldName, newName)) |
| + return 0; |
| + |
| + /* If the errno is EXDEV, then read old file, write newfile and |
| + * remove the oldfile */ |
| + if (errno == EXDEV) { |
| + /* Open the old file to read */ |
| + if ((fd_old = open(oldName, O_RDONLY)) < 0) |
| + return 1; |
| + |
| + /* Create the file to write, keep the same attribute as the old file */ |
| + if (stat(oldName, &sbprev)) |
| + return 1; |
| + else { |
| + if ((fd_new = createOutputFile(newName, |
| + O_WRONLY | O_CREAT | O_TRUNC, &sbprev, acl, 0)) < 0 ) |
| + return 1; |
| + } |
| + |
| + /* Read and write */ |
| + while ((n = read(fd_old, buf, BUFSIZ)) > 0) |
| + if (write(fd_new, buf, n) != n) |
| + return 1; |
| + |
| + if ((close(fd_old) < 0) || |
| + removeLogFile(oldName, log) || |
| + (close(fd_new) < 0)) |
| + return 1; |
| + |
| + return 0; |
| + } |
| + |
| + return 1; |
| +} |
| + |
| /* find the rotated file with the highest index */ |
| static int findLastRotated(const struct logNames *rotNames, |
| const char *fileext, const char *compext) |
| @@ -1958,15 +2005,15 @@ static int prerotateSingleLog(const struct logInfo *log, unsigned logNum, |
| } |
| |
| message(MESS_DEBUG, |
| - "renaming %s to %s (rotatecount %d, logstart %d, i %d), \n", |
| + "moving %s to %s (rotatecount %d, logstart %d, i %d), \n", |
| oldName, newName, rotateCount, logStart, i); |
| |
| - if (!debug && rename(oldName, newName)) { |
| + if (!debug && mvFile(oldName, newName, log, prev_acl)) { |
| if (errno == ENOENT) { |
| message(MESS_DEBUG, "old log %s does not exist\n", |
| oldName); |
| } else { |
| - message(MESS_ERROR, "error renaming %s to %s: %s\n", |
| + message(MESS_ERROR, "error moving %s to %s: %s\n", |
| oldName, newName, strerror(errno)); |
| hasErrors = 1; |
| } |
| @@ -2051,10 +2098,10 @@ static int rotateSingleLog(const struct logInfo *log, unsigned logNum, |
| return 1; |
| } |
| |
| - message(MESS_DEBUG, "renaming %s to %s\n", log->files[logNum], |
| + message(MESS_DEBUG, "moving %s to %s\n", log->files[logNum], |
| tmpFilename); |
| - if (!debug && !hasErrors && rename(log->files[logNum], tmpFilename)) { |
| - message(MESS_ERROR, "failed to rename %s to %s: %s\n", |
| + if (!debug && !hasErrors && mvFile(log->files[logNum], rotNames->finalName, log, prev_acl)) { |
| + message(MESS_ERROR, "failed to move %s to %s: %s\n", |
| log->files[logNum], tmpFilename, |
| strerror(errno)); |
| hasErrors = 1; |
| @@ -2063,11 +2110,11 @@ static int rotateSingleLog(const struct logInfo *log, unsigned logNum, |
| free(tmpFilename); |
| } |
| else { |
| - message(MESS_DEBUG, "renaming %s to %s\n", log->files[logNum], |
| + message(MESS_DEBUG, "moving %s to %s\n", log->files[logNum], |
| rotNames->finalName); |
| if (!debug && !hasErrors && |
| - rename(log->files[logNum], rotNames->finalName)) { |
| - message(MESS_ERROR, "failed to rename %s to %s: %s\n", |
| + mvFile(log->files[logNum], rotNames->finalName, log, prev_acl)) { |
| + message(MESS_ERROR, "failed to move %s to %s: %s\n", |
| log->files[logNum], rotNames->finalName, |
| strerror(errno)); |
| hasErrors = 1; |
| @@ -2480,7 +2527,7 @@ static int rotateLogSet(const struct logInfo *log, int force) |
| return hasErrors; |
| } |
| |
| -static int writeState(const char *stateFilename) |
| +static int writeState(struct logInfo *log, char *stateFilename) |
| { |
| struct logState *p; |
| FILE *f; |
| @@ -2659,7 +2706,7 @@ static int writeState(const char *stateFilename) |
| fclose(f); |
| |
| if (error == 0) { |
| - if (rename(tmpFilename, stateFilename)) { |
| + if (mvFile(tmpFilename, stateFilename, log, prev_acl)) { |
| message(MESS_ERROR, "error renaming temp state file %s to %s: %s\n", |
| tmpFilename, stateFilename, strerror(errno)); |
| unlink(tmpFilename); |
| @@ -3073,7 +3120,7 @@ int main(int argc, const char **argv) |
| rc |= rotateLogSet(log, force); |
| |
| if (!debug) |
| - rc |= writeState(stateFile); |
| + rc |= writeState(log, stateFile); |
| |
| return (rc != 0); |
| } |