Ejemplo n.º 1
0
/* Try to create missing directories on the path of filename.
 *
 * Note that on a busy server there may theoretically be many cronolog
 * processes trying simultaneously to create the same subdirectories
 * so ignore any EEXIST errors on mkdir -- they probably just mean
 * that another process got there first.
 *
 * Unless CHECK_ALL_PREFIX_DIRS is defined, we save the directory of
 * the last file tested -- any common prefix should exist.  This
 * probably only saves a few stat system calls at the start of each
 * log period, but it might as well be done.
 */
void
create_subdirs(char *filename)
{
#ifndef CHECK_ALL_PREFIX_DIRS
    static char	lastpath[PATH_MAX] = "";
#endif
    struct stat stat_buf;
    char	dirname[PATH_MAX];
    char	*p;

    CRONO_DEBUG(("Creating missing components of \"%s\"\n", filename));
    for (p = filename; (p = strchr(p, '/')); p++)
    {
	if (p == filename)
	{
	    continue;	    /* Don't bother with the root directory */
	}

	memcpy(dirname, filename, p - filename);
	dirname[p-filename] = '\0';

#ifndef CHECK_ALL_PREFIX_DIRS
	if (strncmp(dirname, lastpath, strlen(dirname)) == 0)
	{
	    CRONO_DEBUG(("Initial prefix \"%s\" known to exist\n", dirname));
	    continue;
	}
#endif

	CRONO_DEBUG(("Testing directory \"%s\"\n", dirname));
	if (stat(dirname, &stat_buf) < 0)
	{
	    if (errno != ENOENT)
	    {
		perror(dirname);
		return;
	    }
	    else
	    {
		CRONO_DEBUG(("Directory \"%s\" does not exist -- creating\n", dirname));
#ifndef _MSC_VER
                if ((mkdir(dirname, DIR_MODE) < 0) && (errno != EEXIST))
#else
                if ((mkdir(dirname) < 0) && (errno != EEXIST))
#endif
                {
		    perror(dirname);
		    return;
		}
	    }
	}
    }
#ifndef CHECK_ALL_PREFIX_DIRS
    strcpy(lastpath, dirname);
#endif
}
Ejemplo n.º 2
0
/* Open a new log file: determine the start of the current
 * period, generate the log file name from the fileTemplate,
 * determine the end of the period and open the new log file.
 *
 * Returns the file descriptor of the new log file and also sets the
 * name of the file and the start time of the next period via pointers
 * supplied.
 */
static FILE *new_log_file(const char *fileTemplate, const char *linkname,
                          mode_t linktype, const char *prevlinkname,
                          PERIODICITY periodicity, int period_multiple,
                          int period_delay, char *pfilename,
                          size_t pfilename_len, time_t time_now,
                          time_t *pnext_period) {
  time_t start_of_period;
  struct tm   *tm;
  int log_fd;

  start_of_period = start_of_this_period(time_now, periodicity,
                                         period_multiple);
  tm = localtime(&start_of_period);
  strftime(pfilename, pfilename_len, fileTemplate, tm);
  *pnext_period = start_of_next_period(start_of_period, periodicity,
                                       period_multiple) + period_delay;

  CRONO_DEBUG(("%s (%d): using log file \"%s\" from %s (%d) until %s (%d) "
        "(for %d secs)\n",
        timestamp(time_now), time_now, pfilename,
        timestamp(start_of_period), start_of_period,
        timestamp(*pnext_period), *pnext_period,
        *pnext_period - time_now));

  log_fd = open(pfilename, O_WRONLY|O_CREAT|O_APPEND, FILE_MODE);

#ifndef DONT_CREATE_SUBDIRS
  if ((log_fd < 0) && (errno == ENOENT)) {
    create_subdirs(pfilename);
    log_fd = open(pfilename, O_WRONLY|O_CREAT|O_APPEND, FILE_MODE);
  }
#endif

  if (log_fd < 0) {
    perror(pfilename);
    return NULL;
  }

  if (linkname) {
    /* Create a relative symlink to logs under linkname's directory */
    std::string dir = Util::safe_dirname(linkname);
    if (dir != "/") {
      dir.append("/");
    }
    std::string filename;
    if (!strncmp(pfilename, dir.c_str(), dir.length())) {
      filename = pfilename + dir.length();
    } else {
      filename = pfilename;
    }

    create_link(filename.c_str(), linkname, linktype, prevlinkname);
  }
  return fdopen(log_fd, "a");
}
Ejemplo n.º 3
0
/* Determine the time of the start of the period containing a given time.
 * Break down the time with localtime and subtract the number of
 * seconds since the start of the period.  If the length of period is
 * equal or longer than a day then we have to check tht the
 * calculation is not thrown out by the start or end of daylight
 * saving time.
 */
