#include <asl_store.h>
#include <notify.h>
-#include <TargetConditionals.h>
-
-#if TARGET_IPHONE_SIMULATOR
-#include <dispatch/dispatch.h>
-#include <assert.h>
-#endif
-
-extern time_t asl_parse_time(const char *str);
extern uint64_t asl_file_cursor(asl_file_t *s);
extern uint32_t asl_file_match_start(asl_file_t *s, uint64_t start_id, int32_t direction);
-extern uint32_t asl_file_match_next(asl_file_t *s, aslresponse query, asl_msg_t **msg, uint64_t *last_id, int32_t direction, int32_t ruid, int32_t rgid);
+extern uint32_t asl_file_match_next(asl_file_t *s, asl_msg_list_t *qlist, asl_msg_t **msg, uint64_t *last_id, int32_t direction, int32_t ruid, int32_t rgid);
extern int asl_file_create(const char *path, uid_t uid, gid_t gid, mode_t mode);
#define SECONDS_PER_DAY 86400
* | MAX_ID (uint64_t) |
*
*/
-uint32_t
+ASL_STATUS
asl_store_open_write(const char *basedir, asl_store_t **s)
{
asl_store_t *out;
struct stat sb;
uint32_t i, flags;
- char *path;
+ char path[MAXPATHLEN];
FILE *sd;
uint64_t last_id;
time_t start;
if (basedir == NULL) basedir = PATH_ASL_STORE;
memset(&sb, 0, sizeof(struct stat));
- if (stat(basedir, &sb) != 0) return ASL_STATUS_INVALID_STORE;
- if (!S_ISDIR(sb.st_mode)) return ASL_STATUS_INVALID_STORE;
-
- path = NULL;
- asprintf(&path, "%s/%s", basedir, FILE_ASL_STORE_DATA);
- if (path == NULL) return ASL_STATUS_NO_MEMORY;
+ if (stat(basedir, &sb) != 0)
+ {
+ if (errno != ENOENT) return ASL_STATUS_INVALID_STORE;
+ if (mkdir(basedir, 0755) != 0) return ASL_STATUS_WRITE_FAILED;
+ }
+ else
+ {
+ if (!S_ISDIR(sb.st_mode)) return ASL_STATUS_INVALID_STORE;
+ }
+
+ snprintf(path, sizeof(path), "%s/%s", basedir, FILE_ASL_STORE_DATA);
sd = NULL;
memset(&sb, 0, sizeof(struct stat));
if (stat(path, &sb) != 0)
{
- if (errno != ENOENT)
- {
- free(path);
- return ASL_STATUS_FAILED;
- }
+ if (errno != ENOENT) return ASL_STATUS_FAILED;
sd = fopen(path, "w+");
- free(path);
if (sd == NULL) return ASL_STATUS_FAILED;
else
{
sd = fopen(path, "r+");
- free(path);
if (sd == NULL) return ASL_STATUS_FAILED;
if (fread(&last_id, sizeof(uint64_t), 1, sd) != 1)
return ASL_STATUS_NO_MEMORY;
}
+ out->asl_type = ASL_TYPE_STORE;
+ out->refcount = 1;
+
if (basedir == NULL) out->base_dir = strdup(PATH_ASL_STORE);
else out->base_dir = strdup(basedir);
}
uint32_t
-asl_store_statistics(asl_store_t *s, aslmsg *msg)
+asl_store_set_flags(asl_store_t *s, uint32_t flags)
+{
+ if (s == NULL) return 0;
+ uint32_t oldflags = s->flags;
+ s->flags = flags;
+ return oldflags;
+}
+
+ASL_STATUS
+asl_store_statistics(asl_store_t *s, asl_msg_t **msg)
{
- aslmsg out;
+ asl_msg_t *out;
if (s == NULL) return ASL_STATUS_INVALID_STORE;
if (msg == NULL) return ASL_STATUS_INVALID_ARG;
- out = asl_new(ASL_TYPE_MSG);
+ out = asl_msg_new(ASL_TYPE_MSG);
if (out == NULL) return ASL_STATUS_NO_MEMORY;
/* does nothing for now */
out = (asl_store_t *)calloc(1, sizeof(asl_store_t));
if (out == NULL) return ASL_STATUS_NO_MEMORY;
+ out->asl_type = ASL_TYPE_STORE;
+ out->refcount = 1;
+
if (basedir == NULL) out->base_dir = strdup(PATH_ASL_STORE);
else out->base_dir = strdup(basedir);
}
}
-uint32_t
+asl_store_t *
+asl_store_retain(asl_store_t *s)
+{
+ if (s == NULL) return NULL;
+ asl_retain((asl_object_t)s);
+ return s;
+}
+
+void
+asl_store_release(asl_store_t *s)
+{
+ if (s == NULL) return;
+ asl_release((asl_object_t)s);
+}
+
+ASL_STATUS
asl_store_close(asl_store_t *s)
{
if (s == NULL) return ASL_STATUS_OK;
+ asl_release((asl_object_t)s);
+ return ASL_STATUS_OK;
+}
+
+static void
+_asl_store_free_internal(asl_store_t *s)
+{
+ if (s == NULL) return;
if (s->base_dir != NULL) free(s->base_dir);
s->base_dir = NULL;
if (s->storedata != NULL) fclose(s->storedata);
free(s);
-
- return ASL_STATUS_OK;
}
/*
return x;
}
-uint32_t
+ASL_STATUS
asl_store_sweep_file_cache(asl_store_t *s)
{
if (s == NULL) return ASL_STATUS_INVALID_STORE;
static char *
asl_store_make_ug_path(const char *dir, const char *base, const char *ext, uid_t ruid, gid_t rgid, uid_t *u, gid_t *g, mode_t *m)
{
- char *path = NULL;
+ char *path = NULL;
*u = 0;
*g = 0;
return path;
}
-static uint32_t
+static ASL_STATUS
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;
}
}
-uint32_t
-asl_store_save(asl_store_t *s, aslmsg msg)
+ASL_STATUS
+asl_store_save(asl_store_t *s, asl_msg_t *msg)
{
struct tm ctm;
time_t msg_time, now, bb;
- char *path, *tmp_path, *tstring, *scratch;
+ char *path;
+ char tstring[128], tmp_path[MAXPATHLEN];
const char *val;
uid_t ruid;
gid_t rgid;
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);
+ val = NULL;
+
+ if (asl_msg_lookup(msg, ASL_KEY_TIME, &val, NULL) != 0) msg_time = now;
+ else if (val == NULL) msg_time = now;
+ else msg_time = asl_core_parse_time(val, NULL);
if (msg_time >= s->start_tomorrow)
{
}
}
- 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 ((s->flags & ASL_STORE_FLAG_NO_ACLS) == 0)
+ {
+ val = NULL;
+ if ((asl_msg_lookup(msg, ASL_KEY_READ_UID, &val, NULL) == 0) && (val != NULL)) ruid = atoi(val);
+
+ val = NULL;
+ if ((asl_msg_lookup(msg, ASL_KEY_READ_GID, &val, NULL) == 0) && (val != NULL)) rgid = atoi(val);
+ }
bb = 0;
- val = asl_get(msg, ASL_KEY_EXPIRE_TIME);
- if (val != NULL)
+ if ((s->flags & ASL_STORE_FLAG_NO_TTL) == 0)
{
- bb = 1;
- msg_time = asl_parse_time(val);
+ val = NULL;
+ if ((asl_msg_lookup(msg, ASL_KEY_EXPIRE_TIME, &val, NULL) == 0) && (val != NULL))
+ {
+ bb = 1;
+ msg_time = asl_core_parse_time(val, NULL);
+ }
}
if (fseeko(s->storedata, 0, SEEK_SET) != 0) return ASL_STATUS_WRITE_FAILED;
if (localtime_r((const time_t *)&msg_time, &ctm) == NULL) return ASL_STATUS_FAILED;
- tstring = NULL;
if (bb == 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);
+ snprintf(tstring, sizeof(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);
+ snprintf(tstring, sizeof(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 (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);
-
- }
+ char scratch[MAXPATHLEN];
+ snprintf(scratch, sizeof(scratch), "%s", path);
+ scratch[len - 4] = '\0';
+ snprintf(tmp_path, sizeof(tmp_path), "%s.%llu.asl", scratch, ftime);
}
else
{
/* append timestamp */
- asprintf(&tmp_path, "%s.%llu", path, ftime);
+ snprintf(tmp_path, sizeof(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);
- }
+ if (rename(path, tmp_path) != 0) status = ASL_STATUS_FAILED;
free(path);
}
return status;
}
-static uint32_t
+static ASL_STATUS
asl_store_mkdir(asl_store_t *s, const char *dir, mode_t m)
{
- char *tstring = NULL;
+ char tstring[MAXPATHLEN];
int status;
struct stat sb;
- asprintf(&tstring, "%s/%s", s->base_dir, dir);
- if (tstring == NULL) return ASL_STATUS_NO_MEMORY;
+ snprintf(tstring, sizeof(tstring), "%s/%s", s->base_dir, dir);
memset(&sb, 0, sizeof(struct stat));
status = stat(tstring, &sb);
if (status == 0)
{
/* must be a directory */
- if (!S_ISDIR(sb.st_mode))
- {
- free(tstring);
- return ASL_STATUS_INVALID_STORE;
- }
+ if (!S_ISDIR(sb.st_mode)) return ASL_STATUS_INVALID_STORE;
}
else
{
if (errno == ENOENT)
{
/* doesn't exist - create it */
- if (mkdir(tstring, m) != 0)
- {
- free(tstring);
- return ASL_STATUS_WRITE_FAILED;
- }
+ if (mkdir(tstring, m) != 0) return ASL_STATUS_WRITE_FAILED;
}
else
{
/* stat failed for some other reason */
- free(tstring);
return ASL_STATUS_FAILED;
}
}
- free(tstring);
return ASL_STATUS_OK;
}
-uint32_t
-asl_store_open_aux(asl_store_t *s, aslmsg msg, int *out_fd, char **url)
+ASL_STATUS
+asl_store_open_aux(asl_store_t *s, asl_msg_t *msg, int *out_fd, char **url)
{
struct tm ctm;
time_t msg_time, bb;
- char *path, *dir, *tstring;
+ char *path;
+ char tstring[128], dir[128];
const char *val;
uid_t ruid, u;
gid_t rgid, g;
msg_time = time(NULL);
- 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 ((s->flags & ASL_STORE_FLAG_NO_ACLS) == 0)
+ {
+ val = NULL;
+ if ((asl_msg_lookup(msg, ASL_KEY_READ_UID, &val, NULL) == 0) && (val != NULL)) ruid = atoi(val);
+
+ val = NULL;
+ if ((asl_msg_lookup(msg, ASL_KEY_READ_GID, &val, NULL) == 0) && (val != NULL)) rgid = atoi(val);
+ }
bb = 0;
- val = asl_get(msg, ASL_KEY_EXPIRE_TIME);
- if (val != NULL)
+ if ((s->flags & ASL_STORE_FLAG_NO_TTL) == 0)
{
- bb = 1;
- msg_time = asl_parse_time(val);
+ val = NULL;
+ if ((asl_msg_lookup(msg, ASL_KEY_EXPIRE_TIME, &val, NULL) == 0) && (val != NULL))
+ {
+ bb = 1;
+ msg_time = asl_core_parse_time(val, NULL);
+ }
}
if (localtime_r((const time_t *)&msg_time, &ctm) == NULL) return ASL_STATUS_FAILED;
- dir = NULL;
if (bb == 1)
{
/*
bb = mktime(&ctm);
if (localtime_r((const time_t *)&bb, &ctm) == NULL) return ASL_STATUS_FAILED;
- asprintf(&dir, "BB.AUX.%d.%02d.%02d", ctm.tm_year + 1900, ctm.tm_mon + 1, ctm.tm_mday);
+ snprintf(dir, sizeof(dir), "BB.AUX.%d.%02d.%02d", ctm.tm_year + 1900, ctm.tm_mon + 1, ctm.tm_mday);
}
else
{
- asprintf(&dir, "AUX.%d.%02d.%02d", ctm.tm_year + 1900, ctm.tm_mon + 1, ctm.tm_mday);
+ snprintf(dir, sizeof(dir), "AUX.%d.%02d.%02d", ctm.tm_year + 1900, ctm.tm_mon + 1, ctm.tm_mday);
}
- if (dir == NULL) return ASL_STATUS_NO_MEMORY;
-
status = asl_store_mkdir(s, dir, 0755);
- if (status != ASL_STATUS_OK)
- {
- free(dir);
- return status;
- }
+ if (status != ASL_STATUS_OK) return status;
fid = s->next_id;
s->next_id++;
- tstring = NULL;
- asprintf(&tstring, "%s/%llu", dir, fid);
- free(dir);
- if (tstring == NULL) return ASL_STATUS_NO_MEMORY;
+ snprintf(tstring, sizeof(tstring), "%s/%llu", dir, fid);
u = 0;
g = 0;
m = 0644;
path = asl_store_make_ug_path(s->base_dir, tstring, NULL, ruid, rgid, &u, &g, &m);
- free(tstring);
if (path == NULL) return ASL_STATUS_NO_MEMORY;
fd = asl_file_create(path, u, g, m);
return status;
}
-uint32_t
-asl_store_match_timeout(asl_store_t *s, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction, uint32_t usec)
+asl_msg_list_t *
+asl_store_match(asl_store_t *s, asl_msg_list_t *qlist, uint64_t *last_id, uint64_t start_id, uint32_t count, uint32_t duration, int32_t direction)
{
DIR *dp;
struct dirent *dent;
uint32_t status;
asl_file_t *f;
- char *path;
+ char path[MAXPATHLEN];
asl_file_list_t *files;
+ asl_msg_list_t *res;
- if (s == NULL) return ASL_STATUS_INVALID_STORE;
- if (res == NULL) return ASL_STATUS_INVALID_ARG;
+ if (s == NULL) return NULL;
files = NULL;
* Open all readable files
*/
dp = opendir(s->base_dir);
- if (dp == NULL) return ASL_STATUS_READ_FAILED;
+ if (dp == NULL) return NULL;
while ((dent = readdir(dp)) != NULL)
{
if (dent->d_name[0] == '.') continue;
- path = NULL;
- asprintf(&path, "%s/%s", s->base_dir, dent->d_name);
+ snprintf(path, sizeof(path), "%s/%s", s->base_dir, dent->d_name);
/* NB asl_file_open_read will fail if path is NULL, if the file is not an ASL store file, or if it isn't readable */
status = asl_file_open_read(path, &f);
- if (path != NULL) free(path);
if ((status != ASL_STATUS_OK) || (f == NULL)) continue;
files = asl_file_list_add(files, f);
closedir(dp);
- status = asl_file_list_match_timeout(files, query, res, last_id, start_id, count, direction, usec);
+ res = asl_file_list_match(files, qlist, last_id, start_id, count, duration, direction);
asl_file_list_close(files);
- return status;
+ return res;
}
-uint32_t
-asl_store_match(asl_store_t *s, aslresponse query, aslresponse *res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction)
+/*
+ * PRIVATE FOR DEV TOOLS SUPPORT
+ * DO NOT USE THIS INTERFACE OTHERWISE
+ *
+ * This is only called by a client that compiled with a 10.9 SDK, but is running
+ * with an new 10.10 libasl.
+ *
+ * Only searches the ASL database, so the store (first parameter) is ignored.
+ *
+ * The query and result are old-style message lists.
+ *
+ */
+typedef struct
+{
+ uint32_t count;
+ uint32_t curr;
+ void **msg;
+} asl_msg_list_v1_t;
+
+ASL_STATUS
+asl_store_match_timeout(void *ignored, void *query_v1, void **result_v1, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction, uint32_t usec)
{
- return asl_store_match_timeout(s, query, res, last_id, start_id, count, direction, 0);
+ asl_store_t *asldb = NULL;
+ asl_msg_list_v1_t *listv1;
+ asl_msg_list_t *qlist = NULL;
+ uint32_t status, n;
+
+ if (result_v1 == NULL) return ASL_STATUS_FAILED;
+ *result_v1 = NULL;
+
+ status = asl_store_open_read(NULL, &asldb);
+ if (status != ASL_STATUS_OK) return status;
+
+ /* convert query_v1 into an asl_msg_list_t */
+ listv1 = (asl_msg_list_v1_t *)query_v1;
+ if (listv1 != NULL)
+ {
+ if (listv1->count > 0) qlist = (asl_msg_list_t *)asl_new(ASL_TYPE_LIST);
+
+ for (listv1->curr = 0; listv1->curr < listv1->count; listv1->curr++)
+ {
+ asl_append((asl_object_t)qlist, (asl_object_t)listv1->msg[listv1->curr]);
+ }
+ }
+
+ asl_msg_list_t *result = asl_store_match(asldb, qlist, last_id, start_id, count, usec, direction);
+ asl_release((asl_object_t)asldb);
+ asl_release((asl_object_t)qlist);
+
+ if (result == NULL) return ASL_STATUS_OK;
+
+ n = asl_count((asl_object_t)result);
+ if (n == 0)
+ {
+ asl_release((asl_object_t)result);
+ return ASL_STATUS_OK;
+ }
+
+ listv1 = (asl_msg_list_v1_t *)calloc(1, sizeof(asl_msg_list_v1_t));
+ if (listv1 == NULL)
+ {
+ asl_release((asl_object_t)result);
+ return ASL_STATUS_NO_MEMORY;
+ }
+
+ listv1->count = n;
+ listv1->msg = (void **)calloc(listv1->count, sizeof(void *));
+ if (listv1 == NULL)
+ {
+ free(listv1);
+ asl_release((asl_object_t)result);
+ return ASL_STATUS_NO_MEMORY;
+ }
+
+ for (listv1->curr = 0; listv1->curr < listv1->count; listv1->curr++)
+ {
+ listv1->msg[listv1->curr] = asl_retain(asl_next((asl_object_t)result));
+ }
+
+ listv1->curr = 0;
+ *result_v1 = listv1;
+
+ asl_release((asl_object_t)result);
+ return ASL_STATUS_OK;
}
-uint32_t
+ASL_STATUS
asl_store_match_start(asl_store_t *s, uint64_t start_id, int32_t direction)
{
DIR *dp;
struct dirent *dent;
uint32_t status;
asl_file_t *f;
- char *path;
+ char path[MAXPATHLEN];
asl_file_list_t *files;
if (s == NULL) return ASL_STATUS_INVALID_STORE;
{
if (dent->d_name[0] == '.') continue;
- path = NULL;
- asprintf(&path, "%s/%s", s->base_dir, dent->d_name);
+ snprintf(path, sizeof(path), "%s/%s", s->base_dir, dent->d_name);
- /* NB asl_file_open_read will fail if path is NULL, if the file is not an ASL store file, or if it isn't readable */
+ /*
+ * NB asl_file_open_read will fail if path is NULL,
+ * if it is not an ASL store file, or if it isn't readable.
+ * We expect that.
+ */
status = asl_file_open_read(path, &f);
- if (path != NULL) free(path);
if ((status != ASL_STATUS_OK) || (f == NULL)) continue;
files = asl_file_list_add(files, f);
return ASL_STATUS_OK;
}
-uint32_t
-asl_store_match_next(asl_store_t *s, aslresponse query, aslresponse *res, uint32_t count)
+ASL_STATUS
+asl_store_match_next(asl_store_t *s, asl_msg_list_t *qlist, asl_msg_list_t **res, uint32_t count)
{
if (s == NULL) return ASL_STATUS_INVALID_STORE;
if (s->work == NULL) return ASL_STATUS_OK;
- return asl_file_list_match_next(s->work, query, res, count);
+ return asl_file_list_match_next(s->work, qlist, res, count);
}
-#if TARGET_IPHONE_SIMULATOR
-const char *_path_asl_store(void) {
- static char * path;
- static dispatch_once_t once;
+#pragma mark -
+#pragma mark asl_object support
- dispatch_once(&once, ^{
- char *sim_log_dir = getenv("IPHONE_SIMULATOR_LOG_ROOT");
- assert(sim_log_dir);
+static void
+_jump_dealloc(asl_object_private_t *obj)
+{
+ _asl_store_free_internal((asl_store_t *)obj);
+}
- asprintf(&path, "%s/asl", sim_log_dir);
- assert(path);
- });
+static asl_object_private_t *
+_jump_next(asl_object_private_t *obj)
+{
+ asl_store_t *s = (asl_store_t *)obj;
+ asl_msg_list_t *list;
+ asl_msg_t *out = NULL;
+ uint64_t last = 0;
- return path;
+ if (s == NULL) return NULL;
+ if (s->curr == SIZE_MAX) return NULL;
+
+ s->curr++;
+ list = asl_store_match(s, NULL, &last, s->curr, 1, 0, 1);
+ if (list == NULL)
+ {
+ s->curr = SIZE_MAX;
+ return NULL;
+ }
+
+ s->curr = last;
+ out = asl_msg_list_get_index(list, 0);
+ asl_msg_list_release(list);
+
+ return (asl_object_private_t *)out;
}
-const char *_path_asl_archive(void) {
- static char * path;
- static dispatch_once_t once;
+static asl_object_private_t *
+_jump_prev(asl_object_private_t *obj)
+{
+ asl_store_t *s = (asl_store_t *)obj;
+ asl_msg_list_t *list;
+ asl_msg_t *out = NULL;
+ uint64_t last = 0;
- dispatch_once(&once, ^{
- char *sim_log_dir = getenv("IPHONE_SIMULATOR_LOG_ROOT");
- assert(sim_log_dir);
+ if (s == NULL) return NULL;
+ if (s->curr == 0) return NULL;
- asprintf(&path, "%s/asl.archive", sim_log_dir);
- assert(path);
- });
+ s->curr--;
+ if (s->curr == 0) return NULL;
- return path;
+ list = asl_store_match(s, NULL, &last, s->curr, 1, 0, -1);
+ if (list == NULL)
+ {
+ s->curr = 0;
+ return NULL;
+ }
+
+ s->curr = last;
+ out = asl_msg_list_get_index(list, 0);
+ asl_msg_list_release(list);
+
+ return (asl_object_private_t *)out;
+}
+
+static void
+_jump_set_iteration_index(asl_object_private_t *obj, size_t n)
+{
+ asl_store_t *s = (asl_store_t *)obj;
+ if (s == NULL) return;
+
+ s->curr = n;
+}
+
+static void
+_jump_append(asl_object_private_t *obj, asl_object_private_t *newobj)
+{
+ asl_store_t *s = (asl_store_t *)obj;
+ int type = asl_get_type((asl_object_t)newobj);
+ if (s == NULL) return;
+ if (s->flags & ASL_FILE_FLAG_READ) return;
+
+ if (type == ASL_TYPE_LIST)
+ {
+ asl_msg_t *msg;
+ asl_msg_list_reset_iteration((asl_msg_list_t *)newobj, 0);
+ while (NULL != (msg = asl_msg_list_next((asl_msg_list_t *)newobj)))
+ {
+ if (asl_store_save(s, msg) != ASL_STATUS_OK) return;
+ }
+ }
+ else if ((type == ASL_TYPE_MSG) || (type == ASL_TYPE_QUERY))
+ {
+ asl_store_save(s, (asl_msg_t *)newobj);
+ }
+}
+
+static asl_object_private_t *
+_jump_search(asl_object_private_t *obj, asl_object_private_t *query)
+{
+ asl_store_t *s = (asl_store_t *)obj;
+ int type = asl_get_type((asl_object_t)query);
+ asl_msg_list_t *out = NULL;
+ asl_msg_list_t *ql = NULL;
+ uint64_t last;
+
+ if (query == NULL)
+ {
+ out = asl_store_match(s, NULL, &last, 0, 0, 0, 1);
+ }
+ else if (type == ASL_TYPE_LIST)
+ {
+ out = asl_store_match(s, (asl_msg_list_t *)query, &last, 0, 0, 0, 1);
+ }
+ else if ((type == ASL_TYPE_MSG) || (type == ASL_TYPE_QUERY))
+ {
+ ql = asl_msg_list_new();
+ asl_msg_list_append(ql, query);
+
+ out = asl_store_match(s, ql, &last, 0, 0, 0, 1);
+ asl_msg_list_release(ql);
+ }
+
+ return (asl_object_private_t *)out;
+}
+
+static asl_object_private_t *
+_jump_match(asl_object_private_t *obj, asl_object_private_t *qlist, size_t *last, size_t start, size_t count, uint32_t duration, int32_t dir)
+{
+ uint64_t x;
+ asl_msg_list_t *out;
+
+ out = asl_store_match((asl_store_t *)obj, (asl_msg_list_t *)qlist, &x, start, count, duration, dir);
+ *last = x;
+ return (asl_object_private_t *)out;
+}
+
+__private_extern__ const asl_jump_table_t *
+asl_store_jump_table()
+{
+ static const asl_jump_table_t jump =
+ {
+ .alloc = NULL,
+ .dealloc = &_jump_dealloc,
+ .set_key_val_op = NULL,
+ .unset_key = NULL,
+ .get_val_op_for_key = NULL,
+ .get_key_val_op_at_index = NULL,
+ .count = NULL,
+ .next = &_jump_next,
+ .prev = &_jump_prev,
+ .get_object_at_index = NULL,
+ .set_iteration_index = &_jump_set_iteration_index,
+ .remove_object_at_index = NULL,
+ .append = &_jump_append,
+ .prepend = NULL,
+ .search = &_jump_search,
+ .match = &_jump_match
+ };
+
+ return &jump;
}
-#endif