Beispiel #1
0
static void
db_asl_open(uint32_t dbtype)
{
	uint32_t status;
	struct stat sb;

	if ((dbtype & DB_TYPE_FILE) && (global.file_db == NULL))
	{
		memset(&sb, 0, sizeof(struct stat));
		if (stat(PATH_ASL_STORE, &sb) == 0)
		{
			/* must be a directory */
			if (!S_ISDIR(sb.st_mode))
			{
				asldebug("error: %s is not a directory", PATH_ASL_STORE);
				return;
			}
		}
		else
		{
			if (errno == ENOENT)
			{
				/* /var/log/asl doesn't exist - create it */
				if (mkdir(PATH_ASL_STORE, 0755) != 0)
				{
					asldebug("error: can't create data store %s: %s\n", PATH_ASL_STORE, strerror(errno));
					return;
				}
			}
			else
			{
				/* stat failed for some other reason */
				asldebug("error: can't stat data store %s: %s\n", PATH_ASL_STORE, strerror(errno));
				return;
			}
		}

		/*
		 * One-time store conversion from the old "LongTTL" style to the new "Best Before" style.
		 * bb_convert returns quickly if the store has already been converted.
		 */
		status = bb_convert(PATH_ASL_STORE);
		if (status != ASL_STATUS_OK)
		{
			asldebug("ASL data store conversion failed!: %s\n", asl_core_error(status));
		}

		status = asl_store_open_write(NULL, &(global.file_db));
		if (status != ASL_STATUS_OK)
		{
			asldebug("asl_store_open_write: %s\n", asl_core_error(status));
		}
		else
		{
			if (global.db_file_max != 0) asl_store_max_file_size(global.file_db, global.db_file_max);
			asl_trigger_aslmanager();
		}
	}

	if ((dbtype & DB_TYPE_MEMORY) && (global.memory_db == NULL))
	{
		status = asl_memory_open(global.db_memory_max, &(global.memory_db));
		if (status != ASL_STATUS_OK)
		{
			asldebug("asl_memory_open: %s\n", asl_core_error(status));
		}
	}

	if ((dbtype & DB_TYPE_MINI) && (global.mini_db == NULL))
	{
		status = asl_mini_memory_open(global.db_mini_max, &(global.mini_db));
		if (status != ASL_STATUS_OK)
		{
			asldebug("asl_mini_memory_open: %s\n", asl_core_error(status));
		}
	}
}
Beispiel #2
0
uint32_t
asl_store_save(asl_store_t *s, aslmsg msg)
{
	struct tm ctm;
	time_t msg_time, now, bb;
	char *path, *tmp_path, *tstring, *scratch;
	const char *val;
	uid_t ruid;
	gid_t rgid;
	asl_file_t *f;
	uint32_t status, check_cache, trigger_aslmanager, len;
	uint64_t xid, ftime;
	size_t fsize;

	if (s == NULL) return ASL_STATUS_INVALID_STORE;
	if (msg == NULL) return ASL_STATUS_INVALID_ARG;

	now = time(NULL);

	check_cache = 0;
	if ((s->last_write + FILE_CACHE_TTL) <= now) check_cache = 1;

	trigger_aslmanager = 0;

	msg_time = 0;
	val = asl_get(msg, ASL_KEY_TIME);
	if (val == NULL) msg_time = now;
	else msg_time = asl_parse_time(val);

	if (msg_time >= s->start_tomorrow)
	{
		if (now >= s->start_tomorrow)
		{
			/* new day begins */
			check_cache = 0;
			asl_store_file_closeall(s);

			/*
			 * _asl_start_today should never fail, but if it does,
			 * just push forward one day.  That will probably be correct, and if
			 * it isn't, the next message that gets saved will push it ahead again
			 * until we get to the right date.
			 */
			s->start_today = _asl_start_today();
			if (s->start_today == 0) s->start_today = s->start_tomorrow;

			s->start_tomorrow = s->start_today + SECONDS_PER_DAY;
		}
	}

	val = asl_get(msg, ASL_KEY_READ_UID);
	ruid = -1;
	if (val != NULL) ruid = atoi(val);

	val = asl_get(msg, ASL_KEY_READ_GID);
	rgid = -1;
	if (val != NULL) rgid = atoi(val);

	bb = 0;
	val = asl_get(msg, ASL_KEY_EXPIRE_TIME);
	if (val != NULL)
	{
		bb = 1;
		msg_time = asl_parse_time(val);
	}

	if (fseeko(s->storedata, 0, SEEK_SET) != 0) return ASL_STATUS_WRITE_FAILED;

	xid = asl_core_htonq(s->next_id);
	if (fwrite(&xid, sizeof(uint64_t), 1, s->storedata) != 1) return ASL_STATUS_WRITE_FAILED;

	/* flush data */
	fflush(s->storedata);

	xid = s->next_id;
	s->next_id++;

	s->last_write = now;

	if (localtime_r((const time_t *)&msg_time, &ctm) == NULL) return ASL_STATUS_FAILED;

	tstring = NULL;
	if (bb == 1)
	{
		/*
		 * This supports 12 monthly "Best Before" buckets.
		 * We advance the actual expiry time to day zero of the following month.
		 * mktime() is clever enough to know that you actually mean the last day
		 * of the previous month.  What we get back from localtime is the last
		 * day of the month in which the message expires, which we use in the name.
		 */
		ctm.tm_sec = 0;
		ctm.tm_min = 0;
		ctm.tm_hour = 0;
		ctm.tm_mday = 0;
		ctm.tm_mon += 1;

		bb = mktime(&ctm);

		if (localtime_r((const time_t *)&bb, &ctm) == NULL) return ASL_STATUS_FAILED;
		asprintf(&tstring, "BB.%d.%02d.%02d", ctm.tm_year + 1900, ctm.tm_mon + 1, ctm.tm_mday);
	}
	else
	{
		asprintf(&tstring, "%d.%02d.%02d", ctm.tm_year + 1900, ctm.tm_mon + 1, ctm.tm_mday);
	}

	if (tstring == NULL) return ASL_STATUS_NO_MEMORY;

	status = asl_store_file_open_write(s, tstring, ruid, rgid, bb, &f, now, check_cache);
	free(tstring);
	tstring = NULL;

	if (status != ASL_STATUS_OK) return status;

	status = asl_file_save(f, msg, &xid);
	if (status != ASL_STATUS_OK) return status;

	fsize = asl_file_size(f);
	ftime = asl_file_ctime(f);

	/* if file is larger than max_file_size, rename it and trigger aslmanager */
	if ((s->max_file_size != 0) && (fsize > s->max_file_size))
	{
		trigger_aslmanager = 1;
		status = ASL_STATUS_OK;

		path = asl_store_file_path(s, f);

		asl_store_file_close(s, f);

		if (path != NULL)
		{
			tmp_path = NULL;

			len = strlen(path);
			if ((len >= 4) && (!strcmp(path + len - 4, ".asl")))
			{
				/* rename xxxxxxx.asl to xxxxxxx.timestamp.asl */
				scratch = strdup(path);
				if (scratch != NULL)
				{
					scratch[len - 4] = '\0';
					asprintf(&tmp_path, "%s.%llu.asl", scratch, ftime);
					free(scratch);

				}
			}
			else
			{
				/* append timestamp */
				asprintf(&tmp_path, "%s.%llu", path, ftime);
			}

			if (tmp_path == NULL)
			{
				status = ASL_STATUS_NO_MEMORY;
			}
			else
			{
				if (rename(path, tmp_path) != 0) status = ASL_STATUS_FAILED;
				free(tmp_path);
			}

			free(path);
		}
	}

	if (trigger_aslmanager != 0) asl_trigger_aslmanager();

	return status;
}