time_t
start_of_this_period(time_t start_time, PERIODICITY periodicity, int period_multiple)
{
    struct tm	tm_initial;
    struct tm	tm_adjusted;
    int		expected_mday;

#ifndef _WIN32
    localtime_r(&start_time, &tm_initial);
#else
    struct tm * tempTime;

    tempTime = localtime(&start_time);
    if (nullptr != tempTime)
    {
        memcpy(&tm_initial, tempTime, sizeof(struct tm));

        free(tempTime);
        tempTime = nullptr;
    }
#endif
    switch (periodicity)
    {
    case YEARLY:
    case MONTHLY:
    case WEEKLY:
    case DAILY:
	switch (periodicity)
	{
	case YEARLY:
	    start_time -= (  (tm_initial.tm_yday * SECS_PER_DAY)
			   + (tm_initial.tm_hour * SECS_PER_HOUR)
			   + (tm_initial.tm_min  * SECS_PER_MIN)
			   + (tm_initial.tm_sec));
	    expected_mday = 1;
	    break;

	case MONTHLY:
	    start_time -= (  ((tm_initial.tm_mday - 1) * SECS_PER_DAY)
			   + ( tm_initial.tm_hour      * SECS_PER_HOUR)
			   + ( tm_initial.tm_min       * SECS_PER_MIN)
			   + ( tm_initial.tm_sec));
	    expected_mday = 1;
	    break;

	case WEEKLY:
	    if (weeks_start_on_mondays)
	    {
		tm_initial.tm_wday = (6 + tm_initial.tm_wday) % 7;
	    }
	    start_time -= (  (tm_initial.tm_wday * SECS_PER_DAY)
			   + (tm_initial.tm_hour * SECS_PER_HOUR)
			   + (tm_initial.tm_min  * SECS_PER_MIN)
			   + (tm_initial.tm_sec));
	    expected_mday = tm_initial.tm_mday;
	    break;

	case DAILY:
	    start_time -= (  (tm_initial.tm_hour * SECS_PER_HOUR)
			   + (tm_initial.tm_min  * SECS_PER_MIN )
			   +  tm_initial.tm_sec);
	    expected_mday = tm_initial.tm_mday;
	    break;

	default:
	    fprintf(stderr, "software fault in start_of_this_period()\n");
	    exit(1);
	}

	/* If the time of day is not equal to midnight then we need to
	 * adjust for daylight saving time.  Adjust the time backwards
	 * by the value of the hour, minute and second fields.  If the
	 * day of the month is not as expected one then we must have
	 * adjusted back to the previous day so add 24 hours worth of
	 * seconds.
	 */
#ifndef _WIN32
	localtime_r(&start_time, &tm_adjusted);
#else
	tempTime = localtime(&start_time);
	if (nullptr != tempTime)
	{
	    memcpy(&tm_adjusted, tempTime, sizeof(struct tm));

	    free(tempTime);
	    tempTime = nullptr;
	}
#endif
	if (   (tm_adjusted.tm_hour != 0)
	    || (tm_adjusted.tm_min  != 0)
	    || (tm_adjusted.tm_sec  != 0))
	{
	    char	sign   = '-';
	    time_t      adjust = - (  (tm_adjusted.tm_hour * SECS_PER_HOUR)
				    + (tm_adjusted.tm_min  * SECS_PER_MIN)
				    + (tm_adjusted.tm_sec));

	    if (tm_adjusted.tm_mday != expected_mday)
	    {
		adjust += SECS_PER_DAY;
		sign = '+';
	    }
	    start_time += adjust;

	    if (adjust < 0)
	    {
		adjust = -adjust;
	    }

	    CRONO_DEBUG(("Adjust for dst: %02d/%02d/%04d %02d:%02d:%02d -- %c%0d:%02d:%02d\n",
		   tm_initial.tm_mday, tm_initial.tm_mon+1, tm_initial.tm_year+1900,
		   tm_initial.tm_hour, tm_initial.tm_min,   tm_initial.tm_sec, sign,
		   adjust / SECS_PER_HOUR, (adjust / 60) % 60, adjust % SECS_PER_HOUR));
	}
	break;

    case HOURLY:
	start_time -= (tm_initial.tm_sec + tm_initial.tm_min * SECS_PER_MIN);
	if (period_multiple > 1) {
	    start_time -= SECS_PER_HOUR * (tm_initial.tm_hour -
					   period_multiple * (tm_initial.tm_hour / period_multiple));
	}
	break;

    case PER_MINUTE:
	start_time -= tm_initial.tm_sec;
	if (period_multiple > 1) {
	    start_time -= SECS_PER_MIN * (tm_initial.tm_min -
					  period_multiple * (tm_initial.tm_min / period_multiple));
	}
	break;

    case PER_SECOND:	/* No adjustment needed */
    default:
	break;
    }
    return start_time;
}
Ejemplo n.º 4
0
/* Examine the log file name specifier for strftime conversion
 * specifiers and determine the period between log files.
 * Smallest period allowed is per minute.
 */
