aboutsummaryrefslogtreecommitdiff
path: root/ntpd/ntp_filegen.c
diff options
context:
space:
mode:
Diffstat (limited to 'ntpd/ntp_filegen.c')
-rw-r--r--ntpd/ntp_filegen.c353
1 files changed, 191 insertions, 162 deletions
diff --git a/ntpd/ntp_filegen.c b/ntpd/ntp_filegen.c
index b7b04bdbab6d..a1703a9d13a3 100644
--- a/ntpd/ntp_filegen.c
+++ b/ntpd/ntp_filegen.c
@@ -6,7 +6,7 @@
*
*
* Copyright (C) 1992, 1996 by Rainer Pruy
- * Friedrich-Alexander Universität Erlangen-Nürnberg, Germany
+ * Friedrich-Alexander Universitaet Erlangen-Nuernberg, Germany
*
* This code may be modified and used freely
* provided credits remain intact.
@@ -44,7 +44,7 @@
*/
#define SUFFIX_SEP '.'
-static void filegen_open (FILEGEN *, u_long);
+static void filegen_open (FILEGEN *, u_int32, const time_t*);
static int valid_fileref (const char *, const char *);
static void filegen_init (const char *, const char *, FILEGEN *);
#ifdef DEBUG
@@ -58,17 +58,18 @@ static void filegen_uninit (FILEGEN *);
static void
filegen_init(
- const char * prefix,
- const char * basename,
+ const char * dir,
+ const char * fname,
FILEGEN * fgp
)
{
- fgp->fp = NULL;
- fgp->prefix = prefix; /* Yes, this is TOTALLY lame! */
- fgp->basename = estrdup(basename);
- fgp->id = 0;
- fgp->type = FILEGEN_DAY;
- fgp->flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
+ fgp->fp = NULL;
+ fgp->dir = estrdup(dir);
+ fgp->fname = estrdup(fname);
+ fgp->id_lo = 0;
+ fgp->id_hi = 0;
+ fgp->type = FILEGEN_DAY;
+ fgp->flag = FGEN_FLAG_LINK; /* not yet enabled !!*/
}
@@ -78,10 +79,11 @@ filegen_init(
#ifdef DEBUG
static void
filegen_uninit(
- FILEGEN * fgp
+ FILEGEN *fgp
)
{
- free(fgp->basename);
+ free(fgp->dir);
+ free(fgp->fname);
}
#endif
@@ -94,38 +96,53 @@ filegen_uninit(
static void
filegen_open(
FILEGEN * gen,
- u_long newid
+ u_int32 stamp,
+ const time_t * pivot
)
{
- char *filename;
- char *basename;
- u_int len;
+ char *savename; /* temp store for name collision handling */
+ char *fullname; /* name with any designation extension */
+ char *filename; /* name without designation extension */
+ char *suffix; /* where to print suffix extension */
+ u_int len, suflen;
FILE *fp;
struct calendar cal;
+ struct isodate iso;
+
+ /* get basic filename in buffer, leave room for extensions */
+ len = strlen(gen->dir) + strlen(gen->fname) + 65;
+ filename = emalloc(len);
+ fullname = emalloc(len);
+ savename = NULL;
+ snprintf(filename, len, "%s%s", gen->dir, gen->fname);
+
+ /* where to place suffix */
+ suflen = strlcpy(fullname, filename, len);
+ suffix = fullname + suflen;
+ suflen = len - suflen;
+
+ /* last octet of fullname set to '\0' for truncation check */
+ fullname[len - 1] = '\0';
- len = strlen(gen->prefix) + strlen(gen->basename) + 1;
- basename = emalloc(len);
- snprintf(basename, len, "%s%s", gen->prefix, gen->basename);
-
switch (gen->type) {
default:
msyslog(LOG_ERR,
"unsupported file generations type %d for "
"\"%s\" - reverting to FILEGEN_NONE",
- gen->type, basename);
+ gen->type, filename);
gen->type = FILEGEN_NONE;
- /* fall through to FILEGEN_NONE */
+ break;
case FILEGEN_NONE:
- filename = estrdup(basename);
+ /* no suffix, all set */
break;
case FILEGEN_PID:
- filename = emalloc(len + 1 + 1 + 10);
- snprintf(filename, len + 1 + 1 + 10,
- "%s%c#%ld",
- basename, SUFFIX_SEP, newid);
+ gen->id_lo = getpid();
+ gen->id_hi = 0;
+ snprintf(suffix, suflen, "%c#%ld",
+ SUFFIX_SEP, gen->id_lo);
break;
case FILEGEN_DAY:
@@ -134,52 +151,60 @@ filegen_open(
* would assume it to be easier for humans to interpret
* dates in a format they are used to in everyday life.
*/
- caljulian(newid, &cal);
- filename = emalloc(len + 1 + 4 + 2 + 2);
- snprintf(filename, len + 1 + 4 + 2 + 2,
- "%s%c%04d%02d%02d",
- basename, SUFFIX_SEP,
- cal.year, cal.month, cal.monthday);
+ ntpcal_ntp_to_date(&cal, stamp, pivot);
+ snprintf(suffix, suflen, "%c%04d%02d%02d",
+ SUFFIX_SEP, cal.year, cal.month, cal.monthday);
+ cal.hour = cal.minute = cal.second = 0;
+ gen->id_lo = ntpcal_date_to_ntp(&cal);
+ gen->id_hi = (u_int32)(gen->id_lo + SECSPERDAY);
break;
case FILEGEN_WEEK:
- /*
- * This is still a hack
- * - the term week is not correlated to week as it is used
- * normally - it just refers to a period of 7 days
- * starting at Jan 1 - 'weeks' are counted starting from zero
- */
- caljulian(newid, &cal);
- filename = emalloc(len + 1 + 4 + 1 + 2);
- snprintf(filename, len + 1 + 4 + 1 + 2,
- "%s%c%04dw%02d",
- basename, SUFFIX_SEP,
- cal.year, cal.yearday / 7);
+ isocal_ntp_to_date(&iso, stamp, pivot);
+ snprintf(suffix, suflen, "%c%04dw%02d",
+ SUFFIX_SEP, iso.year, iso.week);
+ iso.hour = iso.minute = iso.second = 0;
+ iso.weekday = 1;
+ gen->id_lo = isocal_date_to_ntp(&iso);
+ gen->id_hi = (u_int32)(gen->id_lo + 7 * SECSPERDAY);
break;
case FILEGEN_MONTH:
- caljulian(newid, &cal);
- filename = emalloc(len + 1 + 4 + 2);
- snprintf(filename, len + 1 + 4 + 2,
- "%s%c%04d%02d",
- basename, SUFFIX_SEP, cal.year, cal.month);
+ ntpcal_ntp_to_date(&cal, stamp, pivot);
+ snprintf(suffix, suflen, "%c%04d%02d",
+ SUFFIX_SEP, cal.year, cal.month);
+ cal.hour = cal.minute = cal.second = 0;
+ cal.monthday = 1;
+ gen->id_lo = ntpcal_date_to_ntp(&cal);
+ cal.month++;
+ gen->id_hi = ntpcal_date_to_ntp(&cal);
break;
case FILEGEN_YEAR:
- caljulian(newid, &cal);
- filename = emalloc(len + 1 + 4);
- snprintf(filename, len + 1 + 4,
- "%s%c%04d",
- basename, SUFFIX_SEP, cal.year);
+ ntpcal_ntp_to_date(&cal, stamp, pivot);
+ snprintf(suffix, suflen, "%c%04d",
+ SUFFIX_SEP, cal.year);
+ cal.hour = cal.minute = cal.second = 0;
+ cal.month = cal.monthday = 1;
+ gen->id_lo = ntpcal_date_to_ntp(&cal);
+ cal.year++;
+ gen->id_hi = ntpcal_date_to_ntp(&cal);
break;
case FILEGEN_AGE:
- filename = emalloc(len + 1 + 2 + 10);
- snprintf(filename, len + 1 + 2 + 10,
- "%s%ca%08ld",
- basename, SUFFIX_SEP, newid);
+ gen->id_lo = current_time - (current_time % SECSPERDAY);
+ gen->id_hi = gen->id_lo + SECSPERDAY;
+ snprintf(suffix, suflen, "%ca%08ld",
+ SUFFIX_SEP, gen->id_lo);
}
+ /* check possible truncation */
+ if ('\0' != fullname[len - 1]) {
+ fullname[len - 1] = '\0';
+ msyslog(LOG_ERR, "logfile name truncated: \"%s\"",
+ fullname);
+ }
+
if (FILEGEN_NONE != gen->type) {
/*
* check for existence of a file with name 'basename'
@@ -195,25 +220,23 @@ filegen_open(
#ifndef S_ISREG
#define S_ISREG(mode) (((mode) & S_IFREG) == S_IFREG)
#endif
- if (stat(basename, &stats) == 0) {
+ if (stat(filename, &stats) == 0) {
/* Hm, file exists... */
if (S_ISREG(stats.st_mode)) {
if (stats.st_nlink <= 1) {
/*
* Oh, it is not linked - try to save it
*/
- char *savename;
-
- savename = emalloc(len + 1 + 1 + 10 + 10);
- snprintf(savename, len + 1 + 1 + 10 + 10,
+ savename = emalloc(len);
+ snprintf(savename, len,
"%s%c%dC%lu",
- basename, SUFFIX_SEP,
+ filename, SUFFIX_SEP,
(int)getpid(), conflicts++);
- if (rename(basename, savename) != 0)
+ if (rename(filename, savename) != 0)
msyslog(LOG_ERR,
"couldn't save %s: %m",
- basename);
+ filename);
free(savename);
} else {
/*
@@ -223,14 +246,14 @@ filegen_open(
*/
if (
#if !defined(VMS)
- unlink(basename) != 0
+ unlink(filename) != 0
#else
- delete(basename) != 0
+ delete(filename) != 0
#endif
)
msyslog(LOG_ERR,
"couldn't unlink %s: %m",
- basename);
+ filename);
}
} else {
/*
@@ -239,7 +262,7 @@ filegen_open(
msyslog(LOG_ERR,
"expected regular file for %s "
"(found mode 0%lo)",
- basename,
+ filename,
(unsigned long)stats.st_mode);
}
} else {
@@ -249,18 +272,18 @@ filegen_open(
*/
if (ENOENT != errno)
msyslog(LOG_ERR, "stat(%s) failed: %m",
- basename);
+ filename);
}
}
/*
* now, try to open new file generation...
*/
- fp = fopen(filename, "a");
-
- DPRINTF(4, ("opening filegen (type=%d/id=%lu) \"%s\"\n",
- gen->type, newid, filename));
+ DPRINTF(4, ("opening filegen (type=%d/stamp=%u) \"%s\"\n",
+ gen->type, stamp, fullname));
+ fp = fopen(fullname, "a");
+
if (NULL == fp) {
/* open failed -- keep previous state
*
@@ -272,14 +295,13 @@ filegen_open(
*/
if (ENOENT != errno)
- msyslog(LOG_ERR, "can't open %s: %m", filename);
+ msyslog(LOG_ERR, "can't open %s: %m", fullname);
} else {
if (NULL != gen->fp) {
fclose(gen->fp);
gen->fp = NULL;
}
gen->fp = fp;
- gen->id = newid;
if (gen->flag & FGEN_FLAG_LINK) {
/*
@@ -287,7 +309,7 @@ filegen_open(
* have to use hardlink for now as I want to allow
* gen->basename spanning directory levels
* this would make it more complex to get the correct
- * filename for symlink
+ * fullname for symlink
*
* Ok, it would just mean taking the part following
* the last '/' in the name.... Should add it later....
@@ -295,22 +317,22 @@ filegen_open(
/* Windows NT does not support file links -Greg Schueman 1/18/97 */
-#if defined SYS_WINNT || defined SYS_VXWORKS
+#if defined(SYS_WINNT) || defined(SYS_VXWORKS)
SetLastError(0); /* On WinNT, don't support FGEN_FLAG_LINK */
#elif defined(VMS)
errno = 0; /* On VMS, don't support FGEN_FLAG_LINK */
#else /* not (VMS) / VXWORKS / WINNT ; DO THE LINK) */
- if (link(filename, basename) != 0)
+ if (link(fullname, filename) != 0)
if (EEXIST != errno)
msyslog(LOG_ERR,
"can't link(%s, %s): %m",
- filename, basename);
+ fullname, filename);
#endif /* SYS_WINNT || VXWORKS */
} /* flags & FGEN_FLAG_LINK */
} /* else fp == NULL */
- free(basename);
free(filename);
+ free(fullname);
return;
}
@@ -325,11 +347,11 @@ filegen_open(
void
filegen_setup(
FILEGEN * gen,
- u_long now
+ u_int32 now
)
{
- u_long new_gen = ~ (u_long) 0;
- struct calendar cal;
+ int current;
+ time_t pivot;
if (!(gen->flag & FGEN_FLAG_ENABLED)) {
if (NULL != gen->fp) {
@@ -338,67 +360,39 @@ filegen_setup(
}
return;
}
-
+
switch (gen->type) {
+ default:
case FILEGEN_NONE:
- if (NULL != gen->fp)
- return; /* file already open */
+ current = TRUE;
break;
case FILEGEN_PID:
- new_gen = getpid();
+ current = ((int)gen->id_lo == getpid());
break;
- case FILEGEN_DAY:
- caljulian(now, &cal);
- cal.hour = cal.minute = cal.second = 0;
- new_gen = caltontp(&cal);
+ case FILEGEN_AGE:
+ current = (gen->id_lo <= current_time) &&
+ (gen->id_hi > current_time);
break;
+ case FILEGEN_DAY:
case FILEGEN_WEEK:
- /* Would be nice to have a calweekstart() routine */
- /* so just use a hack ... */
- /* just round time to integral 7 day period for actual year */
- new_gen = now - (now - calyearstart(now)) % TIMES7(SECSPERDAY)
- + 60;
- /*
- * just to be sure -
- * the computation above would fail in the presence of leap seconds
- * so at least carry the date to the next day (+60 (seconds))
- * and go back to the start of the day via calendar computations
- */
- caljulian(new_gen, &cal);
- cal.hour = cal.minute = cal.second = 0;
- new_gen = caltontp(&cal);
- break;
-
case FILEGEN_MONTH:
- caljulian(now, &cal);
- cal.yearday = (u_short) (cal.yearday - cal.monthday + 1);
- cal.monthday = 1;
- cal.hour = cal.minute = cal.second = 0;
- new_gen = caltontp(&cal);
- break;
-
case FILEGEN_YEAR:
- new_gen = calyearstart(now);
- break;
-
- case FILEGEN_AGE:
- new_gen = current_time - (current_time % SECSPERDAY);
+ current = (gen->id_lo <= now) &&
+ (gen->id_hi > now);
break;
}
/*
* try to open file if not yet open
* reopen new file generation file on change of generation id
*/
- if (NULL == gen->fp || gen->id != new_gen) {
-
- DPRINTF(1, ("filegen %0x %lu %lu %lu\n",
- gen->type, now, gen->id, new_gen));
-
- filegen_open(gen, new_gen);
+ if (NULL == gen->fp || !current) {
+ DPRINTF(1, ("filegen %0x %u\n", gen->type, now));
+ pivot = time(NULL);
+ filegen_open(gen, now, &pivot);
}
}
@@ -409,45 +403,55 @@ filegen_setup(
void
filegen_config(
FILEGEN * gen,
- const char * basename,
+ const char * dir,
+ const char * fname,
u_int type,
u_int flag
)
{
- int file_existed = 0;
+ int file_existed;
+ l_fp now;
+
/*
* if nothing would be changed...
*/
- if ((strcmp(basename, gen->basename) == 0) && type == gen->type
- && flag == gen->flag)
+ if (strcmp(dir, gen->dir) == 0 && strcmp(fname, gen->fname) == 0
+ && type == gen->type && flag == gen->flag)
return;
-
+
/*
* validate parameters
*/
- if (!valid_fileref(gen->prefix, basename))
+ if (!valid_fileref(dir, fname))
return;
if (NULL != gen->fp) {
fclose(gen->fp);
gen->fp = NULL;
- file_existed = 1;
+ file_existed = TRUE;
+ } else {
+ file_existed = FALSE;
}
DPRINTF(3, ("configuring filegen:\n"
- "\tprefix:\t%s\n"
- "\tbasename:\t%s -> %s\n"
+ "\tdir:\t%s -> %s\n"
+ "\tfname:\t%s -> %s\n"
"\ttype:\t%d -> %d\n"
"\tflag: %x -> %x\n",
- gen->prefix,
- gen->basename, basename,
+ gen->dir, dir,
+ gen->fname, fname,
gen->type, type,
gen->flag, flag));
- if (strcmp(gen->basename, basename) != 0) {
- free(gen->basename);
- gen->basename = estrdup(basename);
+ if (strcmp(gen->dir, dir) != 0) {
+ free(gen->dir);
+ gen->dir = estrdup(dir);
+ }
+
+ if (strcmp(gen->fname, fname) != 0) {
+ free(gen->fname);
+ gen->fname = estrdup(fname);
}
gen->type = (u_char)type;
gen->flag = (u_char)flag;
@@ -459,8 +463,6 @@ filegen_config(
* otherwise the new settings will be used anyway at the next open
*/
if (file_existed) {
- l_fp now;
-
get_systime(&now);
filegen_setup(gen, now.l_ui);
}
@@ -473,41 +475,54 @@ filegen_config(
*/
static int
valid_fileref(
- const char * prefix,
- const char * basename
+ const char * dir,
+ const char * fname
)
{
/*
- * prefix cannot be changed dynamically
+ * dir cannot be changed dynamically
* (within the context of filegen)
* so just reject basenames containing '..'
*
* ASSUMPTION:
- * file system parts 'below' prefix may be
+ * file system parts 'below' dir may be
* specified without infringement of security
*
- * restricting prefix to legal values
+ * restricting dir to legal values
* has to be ensured by other means
* (however, it would be possible to perform some checks here...)
*/
- register const char *p = basename;
-
+ const char *p;
+
/*
* Just to catch, dumb errors opening up the world...
*/
- if (NULL == prefix || '\0' == *prefix)
- return 0;
+ if (NULL == dir || '\0' == dir[0])
+ return FALSE;
- if (NULL == basename)
- return 0;
-
- for (p = basename; p; p = strchr(p, DIR_SEP)) {
+ if (NULL == fname)
+ return FALSE;
+
+#ifdef SYS_WINNT
+ /*
+ * Windows treats / equivalent to \, reject any / to ensure
+ * check below for DIR_SEP (\ on windows) are adequate.
+ */
+ if (strchr(fname, '/')) {
+ msyslog(LOG_ERR,
+ "filegen filenames must not contain '/': %s",
+ fname);
+ return FALSE;
+ }
+#endif
+
+ for (p = fname; p != NULL; p = strchr(p, DIR_SEP)) {
if ('.' == p[0] && '.' == p[1]
&& ('\0' == p[2] || DIR_SEP == p[2]))
- return 0;
+ return FALSE;
}
-
- return 1;
+
+ return TRUE;
}
@@ -544,7 +559,7 @@ filegen_get(
void
filegen_register(
- const char * prefix,
+ const char * dir,
const char * name,
FILEGEN * filegen
)
@@ -553,7 +568,7 @@ filegen_register(
DPRINTF(4, ("filegen_register(%s, %p)\n", name, filegen));
- filegen_init(prefix, name, filegen);
+ filegen_init(dir, name, filegen);
ppfe = &filegen_registry;
while (NULL != *ppfe) {
@@ -582,6 +597,20 @@ filegen_register(
/*
+ * filegen_statsdir() - reset each filegen entry's dir to statsdir.
+ */
+void
+filegen_statsdir(void)
+{
+ struct filegen_entry *f;
+
+ for (f = filegen_registry; f != NULL; f = f->next)
+ filegen_config(f->filegen, statsdir, f->filegen->fname,
+ f->filegen->type, f->filegen->flag);
+}
+
+
+/*
* filegen_unregister frees memory allocated by filegen_register for
* name.
*/