blob: 2e931a287621d4b28b4bfcbcbae09ef03adabbcb [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001From 68f29ab490cf987aa34b5f4caf1784b58a021308 Mon Sep 17 00:00:00 2001
2From: Robert Yang <liezhi.yang@windriver.com>
3Date: Tue, 17 Feb 2015 21:08:07 -0800
4Subject: [PATCH] Act as the "mv" command when rotate log
5
6Act as the "mv" command when rotate log, first rename, if failed, then
7read and write.
8
9Upstream-Status: Pending
10
11Signed-off-by: Robert Yang <liezhi.yang@windriver.com>
12---
13 logrotate.c | 71 +++++++++++++++++++++++++++++++++++++++++++++++++----------
14 1 file changed, 59 insertions(+), 12 deletions(-)
15
16diff --git a/logrotate.c b/logrotate.c
17index d3deb6a..cf8bf2c 100644
18--- a/logrotate.c
19+++ b/logrotate.c
20@@ -1157,6 +1157,53 @@ int findNeedRotating(struct logInfo *log, int logNum, int force)
21 return 0;
22 }
23
24+/* Act as the "mv" command, if rename failed, then read the old file and
25+ * write to new file. The function which invokes the mvFile will use
26+ * the strerror(errorno) to handle the error message, so we don't have
27+ * to print the error message here */
28+
29+int mvFile (char *oldName, char *newName, struct logInfo *log, acl_type acl)
30+{
31+ struct stat sbprev;
32+ int fd_old, fd_new, n;
33+ char buf[BUFSIZ];
34+
35+ /* Do the rename first */
36+ if (!rename(oldName, newName))
37+ return 0;
38+
39+ /* If the errno is EXDEV, then read old file, write newfile and
40+ * remove the oldfile */
41+ if (errno == EXDEV) {
42+ /* Open the old file to read */
43+ if ((fd_old = open(oldName, O_RDONLY)) < 0)
44+ return 1;
45+
46+ /* Create the file to write, keep the same attribute as the old file */
47+ if (stat(oldName, &sbprev))
48+ return 1;
49+ else {
50+ if ((fd_new = createOutputFile(newName,
51+ O_WRONLY | O_CREAT | O_TRUNC, &sbprev, acl, 0)) < 0 )
52+ return 1;
53+ }
54+
55+ /* Read and write */
56+ while ((n = read(fd_old, buf, BUFSIZ)) > 0)
57+ if (write(fd_new, buf, n) != n)
58+ return 1;
59+
60+ if ((close(fd_old) < 0) ||
61+ removeLogFile(oldName, log) ||
62+ (close(fd_new) < 0))
63+ return 1;
64+
65+ return 0;
66+ }
67+
68+ return 1;
69+}
70+
71 int prerotateSingleLog(struct logInfo *log, int logNum, struct logState *state,
72 struct logNames *rotNames)
73 {
74@@ -1523,15 +1570,15 @@ int prerotateSingleLog(struct logInfo *log, int logNum, struct logState *state,
75 }
76
77 message(MESS_DEBUG,
78- "renaming %s to %s (rotatecount %d, logstart %d, i %d), \n",
79+ "moving %s to %s (rotatecount %d, logstart %d, i %d), \n",
80 oldName, newName, rotateCount, logStart, i);
81
82- if (!debug && rename(oldName, newName)) {
83+ if (!debug && mvFile(oldName, newName, log, prev_acl)) {
84 if (errno == ENOENT) {
85 message(MESS_DEBUG, "old log %s does not exist\n",
86 oldName);
87 } else {
88- message(MESS_ERROR, "error renaming %s to %s: %s\n",
89+ message(MESS_ERROR, "error moving %s to %s: %s\n",
90 oldName, newName, strerror(errno));
91 hasErrors = 1;
92 }
93@@ -1669,21 +1716,21 @@ int rotateSingleLog(struct logInfo *log, int logNum, struct logState *state,
94 return 1;
95 }
96
97- message(MESS_DEBUG, "renaming %s to %s\n", log->files[logNum],
98+ message(MESS_DEBUG, "moving %s to %s\n", log->files[logNum],
99 tmpFilename);
100- if (!debug && !hasErrors && rename(log->files[logNum], tmpFilename)) {
101- message(MESS_ERROR, "failed to rename %s to %s: %s\n",
102+ if (!debug && !hasErrors && mvFile(log->files[logNum], rotNames->finalName, log, prev_acl)) {
103+ message(MESS_ERROR, "failed to move %s to %s: %s\n",
104 log->files[logNum], tmpFilename,
105 strerror(errno));
106 hasErrors = 1;
107 }
108 }
109 else {
110- message(MESS_DEBUG, "renaming %s to %s\n", log->files[logNum],
111+ message(MESS_DEBUG, "moving %s to %s\n", log->files[logNum],
112 rotNames->finalName);
113 if (!debug && !hasErrors &&
114- rename(log->files[logNum], rotNames->finalName)) {
115- message(MESS_ERROR, "failed to rename %s to %s: %s\n",
116+ mvFile(log->files[logNum], rotNames->finalName, log, prev_acl)) {
117+ message(MESS_ERROR, "failed to move %s to %s: %s\n",
118 log->files[logNum], tmpFilename,
119 strerror(errno));
120 hasErrors = 1;
121@@ -2063,7 +2110,7 @@ int rotateLogSet(struct logInfo *log, int force)
122 return hasErrors;
123 }
124
125-static int writeState(char *stateFilename)
126+static int writeState(struct logInfo *log, char *stateFilename)
127 {
128 struct logState *p;
129 FILE *f;
130@@ -2227,7 +2274,7 @@ static int writeState(char *stateFilename)
131 fclose(f);
132
133 if (error == 0) {
134- if (rename(tmpFilename, stateFilename)) {
135+ if (mvFile(tmpFilename, stateFilename, log, prev_acl)) {
136 unlink(tmpFilename);
137 error = 1;
138 message(MESS_ERROR, "error renaming temp state file %s\n",
139@@ -2525,7 +2572,7 @@ int main(int argc, const char **argv)
140 rc |= rotateLogSet(log, force);
141
142 if (!debug)
143- rc |= writeState(stateFile);
144+ rc |= writeState(log, stateFile);
145
146 return (rc != 0);
147 }