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; }
/* * 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; }
/* 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; }
/* 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; }