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