|
|
22898a |
diff --git a/config.c b/config.c
|
|
|
22898a |
index e6b6a53..e9992e3 100644
|
|
|
22898a |
--- a/config.c
|
|
|
22898a |
+++ b/config.c
|
|
|
22898a |
@@ -220,6 +220,61 @@ static char *readPath(const char *configFile, int lineNum, char *key,
|
|
|
22898a |
return NULL;
|
|
|
22898a |
}
|
|
|
22898a |
|
|
|
22898a |
+static int readModeUidGid(const char *configFile, int lineNum, char *key,
|
|
|
22898a |
+ const char *directive, mode_t *mode, uid_t *uid,
|
|
|
22898a |
+ gid_t *gid) {
|
|
|
22898a |
+ char u[200], g[200];
|
|
|
22898a |
+ int m;
|
|
|
22898a |
+ char tmp;
|
|
|
22898a |
+ int rc;
|
|
|
22898a |
+ struct group *group;
|
|
|
22898a |
+ struct passwd *pw = NULL;
|
|
|
22898a |
+
|
|
|
22898a |
+ rc = sscanf(key, "%o %199s %199s%c", &m, u, g, &tmp);
|
|
|
22898a |
+ /* We support 'key <owner> <group> notation now */
|
|
|
22898a |
+ if (rc == 0) {
|
|
|
22898a |
+ rc = sscanf(key, "%199s %199s%c", u, g, &tmp);
|
|
|
22898a |
+ /* Simulate that we have read mode and keep the default value. */
|
|
|
22898a |
+ if (rc > 0) {
|
|
|
22898a |
+ m = *mode;
|
|
|
22898a |
+ rc += 1;
|
|
|
22898a |
+ }
|
|
|
22898a |
+ }
|
|
|
22898a |
+
|
|
|
22898a |
+ if (rc == 4) {
|
|
|
22898a |
+ message(MESS_ERROR, "%s:%d extra arguments for "
|
|
|
22898a |
+ "%s\n", configFile, lineNum, directive);
|
|
|
22898a |
+ return -1;
|
|
|
22898a |
+ }
|
|
|
22898a |
+
|
|
|
22898a |
+ if (rc > 0) {
|
|
|
22898a |
+ *mode = m;
|
|
|
22898a |
+ }
|
|
|
22898a |
+
|
|
|
22898a |
+ if (rc > 1) {
|
|
|
22898a |
+ pw = getpwnam(u);
|
|
|
22898a |
+ if (!pw) {
|
|
|
22898a |
+ message(MESS_ERROR, "%s:%d unknown user '%s'\n",
|
|
|
22898a |
+ configFile, lineNum, u);
|
|
|
22898a |
+ return -1;
|
|
|
22898a |
+ }
|
|
|
22898a |
+ *uid = pw->pw_uid;
|
|
|
22898a |
+ endpwent();
|
|
|
22898a |
+ }
|
|
|
22898a |
+ if (rc > 2) {
|
|
|
22898a |
+ group = getgrnam(g);
|
|
|
22898a |
+ if (!group) {
|
|
|
22898a |
+ message(MESS_ERROR, "%s:%d unknown group '%s'\n",
|
|
|
22898a |
+ configFile, lineNum, g);
|
|
|
22898a |
+ return -1;
|
|
|
22898a |
+ }
|
|
|
22898a |
+ *gid = group->gr_gid;
|
|
|
22898a |
+ endgrent();
|
|
|
22898a |
+ }
|
|
|
22898a |
+
|
|
|
22898a |
+ return 0;
|
|
|
22898a |
+}
|
|
|
22898a |
+
|
|
|
22898a |
static char *readAddress(const char *configFile, int lineNum, char *key,
|
|
|
22898a |
char **startPtr, char **buf, size_t length)
|
|
|
22898a |
{
|
|
|
22898a |
@@ -249,6 +304,55 @@ static char *readAddress(const char *configFile, int lineNum, char *key,
|
|
|
22898a |
return NULL;
|
|
|
22898a |
}
|
|
|
22898a |
|
|
|
22898a |
+static int do_mkdir(const char *path, mode_t mode, uid_t uid, gid_t gid) {
|
|
|
22898a |
+ struct stat sb;
|
|
|
22898a |
+
|
|
|
22898a |
+ if (stat(path, &sb) != 0) {
|
|
|
22898a |
+ if (mkdir(path, mode) != 0 && errno != EEXIST) {
|
|
|
22898a |
+ message(MESS_ERROR, "error creating %s: %s\n",
|
|
|
22898a |
+ path, strerror(errno));
|
|
|
22898a |
+ return -1;
|
|
|
22898a |
+ }
|
|
|
22898a |
+ if ((uid != sb.st_uid || gid != sb.st_gid) &&
|
|
|
22898a |
+ chown(path, uid, gid)) {
|
|
|
22898a |
+ message(MESS_ERROR, "error setting owner of %s to uid %d and gid %d: %s\n",
|
|
|
22898a |
+ path, uid, gid, strerror(errno));
|
|
|
22898a |
+ return -1;
|
|
|
22898a |
+ }
|
|
|
22898a |
+ }
|
|
|
22898a |
+ else if (!S_ISDIR(sb.st_mode)) {
|
|
|
22898a |
+ message(MESS_ERROR, "path %s already exists, but it is not a directory\n",
|
|
|
22898a |
+ path);
|
|
|
22898a |
+ errno = ENOTDIR;
|
|
|
22898a |
+ return -1;
|
|
|
22898a |
+ }
|
|
|
22898a |
+
|
|
|
22898a |
+ return 0;
|
|
|
22898a |
+}
|
|
|
22898a |
+
|
|
|
22898a |
+static int mkpath(const char *path, mode_t mode, uid_t uid, gid_t gid) {
|
|
|
22898a |
+ char *pp;
|
|
|
22898a |
+ char *sp;
|
|
|
22898a |
+ int rv;
|
|
|
22898a |
+ char *copypath = strdup(path);
|
|
|
22898a |
+
|
|
|
22898a |
+ rv = 0;
|
|
|
22898a |
+ pp = copypath;
|
|
|
22898a |
+ while (rv == 0 && (sp = strchr(pp, '/')) != 0) {
|
|
|
22898a |
+ if (sp != pp) {
|
|
|
22898a |
+ *sp = '\0';
|
|
|
22898a |
+ rv = do_mkdir(copypath, mode, uid, gid);
|
|
|
22898a |
+ *sp = '/';
|
|
|
22898a |
+ }
|
|
|
22898a |
+ pp = sp + 1;
|
|
|
22898a |
+ }
|
|
|
22898a |
+ if (rv == 0) {
|
|
|
22898a |
+ rv = do_mkdir(path, mode, uid, gid);
|
|
|
22898a |
+ }
|
|
|
22898a |
+ free(copypath);
|
|
|
22898a |
+ return rv;
|
|
|
22898a |
+}
|
|
|
22898a |
+
|
|
|
22898a |
static int checkFile(const char *fname)
|
|
|
22898a |
{
|
|
|
22898a |
int i;
|
|
|
22898a |
@@ -330,6 +434,9 @@ static void copyLogInfo(struct logInfo *to, struct logInfo *from)
|
|
|
22898a |
to->createGid = from->createGid;
|
|
|
22898a |
to->suUid = from->suUid;
|
|
|
22898a |
to->suGid = from->suGid;
|
|
|
22898a |
+ to->olddirMode = from->olddirMode;
|
|
|
22898a |
+ to->olddirUid = from->olddirUid;
|
|
|
22898a |
+ to->olddirGid = from->olddirGid;
|
|
|
22898a |
if (from->compress_options_count) {
|
|
|
22898a |
poptDupArgv(from->compress_options_count, from->compress_options_list,
|
|
|
22898a |
&to->compress_options_count, &to->compress_options_list);
|
|
|
22898a |
@@ -539,6 +646,11 @@ int readAllConfigPaths(const char **paths)
|
|
|
22898a |
.createMode = NO_MODE,
|
|
|
22898a |
.createUid = NO_UID,
|
|
|
22898a |
.createGid = NO_GID,
|
|
|
22898a |
+ .olddirMode = NO_MODE,
|
|
|
22898a |
+ .olddirUid = NO_UID,
|
|
|
22898a |
+ .olddirGid = NO_GID,
|
|
|
22898a |
+ .suUid = NO_UID,
|
|
|
22898a |
+ .suGid = NO_GID,
|
|
|
22898a |
.compress_options_list = NULL,
|
|
|
22898a |
.compress_options_count = 0
|
|
|
22898a |
};
|
|
|
22898a |
@@ -579,13 +691,19 @@ static int globerr(const char *pathname, int theerr)
|
|
|
22898a |
free(newlog->what); \
|
|
|
22898a |
newlog->what = NULL; \
|
|
|
22898a |
} while (0);
|
|
|
22898a |
+#define RAISE_ERROR() \
|
|
|
22898a |
+ if (newlog != defConfig) { \
|
|
|
22898a |
+ state = STATE_ERROR; \
|
|
|
22898a |
+ continue; \
|
|
|
22898a |
+ } else { \
|
|
|
22898a |
+ goto error; \
|
|
|
22898a |
+ }
|
|
|
22898a |
#define MAX_NESTING 16U
|
|
|
22898a |
|
|
|
22898a |
static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
{
|
|
|
22898a |
int fd;
|
|
|
22898a |
char *buf, *endtag, *key = NULL;
|
|
|
22898a |
- char foo;
|
|
|
22898a |
off_t length;
|
|
|
22898a |
int lineNum = 1;
|
|
|
22898a |
unsigned long long multiplier;
|
|
|
22898a |
@@ -595,11 +713,8 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
struct logInfo *newlog = defConfig;
|
|
|
22898a |
char *start, *chptr;
|
|
|
22898a |
char *dirName;
|
|
|
22898a |
- struct group *group;
|
|
|
22898a |
struct passwd *pw = NULL;
|
|
|
22898a |
int rc;
|
|
|
22898a |
- char createOwner[200], createGroup[200];
|
|
|
22898a |
- int createMode;
|
|
|
22898a |
struct stat sb, sb2;
|
|
|
22898a |
glob_t globResult;
|
|
|
22898a |
const char **argv;
|
|
|
22898a |
@@ -611,6 +726,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
static unsigned recursion_depth = 0U;
|
|
|
22898a |
char *globerr_msg = NULL;
|
|
|
22898a |
int in_config = 0;
|
|
|
22898a |
+ int rv;
|
|
|
22898a |
struct flock fd_lock = {
|
|
|
22898a |
.l_start = 0,
|
|
|
22898a |
.l_len = 0,
|
|
|
22898a |
@@ -807,53 +923,22 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
} else if (!strcmp(key, "maillast")) {
|
|
|
22898a |
newlog->flags &= ~LOG_FLAG_MAILFIRST;
|
|
|
22898a |
} else if (!strcmp(key, "su")) {
|
|
|
22898a |
+ mode_t tmp_mode = NO_MODE;
|
|
|
22898a |
free(key);
|
|
|
22898a |
key = isolateLine(&start, &buf, length);
|
|
|
22898a |
if (key == NULL)
|
|
|
22898a |
continue;
|
|
|
22898a |
|
|
|
22898a |
- rc = sscanf(key, "%199s %199s%c", createOwner,
|
|
|
22898a |
- createGroup, &foo;;
|
|
|
22898a |
- if (rc == 3) {
|
|
|
22898a |
- message(MESS_ERROR, "%s:%d extra arguments for "
|
|
|
22898a |
- "su\n", configFile, lineNum);
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ rv = readModeUidGid(configFile, lineNum, key, "su",
|
|
|
22898a |
+ &tmp_mode, &newlog->suUid,
|
|
|
22898a |
+ &newlog->suGid);
|
|
|
22898a |
+ if (rv == -1) {
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
-
|
|
|
22898a |
- if (rc > 0) {
|
|
|
22898a |
- pw = getpwnam(createOwner);
|
|
|
22898a |
- if (!pw) {
|
|
|
22898a |
- message(MESS_ERROR, "%s:%d unknown user '%s'\n",
|
|
|
22898a |
- configFile, lineNum, createOwner);
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
- }
|
|
|
22898a |
- newlog->suUid = pw->pw_uid;
|
|
|
22898a |
- endpwent();
|
|
|
22898a |
- }
|
|
|
22898a |
- if (rc > 1) {
|
|
|
22898a |
- group = getgrnam(createGroup);
|
|
|
22898a |
- if (!group) {
|
|
|
22898a |
- message(MESS_ERROR, "%s:%d unknown group '%s'\n",
|
|
|
22898a |
- configFile, lineNum, createGroup);
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
- }
|
|
|
22898a |
- newlog->suGid = group->gr_gid;
|
|
|
22898a |
- endgrent();
|
|
|
22898a |
+ else if (tmp_mode != NO_MODE) {
|
|
|
22898a |
+ message(MESS_ERROR, "%s:%d extra arguments for "
|
|
|
22898a |
+ "su\n", configFile, lineNum);
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
|
|
|
22898a |
newlog->flags |= LOG_FLAG_SU;
|
|
|
22898a |
@@ -863,65 +948,30 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
if (key == NULL)
|
|
|
22898a |
continue;
|
|
|
22898a |
|
|
|
22898a |
- rc = sscanf(key, "%o %199s %199s%c", &createMode,
|
|
|
22898a |
- createOwner, createGroup, &foo;;
|
|
|
22898a |
- /* We support 'create <owner> <group> notation now */
|
|
|
22898a |
- if (rc == 0) {
|
|
|
22898a |
- rc = sscanf(key, "%199s %199s%c",
|
|
|
22898a |
- createOwner, createGroup, &foo;;
|
|
|
22898a |
- /* Simulate that we have read createMode and se it
|
|
|
22898a |
- * to NO_MODE. */
|
|
|
22898a |
- if (rc > 0) {
|
|
|
22898a |
- createMode = NO_MODE;
|
|
|
22898a |
- rc += 1;
|
|
|
22898a |
- }
|
|
|
22898a |
- }
|
|
|
22898a |
- if (rc == 4) {
|
|
|
22898a |
- message(MESS_ERROR, "%s:%d extra arguments for "
|
|
|
22898a |
- "create\n", configFile, lineNum);
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ rv = readModeUidGid(configFile, lineNum, key, "create",
|
|
|
22898a |
+ &newlog->createMode, &newlog->createUid,
|
|
|
22898a |
+ &newlog->createGid);
|
|
|
22898a |
+ if (rv == -1) {
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
|
|
|
22898a |
- if (rc > 0)
|
|
|
22898a |
- newlog->createMode = createMode;
|
|
|
22898a |
-
|
|
|
22898a |
- if (rc > 1) {
|
|
|
22898a |
- pw = getpwnam(createOwner);
|
|
|
22898a |
- if (!pw) {
|
|
|
22898a |
- message(MESS_ERROR, "%s:%d unknown user '%s'\n",
|
|
|
22898a |
- configFile, lineNum, createOwner);
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
- }
|
|
|
22898a |
- newlog->createUid = pw->pw_uid;
|
|
|
22898a |
- endpwent();
|
|
|
22898a |
- }
|
|
|
22898a |
- if (rc > 2) {
|
|
|
22898a |
- group = getgrnam(createGroup);
|
|
|
22898a |
- if (!group) {
|
|
|
22898a |
- message(MESS_ERROR, "%s:%d unknown group '%s'\n",
|
|
|
22898a |
- configFile, lineNum, createGroup);
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
- }
|
|
|
22898a |
- newlog->createGid = group->gr_gid;
|
|
|
22898a |
- endgrent();
|
|
|
22898a |
+ newlog->flags |= LOG_FLAG_CREATE;
|
|
|
22898a |
+ } else if (!strcmp(key, "createolddir")) {
|
|
|
22898a |
+ free(key);
|
|
|
22898a |
+ key = isolateLine(&start, &buf, length);
|
|
|
22898a |
+ if (key == NULL)
|
|
|
22898a |
+ continue;
|
|
|
22898a |
+
|
|
|
22898a |
+ rv = readModeUidGid(configFile, lineNum, key, "createolddir",
|
|
|
22898a |
+ &newlog->olddirMode, &newlog->olddirUid,
|
|
|
22898a |
+ &newlog->olddirGid);
|
|
|
22898a |
+ if (rv == -1) {
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
|
|
|
22898a |
- newlog->flags |= LOG_FLAG_CREATE;
|
|
|
22898a |
+ newlog->flags |= LOG_FLAG_OLDDIRCREATE;
|
|
|
22898a |
+ } else if (!strcmp(key, "nocreateolddir")) {
|
|
|
22898a |
+ newlog->flags &= ~LOG_FLAG_OLDDIRCREATE;
|
|
|
22898a |
} else if (!strcmp(key, "nocreate")) {
|
|
|
22898a |
newlog->flags &= ~LOG_FLAG_CREATE;
|
|
|
22898a |
} else if (!strcmp(key, "size") || !strcmp(key, "minsize") ||
|
|
|
22898a |
@@ -945,12 +995,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
free(opt);
|
|
|
22898a |
message(MESS_ERROR, "%s:%d unknown unit '%c'\n",
|
|
|
22898a |
configFile, lineNum, key[l]);
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
} else {
|
|
|
22898a |
multiplier = 1;
|
|
|
22898a |
}
|
|
|
22898a |
@@ -960,12 +1005,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
message(MESS_ERROR, "%s:%d bad size '%s'\n",
|
|
|
22898a |
configFile, lineNum, key);
|
|
|
22898a |
free(opt);
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
if (!strncmp(opt, "size", 4)) {
|
|
|
22898a |
newlog->criterium = ROT_SIZE;
|
|
|
22898a |
@@ -1015,12 +1055,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
message(MESS_ERROR,
|
|
|
22898a |
"%s:%d bad rotation count '%s'\n",
|
|
|
22898a |
configFile, lineNum, key);
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
}
|
|
|
22898a |
else continue;
|
|
|
22898a |
@@ -1034,12 +1069,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
if (*chptr || newlog->logStart < 0) {
|
|
|
22898a |
message(MESS_ERROR, "%s:%d bad start count '%s'\n",
|
|
|
22898a |
configFile, lineNum, key);
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
}
|
|
|
22898a |
else continue;
|
|
|
22898a |
@@ -1052,12 +1082,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
if (*chptr || newlog->rotateAge < 0) {
|
|
|
22898a |
message(MESS_ERROR, "%s:%d bad maximum age '%s'\n",
|
|
|
22898a |
configFile, lineNum, start);
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
}
|
|
|
22898a |
else continue;
|
|
|
22898a |
@@ -1069,12 +1094,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
freeLogItem(logAddress);
|
|
|
22898a |
if (!(newlog->logAddress = readAddress(configFile, lineNum,
|
|
|
22898a |
"mail", &start, &buf, length))) {
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
else continue;
|
|
|
22898a |
} else if (!strcmp(key, "nomail")) {
|
|
|
22898a |
@@ -1177,31 +1197,8 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
|
|
|
22898a |
if (!(newlog->oldDir = readPath(configFile, lineNum,
|
|
|
22898a |
"olddir", &start, &buf, length))) {
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
- }
|
|
|
22898a |
-
|
|
|
22898a |
-#if 0
|
|
|
22898a |
- if (stat(newlog->oldDir, &sb)) {
|
|
|
22898a |
- message(MESS_ERROR, "%s:%d error verifying olddir "
|
|
|
22898a |
- "path %s: %s\n", configFile, lineNum,
|
|
|
22898a |
- newlog->oldDir, strerror(errno));
|
|
|
22898a |
- free(newlog->oldDir);
|
|
|
22898a |
- goto error;
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
-
|
|
|
22898a |
- if (!S_ISDIR(sb.st_mode)) {
|
|
|
22898a |
- message(MESS_ERROR, "%s:%d olddir path %s is not a "
|
|
|
22898a |
- "directory\n", configFile, lineNum,
|
|
|
22898a |
- newlog->oldDir);
|
|
|
22898a |
- free(newlog->oldDir);
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
-#endif
|
|
|
22898a |
message(MESS_DEBUG, "olddir is now %s\n", newlog->oldDir);
|
|
|
22898a |
} else if (!strcmp(key, "extension")) {
|
|
|
22898a |
if ((key = isolateValue
|
|
|
22898a |
@@ -1222,24 +1219,14 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
if (!
|
|
|
22898a |
(newlog->compress_prog =
|
|
|
22898a |
readPath(configFile, lineNum, "compress", &start, &buf, length))) {
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
|
|
|
22898a |
if (access(newlog->compress_prog, X_OK)) {
|
|
|
22898a |
message(MESS_ERROR,
|
|
|
22898a |
"%s:%d compression program %s is not an executable file\n",
|
|
|
22898a |
configFile, lineNum, newlog->compress_prog);
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
|
|
|
22898a |
message(MESS_DEBUG, "compress_prog is now %s\n",
|
|
|
22898a |
@@ -1252,24 +1239,14 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
(newlog->uncompress_prog =
|
|
|
22898a |
readPath(configFile, lineNum, "uncompress",
|
|
|
22898a |
&start, &buf, length))) {
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
|
|
|
22898a |
if (access(newlog->uncompress_prog, X_OK)) {
|
|
|
22898a |
message(MESS_ERROR,
|
|
|
22898a |
"%s:%d uncompression program %s is not an executable file\n",
|
|
|
22898a |
configFile, lineNum, newlog->uncompress_prog);
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
|
|
|
22898a |
message(MESS_DEBUG, "uncompress_prog is now %s\n",
|
|
|
22898a |
@@ -1285,12 +1262,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
}
|
|
|
22898a |
|
|
|
22898a |
if (!(options = isolateLine(&start, &buf, length))) {
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
|
|
|
22898a |
if (poptParseArgvString(options,
|
|
|
22898a |
@@ -1300,12 +1272,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
"%s:%d invalid compression options\n",
|
|
|
22898a |
configFile, lineNum);
|
|
|
22898a |
free(options);
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
|
|
|
22898a |
message(MESS_DEBUG, "compress_options is now %s\n",
|
|
|
22898a |
@@ -1318,12 +1285,7 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
(newlog->compress_ext =
|
|
|
22898a |
readPath(configFile, lineNum, "compress-ext",
|
|
|
22898a |
&start, &buf, length))) {
|
|
|
22898a |
- if (newlog != defConfig) {
|
|
|
22898a |
- state = STATE_ERROR;
|
|
|
22898a |
- continue;
|
|
|
22898a |
- } else {
|
|
|
22898a |
- goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ RAISE_ERROR();
|
|
|
22898a |
}
|
|
|
22898a |
|
|
|
22898a |
message(MESS_DEBUG, "compress_ext is now %s\n",
|
|
|
22898a |
@@ -1484,45 +1446,57 @@ static int readConfigFile(const char *configFile, struct logInfo *defConfig)
|
|
|
22898a |
globerr_msg = NULL;
|
|
|
22898a |
if (!(newlog->flags & LOG_FLAG_MISSINGOK))
|
|
|
22898a |
goto error;
|
|
|
22898a |
- }
|
|
|
22898a |
+ }
|
|
|
22898a |
|
|
|
22898a |
- if (newlog->oldDir) {
|
|
|
22898a |
+ if (newlog->oldDir) {
|
|
|
22898a |
for (i = 0; i < newlog->numFiles; i++) {
|
|
|
22898a |
char *ld;
|
|
|
22898a |
+ int rv;
|
|
|
22898a |
dirName = ourDirName(newlog->files[i]);
|
|
|
22898a |
if (stat(dirName, &sb2)) {
|
|
|
22898a |
- message(MESS_ERROR,
|
|
|
22898a |
- "%s:%d error verifying log file "
|
|
|
22898a |
- "path %s: %s\n", configFile, lineNum,
|
|
|
22898a |
- dirName, strerror(errno));
|
|
|
22898a |
- free(dirName);
|
|
|
22898a |
- goto error;
|
|
|
22898a |
+ message(MESS_ERROR,
|
|
|
22898a |
+ "%s:%d error verifying log file "
|
|
|
22898a |
+ "path %s: %s\n", configFile, lineNum,
|
|
|
22898a |
+ dirName, strerror(errno));
|
|
|
22898a |
+ free(dirName);
|
|
|
22898a |
+ goto error;
|
|
|
22898a |
}
|
|
|
22898a |
- ld = alloca(strlen(dirName) + strlen(newlog->oldDir) +
|
|
|
22898a |
- 2);
|
|
|
22898a |
+ ld = alloca(strlen(dirName) + strlen(newlog->oldDir) + 2);
|
|
|
22898a |
sprintf(ld, "%s/%s", dirName, newlog->oldDir);
|
|
|
22898a |
free(dirName);
|
|
|
22898a |
|
|
|
22898a |
- if (newlog->oldDir[0] != '/')
|
|
|
22898a |
- dirName = ld;
|
|
|
22898a |
- else
|
|
|
22898a |
- dirName = newlog->oldDir;
|
|
|
22898a |
- if (stat(dirName, &sb)) {
|
|
|
22898a |
- message(MESS_ERROR, "%s:%d error verifying olddir "
|
|
|
22898a |
- "path %s: %s\n", configFile, lineNum,
|
|
|
22898a |
- dirName, strerror(errno));
|
|
|
22898a |
- goto error;
|
|
|
22898a |
+ if (newlog->oldDir[0] != '/') {
|
|
|
22898a |
+ dirName = ld;
|
|
|
22898a |
+ }
|
|
|
22898a |
+ else {
|
|
|
22898a |
+ dirName = newlog->oldDir;
|
|
|
22898a |
+ }
|
|
|
22898a |
+
|
|
|
22898a |
+ rv = stat(dirName, &sb);
|
|
|
22898a |
+ if (rv) {
|
|
|
22898a |
+ if (errno == ENOENT && newlog->flags & LOG_FLAG_OLDDIRCREATE) {
|
|
|
22898a |
+ if (mkpath(dirName, newlog->olddirMode,
|
|
|
22898a |
+ newlog->olddirUid, newlog->olddirGid)) {
|
|
|
22898a |
+ goto error;
|
|
|
22898a |
+ }
|
|
|
22898a |
+ }
|
|
|
22898a |
+ else {
|
|
|
22898a |
+ message(MESS_ERROR, "%s:%d error verifying olddir "
|
|
|
22898a |
+ "path %s: %s\n", configFile, lineNum,
|
|
|
22898a |
+ dirName, strerror(errno));
|
|
|
22898a |
+ goto error;
|
|
|
22898a |
+ }
|
|
|
22898a |
}
|
|
|
22898a |
|
|
|
22898a |
if (sb.st_dev != sb2.st_dev) {
|
|
|
22898a |
- message(MESS_ERROR,
|
|
|
22898a |
- "%s:%d olddir %s and log file %s "
|
|
|
22898a |
- "are on different devices\n", configFile,
|
|
|
22898a |
- lineNum, newlog->oldDir, newlog->files[i]);
|
|
|
22898a |
- goto error;
|
|
|
22898a |
+ message(MESS_ERROR,
|
|
|
22898a |
+ "%s:%d olddir %s and log file %s "
|
|
|
22898a |
+ "are on different devices\n", configFile,
|
|
|
22898a |
+ lineNum, newlog->oldDir, newlog->files[i]);
|
|
|
22898a |
+ goto error;
|
|
|
22898a |
}
|
|
|
22898a |
}
|
|
|
22898a |
- }
|
|
|
22898a |
+ }
|
|
|
22898a |
|
|
|
22898a |
newlog = defConfig;
|
|
|
22898a |
state = STATE_DEFINITION_END;
|
|
|
22898a |
diff --git a/logrotate.8 b/logrotate.8
|
|
|
22898a |
index 8cb9c2f..2cd2370 100644
|
|
|
22898a |
--- a/logrotate.8
|
|
|
22898a |
+++ b/logrotate.8
|
|
|
22898a |
@@ -216,6 +216,16 @@ file for the omitted attributes. This option can be disabled using the
|
|
|
22898a |
\fBnocreate\fR option.
|
|
|
22898a |
|
|
|
22898a |
.TP
|
|
|
22898a |
+\fBcreateolddir \fImode\fR \fIowner\fR \fIgroup\fR
|
|
|
22898a |
+If the directory specified by \fBolddir\fR directive does not exist, it is
|
|
|
22898a |
+created. \fImode\fR specifies the mode for the \fBolddir\fR directory
|
|
|
22898a |
+in octal (the same as \fBchmod\fR(2)), \fIowner\fR specifies the user name
|
|
|
22898a |
+who will own the \fBolddir\fR directory, and \fIgroup\fR specifies the group
|
|
|
22898a |
+the \fBolddir\fR directory will belong to. This option can be disabled using the
|
|
|
22898a |
+\fBnocreateolddir\fR option.
|
|
|
22898a |
+
|
|
|
22898a |
+
|
|
|
22898a |
+.TP
|
|
|
22898a |
\fBdaily\fR
|
|
|
22898a |
Log files are rotated every day.
|
|
|
22898a |
|
|
|
22898a |
@@ -350,6 +360,10 @@ Do not truncate the original log file in place after creating a copy
|
|
|
22898a |
New log files are not created (this overrides the \fBcreate\fR option).
|
|
|
22898a |
|
|
|
22898a |
.TP
|
|
|
22898a |
+\fBnocreateolddir\fR
|
|
|
22898a |
+\fBolddir\fR directory is not created by logrotate when it does not exist.
|
|
|
22898a |
+
|
|
|
22898a |
+.TP
|
|
|
22898a |
\fBnodelaycompress\fR
|
|
|
22898a |
Do not postpone compression of the previous log file to the next rotation cycle
|
|
|
22898a |
(this overrides the \fBdelaycompress\fR option).
|
|
|
22898a |
diff --git a/logrotate.h b/logrotate.h
|
|
|
22898a |
index 813418e..cf42703 100644
|
|
|
22898a |
--- a/logrotate.h
|
|
|
22898a |
+++ b/logrotate.h
|
|
|
22898a |
@@ -20,6 +20,7 @@
|
|
|
22898a |
#define LOG_FLAG_SHRED (1 << 10)
|
|
|
22898a |
#define LOG_FLAG_SU (1 << 11)
|
|
|
22898a |
#define LOG_FLAG_DATEYESTERDAY (1 << 12)
|
|
|
22898a |
+#define LOG_FLAG_OLDDIRCREATE (1 << 13)
|
|
|
22898a |
|
|
|
22898a |
#define NO_MODE ((mode_t) -1)
|
|
|
22898a |
#define NO_UID ((uid_t) -1)
|
|
|
22898a |
@@ -55,6 +56,9 @@ struct logInfo {
|
|
|
22898a |
gid_t createGid;
|
|
|
22898a |
uid_t suUid; /* switch user to this uid and group to this gid */
|
|
|
22898a |
gid_t suGid;
|
|
|
22898a |
+ mode_t olddirMode;
|
|
|
22898a |
+ uid_t olddirUid;
|
|
|
22898a |
+ uid_t olddirGid;
|
|
|
22898a |
/* these are at the end so they end up nil */
|
|
|
22898a |
const char **compress_options_list;
|
|
|
22898a |
int compress_options_count;
|
|
|
22898a |
diff --git a/test/test b/test/test
|
|
|
22898a |
index 25b76a6..e9ce46f 100755
|
|
|
22898a |
--- a/test/test
|
|
|
22898a |
+++ b/test/test
|
|
|
22898a |
@@ -453,9 +453,15 @@ cleanup 13
|
|
|
22898a |
# ------------------------------- Test 13 ------------------------------------
|
|
|
22898a |
preptest test.log 13 1 0
|
|
|
22898a |
rm -rf testdir
|
|
|
22898a |
-mkdir testdir
|
|
|
22898a |
$RLR test-config.13 --force
|
|
|
22898a |
|
|
|
22898a |
+ls -l|grep testdir|grep "drwx------." 2>/dev/null >/dev/null
|
|
|
22898a |
+if [ $? != 0 ]; then
|
|
|
22898a |
+ echo "testdir should have mode 2700, but it has:"
|
|
|
22898a |
+ ls -l|grep testdir
|
|
|
22898a |
+ exit 3
|
|
|
22898a |
+fi
|
|
|
22898a |
+
|
|
|
22898a |
checkoutput <
|
|
|
22898a |
test.log 0
|
|
|
22898a |
testdir/test.log.1 0 zero
|
|
|
22898a |
@@ -888,13 +894,15 @@ $RLR test-config.35 --force
|
|
|
22898a |
|
|
|
22898a |
getfacl test.log|grep "user:nobody:rwx" >/dev/null
|
|
|
22898a |
if [ $? != 0 ]; then
|
|
|
22898a |
- echo "test.log must not contain user:nobody:rwx"
|
|
|
22898a |
+ echo "test.log must contain user:nobody:rwx"
|
|
|
22898a |
+ getfacl test.log
|
|
|
22898a |
exit 3
|
|
|
22898a |
fi
|
|
|
22898a |
|
|
|
22898a |
getfacl test.log.1|grep "user:nobody:rwx" >/dev/null
|
|
|
22898a |
if [ $? != 0 ]; then
|
|
|
22898a |
echo "test.log.1 must contain user:nobody:rwx"
|
|
|
22898a |
+ getfacl test.log.1
|
|
|
22898a |
exit 3
|
|
|
22898a |
fi
|
|
|
22898a |
|
|
|
22898a |
diff --git a/test/test-config.13.in b/test/test-config.13.in
|
|
|
22898a |
index 31a29ef..dc2efd5 100644
|
|
|
22898a |
--- a/test/test-config.13.in
|
|
|
22898a |
+++ b/test/test-config.13.in
|
|
|
22898a |
@@ -4,4 +4,5 @@ create
|
|
|
22898a |
monthly
|
|
|
22898a |
rotate 1
|
|
|
22898a |
olddir &DIR&/testdir
|
|
|
22898a |
+ createolddir 700 &USER& &GROUP&
|
|
|
22898a |
}
|