PERIODICITY
determine_periodicity(char *spec)
{
    PERIODICITY	periodicity = ONCE_ONLY;
    char 	ch;

    CRONO_DEBUG(("Determining periodicity of \"%s\"\n", spec));
    while ((ch = *spec++) != 0)
    {
	if (ch == '%')
	{
	    ch = *spec++;
	    if (!ch) break;

	    switch (ch)
	    {
	    case 'y':		/* two digit year */
	    case 'Y':		/* four digit year */
		if (periodicity > YEARLY)
		{
		    CRONO_DEBUG(("%%%c -> yearly\n", ch));
		    periodicity = YEARLY;
		}
		break;

	    case 'b':		/* abbreviated month name */
	    case 'h':		/* abbreviated month name (non-standard) */
	    case 'B':		/* full month name */
	    case 'm':		/* month as two digit number (with
				   leading zero) */
		if (periodicity > MONTHLY)
		{
		    CRONO_DEBUG(("%%%c -> monthly\n", ch));
		    periodicity = MONTHLY;
		}
  	        break;

	    case 'U':		/* week number (weeks start on Sunday) */
	    case 'W':		/* week number (weeks start on Monday) */
	        if (periodicity > WEEKLY)
		{
		    CRONO_DEBUG(("%%%c -> weeky\n", ch));
		    periodicity = WEEKLY;
		    weeks_start_on_mondays = (ch == 'W');
		}
		break;

	    case 'a':		/* abbreviated weekday name */
	    case 'A':		/* full weekday name */
	    case 'd':		/* day of the month (with leading zero) */
	    case 'e':		/* day of the month (with leading space -- non-standard) */
	    case 'j':		/* day of the year (with leading zeroes) */
	    case 'w':		/* day of the week (0-6) */
	    case 'D':		/* full date spec (non-standard) */
	    case 'x':		/* full date spec */
	        if (periodicity > DAILY)
		{
		    CRONO_DEBUG(("%%%c -> daily\n", ch));
		    periodicity = DAILY;
		}
  	        break;

	    case 'H':		/* hour (24 hour clock) */
	    case 'I':		/* hour (12 hour clock) */
	    case 'p':		/* AM/PM indicator */
	        if (periodicity > HOURLY)
		{
		    CRONO_DEBUG(("%%%c -> hourly\n", ch));
		    periodicity = HOURLY;
		}
		break;

	    case 'M':		/* minute */
	        if (periodicity > PER_MINUTE)
		{
		    CRONO_DEBUG(("%%%c -> per minute\n", ch));
		    periodicity = PER_MINUTE;
		}
		break;

	    case 'S':		/* second */
	    case 's':		/* seconds since the epoch (GNU non-standard) */
	    case 'c':		/* full time and date spec */
	    case 'T':		/* full time spec */
	    case 'r':		/* full time spec (non-standard) */
	    case 'R':		/* full time spec (non-standard) */
		CRONO_DEBUG(("%%%c -> per second", ch));
		periodicity = PER_SECOND;

	    default:		/* ignore anything else */
		CRONO_DEBUG(("ignoring %%%c\n", ch));
	        break;
	    }
	}
    }
    return periodicity;
}