Exemple #1
0
uint32_t
ymd_file_filter(const char *name, const char *path, uint32_t keep_mask, mode_t ymd_mode, uid_t ymd_uid, gid_t ymd_gid)
{
	asl_file_t *f = NULL;
	uint8_t km = keep_mask;
	uint32_t status, len, dstcount = 0;
	char src[MAXPATHLEN];
	char dst[MAXPATHLEN];

	if (snprintf(src, MAXPATHLEN, "%s/%s", path, name) >= MAXPATHLEN) return ASL_STATUS_FAILED;
	if (snprintf(dst, MAXPATHLEN, "%s/%s", path, name) >= MAXPATHLEN) return ASL_STATUS_FAILED;
	len = strlen(src) - 3;
	snprintf(dst + len, 4, "tmp");

	//TODO: check if src file is already filtered
	debug_log(ASL_LEVEL_NOTICE, "  filter %s %s ---> %s\n", src, keep_str(km), dst);

	status = ASL_STATUS_OK;

	if (dryrun == 0)
	{
		status = asl_file_open_read(name, &f);
		if (status != ASL_STATUS_OK) return status;

		status = asl_file_filter_level(f, dst, keep_mask, ymd_mode, ymd_uid, ymd_gid, &dstcount, aux_url_callback);
		asl_file_close(f);
	}

	filesystem_unlink(src);
	if ((status != ASL_STATUS_OK) || (dstcount == 0)) filesystem_unlink(dst);
	else filesystem_rename(dst, src);

	return status;
}
Exemple #2
0
/*
 * Sweep the file cache.
 * Close any files that have not been used in the last FILE_CACHE_TTL seconds.
 * Returns least recently used or unused cache slot.
 */
static uint32_t
asl_store_file_cache_lru(asl_store_t *s, time_t now, uint32_t ignorex)
{
	time_t min;
	uint32_t i, x;

	if (s == NULL) return 0;

	x = 0;
	min = now - FILE_CACHE_TTL;

	for (i = 0; i < FILE_CACHE_SIZE; i++)
	{
		if ((i != ignorex) && (s->file_cache[i].ts < min))
		{
			asl_file_close(s->file_cache[i].f);
			s->file_cache[i].f = NULL;
			if (s->file_cache[i].path != NULL) free(s->file_cache[i].path);
			s->file_cache[i].path = NULL;
			s->file_cache[i].u = -1;
			s->file_cache[i].g = -1;
			s->file_cache[i].bb = 0;
			s->file_cache[i].ts = 0;
		}

		if (s->file_cache[i].ts < s->file_cache[x].ts) x = i;
	}

	return x;
}
Exemple #3
0
/*
 * Copy ASL files by reading and writing each record.
 */
