]> git.saurik.com Git - apple/syslog.git/blame - libsystem_asl.tproj/src/asl_legacy1.c
syslog-385.tar.gz
[apple/syslog.git] / libsystem_asl.tproj / src / asl_legacy1.c
CommitLineData
81582353
A
1/*
2 * Copyright (c) 2007-2011 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@ */
22
23#include <asl_core.h>
24#include <asl_legacy1.h>
25#include <asl_private.h>
26#include <stdlib.h>
27#include <sys/file.h>
28#include <sys/stat.h>
29#include <sys/errno.h>
30#include <string.h>
31#include <membership.h>
32#include <mach/mach.h>
33#include <sys/syslimits.h>
34#include <sys/types.h>
35#include <time.h>
36#include <sys/mman.h>
37
38#define forever for(;;)
39
40#define FILE_MODE 0600
41
42#define DB_RECORD_LEN 80
43
44#define DB_HEADER_COOKIE_OFFSET 0
45#define DB_HEADER_VERS_OFFSET 12
46
47#define DB_TYPE_EMPTY 0
48#define DB_TYPE_HEADER 1
49#define DB_TYPE_MESSAGE 2
50#define DB_TYPE_KVLIST 3
51#define DB_TYPE_STRING 4
52#define DB_TYPE_STRCONT 5
53
54/*
55 * Magic Cookie for database files.
56 * MAXIMUM 12 CHARS! (DB_HEADER_VERS_OFFSET)
57 */
58#define ASL_DB_COOKIE "ASL DB"
59#define ASL_DB_COOKIE_LEN 6
60
61#define ASL_INDEX_NULL 0xffffffff
62
63#define DB_HLEN_EMPTY 0
64#define DB_HLEN_HEADER 13
65#define DB_HLEN_MESSAGE 13
66#define DB_HLEN_KVLIST 9
67#define DB_HLEN_STRING 25
68#define DB_HLEN_STRCONT 5
69
70#define MSG_OFF_KEY_TYPE 0
71#define MSG_OFF_KEY_NEXT 1
72#define MSG_OFF_KEY_ID 5
73#define MSG_OFF_KEY_RUID 13
74#define MSG_OFF_KEY_RGID 17
75#define MSG_OFF_KEY_TIME 21
76#define MSG_OFF_KEY_HOST 29
77#define MSG_OFF_KEY_SENDER 37
78#define MSG_OFF_KEY_FACILITY 45
79#define MSG_OFF_KEY_LEVEL 53
80#define MSG_OFF_KEY_PID 57
81#define MSG_OFF_KEY_UID 61
82#define MSG_OFF_KEY_GID 65
83#define MSG_OFF_KEY_MSG 69
84#define MSG_OFF_KEY_FLAGS 77
85
f3df4c03 86extern int asl_msg_cmp(asl_msg_t *a, asl_msg_t *b);
81582353
A
87
88#define Q_NULL 100001
89#define Q_FAST 100002
90#define Q_SLOW 100003
91#define Q_FAIL 100004
92
93static uint64_t
94_asl_htonq(uint64_t n)
95{
96#ifdef __BIG_ENDIAN__
97 return n;
98#else
99 u_int32_t t;
100 union
101 {
102 u_int64_t q;
103 u_int32_t l[2];
104 } x;
105
106 x.q = n;
107 t = x.l[0];
108 x.l[0] = htonl(x.l[1]);
109 x.l[1] = htonl(t);
110
111 return x.q;
112#endif
113}
114
115static uint64_t
116_asl_ntohq(uint64_t n)
117{
118#ifdef __BIG_ENDIAN__
119 return n;
120#else
121 u_int32_t t;
122 union
123 {
124 u_int64_t q;
125 u_int32_t l[2];
126 } x;
127
128 x.q = n;
129 t = x.l[0];
130 x.l[0] = ntohl(x.l[1]);
131 x.l[1] = ntohl(t);
132
133 return x.q;
134#endif
135}
136
137static uint16_t
138_asl_get_16(char *h)
139{
140 uint16_t x;
141
142 memcpy(&x, h, 2);
143 return ntohs(x);
144}
145
146static uint32_t
147_asl_get_32(char *h)
148{
149 uint32_t x;
150
151 memcpy(&x, h, 4);
152 return ntohl(x);
153}
154
155static uint64_t
156_asl_get_64(char *h)
157{
158 uint64_t x;
159
160 memcpy(&x, h, 8);
161 return _asl_ntohq(x);
162}
163
164#define header_get_next(h) _asl_get_32(h + 1)
165#define header_get_id(h) _asl_get_64(h + 5)
166#define header_get_hash(h) _asl_get_32(h + 17)
167
168/*
169 * callback for sorting slotlist
170 * primary sort is by xid
171 * secondary sort is by slot, which happens when xid is 0
172 * this allows us to quickly find xids (using binary search on the xid key)
173 * it's also used to find slots quickly from record_chain_free()
174 */
175static int
176slot_comp(const void *a, const void *b)
177{
178 asl_legacy1_slot_info_t *ai, *bi;
179
180 if (a == NULL)
181 {
182 if (b == NULL) return 0;
183 return -1;
184 }
185
186 if (b == NULL) return 1;
187
188 ai = (asl_legacy1_slot_info_t *)a;
189 bi = (asl_legacy1_slot_info_t *)b;
190
191 if (ai->xid < bi->xid) return -1;
192
193 if (ai->xid == bi->xid)
194 {
195 if (ai->slot < bi->slot) return -1;
196 if (ai->slot == bi->slot) return 0;
197 return 1;
198 }
199
200 return 1;
201}
202
203/* find an xid in the slot list */
204static uint32_t
205slotlist_find(asl_legacy1_t *s, uint64_t xid, int32_t direction)
206{
207 uint32_t top, bot, mid, range;
208
209 if (s == NULL) return ASL_INDEX_NULL;
210 if (s->slotlist_count == 0) return ASL_INDEX_NULL;
211 if (xid == 0) return ASL_INDEX_NULL;
212
213 top = s->slotlist_count - 1;
214 bot = 0;
215 mid = top / 2;
216
217 range = top - bot;
218 while (range > 1)
219 {
220 if (xid == s->slotlist[mid].xid) return mid;
221 else if (xid < s->slotlist[mid].xid) top = mid;
222 else bot = mid;
223
224 range = top - bot;
225 mid = bot + (range / 2);
226 }
227
228 if (xid == s->slotlist[top].xid) return top;
229 if (xid == s->slotlist[bot].xid) return bot;
230
f3df4c03 231 if (direction >= 0) return ASL_INDEX_NULL;
81582353
A
232 if (direction < 0) return bot;
233 return top;
234}
235
f3df4c03 236static ASL_STATUS
81582353
A
237slotlist_init(asl_legacy1_t *s, uint32_t count)
238{
239 uint32_t i, si, status, hash, addslot;
240 uint64_t xid;
241 uint8_t t;
242 size_t rcount;
243 char tmp[DB_RECORD_LEN];
244
245 /* Start at first slot after the header */
246 status = fseek(s->db, DB_RECORD_LEN, SEEK_SET);
247 if (status != 0) return ASL_STATUS_READ_FAILED;
248
249 s->slotlist = (asl_legacy1_slot_info_t *)calloc(count, sizeof(asl_legacy1_slot_info_t));
250 if (s->slotlist == NULL) return ASL_STATUS_NO_MEMORY;
251
252 si = 0;
253
254 for (i = 1; i < count; i++)
255 {
256 rcount = fread(tmp, DB_RECORD_LEN, 1, s->db);
257 if (rcount != 1) return ASL_STATUS_READ_FAILED;
258
259 t = tmp[0];
260 addslot = 0;
261 xid = 0;
262 hash = 0;
263
264 if (t == DB_TYPE_EMPTY) addslot = 1;
265
266 if (t == DB_TYPE_STRING)
267 {
268 addslot = 1;
269 xid = header_get_id(tmp);
270 hash = header_get_hash(tmp);
271 }
272
273 if (t == DB_TYPE_MESSAGE)
274 {
275 addslot = 1;
276 xid = header_get_id(tmp);
277 }
278
279 if (addslot == 1)
280 {
281 s->slotlist[si].type = t;
282 s->slotlist[si].slot = i;
283 s->slotlist[si].xid = xid;
284 s->slotlist[si].hash = hash;
285 si++;
286 }
287 }
288
289 s->slotlist = (asl_legacy1_slot_info_t *)reallocf(s->slotlist, si * sizeof(asl_legacy1_slot_info_t));
290 if (s->slotlist == NULL) return ASL_STATUS_NO_MEMORY;
291 s->slotlist_count = si;
292
293 /* slotlist is sorted by xid */
294 qsort((void *)s->slotlist, s->slotlist_count, sizeof(asl_legacy1_slot_info_t), slot_comp);
295
296 return ASL_STATUS_OK;
297}
298
f3df4c03 299ASL_STATUS
81582353
A
300asl_legacy1_open(const char *path, asl_legacy1_t **out)
301{
302 asl_legacy1_t *s;
303 struct stat sb;
304 int status;
305 size_t rcount;
306 char cbuf[DB_RECORD_LEN];
307 off_t fsize;
308 uint32_t count;
309
310 memset(&sb, 0, sizeof(struct stat));
311 status = stat(path, &sb);
312 if (status < 0) return ASL_STATUS_FAILED;
313
314 fsize = sb.st_size;
315
316 s = (asl_legacy1_t *)calloc(1, sizeof(asl_legacy1_t));
317 if (s == NULL) return ASL_STATUS_NO_MEMORY;
318
319 s->db = fopen(path, "r");
320 if (s->db == NULL)
321 {
322 free(s);
323 return ASL_STATUS_INVALID_STORE;
324 }
325
326 memset(cbuf, 0, DB_RECORD_LEN);
327 rcount = fread(cbuf, DB_RECORD_LEN, 1, s->db);
328 if (rcount != 1)
329 {
330 fclose(s->db);
331 free(s);
332 return ASL_STATUS_READ_FAILED;
333 }
334
335 /* Check the database Magic Cookie */
336 if (strncmp(cbuf, ASL_DB_COOKIE, ASL_DB_COOKIE_LEN))
337 {
338 fclose(s->db);
339 free(s);
340 return ASL_STATUS_INVALID_STORE;
341 }
342
343 count = fsize / DB_RECORD_LEN;
344
345 status = slotlist_init(s, count);
346
347 *out = s;
348 return ASL_STATUS_OK;
349}
350
f3df4c03 351ASL_STATUS
81582353
A
352asl_legacy1_close(asl_legacy1_t *s)
353{
354 if (s == NULL) return ASL_STATUS_INVALID_STORE;
355
356 if (s->slotlist != NULL) free(s->slotlist);
357 if (s->db != NULL) fclose(s->db);
358 free(s);
359
360 return ASL_STATUS_OK;
361}
362
f3df4c03 363static ASL_STATUS
81582353
A
364string_fetch_slot(asl_legacy1_t *s, uint32_t slot, char **out)
365{
366 off_t offset;
367 uint8_t type;
368 uint32_t next, x, remaining;
369 size_t rcount, len;
370 int status;
371 char *outstr, *p, tmp[DB_RECORD_LEN];
372
373 if (s == NULL) return ASL_STATUS_INVALID_STORE;
374 if (out == NULL) return ASL_STATUS_INVALID_ARG;
375
376 *out = NULL;
377 offset = slot * DB_RECORD_LEN;
378 status = fseek(s->db, offset, SEEK_SET);
379
380 if (status < 0) return ASL_STATUS_READ_FAILED;
381
382 rcount = fread(tmp, DB_RECORD_LEN, 1, s->db);
383 if (rcount != 1) return ASL_STATUS_READ_FAILED;
384
385 type = tmp[0];
386 if (type != DB_TYPE_STRING) return ASL_STATUS_INVALID_STRING;
387
388 len = _asl_get_32(tmp + 21);
389 if (len == 0) return ASL_STATUS_OK;
390
391 next = header_get_next(tmp);
392
393 outstr = calloc(1, len);
394 if (outstr == NULL) return ASL_STATUS_NO_MEMORY;
395
396 p = outstr;
397 remaining = len;
398
399 x = DB_RECORD_LEN - DB_HLEN_STRING;
400 if (x > remaining) x = remaining;
401
402 memcpy(p, tmp + DB_HLEN_STRING, x);
403 p += x;
404 remaining -= x;
405
406 while ((next != 0) && (remaining > 0))
407 {
408 offset = next * DB_RECORD_LEN;
409 status = fseek(s->db, offset, SEEK_SET);
410
411 if (status < 0)
412 {
413 free(outstr);
414 return ASL_STATUS_READ_FAILED;
415 }
416
417 rcount = fread(tmp, DB_RECORD_LEN, 1, s->db);
418 if (rcount != 1)
419 {
420 free(outstr);
421 return ASL_STATUS_READ_FAILED;
422 }
423
424 next = header_get_next(tmp);
425
426 x = DB_RECORD_LEN - DB_HLEN_STRCONT;
427 if (x > remaining) x = remaining;
428
429 memcpy(p, tmp + DB_HLEN_STRCONT, x);
430 p += x;
431 remaining -= x;
432 }
433
434 if ((next != 0) || (remaining != 0))
435 {
436 free(outstr);
437 return ASL_STATUS_READ_FAILED;
438 }
439
440 *out = outstr;
441 return ASL_STATUS_OK;
442}
443
f3df4c03 444static ASL_STATUS
81582353
A
445string_fetch_sid(asl_legacy1_t *s, uint64_t sid, char **out)
446{
447 uint32_t i, len, ref;
448 uint64_t nsid;
449 uint8_t inls;
450 char *p;
451
452 if (s == NULL) return ASL_STATUS_INVALID_STORE;
453 if (out == NULL) return ASL_STATUS_INVALID_ARG;
454
455 *out = NULL;
456 if (sid == ASL_REF_NULL) return ASL_STATUS_OK;
457
458 ref = 0;
459
460 inls = 0;
461 nsid = _asl_htonq(sid);
462 memcpy(&inls, &nsid, 1);
463 if (inls & 0x80)
464 {
465 /* inline string */
466 inls &= 0x0f;
467 len = inls;
468 *out = calloc(1, len);
469 if (*out == NULL) return ASL_STATUS_NO_MEMORY;
470 p = 1 + (char *)&nsid;
471 memcpy(*out, p, len);
472 return ASL_STATUS_OK;
473 }
474
475 /* Find the string in the database */
476 i = slotlist_find(s, sid, 0);
477 if (i == ASL_INDEX_NULL) return ASL_STATUS_NOT_FOUND;
478
479 return string_fetch_slot(s, s->slotlist[i].slot, out);
480}
481
482static uint32_t
f3df4c03 483asl_legacy1_fetch_helper_32(asl_legacy1_t *s, char **p, asl_msg_t *m, const char *key, int ignore, uint32_t ignoreval)
81582353
A
484{
485 uint32_t out, doit;
486 char str[256];
487
488 out = _asl_get_32(*p);
489 *p += sizeof(uint32_t);
490
491 if ((m == NULL) || (key == NULL)) return out;
492
493 doit = 1;
494 if ((ignore != 0) && (out == ignoreval)) doit = 0;
495 if (doit != 0)
496 {
497 snprintf(str, sizeof(str), "%u", out);
f3df4c03 498 asl_msg_set_key_val(m, key, str);
81582353
A
499 }
500
501 return out;
502}
503
504static uint64_t
f3df4c03 505asl_legacy1_fetch_helper_64(asl_legacy1_t *s, char **p, asl_msg_t *m, const char *key)
81582353
A
506{
507 uint64_t out;
508 char str[256];
509
510 out = _asl_get_64(*p);
511 *p += sizeof(uint64_t);
512
513 if ((m == NULL) || (key == NULL)) return out;
514
515 snprintf(str, sizeof(str), "%llu", out);
f3df4c03 516 asl_msg_set_key_val(m, key, str);
81582353
A
517
518 return out;
519}
520
521static uint64_t
f3df4c03 522asl_legacy1_fetch_helper_str(asl_legacy1_t *s, char **p, asl_msg_t *m, const char *key, uint32_t *err)
81582353
A
523{
524 uint64_t out;
525 char *val;
526 uint32_t status;
527
528 out = _asl_get_64(*p);
529 *p += sizeof(uint64_t);
530
531 val = NULL;
532 status = ASL_STATUS_OK;
533 if (out != 0) status = string_fetch_sid(s, out, &val);
534
535 if (err != NULL) *err = status;
536 if ((status == ASL_STATUS_OK) && (val != NULL))
537 {
f3df4c03 538 asl_msg_set_key_val(m, key, val);
81582353
A
539 free(val);
540 }
541
542 return out;
543}
544
f3df4c03
A
545static ASL_STATUS
546msg_fetch(asl_legacy1_t *s, uint32_t slot, asl_msg_t **out)
81582353
A
547{
548 off_t offset;
549 uint32_t status, i, n, kvcount, next;
550 uint16_t flags;
551 uint64_t sid;
552 size_t rcount;
f3df4c03 553 asl_msg_t *msg;
81582353
A
554 int fstatus;
555 char *p, tmp[DB_RECORD_LEN], *key, *val;
556
557 if (s == NULL) return ASL_STATUS_INVALID_STORE;
558 if (out == NULL) return ASL_STATUS_INVALID_ARG;
559
560 *out = NULL;
561
562 offset = slot * DB_RECORD_LEN;
563 fstatus = fseek(s->db, offset, SEEK_SET);
564
565 if (fstatus < 0) return ASL_STATUS_READ_FAILED;
566
567 rcount = fread(tmp, DB_RECORD_LEN, 1, s->db);
568 if (rcount != 1) return ASL_STATUS_READ_FAILED;
569
570 flags = _asl_get_16(tmp + MSG_OFF_KEY_FLAGS);
571
f3df4c03 572 msg = asl_msg_new(ASL_TYPE_MSG);
81582353
A
573 if (msg == NULL) return ASL_STATUS_NO_MEMORY;
574
575 p = tmp + 5;
576
577 asl_legacy1_fetch_helper_64(s, &p, msg, ASL_KEY_MSG_ID);
578 asl_legacy1_fetch_helper_32(s, &p, msg, ASL_KEY_READ_UID, 1, (uint32_t)-1);
579 asl_legacy1_fetch_helper_32(s, &p, msg, ASL_KEY_READ_GID, 1, (uint32_t)-1);
580 asl_legacy1_fetch_helper_64(s, &p, msg, ASL_KEY_TIME);
581 asl_legacy1_fetch_helper_str(s, &p, msg, ASL_KEY_HOST, &status);
582 asl_legacy1_fetch_helper_str(s, &p, msg, ASL_KEY_SENDER, &status);
583 asl_legacy1_fetch_helper_str(s, &p, msg, ASL_KEY_FACILITY, &status);
584 asl_legacy1_fetch_helper_32(s, &p, msg, ASL_KEY_LEVEL, 0, 0);
585 asl_legacy1_fetch_helper_32(s, &p, msg, ASL_KEY_PID, 0, 0);
586 asl_legacy1_fetch_helper_32(s, &p, msg, ASL_KEY_UID, 0, 0);
587 asl_legacy1_fetch_helper_32(s, &p, msg, ASL_KEY_GID, 0, 0);
588 asl_legacy1_fetch_helper_str(s, &p, msg, ASL_KEY_MSG, &status);
589
590 next = header_get_next(tmp);
591
592 kvcount = 0;
593 n = 0;
594
595 while (next != 0)
596 {
597 offset = next * DB_RECORD_LEN;
598 fstatus = fseek(s->db, offset, SEEK_SET);
599 if (fstatus < 0)
600 {
f3df4c03 601 asl_msg_release(msg);
81582353
A
602 return ASL_STATUS_READ_FAILED;
603 }
604
605 rcount = fread(tmp, DB_RECORD_LEN, 1, s->db);
606 if (rcount != 1)
607 {
f3df4c03 608 asl_msg_release(msg);
81582353
A
609 return ASL_STATUS_READ_FAILED;
610 }
611
612 if (kvcount == 0) kvcount = _asl_get_32(tmp + 5);
613
614 p = tmp + 9;
615
616 for (i = 0; (i < 4) && (n < kvcount); i++)
617 {
618 key = NULL;
619 sid = _asl_get_64(p);
620 p += 8;
621 status = string_fetch_sid(s, sid, &key);
622
623 val = NULL;
624 sid = _asl_get_64(p);
625 p += 8;
626 if (status == ASL_STATUS_OK) status = string_fetch_sid(s, sid, &val);
627
f3df4c03 628 if ((status == ASL_STATUS_OK) && (key != NULL)) asl_msg_set_key_val(msg, key, val);
81582353
A
629 if (key != NULL) free(key);
630 if (val != NULL) free(val);
631
632 n++;
633 }
634
635 next = header_get_next(tmp);
636 }
637
638 *out = msg;
639 return ASL_STATUS_OK;
640}
641
642uint32_t
f3df4c03 643asl_legacy1_fetch(asl_legacy1_t *s, uint64_t msgid, asl_msg_t **out)
81582353
A
644{
645 uint32_t i, status;
646
647 if (s == NULL) return ASL_STATUS_INVALID_STORE;
648 if (msgid == ASL_REF_NULL) return ASL_STATUS_INVALID_ARG;
649 if (out == NULL) return ASL_STATUS_INVALID_ARG;
650
651 i = slotlist_find(s, msgid, 0);
652 if (i == ASL_INDEX_NULL) return ASL_STATUS_INVALID_ID;
653
654 /* read the message */
655 status = msg_fetch(s, s->slotlist[i].slot, out);
656 if (status != ASL_STATUS_OK) return status;
657 if (*out == NULL) return ASL_STATUS_FAILED;
658
659 return status;
660}
661
662static uint32_t
663next_search_slot(asl_legacy1_t *s, uint32_t last_si, int32_t direction)
664{
665 uint32_t i;
666
667 if (direction >= 0)
668 {
669 for (i = last_si + 1; i < s->slotlist_count; i++)
670 {
671 if (s->slotlist[i].type == DB_TYPE_MESSAGE) return i;
672 }
673
674 return ASL_INDEX_NULL;
675 }
676
677 if (last_si == 0) return ASL_INDEX_NULL;
678 if (last_si > s->slotlist_count) return ASL_INDEX_NULL;
679
680 for (i = last_si - 1; i > 0; i--)
681 {
682 if (s->slotlist[i].type == DB_TYPE_MESSAGE) return i;
683 }
684
685 if (s->slotlist[0].type == DB_TYPE_MESSAGE) return 0;
686
687 return ASL_INDEX_NULL;
688}
689
81582353
A
690/*
691 * Input to asl_legacy1_match is a list of queries.
692 * A record in the store matches if it matches any query (i.e. query list is "OR"ed)
693 *
694 * If counting up (direction is positive) find first record with ID > start_id.
695 * Else if counting down (direction is negative) find first record with ID < start_id.
696 *
697 * Set match flag on.
698 * If any query is NULL, set match flog off (skips matching below).
699 * Else if all queries only check "standard" keys, set std flag to on.
700 *
701 * If all queries are marked as "never matches", return NULL.
702 *
703 * match loop:
704 * fetch record (with std flag)
705 * if match flag is off, decode record and add it to result.
706 * else for each query:
707 * if query is NULL (shouldn't happen) decode record and add it to result. Return to match loop.
708 * else if query never matches, ignore it.
709 * else decode record and use asl_cmp. If it succeeds, add record to result. Return to match loop.
710 *
711 * return results.
712 */
f3df4c03 713static ASL_STATUS
81582353
A
714match_worker(asl_legacy1_t *s, asl_msg_list_t *query, asl_msg_list_t **res, uint64_t *last_id, uint64_t **idlist, uint32_t *idcount, uint64_t start_id, int32_t count, int32_t direction)
715{
716 uint32_t mx, si, slot, i, qcount, match, didmatch, status;
717 uint64_t xid;
f3df4c03 718 asl_msg_t *msg;
81582353
A
719
720 if (s == NULL) return ASL_STATUS_INVALID_STORE;
721 if ((res == NULL) && (idlist == NULL)) return ASL_STATUS_INVALID_ARG;
722 if (last_id == NULL) return ASL_STATUS_INVALID_ARG;
723 if (idcount == NULL) return ASL_STATUS_INVALID_ARG;
724
725 if (res != NULL) *res = NULL;
726 if (idlist != NULL) *idlist = NULL;
727
728 mx = 0;
729
730 if (direction < 0) direction = -1;
731 else direction = 1;
732
733 si = ASL_INDEX_NULL;
734 if ((direction == -1) && (start_id == ASL_REF_NULL)) si = s->slotlist_count;
735 else si = slotlist_find(s, start_id, direction);
736
737 si = next_search_slot(s, si, direction);
738 if (si == ASL_INDEX_NULL) return ASL_STATUS_OK;
739 if (si >= s->slotlist_count) return ASL_STATUS_FAILED;
740
741 slot = s->slotlist[si].slot;
742
743 match = 1;
744 qcount = 0;
745
746 if (query == NULL) match = 0;
747 else if (query->count == 0) match = 0;
748 else qcount = query->count;
749
750 /*
751 * initialize result list if we've been asked to return messages
752 */
753 if (res != NULL)
754 {
f3df4c03 755 *res = asl_msg_list_new();
81582353
A
756 if (*res == NULL) return ASL_STATUS_NO_MEMORY;
757 }
758
759 status = ASL_STATUS_OK;
760
761 /*
762 * loop through records
763 */
764 *idcount = 0;
765 while ((count == 0) || (*idcount < count))
766 {
767 if (si == ASL_INDEX_NULL) break;
768 if (si >= s->slotlist_count) break;
769
770 slot = s->slotlist[si].slot;
771 xid = s->slotlist[si].xid;
772
773 *last_id = xid;
774
775 status = msg_fetch(s, slot, &msg);
776
777 didmatch = 0;
778 if (match == 0)
779 {
780 didmatch = 1;
781 }
782 else
783 {
784 for (i = 0; i < qcount; i++)
785 {
f3df4c03 786 didmatch = asl_msg_cmp(query->msg[i], msg);
81582353
A
787 if (didmatch == 1) break;
788 }
789 }
790
f3df4c03
A
791 if (didmatch == 1) asl_msg_list_append(*res, msg);
792 asl_msg_release(msg);
81582353
A
793
794 si = next_search_slot(s, si, direction);
795 }
796
797 return status;
798}
799
f3df4c03 800ASL_STATUS
81582353
A
801asl_legacy1_match(asl_legacy1_t *s, asl_msg_list_t *query, asl_msg_list_t **res, uint64_t *last_id, uint64_t start_id, uint32_t count, int32_t direction)
802{
803 uint32_t idcount;
804
805 idcount = 0;
806 return match_worker(s, query, res, last_id, NULL, &idcount, start_id, count, direction);
807}