]> git.saurik.com Git - apple/syslog.git/blob - aslcommon/asl_memory.c
syslog-385.tar.gz
[apple/syslog.git] / aslcommon / asl_memory.c
1 /*
2 * Copyright (c) 2007-2010 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
24 #include <unistd.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <sys/errno.h>
28 #include <string.h>
29 #include <sys/types.h>
30 #include <time.h>
31 #include <asl_core.h>
32 #include <asl_msg.h>
33 #include <asl_msg_list.h>
34 #include <asl_private.h>
35 #include "asl_memory.h"
36
37 #define DEFAULT_MAX_RECORDS 2000
38 #define DEFAULT_MAX_STRING_MEMORY 4096000
39
40 #define forever for(;;)
41
42 uint32_t
43 asl_memory_statistics(asl_memory_t *s, asl_msg_t **msg)
44 {
45 asl_msg_t * out;
46 uint32_t i, n;
47 uint64_t size;
48 char str[256];
49
50 if (s == NULL) return ASL_STATUS_INVALID_STORE;
51 if (msg == NULL) return ASL_STATUS_INVALID_ARG;
52
53 out = asl_msg_new(ASL_TYPE_MSG);
54 if (out == NULL) return ASL_STATUS_NO_MEMORY;
55
56 size = sizeof(asl_memory_t);
57 size += ((s->record_count + 1) * sizeof(mem_record_t));
58
59 for (i = 0; i < s->string_count; i++)
60 {
61 size += sizeof(mem_string_t);
62 if (s->string_cache[i]->str != NULL) size += (strlen(s->string_cache[i]->str) + 1);
63 }
64
65 snprintf(str, sizeof(str), "%llu", size);
66 asl_msg_set_key_val(out, "Size", str);
67
68 n = 0;
69 for (i = 0; i < s->record_count; i++) if (s->record[i]->mid != 0) n++;
70
71 snprintf(str, sizeof(str), "%u", s->record_count);
72 asl_msg_set_key_val(out, "MaxRecords", str);
73
74 snprintf(str, sizeof(str), "%u", n);
75 asl_msg_set_key_val(out, "RecordCount", str);
76
77 snprintf(str, sizeof(str), "%u", s->string_count);
78 asl_msg_set_key_val(out, "StringCount", str);
79
80 snprintf(str, sizeof(str), "%lu", s->curr_string_mem);
81 asl_msg_set_key_val(out, "StringMemory", str);
82
83 snprintf(str, sizeof(str), "%lu", s->max_string_mem);
84 asl_msg_set_key_val(out, "MaxStringMemory", str);
85
86 *msg = out;
87 return ASL_STATUS_OK;
88 }
89
90 uint32_t
91 asl_memory_close(asl_memory_t *s)
92 {
93 if (s == NULL) return ASL_STATUS_OK;
94
95 dispatch_sync(s->queue, ^{
96 uint32_t i;
97
98 if (s->record != NULL)
99 {
100 for (i = 0; i < s->record_count; i++)
101 {
102 free(s->record[i]);
103 s->record[i] = NULL;
104 }
105
106 free(s->record);
107 s->record = NULL;
108 }
109
110 free(s->buffer_record);
111 s->buffer_record = NULL;
112
113 if (s->string_cache != NULL)
114 {
115 for (i = 0; i < s->string_count; i++)
116 {
117 if (s->string_cache[i] != NULL)
118 {
119 free(s->string_cache[i]->str);
120 free(s->string_cache[i]);
121 }
122
123 s->string_cache[i] = NULL;
124 }
125
126 free(s->string_cache);
127 s->string_cache = NULL;
128 }
129 });
130
131 dispatch_release(s->queue);
132
133 free(s);
134
135 return ASL_STATUS_OK;
136 }
137
138 uint32_t
139 asl_memory_open(uint32_t max_records, size_t max_str_mem, asl_memory_t **s)
140 {
141 asl_memory_t *out;
142 uint32_t i;
143
144 if (s == NULL) return ASL_STATUS_INVALID_ARG;
145
146 if (max_records == 0) max_records = DEFAULT_MAX_RECORDS;
147 if (max_str_mem == 0) max_str_mem = DEFAULT_MAX_STRING_MEMORY;
148
149 out = calloc(1, sizeof(asl_memory_t));
150 if (out == NULL) return ASL_STATUS_NO_MEMORY;
151
152 out->queue = dispatch_queue_create("ASL Memory Queue", NULL);
153 if (out->queue == NULL)
154 {
155 free(out);
156 return ASL_STATUS_NO_MEMORY;
157 }
158
159 out->max_string_mem = max_str_mem;
160
161 out->record_count = max_records;
162 out->record = (mem_record_t **)calloc(max_records, sizeof(mem_record_t *));
163 if (out->record == NULL)
164 {
165 dispatch_release(out->queue);
166 free(out);
167 return ASL_STATUS_NO_MEMORY;
168 }
169
170 for (i = 0; i < max_records; i++)
171 {
172 out->record[i] = (mem_record_t *)calloc(1, sizeof(mem_record_t));
173 if (out->record[i] == NULL)
174 {
175 asl_memory_close(out);
176 return ASL_STATUS_NO_MEMORY;
177 }
178 }
179
180 out->buffer_record = (mem_record_t *)calloc(1, sizeof(mem_record_t));
181 if (out->buffer_record == NULL)
182 {
183 asl_memory_close(out);
184 return ASL_STATUS_NO_MEMORY;
185 }
186
187 *s = out;
188 return ASL_STATUS_OK;
189 }
190
191 static void
192 asl_memory_reset(asl_memory_t *s)
193 {
194 uint32_t i;
195 if (s == NULL) return;
196
197 /* clear all message records */
198 for (i = 0; i < s->record_count; i++)
199 {
200 memset(s->record[i], 0, sizeof(mem_record_t));
201 }
202
203 /* reset the string cache */
204 if (s->string_cache != NULL)
205 {
206 for (i = 0; i < s->string_count; i++)
207 {
208 if (s->string_cache[i] != NULL)
209 {
210 free(s->string_cache[i]->str);
211 free(s->string_cache[i]);
212 }
213
214 s->string_cache[i] = NULL;
215 }
216
217 free(s->string_cache);
218 s->string_cache = NULL;
219 }
220
221 s->string_count = 0;
222 }
223
224 static mem_string_t *
225 asl_memory_string_new(const char *str, uint32_t len, uint32_t hash)
226 {
227 mem_string_t *out;
228
229 if (str == NULL) return NULL;
230
231 out = (mem_string_t *)calloc(1, sizeof(mem_string_t));
232 if (out == NULL) return NULL;
233
234 out->hash = hash;
235 out->refcount = 1;
236 out->str = malloc(len + 1);
237 if (out->str == NULL)
238 {
239 free(out);
240 return NULL;
241 }
242
243 memcpy(out->str, str, len);
244 out->str[len] = 0;
245
246 return out;
247 }
248
249 /*
250 * Find the first hash greater than or equal to a given hash in the string cache.
251 * Return s->string_count if hash is greater than last hash in the string cache.
252 * Caller must check if the hashes match or not.
253 *
254 * This routine is used both to find strings in the cache and to determine where to insert
255 * new strings. Note that the caller needs to do extra work after calling this routine.
256 */
257 static uint32_t
258 asl_memory_string_cache_search_hash(asl_memory_t *s, uint32_t hash)
259 {
260 uint32_t top, bot, mid, range;
261 mem_string_t *ms;
262
263 if (s->string_count == 0) return 0;
264 if (s->string_count == 1)
265 {
266 ms = s->string_cache[0];
267 if (hash < ms->hash) return 0;
268 return 1;
269 }
270
271 range = top = s->string_count - 1;
272 bot = 0;
273 mid = top / 2;
274
275 while (range > 1)
276 {
277 ms = s->string_cache[mid];
278
279 if (hash == ms->hash)
280 {
281 while (mid > 0)
282 {
283 ms = s->string_cache[mid - 1];
284 if (hash != ms->hash) break;
285 mid--;
286 }
287
288 return mid;
289 }
290 else
291 {
292 ms = s->string_cache[mid];
293 if (hash < ms->hash) top = mid;
294 else bot = mid;
295 }
296
297 range = top - bot;
298 mid = bot + (range / 2);
299 }
300
301 ms = s->string_cache[bot];
302 if (hash <= ms->hash) return bot;
303
304 ms = s->string_cache[top];
305 if (hash <= ms->hash) return top;
306
307 return s->string_count;
308 }
309
310 /*
311 * Search the string cache.
312 * If the string is in the cache, increment refcount and return it.
313 * If the string is not in cache and create flag is on, create a new string.
314 * Otherwise, return NULL.
315 */
316 static mem_string_t *
317 asl_memory_string_retain(asl_memory_t *s, const char *str, int create)
318 {
319 uint32_t i, where, hash, len;
320 mem_string_t *new;
321
322 if (s == NULL) return NULL;
323 if (str == NULL) return NULL;
324 len = strlen(str);
325
326 /* check the cache */
327 hash = asl_core_string_hash(str, len);
328 where = asl_memory_string_cache_search_hash(s, hash);
329
330 /* asl_memory_string_cache_search_hash just tells us where to look */
331 if (where < s->string_count)
332 {
333 while (s->string_cache[where]->hash == hash)
334 {
335 if (!strcmp(str, s->string_cache[where]->str))
336 {
337 s->string_cache[where]->refcount++;
338 return s->string_cache[where];
339 }
340
341 where++;
342 }
343 }
344
345 /* not found */
346 if (create == 0) return NULL;
347
348 /* create a new mem_string_t and insert into the cache at index 'where' */
349 new = asl_memory_string_new(str, len, hash);
350 if (new == NULL) return NULL;
351
352 s->string_cache = (mem_string_t **)reallocf(s->string_cache, (s->string_count + 1) * sizeof(void *));
353 if (s->string_cache == NULL)
354 {
355 s->string_count = 0;
356 free(new);
357 return NULL;
358 }
359
360 for (i = s->string_count; i > where; i--) s->string_cache[i] = s->string_cache[i - 1];
361
362 s->curr_string_mem += (sizeof(mem_string_t) + len + 1);
363 s->string_cache[where] = new;
364 s->string_count++;
365
366 return s->string_cache[where];
367 }
368
369 static uint32_t
370 asl_memory_string_release(asl_memory_t *s, mem_string_t *m)
371 {
372 uint32_t i, where;
373
374 if (s == NULL) return ASL_STATUS_INVALID_STORE;
375 if (m == NULL) return ASL_STATUS_OK;
376
377 if (m->refcount > 0) m->refcount--;
378 if (m->refcount > 0) return ASL_STATUS_OK;
379
380 where = asl_memory_string_cache_search_hash(s, m->hash);
381 if (s->string_cache[where]->hash != m->hash) return ASL_STATUS_OK;
382
383 while (s->string_cache[where] != m)
384 {
385 if (s->string_cache[where]->hash != m->hash) return ASL_STATUS_OK;
386
387 where++;
388 if (where >= s->string_count) return ASL_STATUS_OK;
389 }
390
391 for (i = where + 1; i < s->string_count; i++) s->string_cache[i - 1] = s->string_cache[i];
392
393 if (m->str == NULL) s->curr_string_mem -= sizeof(mem_string_t);
394 else s->curr_string_mem -= (sizeof(mem_string_t) + strlen(m->str) + 1);
395
396 free(m->str);
397 free(m);
398
399 s->string_count--;
400
401 if (s->string_count == 0)
402 {
403 free(s->string_cache);
404 s->string_cache = NULL;
405 return ASL_STATUS_OK;
406 }
407
408 s->string_cache = (mem_string_t **)reallocf(s->string_cache, s->string_count * sizeof(void *));
409 if (s->string_cache == NULL)
410 {
411 s->string_count = 0;
412 return ASL_STATUS_NO_MEMORY;
413 }
414
415 return ASL_STATUS_OK;
416 }
417
418 /*
419 * Release all a record's strings and reset it's values
420 */
421 static void
422 asl_memory_record_clear(asl_memory_t *s, mem_record_t *r)
423 {
424 uint32_t i;
425
426 if (s == NULL) return;
427 if (r == NULL) return;
428
429 asl_memory_string_release(s, r->host);
430 asl_memory_string_release(s, r->sender);
431 asl_memory_string_release(s, r->sender_mach_uuid);
432 asl_memory_string_release(s, r->facility);
433 asl_memory_string_release(s, r->message);
434 asl_memory_string_release(s, r->refproc);
435 asl_memory_string_release(s, r->session);
436
437 for (i = 0; i < r->kvcount; i++) asl_memory_string_release(s, r->kvlist[i]);
438
439 if (r->kvlist != NULL) free(r->kvlist);
440 memset(r, 0, sizeof(mem_record_t));
441 }
442
443 static void
444 asl_memory_record_free(asl_memory_t *s, mem_record_t *r)
445 {
446 asl_memory_record_clear(s, r);
447 free(r);
448 }
449
450 /*
451 * Encode an asl_msg_t as a record structure.
452 * Creates and caches strings.
453 */
454 static uint32_t
455 asl_memory_message_encode(asl_memory_t *s, asl_msg_t *msg)
456 {
457 uint32_t x;
458 mem_string_t *k, *v;
459 mem_record_t *r;
460 const char *key, *val;
461
462 if (s == NULL) return ASL_STATUS_INVALID_STORE;
463 if (s->buffer_record == NULL) return ASL_STATUS_INVALID_STORE;
464 if (msg == NULL) return ASL_STATUS_INVALID_MESSAGE;
465
466 r = s->buffer_record;
467
468 memset(r, 0, sizeof(mem_record_t));
469
470 r->flags = 0;
471 r->level = ASL_LEVEL_DEBUG;
472 r->pid = -1;
473 r->uid = -2;
474 r->gid = -2;
475 r->ruid = -1;
476 r->rgid = -1;
477 r->time = (uint64_t)-1;
478 r->nano = (uint32_t)-1;
479
480 key = NULL;
481 val = NULL;
482
483 for (x = asl_msg_fetch((asl_msg_t *)msg, 0, &key, &val, NULL); x != IndexNull; x = asl_msg_fetch((asl_msg_t *)msg, x, &key, &val, NULL))
484 {
485 if (key == NULL) continue;
486
487 else if (!strcmp(key, ASL_KEY_TIME))
488 {
489 if (val != NULL) r->time = asl_core_parse_time(val, NULL);
490 }
491 else if (!strcmp(key, ASL_KEY_TIME_NSEC))
492 {
493 if (val != NULL) r->nano = atoi(val);
494 }
495 else if (!strcmp(key, ASL_KEY_HOST))
496 {
497 if (val != NULL) r->host = asl_memory_string_retain(s, val, 1);
498 }
499 else if (!strcmp(key, ASL_KEY_SENDER))
500 {
501 if (val != NULL) r->sender = asl_memory_string_retain(s, val, 1);
502 }
503 else if (!strcmp(key, ASL_KEY_PID))
504 {
505 if (val != NULL) r->pid = atoi(val);
506 }
507 else if (!strcmp(key, ASL_KEY_REF_PID))
508 {
509 if (val != NULL) r->refpid = atoi(val);
510 }
511 else if (!strcmp(key, ASL_KEY_UID))
512 {
513 if (val != NULL) r->uid = atoi(val);
514 }
515 else if (!strcmp(key, ASL_KEY_GID))
516 {
517 if (val != NULL) r->gid = atoi(val);
518 }
519 else if (!strcmp(key, ASL_KEY_LEVEL))
520 {
521 if (val != NULL) r->level = atoi(val);
522 }
523 else if (!strcmp(key, ASL_KEY_MSG))
524 {
525 if (val != NULL) r->message = asl_memory_string_retain(s, val, 1);
526 }
527 else if (!strcmp(key, ASL_KEY_SENDER_MACH_UUID))
528 {
529 if (val != NULL) r->sender_mach_uuid = asl_memory_string_retain(s, val, 1);
530 }
531 else if (!strcmp(key, ASL_KEY_FACILITY))
532 {
533 if (val != NULL) r->facility = asl_memory_string_retain(s, val, 1);
534 }
535 else if (!strcmp(key, ASL_KEY_REF_PROC))
536 {
537 if (val != NULL) r->refproc = asl_memory_string_retain(s, val, 1);
538 }
539 else if (!strcmp(key, ASL_KEY_SESSION))
540 {
541 if (val != NULL) r->session = asl_memory_string_retain(s, val, 1);
542 }
543 else if (!strcmp(key, ASL_KEY_READ_UID))
544 {
545 if (((r->flags & ASL_MSG_FLAG_READ_UID_SET) == 0) && (val != NULL))
546 {
547 r->ruid = atoi(val);
548 r->flags |= ASL_MSG_FLAG_READ_UID_SET;
549 }
550 }
551 else if (!strcmp(key, ASL_KEY_READ_GID))
552 {
553 if (((r->flags & ASL_MSG_FLAG_READ_GID_SET) == 0) && (val != NULL))
554 {
555 r->rgid = atoi(val);
556 r->flags |= ASL_MSG_FLAG_READ_GID_SET;
557 }
558 }
559 else if (!strcmp(key, ASL_KEY_OS_ACTIVITY_ID))
560 {
561 if (val != NULL) r->os_activity_id = atoll(val);
562 }
563 else if (!strcmp(key, ASL_KEY_MSG_ID))
564 {
565 /* Ignore */
566 continue;
567 }
568 else
569 {
570 k = asl_memory_string_retain(s, key, 1);
571 if (k == NULL) continue;
572
573 v = NULL;
574 if (val != NULL) v = asl_memory_string_retain(s, val, 1);
575
576 r->kvlist = (mem_string_t **)reallocf(r->kvlist, (r->kvcount + 2) * sizeof(mem_string_t *));
577 if (r->kvlist == NULL)
578 {
579 asl_memory_record_clear(s, r);
580 return ASL_STATUS_NO_MEMORY;
581 }
582
583 r->kvlist[r->kvcount++] = k;
584 r->kvlist[r->kvcount++] = v;
585 }
586 }
587
588 return ASL_STATUS_OK;
589 }
590
591 uint32_t
592 asl_memory_save(asl_memory_t *s, asl_msg_t *msg, uint64_t *mid)
593 {
594 __block uint32_t status;
595
596 if (s == NULL) return ASL_STATUS_INVALID_STORE;
597 if (s->buffer_record == NULL) return ASL_STATUS_INVALID_STORE;
598
599 dispatch_sync(s->queue, ^{
600 mem_record_t *t;
601
602 /* asl_memory_message_encode creates and caches strings */
603 status = asl_memory_message_encode(s, msg);
604 if (status == ASL_STATUS_OK)
605 {
606 uint32_t loop_start_index = s->record_first;
607
608 if (*mid != 0)
609 {
610 s->buffer_record->mid = *mid;
611 }
612 else
613 {
614 s->buffer_record->mid = asl_core_new_msg_id(0);
615 *mid = s->buffer_record->mid;
616 }
617
618 /* clear the first record */
619 t = s->record[s->record_first];
620 asl_memory_record_clear(s, t);
621
622 /* add the new record to the record list (swap in the buffer record) */
623 s->record[s->record_first] = s->buffer_record;
624 s->buffer_record = t;
625
626 /* record list is a circular queue */
627 s->record_first++;
628 if (s->record_first >= s->record_count) s->record_first = 0;
629
630 /* delete records if too much memory is in use */
631 while (s->curr_string_mem > s->max_string_mem)
632 {
633 asl_memory_record_clear(s, s->record[s->record_first]);
634 s->record_first++;
635 if (s->record_first >= s->record_count) s->record_first = 0;
636 if (s->record_first == loop_start_index)
637 {
638 /* The entire ring has been cleared. This should never happen. */
639 asl_memory_reset(s);
640 status = ASL_STATUS_FAILED;
641 break;
642 }
643 }
644 }
645 });
646
647 return status;
648 }
649
650 /*
651 * Decodes a record structure.
652 */
653 static uint32_t
654 asl_memory_message_decode(asl_memory_t *s, mem_record_t *r, asl_msg_t **out)
655 {
656 uint32_t i;
657 asl_msg_t *msg;
658 char tmp[64];
659 const char *key, *val;
660
661 if (s == NULL) return ASL_STATUS_INVALID_STORE;
662 if (r == NULL) return ASL_STATUS_INVALID_ARG;
663 if (out == NULL) return ASL_STATUS_INVALID_ARG;
664
665 *out = NULL;
666
667 msg = asl_msg_new(ASL_TYPE_MSG);
668 if (msg == NULL) return ASL_STATUS_NO_MEMORY;
669
670 /* Message ID */
671 snprintf(tmp, sizeof(tmp), "%llu", r->mid);
672 asl_msg_set_key_val(msg, ASL_KEY_MSG_ID, tmp);
673
674 /* Level */
675 snprintf(tmp, sizeof(tmp), "%u", r->level);
676 asl_msg_set_key_val(msg, ASL_KEY_LEVEL, tmp);
677
678 /* Time */
679 if (r->time != (uint64_t)-1)
680 {
681 snprintf(tmp, sizeof(tmp), "%llu", r->time);
682 asl_msg_set_key_val(msg, ASL_KEY_TIME, tmp);
683 }
684
685 /* Nanoseconds */
686 if (r->nano != (uint32_t)-1)
687 {
688 snprintf(tmp, sizeof(tmp), "%u", r->nano);
689 asl_msg_set_key_val(msg, ASL_KEY_TIME_NSEC, tmp);
690 }
691
692 /* Host */
693 if (r->host != NULL)
694 {
695 asl_msg_set_key_val(msg, ASL_KEY_HOST, r->host->str);
696 }
697
698 /* Sender */
699 if (r->sender != NULL)
700 {
701 asl_msg_set_key_val(msg, ASL_KEY_SENDER, r->sender->str);
702 }
703
704 /* Sender mach UUID */
705 if (r->sender_mach_uuid != NULL)
706 {
707 asl_msg_set_key_val(msg, ASL_KEY_SENDER_MACH_UUID, r->sender_mach_uuid->str);
708 }
709
710 /* Facility */
711 if (r->facility != NULL)
712 {
713 asl_msg_set_key_val(msg, ASL_KEY_FACILITY, r->facility->str);
714 }
715
716 /* Ref Proc */
717 if (r->refproc != NULL)
718 {
719 asl_msg_set_key_val(msg, ASL_KEY_REF_PROC, r->refproc->str);
720 }
721
722 /* Session */
723 if (r->session != NULL)
724 {
725 asl_msg_set_key_val(msg, ASL_KEY_SESSION, r->session->str);
726 }
727
728 /* PID */
729 if (r->pid != -1)
730 {
731 snprintf(tmp, sizeof(tmp), "%d", r->pid);
732 asl_msg_set_key_val(msg, ASL_KEY_PID, tmp);
733 }
734
735 /* REF PID */
736 if (r->refpid != 0)
737 {
738 snprintf(tmp, sizeof(tmp), "%d", r->refpid);
739 asl_msg_set_key_val(msg, ASL_KEY_REF_PID, tmp);
740 }
741
742 /* UID */
743 if (r->uid != -2)
744 {
745 snprintf(tmp, sizeof(tmp), "%d", r->uid);
746 asl_msg_set_key_val(msg, ASL_KEY_UID, tmp);
747 }
748
749 /* GID */
750 if (r->gid != -2)
751 {
752 snprintf(tmp, sizeof(tmp), "%d", r->gid);
753 asl_msg_set_key_val(msg, ASL_KEY_GID, tmp);
754 }
755
756 /* Message */
757 if (r->message != NULL)
758 {
759 asl_msg_set_key_val(msg, ASL_KEY_MSG, r->message->str);
760 }
761
762 /* ReadUID */
763 if (r->flags & ASL_MSG_FLAG_READ_UID_SET)
764 {
765 snprintf(tmp, sizeof(tmp), "%d", r->ruid);
766 asl_msg_set_key_val(msg, ASL_KEY_READ_UID, tmp);
767 }
768
769 /* ReadGID */
770 if (r->flags & ASL_MSG_FLAG_READ_GID_SET)
771 {
772 snprintf(tmp, sizeof(tmp), "%d", r->rgid);
773 asl_msg_set_key_val(msg, ASL_KEY_READ_GID, tmp);
774 }
775
776 /* OSActivityID */
777 if (r->os_activity_id != 0)
778 {
779 snprintf(tmp, sizeof(tmp), "%llu", r->os_activity_id);
780 asl_msg_set_key_val(msg, ASL_KEY_OS_ACTIVITY_ID, tmp);
781 }
782
783 /* Key - Value List */
784 for (i = 0; i < r->kvcount; i++)
785 {
786 key = NULL;
787 val = NULL;
788
789 if (r->kvlist[i] != NULL) key = r->kvlist[i]->str;
790 i++;
791 if (r->kvlist[i] != NULL) val = r->kvlist[i]->str;
792
793 if (key != NULL) asl_msg_set_key_val(msg, key, val);
794 }
795
796 *out = msg;
797 return ASL_STATUS_OK;
798 }
799
800 uint32_t
801 asl_memory_fetch(asl_memory_t *s, uint64_t mid, asl_msg_t **msg, int32_t ruid, int32_t rgid)
802 {
803 __block uint32_t status;
804
805 if (s == NULL) return ASL_STATUS_INVALID_STORE;
806 if (msg == NULL) return ASL_STATUS_INVALID_ARG;
807
808 status = ASL_STATUS_INVALID_ID;
809
810 dispatch_sync(s->queue, ^{
811 uint32_t i;
812
813 for (i = 0; i < s->record_count; i++)
814 {
815 if (s->record[i]->mid == 0) break;
816
817 if (s->record[i]->mid == mid)
818 {
819 status = asl_core_check_access(s->record[i]->ruid, s->record[i]->rgid, ruid, rgid, s->record[i]->flags);
820 if (status != ASL_STATUS_OK) break;
821
822 status = asl_memory_message_decode(s, s->record[i], msg);
823 break;
824 }
825 }
826 });
827
828 return status;
829 }
830
831 static mem_record_t *
832 asl_memory_query_to_record(asl_memory_t *s, asl_msg_t *q, uint32_t *type)
833 {
834 mem_record_t *out;
835 uint32_t i, x;
836 uint16_t op;
837 mem_string_t *mkey, *mval;
838 const char *key, *val;
839
840 if (type == NULL) return NULL;
841
842 if (s == NULL)
843 {
844 *type = ASL_QUERY_MATCH_ERROR;
845 return NULL;
846 }
847
848 /* NULL query matches anything */
849 *type = ASL_QUERY_MATCH_TRUE;
850 if (q == NULL) return NULL;
851 if (asl_msg_count((asl_msg_t *)q) == 0) return NULL;
852
853
854 /* we can only do fast match on equality tests */
855 *type = ASL_QUERY_MATCH_SLOW;
856
857 for (x = asl_msg_fetch((asl_msg_t *)q, 0, NULL, NULL, &op); x != IndexNull; x = asl_msg_fetch((asl_msg_t *)q, x, NULL, NULL, &op))
858 {
859 if (op != ASL_QUERY_OP_EQUAL) return NULL;
860 }
861
862 out = (mem_record_t *)calloc(1, sizeof(mem_record_t));
863 if (out == NULL)
864 {
865 *type = ASL_QUERY_MATCH_ERROR;
866 return NULL;
867 }
868
869 for (x = asl_msg_fetch((asl_msg_t *)q, 0, &key, &val, &op); x != IndexNull; x = asl_msg_fetch((asl_msg_t *)q, x, &key, &val, &op))
870 {
871 if (key == NULL) continue;
872
873 else if (!strcmp(key, ASL_KEY_MSG_ID))
874 {
875 if (val == NULL) continue;
876
877 if (*type & ASL_QUERY_MATCH_MSG_ID)
878 {
879 asl_memory_record_free(s, out);
880 *type = ASL_QUERY_MATCH_SLOW;
881 return NULL;
882 }
883
884 *type |= ASL_QUERY_MATCH_MSG_ID;
885 out->mid = atoll(val);
886 }
887 else if (!strcmp(key, ASL_KEY_TIME))
888 {
889 if (val == NULL) continue;
890
891 if (*type & ASL_QUERY_MATCH_TIME)
892 {
893 asl_memory_record_free(s, out);
894 *type = ASL_QUERY_MATCH_SLOW;
895 return NULL;
896 }
897
898 *type |= ASL_QUERY_MATCH_TIME;
899 out->time = asl_core_parse_time(val, NULL);
900 }
901 else if (!strcmp(key, ASL_KEY_TIME_NSEC))
902 {
903 if (val == NULL) continue;
904
905 if (*type & ASL_QUERY_MATCH_NANO)
906 {
907 asl_memory_record_free(s, out);
908 *type = ASL_QUERY_MATCH_SLOW;
909 return NULL;
910 }
911
912 *type |= ASL_QUERY_MATCH_NANO;
913 out->nano = atoll(val);
914 }
915 else if (!strcmp(key, ASL_KEY_LEVEL))
916 {
917 if (val == NULL) continue;
918
919 if (*type & ASL_QUERY_MATCH_LEVEL)
920 {
921 asl_memory_record_free(s, out);
922 *type = ASL_QUERY_MATCH_SLOW;
923 return NULL;
924 }
925
926 *type |= ASL_QUERY_MATCH_LEVEL;
927 out->level = atoi(val);
928 }
929 else if (!strcmp(key, ASL_KEY_PID))
930 {
931 if (val == NULL) continue;
932
933 if (*type & ASL_QUERY_MATCH_PID)
934 {
935 asl_memory_record_free(s, out);
936 *type = ASL_QUERY_MATCH_SLOW;
937 return NULL;
938 }
939
940 *type |= ASL_QUERY_MATCH_PID;
941 out->pid = atoi(val);
942 }
943 else if (!strcmp(key, ASL_KEY_UID))
944 {
945 if (val == NULL) continue;
946
947 if (*type & ASL_QUERY_MATCH_UID)
948 {
949 asl_memory_record_free(s, out);
950 *type = ASL_QUERY_MATCH_SLOW;
951 return NULL;
952 }
953
954 *type |= ASL_QUERY_MATCH_UID;
955 out->uid = atoi(val);
956 }
957 else if (!strcmp(key, ASL_KEY_GID))
958 {
959 if (val == NULL) continue;
960
961 if (*type & ASL_QUERY_MATCH_GID)
962 {
963 asl_memory_record_free(s, out);
964 *type = ASL_QUERY_MATCH_SLOW;
965 return NULL;
966 }
967
968 *type |= ASL_QUERY_MATCH_GID;
969 out->gid = atoi(val);
970 }
971 else if (!strcmp(key, ASL_KEY_READ_UID))
972 {
973 if (val == NULL) continue;
974
975 if (*type & ASL_QUERY_MATCH_RUID)
976 {
977 asl_memory_record_free(s, out);
978 *type = ASL_QUERY_MATCH_SLOW;
979 return NULL;
980 }
981
982 *type |= ASL_QUERY_MATCH_RUID;
983 out->ruid = atoi(val);
984 }
985 else if (!strcmp(key, ASL_KEY_READ_GID))
986 {
987 if (val == NULL) continue;
988
989 if (*type & ASL_QUERY_MATCH_RGID)
990 {
991 asl_memory_record_free(s, out);
992 *type = ASL_QUERY_MATCH_SLOW;
993 return NULL;
994 }
995
996 *type |= ASL_QUERY_MATCH_RGID;
997 out->rgid = atoi(val);
998 }
999 else if (!strcmp(key, ASL_KEY_REF_PID))
1000 {
1001 if (val == NULL) continue;
1002
1003 if (*type & ASL_QUERY_MATCH_REF_PID)
1004 {
1005 asl_memory_record_free(s, out);
1006 *type = ASL_QUERY_MATCH_SLOW;
1007 return NULL;
1008 }
1009
1010 *type |= ASL_QUERY_MATCH_REF_PID;
1011 out->refpid = atoi(val);
1012 }
1013 else if (!strcmp(key, ASL_KEY_HOST))
1014 {
1015 if (val == NULL) continue;
1016
1017 if (*type & ASL_QUERY_MATCH_HOST)
1018 {
1019 asl_memory_record_free(s, out);
1020 *type = ASL_QUERY_MATCH_SLOW;
1021 return NULL;
1022 }
1023
1024 *type |= ASL_QUERY_MATCH_HOST;
1025 out->host = asl_memory_string_retain(s, val, 0);
1026 if (out->host == NULL)
1027 {
1028 asl_memory_record_free(s, out);
1029 *type = ASL_QUERY_MATCH_FALSE;
1030 return NULL;
1031 }
1032 }
1033 else if (!strcmp(key, ASL_KEY_SENDER))
1034 {
1035 if (val == NULL) continue;
1036
1037 if (*type & ASL_QUERY_MATCH_SENDER)
1038 {
1039 asl_memory_record_free(s, out);
1040 *type = ASL_QUERY_MATCH_SLOW;
1041 return NULL;
1042 }
1043
1044 *type |= ASL_QUERY_MATCH_SENDER;
1045 out->sender = asl_memory_string_retain(s, val, 0);
1046 if (out->sender == NULL)
1047 {
1048 asl_memory_record_free(s, out);
1049 *type = ASL_QUERY_MATCH_FALSE;
1050 return NULL;
1051 }
1052 }
1053 else if (!strcmp(key, ASL_KEY_SENDER_MACH_UUID))
1054 {
1055 if (val == NULL) continue;
1056
1057 if (*type & ASL_QUERY_MATCH_SMUUID)
1058 {
1059 asl_memory_record_free(s, out);
1060 *type = ASL_QUERY_MATCH_SLOW;
1061 return NULL;
1062 }
1063
1064 *type |= ASL_QUERY_MATCH_SMUUID;
1065 out->sender = asl_memory_string_retain(s, val, 0);
1066 if (out->sender_mach_uuid == NULL)
1067 {
1068 asl_memory_record_free(s, out);
1069 *type = ASL_QUERY_MATCH_FALSE;
1070 return NULL;
1071 }
1072 }
1073 else if (!strcmp(key, ASL_KEY_FACILITY))
1074 {
1075 if (val == NULL) continue;
1076
1077 if (*type & ASL_QUERY_MATCH_FACILITY)
1078 {
1079 asl_memory_record_free(s, out);
1080 *type = ASL_QUERY_MATCH_SLOW;
1081 return NULL;
1082 }
1083
1084 *type |= ASL_QUERY_MATCH_FACILITY;
1085 out->facility = asl_memory_string_retain(s, val, 0);
1086 if (out->facility == NULL)
1087 {
1088 asl_memory_record_free(s, out);
1089 *type = ASL_QUERY_MATCH_FALSE;
1090 return NULL;
1091 }
1092 }
1093 else if (!strcmp(key, ASL_KEY_MSG))
1094 {
1095 if (val == NULL) continue;
1096
1097 if (*type & ASL_QUERY_MATCH_MESSAGE)
1098 {
1099 asl_memory_record_free(s, out);
1100 *type = ASL_QUERY_MATCH_SLOW;
1101 return NULL;
1102 }
1103
1104 *type |= ASL_QUERY_MATCH_MESSAGE;
1105 out->message = asl_memory_string_retain(s, val, 0);
1106 if (out->message == NULL)
1107 {
1108 asl_memory_record_free(s, out);
1109 *type = ASL_QUERY_MATCH_FALSE;
1110 return NULL;
1111 }
1112 }
1113 else if (!strcmp(key, ASL_KEY_REF_PROC))
1114 {
1115 if (val == NULL) continue;
1116
1117 if (*type & ASL_QUERY_MATCH_REF_PROC)
1118 {
1119 asl_memory_record_free(s, out);
1120 *type = ASL_QUERY_MATCH_SLOW;
1121 return NULL;
1122 }
1123
1124 *type |= ASL_QUERY_MATCH_REF_PROC;
1125 out->refproc = asl_memory_string_retain(s, val, 0);
1126 if (out->refproc == NULL)
1127 {
1128 asl_memory_record_free(s, out);
1129 *type = ASL_QUERY_MATCH_FALSE;
1130 return NULL;
1131 }
1132 }
1133 else if (!strcmp(key, ASL_KEY_SESSION))
1134 {
1135 if (val == NULL) continue;
1136
1137 if (*type & ASL_QUERY_MATCH_SESSION)
1138 {
1139 asl_memory_record_free(s, out);
1140 *type = ASL_QUERY_MATCH_SLOW;
1141 return NULL;
1142 }
1143
1144 *type |= ASL_QUERY_MATCH_SESSION;
1145 out->session = asl_memory_string_retain(s, val, 0);
1146 if (out->session == NULL)
1147 {
1148 asl_memory_record_free(s, out);
1149 *type = ASL_QUERY_MATCH_FALSE;
1150 return NULL;
1151 }
1152 }
1153 else
1154 {
1155 mkey = asl_memory_string_retain(s, key, 0);
1156 if (mkey == NULL)
1157 {
1158 asl_memory_record_free(s, out);
1159 *type = ASL_QUERY_MATCH_FALSE;
1160 return NULL;
1161 }
1162
1163 for (i = 0; i < out->kvcount; i += 2)
1164 {
1165 if (out->kvlist[i] == mkey)
1166 {
1167 asl_memory_record_free(s, out);
1168 *type = ASL_QUERY_MATCH_SLOW;
1169 return NULL;
1170 }
1171 }
1172
1173 mval = asl_memory_string_retain(s, val, 0);
1174
1175 if (out->kvcount == 0)
1176 {
1177 out->kvlist = (mem_string_t **)calloc(2, sizeof(mem_string_t *));
1178 }
1179 else
1180 {
1181 out->kvlist = (mem_string_t **)reallocf(out->kvlist, (out->kvcount + 2) * sizeof(mem_string_t *));
1182 }
1183
1184 if (out->kvlist == NULL)
1185 {
1186 asl_memory_record_free(s, out);
1187 *type = ASL_QUERY_MATCH_ERROR;
1188 return NULL;
1189 }
1190
1191 out->kvlist[out->kvcount++] = mkey;
1192 out->kvlist[out->kvcount++] = mval;
1193 }
1194 }
1195
1196 return out;
1197 }
1198
1199 static uint32_t
1200 asl_memory_fast_match(asl_memory_t *s, mem_record_t *r, uint32_t qtype, mem_record_t *q)
1201 {
1202 uint32_t i, j;
1203
1204 if (s == NULL) return 0;
1205 if (r == NULL) return 0;
1206 if (q == NULL) return 1;
1207
1208 if ((qtype & ASL_QUERY_MATCH_MSG_ID) && (q->mid != r->mid)) return 0;
1209 if ((qtype & ASL_QUERY_MATCH_TIME) && (q->time != r->time)) return 0;
1210 if ((qtype & ASL_QUERY_MATCH_NANO) && (q->nano != r->nano)) return 0;
1211 if ((qtype & ASL_QUERY_MATCH_LEVEL) && (q->level != r->level)) return 0;
1212 if ((qtype & ASL_QUERY_MATCH_PID) && (q->pid != r->pid)) return 0;
1213 if ((qtype & ASL_QUERY_MATCH_UID) && (q->uid != r->uid)) return 0;
1214 if ((qtype & ASL_QUERY_MATCH_GID) && (q->gid != r->gid)) return 0;
1215 if ((qtype & ASL_QUERY_MATCH_RUID) && (q->ruid != r->ruid)) return 0;
1216 if ((qtype & ASL_QUERY_MATCH_RGID) && (q->rgid != r->rgid)) return 0;
1217 if ((qtype & ASL_QUERY_MATCH_REF_PID) && (q->refpid != r->refpid)) return 0;
1218 if ((qtype & ASL_QUERY_MATCH_HOST) && (q->host != r->host)) return 0;
1219 if ((qtype & ASL_QUERY_MATCH_SENDER) && (q->sender != r->sender)) return 0;
1220 if ((qtype & ASL_QUERY_MATCH_SMUUID) && (q->sender_mach_uuid != r->sender_mach_uuid)) return 0;
1221 if ((qtype & ASL_QUERY_MATCH_FACILITY) && (q->facility != r->facility)) return 0;
1222 if ((qtype & ASL_QUERY_MATCH_MESSAGE) && (q->message != r->message)) return 0;
1223 if ((qtype & ASL_QUERY_MATCH_REF_PROC) && (q->refproc != r->refproc)) return 0;
1224 if ((qtype & ASL_QUERY_MATCH_SESSION) && (q->session != r->session)) return 0;
1225
1226 for (i = 0; i < q->kvcount; i += 2)
1227 {
1228 for (j = 0; j < r->kvcount; j += 2)
1229 {
1230 if (q->kvlist[i] == r->kvlist[j])
1231 {
1232 if (q->kvlist[i + 1] == r->kvlist[j + 1]) break;
1233 return 0;
1234 }
1235 }
1236
1237 if (j >= r->kvcount) return 0;
1238 }
1239
1240 return 1;
1241 }
1242
1243 static uint32_t
1244 asl_memory_slow_match(asl_memory_t *s, mem_record_t *r, asl_msg_t *rawq)
1245 {
1246 asl_msg_t *rawm;
1247 uint32_t status;
1248
1249 rawm = NULL;
1250 status = asl_memory_message_decode(s, r, &rawm);
1251 if (status != ASL_STATUS_OK) return 0;
1252
1253 status = 0;
1254 if (asl_msg_cmp((asl_msg_t *)rawq, (asl_msg_t *)rawm) != 0) status = 1;
1255 asl_msg_release(rawm);
1256 return status;
1257 }
1258
1259 static uint32_t
1260 asl_memory_match_restricted_uuid_internal(asl_memory_t *s, asl_msg_list_t *query, asl_msg_list_t **res, uint64_t *last_id, uint64_t start_id, uint32_t count, uint32_t duration, int32_t direction, int32_t ruid, int32_t rgid, const char *uuid_str)
1261 {
1262 uint32_t status, i, where, start, j, do_match, did_match, rescount, *qtype;
1263 mem_record_t **qp;
1264 asl_msg_t *m;
1265 size_t qcount;
1266 struct timeval now, finish;
1267
1268 qp = NULL;
1269 qtype = NULL;
1270 rescount = 0;
1271 qcount = asl_msg_list_count(query);
1272
1273 if (qcount == 0)
1274 {
1275 do_match = 0;
1276 }
1277 else
1278 {
1279 qp = (mem_record_t **)calloc(qcount, sizeof(mem_record_t *));
1280 if (qp == NULL) return ASL_STATUS_NO_MEMORY;
1281
1282 qtype = (uint32_t *)calloc(qcount, sizeof(uint32_t));
1283 if (qtype == NULL)
1284 {
1285 free(qp);
1286 return ASL_STATUS_NO_MEMORY;
1287 }
1288
1289 do_match = 0;
1290 for (i = 0; i < qcount; i++)
1291 {
1292 qp[i] = asl_memory_query_to_record(s, asl_msg_list_get_index(query, i), &(qtype[i]));
1293 if (qtype[i] == ASL_QUERY_MATCH_ERROR)
1294 {
1295 for (j = 0; j < i; j++) asl_memory_record_free(s, qp[j]);
1296 free(qp);
1297 free(qtype);
1298 return ASL_STATUS_FAILED;
1299 }
1300
1301 if (qtype[i] != ASL_QUERY_MATCH_TRUE) do_match = 1;
1302 }
1303 }
1304
1305 for (i = 0; i < s->record_count; i++)
1306 {
1307 if (direction >= 0)
1308 {
1309 where = (s->record_first + i) % s->record_count;
1310 if (s->record[where]->mid == 0) continue;
1311 if (s->record[where]->mid >= start_id) break;
1312 }
1313 else
1314 {
1315 where = ((s->record_count - (i + 1)) + s->record_first) % s->record_count;
1316 if (s->record[where]->mid == 0) continue;
1317 if (s->record[where]->mid <= start_id) break;
1318 }
1319 }
1320
1321 if (i >= s->record_count)
1322 {
1323 if (qp != NULL)
1324 {
1325 for (i = 0; i < qcount; i++) asl_memory_record_free(s, qp[i]);
1326 free(qp);
1327 free(qtype);
1328 }
1329
1330 return ASL_STATUS_OK;
1331 }
1332
1333 /* start the timer if a duration was specified */
1334 memset(&finish, 0, sizeof(struct timeval));
1335 if (duration != 0)
1336 {
1337 if (gettimeofday(&finish, NULL) == 0)
1338 {
1339 finish.tv_sec += (duration / USEC_PER_SEC);
1340 finish.tv_usec += (duration % USEC_PER_SEC);
1341 if (finish.tv_usec > USEC_PER_SEC)
1342 {
1343 finish.tv_usec -= USEC_PER_SEC;
1344 finish.tv_sec += 1;
1345 }
1346 }
1347 else
1348 {
1349 /* shouldn't happen, but if gettimeofday failed we just run without a timeout */
1350 memset(&finish, 0, sizeof(struct timeval));
1351 }
1352 }
1353
1354 start = where;
1355
1356 /*
1357 * loop through records
1358 */
1359 for (i = 0; i < s->record_count; i++)
1360 {
1361 status = ASL_STATUS_INVALID_ID;
1362 if (s->record[where]->mid != 0) status = asl_core_check_access(s->record[where]->ruid, s->record[where]->rgid, ruid, rgid, s->record[where]->flags);
1363
1364 if ((status == ASL_STATUS_OK) && (uuid_str != NULL))
1365 {
1366 if (s->record[where]->sender_mach_uuid == NULL) status = ASL_STATUS_INVALID_ID;
1367 else if (strcmp(s->record[where]->sender_mach_uuid->str, uuid_str) != 0) status = ASL_STATUS_INVALID_ID;
1368 }
1369
1370 if (status != ASL_STATUS_OK)
1371 {
1372 if (direction >= 0)
1373 {
1374 where++;
1375 if (where >= s->record_count) where = 0;
1376 }
1377 else
1378 {
1379 if (where == 0) where = s->record_count - 1;
1380 else where--;
1381 }
1382
1383 if (where == s->record_first) break;
1384 continue;
1385 }
1386
1387 s->record[where]->flags &= ASL_MSG_FLAG_SEARCH_CLEAR;
1388 *last_id = s->record[where]->mid;
1389 did_match = 1;
1390
1391 if (do_match != 0)
1392 {
1393 did_match = 0;
1394
1395 for (j = 0; (j < qcount) && (did_match == 0); j++)
1396 {
1397 if (qtype[j] == ASL_QUERY_MATCH_TRUE)
1398 {
1399 did_match = 1;
1400 }
1401 else if (qtype[j] == ASL_QUERY_MATCH_FALSE)
1402 {
1403 did_match = 0;
1404 }
1405 else if (qtype[j] == ASL_QUERY_MATCH_SLOW)
1406 {
1407 did_match = asl_memory_slow_match(s, s->record[where], asl_msg_list_get_index(query, j));
1408 }
1409 else
1410 {
1411 did_match = asl_memory_fast_match(s, s->record[where], qtype[j], qp[j]);
1412 }
1413 }
1414 }
1415
1416 if (did_match == 1)
1417 {
1418 s->record[where]->flags |= ASL_MSG_FLAG_SEARCH_MATCH;
1419 rescount++;
1420 if ((count != 0) && (rescount >= count)) break;
1421 }
1422
1423 /* check the timer */
1424 if ((finish.tv_sec != 0) && (gettimeofday(&now, NULL) == 0))
1425 {
1426 if ((now.tv_sec > finish.tv_sec) || ((now.tv_sec == finish.tv_sec) && (now.tv_usec > finish.tv_usec))) break;
1427 }
1428
1429 if (direction >= 0)
1430 {
1431 where++;
1432 if (where >= s->record_count) where = 0;
1433 }
1434 else
1435 {
1436 if (where == 0) where = s->record_count - 1;
1437 else where--;
1438 }
1439
1440 if (where == s->record_first) break;
1441 }
1442
1443 if (qp != NULL)
1444 {
1445 for (i = 0; i < qcount; i++) asl_memory_record_free(s, qp[i]);
1446 free(qp);
1447 free(qtype);
1448 }
1449
1450 *res = NULL;
1451 if (rescount == 0) return ASL_STATUS_OK;
1452
1453 *res = asl_msg_list_new();
1454 if (*res == NULL) return ASL_STATUS_NO_MEMORY;
1455
1456 where = start;
1457 forever
1458 {
1459 int n = 0;
1460
1461 if (s->record[where]->flags & ASL_MSG_FLAG_SEARCH_MATCH)
1462 {
1463 s->record[where]->flags &= ASL_MSG_FLAG_SEARCH_CLEAR;
1464
1465 status = asl_memory_message_decode(s, s->record[where], &m);
1466 if (status != ASL_STATUS_OK)
1467 {
1468 asl_msg_list_release(*res);
1469 *res = NULL;
1470 return status;
1471 }
1472
1473 asl_msg_list_append(*res, m);
1474 asl_msg_release(m);
1475 n++;
1476 if (n == rescount) break;
1477 }
1478
1479 if (direction >= 0)
1480 {
1481 where++;
1482 if (where >= s->record_count) where = 0;
1483 }
1484 else
1485 {
1486 if (where == 0) where = s->record_count - 1;
1487 else where--;
1488 }
1489
1490 if (where == s->record_first) break;
1491 }
1492
1493 return ASL_STATUS_OK;
1494 }
1495
1496 uint32_t
1497 asl_memory_match_restricted_uuid(asl_memory_t *s, asl_msg_list_t *query, asl_msg_list_t **res, uint64_t *last_id, uint64_t start_id, uint32_t count, uint32_t duration, int32_t direction, int32_t ruid, int32_t rgid, const char *uuid_str)
1498 {
1499 __block uint32_t status;
1500
1501 if (s == NULL) return ASL_STATUS_INVALID_STORE;
1502 if (res == NULL) return ASL_STATUS_INVALID_ARG;
1503
1504 dispatch_sync(s->queue, ^{
1505 status = asl_memory_match_restricted_uuid_internal(s, query, res, last_id, start_id, count, duration, direction, ruid, rgid, uuid_str);
1506 });
1507
1508 return status;
1509 }
1510
1511 uint32_t
1512 asl_memory_match(asl_memory_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, int32_t ruid, int32_t rgid)
1513 {
1514 __block uint32_t status;
1515
1516 if (s == NULL) return ASL_STATUS_INVALID_STORE;
1517 if (res == NULL) return ASL_STATUS_INVALID_ARG;
1518
1519 dispatch_sync(s->queue, ^{
1520 status = asl_memory_match_restricted_uuid_internal(s, query, res, last_id, start_id, count, 0, direction, ruid, rgid, NULL);
1521 });
1522
1523 return status;
1524 }