uint32_t
copy_asl_file(const char *src, const char *dst, mode_t mode)
{
	asl_msg_list_t *res;
	asl_file_t *f;
	uint32_t status, i;
	uint64_t mid;
	size_t rcount;

	if (src == NULL) return ASL_STATUS_INVALID_ARG;
	if (dst == NULL) return ASL_STATUS_INVALID_ARG;

	f = NULL;
	status = asl_file_open_read(src, &f);
	if (status != ASL_STATUS_OK) return status;

	res = NULL;
	mid = 0;

	res = asl_file_match(f, NULL, &mid, 0, 0, 0, 1);
	asl_file_close(f);

	if (res == NULL) return ASL_STATUS_OK;
	rcount = asl_msg_list_count(res);
	if (rcount == 0)
	{
		asl_msg_list_release(res);
		return ASL_STATUS_OK;
	}

	f = NULL;
	status = asl_file_open_write(dst, mode, -1, -1, &f);
	if (status != ASL_STATUS_OK) return status;
	if (f == ASL_STATUS_OK) return ASL_STATUS_FAILED;

	f->flags = ASL_FILE_FLAG_PRESERVE_MSG_ID;

	for (i = 0; i < rcount; i++)
	{
		mid = 0;
		status = asl_file_save(f, asl_msg_list_get_index(res, i), &mid);
		if (status != ASL_STATUS_OK) break;
	}

	asl_file_close(f);
	return status;
}
Exemple #4
0
static uint32_t
asl_store_file_open_write(asl_store_t *s, char *tstring, int32_t ruid, int32_t rgid, time_t bb, asl_file_t **f, time_t now, uint32_t check_cache)
{
	char *path;
	mode_t m;
	int32_t i, x;
	uid_t u;
	gid_t g;
	uint32_t status;
	asl_file_t *out;

	if (s == NULL) return ASL_STATUS_INVALID_STORE;

	/* see if the file is already open and in the cache */
	for (i = 0; i < FILE_CACHE_SIZE; i++)
	{
		if ((s->file_cache[i].u == ruid) && (s->file_cache[i].g == rgid) && (s->file_cache[i].bb == bb) && (s->file_cache[i].f != NULL))
		{
			s->file_cache[i].ts = now;
			*f = s->file_cache[i].f;
			if (check_cache == 1) asl_store_file_cache_lru(s, now, i);
			return ASL_STATUS_OK;
		}
	}

	u = 0;
	g = 0;
	m = 0644;
	path = asl_store_make_ug_path(s->base_dir, tstring, "asl", (uid_t)ruid, (gid_t)rgid, &u, &g, &m);
	if (path == NULL) return ASL_STATUS_NO_MEMORY;

	out = NULL;
	status = asl_file_open_write(path, m, u, g, &out);
	if (status != ASL_STATUS_OK)
	{
		free(path);
		return status;
	}

	x = asl_store_file_cache_lru(s, now, FILE_CACHE_SIZE);
	if (s->file_cache[x].f != NULL) asl_file_close(s->file_cache[x].f);
	if (s->file_cache[x].path != NULL) free(s->file_cache[x].path);

	s->file_cache[x].f = out;
	s->file_cache[x].path = path;
	s->file_cache[x].u = ruid;
	s->file_cache[x].g = rgid;
	s->file_cache[x].bb = bb;
	s->file_cache[x].ts = time(NULL);

	*f = out;

	return ASL_STATUS_OK;
}
Exemple #5
0
__private_extern__ void
asl_store_file_closeall(asl_store_t *s)
{
	uint32_t i;

	if (s == NULL) return;

	for (i = 0; i < FILE_CACHE_SIZE; i++)
	{
		if (s->file_cache[i].f != NULL) asl_file_close(s->file_cache[i].f);
		s->file_cache[i].f = NULL;
		if (s->file_cache[i].path != NULL) free(s->file_cache[i].path);
		s->file_cache[i].path = NULL;
		s->file_cache[i].u = -1;
		s->file_cache[i].g = -1;
		s->file_cache[i].bb = 0;
		s->file_cache[i].ts = 0;
	}
}
Exemple #6
0
uint32_t
bb_convert(const char *name)
{
	struct stat sb;
	asl_store_t *store;
	uint32_t status;
	asl_search_result_t *expire_time_records;
	DIR *dp;
	struct dirent *dent;
	int i;
	name_list_t *list, *e;
	char *path;

	if (name != NULL) store_path = name;

	/* StoreData must exist */
	path = NULL;
	asprintf(&path, "%s/%s", store_path, FILE_ASL_STORE_DATA);
	if (path == NULL) return ASL_STATUS_NO_MEMORY;

	memset(&sb, 0, sizeof(struct stat));
	i = stat(path, &sb);
	free(path);
	if (i != 0) return ASL_STATUS_INVALID_STORE;

	/* must be a regular file */
	if (!S_ISREG(sb.st_mode)) return ASL_STATUS_INVALID_STORE;

	/* check is the store has already been converted */
	if (sb.st_size > sizeof(uint64_t)) return ASL_STATUS_OK;

	/* find ASLExpireTime messages */
	status = asl_store_open_read(store_path, &store);
	if (status != ASL_STATUS_OK) return status;

	expire_time_records = NULL;
	status = do_ASLExpireTime_search(store, &expire_time_records);

	asl_store_close(store);
	if (status != ASL_STATUS_OK) return status;

	/* unlink BB.* and LongTTL.* */
	dp = opendir(store_path);
	if (dp == NULL) return ASL_STATUS_READ_FAILED;

	while ((dent = readdir(dp)) != NULL)
	{
		if ((!strncmp(dent->d_name, "BB.", 3)) || (!strncmp(dent->d_name, "LongTTL.", 8)))
		{
			path = NULL;
			asprintf(&path, "%s/%s", store_path, dent->d_name);
			if (path == NULL)
			{
				closedir(dp);
				return ASL_STATUS_NO_MEMORY;
			}

			unlink(path);
			free(path);
		}
	}

	closedir(dp);

	if ((expire_time_records == NULL) || (expire_time_records->count == 0)) return finish_conversion();

	/* sort by ASLMessageID */
	qsort(expire_time_records->msg, expire_time_records->count, sizeof(aslmsg), sort_compare);

	/* save the ASLExpireTime messages into a new set of BB files */
	for (i = 0; i < expire_time_records->count; i++)
	{
		status = save_bb_msg((aslmsg)expire_time_records->msg[i]);
		if (status != ASL_STATUS_OK)
		{
			if (cache_file != NULL) asl_file_close(cache_file);
			return status;
		}
	}

	if (cache_file != NULL) asl_file_close(cache_file);

	aslresponse_free(expire_time_records);

	/* Re-write each YMD file without messages that have an ASLExpireTime */
	dp = opendir(store_path);
	if (dp == NULL) return ASL_STATUS_READ_FAILED;

	list = NULL;

	while ((dent = readdir(dp)) != NULL)
	{
		if ((dent->d_name[0] < '0') || (dent->d_name[0] > '9')) continue;
		list = add_to_list(list, dent->d_name);
	}

	closedir(dp);

	for (e = list; e != NULL; e = e->next)
	{
		status = do_ASLExpireTime_filter(e->name);
		if (status != ASL_STATUS_OK)
		{
			free_list(list);
			return status;
		}
	}

	free_list(list);

	return finish_conversion();
}
Exemple #7
0
/* save a message to an appropriately named BB file */
static uint32_t 
save_bb_msg(aslmsg msg)
{
	const char *val;
	uid_t u, ruid;
	gid_t g, rgid;
	struct tm ctm;
	time_t msg_time, bb;
	char *path, *tstring;
	asl_file_t *out;
	uint64_t mid;
	mode_t m;
	uint32_t status;

	if (msg == NULL) return ASL_STATUS_OK;

	val = asl_get(msg, ASL_KEY_EXPIRE_TIME);
	if (val == NULL)  return ASL_STATUS_INVALID_ARG;
	msg_time = asl_parse_time(val);

	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);

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

	/*
	 * This supports 12 monthy "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);

	u = 0;
	g = 0;
	if (ruid != -1) u = ruid;
	if (rgid != -1) g = rgid;

	out = NULL;

	if (cache_file != NULL)
	{
		if ((cache_uid == u) && (cache_gid == g) && (cache_bb == bb))
		{
			out = cache_file;
		}
		else
		{
			asl_file_close(cache_file);
			cache_file = NULL;
			cache_uid = -1;
			cache_gid = -1;
			cache_bb = 0;
		}
	}

	if (out == NULL)
	{
		if (localtime_r((const time_t *)&bb, &ctm) == NULL) return ASL_STATUS_FAILED;

		tstring = NULL;
		asprintf(&tstring, "%s/BB.%d.%02d.%02d", store_path, ctm.tm_year + 1900, ctm.tm_mon + 1, ctm.tm_mday);
		if (tstring == NULL) return ASL_STATUS_NO_MEMORY;

		path = NULL;
		m = 0644;

		if (ruid == -1)
		{
			if (rgid == -1)
			{
				asprintf(&path, "%s.asl", tstring);
			}
			else
			{
				m = 0640;
				asprintf(&path, "%s.G%d.asl", tstring, g);
			}
		}
		else
		{
			if (rgid == -1)
			{
				m = 0600;
				asprintf(&path, "%s.U%d.asl", tstring, u);
			}
			else
			{
				m = 0640;
				asprintf(&path, "%s.U%d.G%u.asl", tstring, u, g);
			}
		}

		if (path == NULL) return ASL_STATUS_NO_MEMORY;

		status = asl_file_open_write(path, m, u, g, &out);
		free(path);
		if (status != ASL_STATUS_OK) return status;
		if (out == NULL) return ASL_STATUS_FAILED;

		out->flags = ASL_FILE_FLAG_PRESERVE_MSG_ID;

		cache_file = out;
		cache_uid = u;
		cache_gid = g;
		cache_bb = bb;
	}

	status = asl_file_save(out, msg, &mid);

	return status;
}
Exemple #8
0
/* remove all messages that have an ASLExpireTime key */
static uint32_t
do_ASLExpireTime_filter(const char *name)
{
	aslmsg msg;
	asl_file_t *in, *out;
	uint32_t status;
	uint64_t mid;
	char *inpath, *outpath;
	struct stat sb;

	if (name == NULL) return ASL_STATUS_INVALID_ARG;

	in = NULL;
	inpath = NULL;
	asprintf(&inpath, "%s/%s", store_path, name);
	if (inpath == NULL) return ASL_STATUS_NO_MEMORY;

	memset(&sb, 0, sizeof(struct stat));
	if (stat(inpath, &sb) < 0)
	{
		free(inpath);
		return ASL_STATUS_INVALID_STORE;
	}

	status = asl_file_open_read(inpath, &in);
	if (status != ASL_STATUS_OK) 
	{
		free(inpath);
		return ASL_STATUS_OK;
	}

	out = NULL;
	outpath = NULL;
	asprintf(&outpath, "%s/%s", store_path, TEMP_NAME);
	if (outpath == NULL)
	{
		asl_file_close(in);
		free(inpath);
		return ASL_STATUS_NO_MEMORY;
	}

	status = asl_file_open_write(outpath, sb.st_mode, sb.st_uid, sb.st_gid, &out);
	if (status != ASL_STATUS_OK)
	{
		asl_file_close(in);
		free(inpath);
		free(outpath);
		return status;
	}

	out->flags = ASL_FILE_FLAG_PRESERVE_MSG_ID;

	msg = NULL;
	while (asl_file_fetch_next(in, &msg) == ASL_STATUS_OK)
	{
		if (msg == NULL) break;

		mid = 0;

		if (asl_get(msg, ASL_KEY_EXPIRE_TIME) == NULL) status = asl_file_save(out, msg, &mid);

		asl_free(msg);
		msg = NULL;

		if (status != ASL_STATUS_OK) break;
	}

	asl_file_close(in);
	asl_file_close(out);

	unlink(inpath);
	rename(outpath, inpath);

	free(inpath);
	free(outpath);

	return status;
}