2 * Copyright (c) 2007-2010 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #include "asl_memory.h"
29 #include <sys/errno.h>
31 #include <sys/types.h>
33 #include <asl_private.h>
35 #define DEFAULT_MAX_RECORDS 2000
36 #define MEM_STRING_HEADER_SIZE 8
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
);
43 asl_memory_statistics(asl_memory_t
*s
, aslmsg
*msg
)
50 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
51 if (msg
== NULL
) return ASL_STATUS_INVALID_ARG
;
53 out
= asl_new(ASL_TYPE_MSG
);
54 if (out
== NULL
) return ASL_STATUS_NO_MEMORY
;
56 size
= sizeof(asl_memory_t
);
57 size
+= ((s
->record_count
+ 1) * sizeof(mem_record_t
));
59 for (i
= 0; i
< s
->string_count
; i
++)
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);
65 snprintf(str
, sizeof(str
), "%llu", size
);
66 asl_set(out
, "Size", str
);
69 for (i
= 0; i
< s
->record_count
; i
++) if (s
->record
[i
]->mid
!= 0) n
++;
71 snprintf(str
, sizeof(str
), "%u", n
);
72 asl_set(out
, "RecordCount", str
);
74 snprintf(str
, sizeof(str
), "%u", s
->string_count
);
75 asl_set(out
, "StringCount", str
);
82 asl_memory_close(asl_memory_t
*s
)
86 if (s
== NULL
) return ASL_STATUS_OK
;
88 if (s
->record
!= NULL
)
90 for (i
= 0; i
< s
->record_count
; i
++)
92 if (s
->record
[i
] != NULL
) free(s
->record
[i
]);
100 if (s
->buffer_record
!= NULL
) free(s
->buffer_record
);
102 if (s
->string_cache
!= NULL
)
104 for (i
= 0; i
< s
->string_count
; i
++)
106 if (s
->string_cache
[i
] != NULL
) free(s
->string_cache
[i
]);
107 s
->string_cache
[i
] = NULL
;
110 free(s
->string_cache
);
111 s
->string_cache
= NULL
;
116 return ASL_STATUS_OK
;
120 asl_memory_open(uint32_t max_records
, asl_memory_t
**s
)
125 if (s
== NULL
) return ASL_STATUS_INVALID_ARG
;
127 if (max_records
== 0) max_records
= DEFAULT_MAX_RECORDS
;
129 out
= calloc(1, sizeof(asl_memory_t
));
130 if (out
== NULL
) return ASL_STATUS_NO_MEMORY
;
132 out
->record_count
= max_records
;
133 out
->record
= (mem_record_t
**)calloc(max_records
, sizeof(mem_record_t
*));
134 if (out
->record
== NULL
)
137 return ASL_STATUS_NO_MEMORY
;
140 for (i
= 0; i
< max_records
; i
++)
142 out
->record
[i
] = (mem_record_t
*)calloc(1, sizeof(mem_record_t
));
143 if (out
->record
[i
] == NULL
)
145 asl_memory_close(out
);
146 return ASL_STATUS_NO_MEMORY
;
150 out
->buffer_record
= (mem_record_t
*)calloc(1, sizeof(mem_record_t
));
151 if (out
->buffer_record
== NULL
)
153 asl_memory_close(out
);
154 return ASL_STATUS_NO_MEMORY
;
158 return ASL_STATUS_OK
;
161 static mem_string_t
*
162 mem_string_new(const char *str
, uint32_t len
, uint32_t hash
)
167 if (str
== NULL
) return NULL
;
169 ss
= MEM_STRING_HEADER_SIZE
+ len
+ 1;
170 out
= (mem_string_t
*)calloc(1, ss
);
171 if (out
== NULL
) return NULL
;
175 memcpy(out
->str
, str
, len
);
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.
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.
189 asl_memory_string_cache_search_hash(asl_memory_t
*s
, uint32_t hash
)
191 uint32_t top
, bot
, mid
, range
;
194 if (s
->string_count
== 0) return 0;
195 if (s
->string_count
== 1)
197 ms
= (mem_string_t
*)s
->string_cache
[0];
198 if (hash
< ms
->hash
) return 0;
202 range
= top
= s
->string_count
- 1;
208 ms
= (mem_string_t
*)s
->string_cache
[mid
];
210 if (hash
== ms
->hash
)
214 ms
= (mem_string_t
*)s
->string_cache
[mid
- 1];
215 if (hash
!= ms
->hash
) break;
223 ms
= (mem_string_t
*)s
->string_cache
[mid
];
224 if (hash
< ms
->hash
) top
= mid
;
229 mid
= bot
+ (range
/ 2);
232 ms
= (mem_string_t
*)s
->string_cache
[bot
];
233 if (hash
<= ms
->hash
) return bot
;
235 ms
= (mem_string_t
*)s
->string_cache
[top
];
236 if (hash
<= ms
->hash
) return top
;
238 return s
->string_count
;
242 * Search the string cache.
243 * If the string is in the cache, increment refcount and return it.
244 * If the string is not in cache and create flag is on, create a new string.
245 * Otherwise, return NULL.
247 static mem_string_t
*
248 asl_memory_string_retain(asl_memory_t
*s
, const char *str
, int create
)
250 uint32_t i
, where
, hash
, len
;
252 if (s
== NULL
) return NULL
;
253 if (str
== NULL
) return NULL
;
256 /* check the cache */
257 hash
= asl_core_string_hash(str
, len
);
258 where
= asl_memory_string_cache_search_hash(s
, hash
);
260 /* asl_memory_string_cache_search_hash just tells us where to look */
261 if (where
< s
->string_count
)
263 while (((mem_string_t
*)(s
->string_cache
[where
]))->hash
== hash
)
265 if (!strcmp(str
, ((mem_string_t
*)(s
->string_cache
[where
]))->str
))
267 ((mem_string_t
*)(s
->string_cache
[where
]))->refcount
++;
268 return s
->string_cache
[where
];
276 if (create
== 0) return NULL
;
278 /* create a new mem_string_t and insert into the cache at index 'where' */
279 if (s
->string_count
== 0)
281 s
->string_cache
= (void **)calloc(1, sizeof(void *));
285 s
->string_cache
= (void **)reallocf(s
->string_cache
, (s
->string_count
+ 1) * sizeof(void *));
286 for (i
= s
->string_count
; i
> where
; i
--) s
->string_cache
[i
] = s
->string_cache
[i
- 1];
289 if (s
->string_cache
== NULL
)
296 s
->string_cache
[where
] = mem_string_new(str
, len
, hash
);
298 return s
->string_cache
[where
];
302 asl_memory_string_release(asl_memory_t
*s
, mem_string_t
*m
)
306 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
307 if (m
== NULL
) return ASL_STATUS_OK
;
309 if (m
->refcount
> 0) m
->refcount
--;
310 if (m
->refcount
> 0) return ASL_STATUS_OK
;
312 where
= asl_memory_string_cache_search_hash(s
, m
->hash
);
313 if (((mem_string_t
*)(s
->string_cache
[where
]))->hash
!= m
->hash
) return ASL_STATUS_OK
;
315 while (s
->string_cache
[where
] != m
)
317 if (((mem_string_t
*)(s
->string_cache
[where
]))->hash
!= m
->hash
) return ASL_STATUS_OK
;
320 if (where
>= s
->string_count
) return ASL_STATUS_OK
;
323 for (i
= where
+ 1; i
< s
->string_count
; i
++) s
->string_cache
[i
- 1] = s
->string_cache
[i
];
328 if (s
->string_count
== 0)
330 free(s
->string_cache
);
331 s
->string_cache
= NULL
;
332 return ASL_STATUS_OK
;
335 s
->string_cache
= (void **)reallocf(s
->string_cache
, s
->string_count
* sizeof(void *));
336 if (s
->string_cache
== NULL
)
339 return ASL_STATUS_NO_MEMORY
;
342 return ASL_STATUS_OK
;
346 * Release all a record's strings and reset it's values
349 asl_memory_record_clear(asl_memory_t
*s
, mem_record_t
*r
)
353 if (s
== NULL
) return;
354 if (r
== NULL
) return;
356 asl_memory_string_release(s
, r
->host
);
357 asl_memory_string_release(s
, r
->sender
);
358 asl_memory_string_release(s
, r
->facility
);
359 asl_memory_string_release(s
, r
->message
);
360 asl_memory_string_release(s
, r
->refproc
);
361 asl_memory_string_release(s
, r
->session
);
363 for (i
= 0; i
< r
->kvcount
; i
++) asl_memory_string_release(s
, r
->kvlist
[i
]);
365 if (r
->kvlist
!= NULL
) free(r
->kvlist
);
366 memset(r
, 0, sizeof(mem_record_t
));
370 asl_memory_record_free(asl_memory_t
*s
, mem_record_t
*r
)
372 asl_memory_record_clear(s
, r
);
377 * Encode an aslmsg as a record structure.
378 * Creates and caches strings.
381 asl_memory_message_encode(asl_memory_t
*s
, aslmsg msg
)
386 const char *key
, *val
;
388 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
389 if (s
->buffer_record
== NULL
) return ASL_STATUS_INVALID_STORE
;
390 if (msg
== NULL
) return ASL_STATUS_INVALID_MESSAGE
;
392 r
= s
->buffer_record
;
394 memset(r
, 0, sizeof(mem_record_t
));
397 r
->level
= ASL_LEVEL_DEBUG
;
403 r
->time
= (uint64_t)-1;
404 r
->nano
= (uint32_t)-1;
409 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
))
411 if (key
== NULL
) continue;
413 else if (!strcmp(key
, ASL_KEY_TIME
))
415 if (val
!= NULL
) r
->time
= asl_parse_time(val
);
417 else if (!strcmp(key
, ASL_KEY_TIME_NSEC
))
419 if (val
!= NULL
) r
->nano
= atoi(val
);
421 else if (!strcmp(key
, ASL_KEY_HOST
))
423 if (val
!= NULL
) r
->host
= asl_memory_string_retain(s
, val
, 1);
425 else if (!strcmp(key
, ASL_KEY_SENDER
))
427 if (val
!= NULL
) r
->sender
= asl_memory_string_retain(s
, val
, 1);
429 else if (!strcmp(key
, ASL_KEY_PID
))
431 if (val
!= NULL
) r
->pid
= atoi(val
);
433 else if (!strcmp(key
, ASL_KEY_REF_PID
))
435 if (val
!= NULL
) r
->refpid
= atoi(val
);
437 else if (!strcmp(key
, ASL_KEY_UID
))
439 if (val
!= NULL
) r
->uid
= atoi(val
);
441 else if (!strcmp(key
, ASL_KEY_GID
))
443 if (val
!= NULL
) r
->gid
= atoi(val
);
445 else if (!strcmp(key
, ASL_KEY_LEVEL
))
447 if (val
!= NULL
) r
->level
= atoi(val
);
449 else if (!strcmp(key
, ASL_KEY_MSG
))
451 if (val
!= NULL
) r
->message
= asl_memory_string_retain(s
, val
, 1);
453 else if (!strcmp(key
, ASL_KEY_FACILITY
))
455 if (val
!= NULL
) r
->facility
= asl_memory_string_retain(s
, val
, 1);
457 else if (!strcmp(key
, ASL_KEY_REF_PROC
))
459 if (val
!= NULL
) r
->refproc
= asl_memory_string_retain(s
, val
, 1);
461 else if (!strcmp(key
, ASL_KEY_SESSION
))
463 if (val
!= NULL
) r
->session
= asl_memory_string_retain(s
, val
, 1);
465 else if (!strcmp(key
, ASL_KEY_READ_UID
))
467 if (((r
->flags
& ASL_MSG_FLAG_READ_UID_SET
) == 0) && (val
!= NULL
))
470 r
->flags
|= ASL_MSG_FLAG_READ_UID_SET
;
473 else if (!strcmp(key
, ASL_KEY_READ_GID
))
475 if (((r
->flags
& ASL_MSG_FLAG_READ_GID_SET
) == 0) && (val
!= NULL
))
478 r
->flags
|= ASL_MSG_FLAG_READ_GID_SET
;
481 else if (!strcmp(key
, ASL_KEY_MSG_ID
))
488 k
= asl_memory_string_retain(s
, key
, 1);
489 if (k
== NULL
) continue;
492 if (val
!= NULL
) v
= asl_memory_string_retain(s
, val
, 1);
496 r
->kvlist
= (mem_string_t
**)calloc(2, sizeof(mem_string_t
*));
500 r
->kvlist
= (mem_string_t
**)realloc(r
->kvlist
, (r
->kvcount
+ 2) * sizeof(mem_string_t
*));
503 if (r
->kvlist
== NULL
)
505 asl_memory_record_clear(s
, r
);
506 return ASL_STATUS_NO_MEMORY
;
509 r
->kvlist
[r
->kvcount
++] = k
;
510 r
->kvlist
[r
->kvcount
++] = v
;
514 return ASL_STATUS_OK
;
518 asl_memory_save(asl_memory_t
*s
, aslmsg msg
, uint64_t *mid
)
523 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
524 if (s
->buffer_record
== NULL
) return ASL_STATUS_INVALID_STORE
;
526 /* asl_memory_message_encode creates and caches strings */
527 status
= asl_memory_message_encode(s
, msg
);
528 if (status
!= ASL_STATUS_OK
) return status
;
532 s
->buffer_record
->mid
= *mid
;
536 s
->buffer_record
->mid
= asl_core_new_msg_id(0);
537 *mid
= s
->buffer_record
->mid
;
540 /* clear the first record */
541 t
= s
->record
[s
->record_first
];
542 asl_memory_record_clear(s
, t
);
544 /* add the new record to the record list (swap in the buffer record) */
545 s
->record
[s
->record_first
] = s
->buffer_record
;
546 s
->buffer_record
= t
;
548 /* record list is a circular queue */
550 if (s
->record_first
>= s
->record_count
) s
->record_first
= 0;
556 * Decodes a record structure.
559 asl_memory_message_decode(asl_memory_t
*s
, mem_record_t
*r
, aslmsg
*out
)
564 const char *key
, *val
;
566 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
567 if (r
== NULL
) return ASL_STATUS_INVALID_ARG
;
568 if (out
== NULL
) return ASL_STATUS_INVALID_ARG
;
572 msg
= asl_new(ASL_TYPE_MSG
);
573 if (msg
== NULL
) return ASL_STATUS_NO_MEMORY
;
576 snprintf(tmp
, sizeof(tmp
), "%llu", r
->mid
);
577 asl_set(msg
, ASL_KEY_MSG_ID
, tmp
);
580 snprintf(tmp
, sizeof(tmp
), "%u", r
->level
);
581 asl_set(msg
, ASL_KEY_LEVEL
, tmp
);
584 if (r
->time
!= (uint64_t)-1)
586 snprintf(tmp
, sizeof(tmp
), "%llu", r
->time
);
587 asl_set(msg
, ASL_KEY_TIME
, tmp
);
591 if (r
->nano
!= (uint32_t)-1)
593 snprintf(tmp
, sizeof(tmp
), "%u", r
->nano
);
594 asl_set(msg
, ASL_KEY_TIME_NSEC
, tmp
);
600 asl_set(msg
, ASL_KEY_HOST
, r
->host
->str
);
604 if (r
->sender
!= NULL
)
606 asl_set(msg
, ASL_KEY_SENDER
, r
->sender
->str
);
610 if (r
->facility
!= NULL
)
612 asl_set(msg
, ASL_KEY_FACILITY
, r
->facility
->str
);
616 if (r
->refproc
!= NULL
)
618 asl_set(msg
, ASL_KEY_REF_PROC
, r
->refproc
->str
);
622 if (r
->session
!= NULL
)
624 asl_set(msg
, ASL_KEY_SESSION
, r
->session
->str
);
630 snprintf(tmp
, sizeof(tmp
), "%d", r
->pid
);
631 asl_set(msg
, ASL_KEY_PID
, tmp
);
637 snprintf(tmp
, sizeof(tmp
), "%d", r
->refpid
);
638 asl_set(msg
, ASL_KEY_REF_PID
, tmp
);
644 snprintf(tmp
, sizeof(tmp
), "%d", r
->uid
);
645 asl_set(msg
, ASL_KEY_UID
, tmp
);
651 snprintf(tmp
, sizeof(tmp
), "%d", r
->gid
);
652 asl_set(msg
, ASL_KEY_GID
, tmp
);
656 if (r
->message
!= NULL
)
658 asl_set(msg
, ASL_KEY_MSG
, r
->message
->str
);
662 if (r
->flags
& ASL_MSG_FLAG_READ_UID_SET
)
664 snprintf(tmp
, sizeof(tmp
), "%d", r
->ruid
);
665 asl_set(msg
, ASL_KEY_READ_UID
, tmp
);
669 if (r
->flags
& ASL_MSG_FLAG_READ_GID_SET
)
671 snprintf(tmp
, sizeof(tmp
), "%d", r
->rgid
);
672 asl_set(msg
, ASL_KEY_READ_GID
, tmp
);
675 /* Key - Value List */
676 for (i
= 0; i
< r
->kvcount
; i
++)
681 if ((r
->kvlist
[i
] != NULL
) && (r
->kvlist
[i
]->str
!= NULL
)) key
= r
->kvlist
[i
]->str
;
683 if ((r
->kvlist
[i
] != NULL
) && (r
->kvlist
[i
]->str
!= NULL
)) val
= r
->kvlist
[i
]->str
;
685 if (key
!= NULL
) asl_set(msg
, key
, val
);
689 return ASL_STATUS_OK
;
693 asl_memory_fetch(asl_memory_t
*s
, uint64_t mid
, aslmsg
*msg
, int32_t ruid
, int32_t rgid
)
697 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
698 if (msg
== NULL
) return ASL_STATUS_INVALID_ARG
;
700 for (i
= 0; i
< s
->record_count
; i
++)
702 if (s
->record
[i
]->mid
== 0) break;
704 if (s
->record
[i
]->mid
== mid
)
706 status
= asl_core_check_access(s
->record
[i
]->ruid
, s
->record
[i
]->rgid
, ruid
, rgid
, s
->record
[i
]->flags
);
707 if (status
!= ASL_STATUS_OK
) return status
;
708 return asl_memory_message_decode(s
, s
->record
[i
], msg
);
712 return ASL_STATUS_INVALID_ID
;
715 static mem_record_t
*
716 asl_memory_query_to_record(asl_memory_t
*s
, aslmsg q
, uint32_t *type
)
720 mem_string_t
*mkey
, *mval
;
721 const char *key
, *val
;
723 if (type
== NULL
) return NULL
;
727 *type
= ASL_QUERY_MATCH_ERROR
;
731 /* NULL query matches anything */
732 *type
= ASL_QUERY_MATCH_TRUE
;
733 if (q
== NULL
) return NULL
;
734 if (asl_msg_count((asl_msg_t
*)q
) == 0) return NULL
;
737 /* we can only do fast match on equality tests */
738 *type
= ASL_QUERY_MATCH_SLOW
;
740 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
))
742 if (op
!= ASL_QUERY_OP_EQUAL
) return NULL
;
745 out
= (mem_record_t
*)calloc(1, sizeof(mem_record_t
));
748 *type
= ASL_QUERY_MATCH_ERROR
;
752 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
))
754 if (key
== NULL
) continue;
756 else if (!strcmp(key
, ASL_KEY_MSG_ID
))
758 if (val
== NULL
) continue;
760 if (*type
& ASL_QUERY_MATCH_MSG_ID
)
762 asl_memory_record_free(s
, out
);
763 *type
= ASL_QUERY_MATCH_SLOW
;
767 *type
|= ASL_QUERY_MATCH_MSG_ID
;
768 out
->mid
= atoll(val
);
770 else if (!strcmp(key
, ASL_KEY_TIME
))
772 if (val
== NULL
) continue;
774 if (*type
& ASL_QUERY_MATCH_TIME
)
776 asl_memory_record_free(s
, out
);
777 *type
= ASL_QUERY_MATCH_SLOW
;
781 *type
|= ASL_QUERY_MATCH_TIME
;
782 out
->time
= asl_parse_time(val
);
784 else if (!strcmp(key
, ASL_KEY_TIME_NSEC
))
786 if (val
== NULL
) continue;
788 if (*type
& ASL_QUERY_MATCH_NANO
)
790 asl_memory_record_free(s
, out
);
791 *type
= ASL_QUERY_MATCH_SLOW
;
795 *type
|= ASL_QUERY_MATCH_NANO
;
796 out
->nano
= atoll(val
);
798 else if (!strcmp(key
, ASL_KEY_LEVEL
))
800 if (val
== NULL
) continue;
802 if (*type
& ASL_QUERY_MATCH_LEVEL
)
804 asl_memory_record_free(s
, out
);
805 *type
= ASL_QUERY_MATCH_SLOW
;
809 *type
|= ASL_QUERY_MATCH_LEVEL
;
810 out
->level
= atoi(val
);
812 else if (!strcmp(key
, ASL_KEY_PID
))
814 if (val
== NULL
) continue;
816 if (*type
& ASL_QUERY_MATCH_PID
)
818 asl_memory_record_free(s
, out
);
819 *type
= ASL_QUERY_MATCH_SLOW
;
823 *type
|= ASL_QUERY_MATCH_PID
;
824 out
->pid
= atoi(val
);
826 else if (!strcmp(key
, ASL_KEY_UID
))
828 if (val
== NULL
) continue;
830 if (*type
& ASL_QUERY_MATCH_UID
)
832 asl_memory_record_free(s
, out
);
833 *type
= ASL_QUERY_MATCH_SLOW
;
837 *type
|= ASL_QUERY_MATCH_UID
;
838 out
->uid
= atoi(val
);
840 else if (!strcmp(key
, ASL_KEY_GID
))
842 if (val
== NULL
) continue;
844 if (*type
& ASL_QUERY_MATCH_GID
)
846 asl_memory_record_free(s
, out
);
847 *type
= ASL_QUERY_MATCH_SLOW
;
851 *type
|= ASL_QUERY_MATCH_GID
;
852 out
->gid
= atoi(val
);
854 else if (!strcmp(key
, ASL_KEY_READ_UID
))
856 if (val
== NULL
) continue;
858 if (*type
& ASL_QUERY_MATCH_RUID
)
860 asl_memory_record_free(s
, out
);
861 *type
= ASL_QUERY_MATCH_SLOW
;
865 *type
|= ASL_QUERY_MATCH_RUID
;
866 out
->ruid
= atoi(val
);
868 else if (!strcmp(key
, ASL_KEY_READ_GID
))
870 if (val
== NULL
) continue;
872 if (*type
& ASL_QUERY_MATCH_RGID
)
874 asl_memory_record_free(s
, out
);
875 *type
= ASL_QUERY_MATCH_SLOW
;
879 *type
|= ASL_QUERY_MATCH_RGID
;
880 out
->rgid
= atoi(val
);
882 else if (!strcmp(key
, ASL_KEY_REF_PID
))
884 if (val
== NULL
) continue;
886 if (*type
& ASL_QUERY_MATCH_REF_PID
)
888 asl_memory_record_free(s
, out
);
889 *type
= ASL_QUERY_MATCH_SLOW
;
893 *type
|= ASL_QUERY_MATCH_REF_PID
;
894 out
->refpid
= atoi(val
);
896 else if (!strcmp(key
, ASL_KEY_HOST
))
898 if (val
== NULL
) continue;
900 if (*type
& ASL_QUERY_MATCH_HOST
)
902 asl_memory_record_free(s
, out
);
903 *type
= ASL_QUERY_MATCH_SLOW
;
907 *type
|= ASL_QUERY_MATCH_HOST
;
908 out
->host
= asl_memory_string_retain(s
, val
, 0);
909 if (out
->host
== NULL
)
911 asl_memory_record_free(s
, out
);
912 *type
= ASL_QUERY_MATCH_FALSE
;
916 else if (!strcmp(key
, ASL_KEY_SENDER
))
918 if (val
== NULL
) continue;
920 if (*type
& ASL_QUERY_MATCH_SENDER
)
922 asl_memory_record_free(s
, out
);
923 *type
= ASL_QUERY_MATCH_SLOW
;
927 *type
|= ASL_QUERY_MATCH_SENDER
;
928 out
->sender
= asl_memory_string_retain(s
, val
, 0);
929 if (out
->sender
== NULL
)
931 asl_memory_record_free(s
, out
);
932 *type
= ASL_QUERY_MATCH_FALSE
;
936 else if (!strcmp(key
, ASL_KEY_FACILITY
))
938 if (val
== NULL
) continue;
940 if (*type
& ASL_QUERY_MATCH_FACILITY
)
942 asl_memory_record_free(s
, out
);
943 *type
= ASL_QUERY_MATCH_SLOW
;
947 *type
|= ASL_QUERY_MATCH_FACILITY
;
948 out
->facility
= asl_memory_string_retain(s
, val
, 0);
949 if (out
->facility
== NULL
)
951 asl_memory_record_free(s
, out
);
952 *type
= ASL_QUERY_MATCH_FALSE
;
956 else if (!strcmp(key
, ASL_KEY_MSG
))
958 if (val
== NULL
) continue;
960 if (*type
& ASL_QUERY_MATCH_MESSAGE
)
962 asl_memory_record_free(s
, out
);
963 *type
= ASL_QUERY_MATCH_SLOW
;
967 *type
|= ASL_QUERY_MATCH_MESSAGE
;
968 out
->message
= asl_memory_string_retain(s
, val
, 0);
969 if (out
->message
== NULL
)
971 asl_memory_record_free(s
, out
);
972 *type
= ASL_QUERY_MATCH_FALSE
;
976 else if (!strcmp(key
, ASL_KEY_REF_PROC
))
978 if (val
== NULL
) continue;
980 if (*type
& ASL_QUERY_MATCH_REF_PROC
)
982 asl_memory_record_free(s
, out
);
983 *type
= ASL_QUERY_MATCH_SLOW
;
987 *type
|= ASL_QUERY_MATCH_REF_PROC
;
988 out
->refproc
= asl_memory_string_retain(s
, val
, 0);
989 if (out
->refproc
== NULL
)
991 asl_memory_record_free(s
, out
);
992 *type
= ASL_QUERY_MATCH_FALSE
;
996 else if (!strcmp(key
, ASL_KEY_SESSION
))
998 if (val
== NULL
) continue;
1000 if (*type
& ASL_QUERY_MATCH_SESSION
)
1002 asl_memory_record_free(s
, out
);
1003 *type
= ASL_QUERY_MATCH_SLOW
;
1007 *type
|= ASL_QUERY_MATCH_SESSION
;
1008 out
->session
= asl_memory_string_retain(s
, val
, 0);
1009 if (out
->session
== NULL
)
1011 asl_memory_record_free(s
, out
);
1012 *type
= ASL_QUERY_MATCH_FALSE
;
1018 mkey
= asl_memory_string_retain(s
, key
, 0);
1021 asl_memory_record_free(s
, out
);
1022 *type
= ASL_QUERY_MATCH_FALSE
;
1026 for (i
= 0; i
< out
->kvcount
; i
+= 2)
1028 if (out
->kvlist
[i
] == mkey
)
1030 asl_memory_record_free(s
, out
);
1031 *type
= ASL_QUERY_MATCH_SLOW
;
1036 mval
= asl_memory_string_retain(s
, val
, 0);
1038 if (out
->kvcount
== 0)
1040 out
->kvlist
= (mem_string_t
**)calloc(2, sizeof(mem_string_t
*));
1044 out
->kvlist
= (mem_string_t
**)realloc(out
->kvlist
, (out
->kvcount
+ 2) * sizeof(mem_string_t
*));
1047 if (out
->kvlist
== NULL
)
1049 asl_memory_record_free(s
, out
);
1050 *type
= ASL_QUERY_MATCH_ERROR
;
1054 out
->kvlist
[out
->kvcount
++] = mkey
;
1055 out
->kvlist
[out
->kvcount
++] = mval
;
1063 asl_memory_fast_match(asl_memory_t
*s
, mem_record_t
*r
, uint32_t qtype
, mem_record_t
*q
)
1067 if (s
== NULL
) return 0;
1068 if (r
== NULL
) return 0;
1069 if (q
== NULL
) return 1;
1071 if ((qtype
& ASL_QUERY_MATCH_MSG_ID
) && (q
->mid
!= r
->mid
)) return 0;
1072 if ((qtype
& ASL_QUERY_MATCH_TIME
) && (q
->time
!= r
->time
)) return 0;
1073 if ((qtype
& ASL_QUERY_MATCH_NANO
) && (q
->nano
!= r
->nano
)) return 0;
1074 if ((qtype
& ASL_QUERY_MATCH_LEVEL
) && (q
->level
!= r
->level
)) return 0;
1075 if ((qtype
& ASL_QUERY_MATCH_PID
) && (q
->pid
!= r
->pid
)) return 0;
1076 if ((qtype
& ASL_QUERY_MATCH_UID
) && (q
->uid
!= r
->uid
)) return 0;
1077 if ((qtype
& ASL_QUERY_MATCH_GID
) && (q
->gid
!= r
->gid
)) return 0;
1078 if ((qtype
& ASL_QUERY_MATCH_RUID
) && (q
->ruid
!= r
->ruid
)) return 0;
1079 if ((qtype
& ASL_QUERY_MATCH_RGID
) && (q
->rgid
!= r
->rgid
)) return 0;
1080 if ((qtype
& ASL_QUERY_MATCH_REF_PID
) && (q
->refpid
!= r
->refpid
)) return 0;
1081 if ((qtype
& ASL_QUERY_MATCH_HOST
) && (q
->host
!= r
->host
)) return 0;
1082 if ((qtype
& ASL_QUERY_MATCH_SENDER
) && (q
->sender
!= r
->sender
)) return 0;
1083 if ((qtype
& ASL_QUERY_MATCH_FACILITY
) && (q
->facility
!= r
->facility
)) return 0;
1084 if ((qtype
& ASL_QUERY_MATCH_MESSAGE
) && (q
->message
!= r
->message
)) return 0;
1085 if ((qtype
& ASL_QUERY_MATCH_REF_PROC
) && (q
->refproc
!= r
->refproc
)) return 0;
1086 if ((qtype
& ASL_QUERY_MATCH_SESSION
) && (q
->session
!= r
->session
)) return 0;
1088 for (i
= 0; i
< q
->kvcount
; i
+= 2)
1090 for (j
= 0; j
< r
->kvcount
; j
+= 2)
1092 if (q
->kvlist
[i
] == r
->kvlist
[j
])
1094 if (q
->kvlist
[i
+ 1] == r
->kvlist
[j
+ 1]) break;
1099 if (j
>= r
->kvcount
) return 0;
1106 asl_memory_slow_match(asl_memory_t
*s
, mem_record_t
*r
, aslmsg rawq
)
1112 status
= asl_memory_message_decode(s
, r
, &rawm
);
1113 if (status
!= ASL_STATUS_OK
) return 0;
1116 if (asl_msg_cmp((asl_msg_t
*)rawq
, (asl_msg_t
*)rawm
) != 0) status
= 1;
1122 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
)
1124 uint32_t status
, i
, where
, start
, j
, do_match
, did_match
, rescount
, *qtype
;
1128 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
1129 if (res
== NULL
) return ASL_STATUS_INVALID_ARG
;
1135 if ((query
== NULL
) || ((query
!= NULL
) && (query
->count
== 0)))
1141 qp
= (mem_record_t
**)calloc(query
->count
, sizeof(mem_record_t
*));
1142 if (qp
== NULL
) return ASL_STATUS_NO_MEMORY
;
1144 qtype
= (uint32_t *)calloc(query
->count
, sizeof(uint32_t));
1148 return ASL_STATUS_NO_MEMORY
;
1152 for (i
= 0; i
< query
->count
; i
++)
1154 qp
[i
] = asl_memory_query_to_record(s
, (aslmsg
)query
->msg
[i
], &(qtype
[i
]));
1155 if (qtype
[i
] == ASL_QUERY_MATCH_ERROR
)
1157 for (j
= 0; j
< i
; j
++) asl_memory_record_free(s
, qp
[j
]);
1160 return ASL_STATUS_FAILED
;
1163 if (qtype
[i
] != ASL_QUERY_MATCH_TRUE
) do_match
= 1;
1167 for (i
= 0; i
< s
->record_count
; i
++)
1171 where
= (s
->record_first
+ i
) % s
->record_count
;
1172 if (s
->record
[where
]->mid
== 0) continue;
1173 if (s
->record
[where
]->mid
>= start_id
) break;
1177 where
= ((s
->record_count
- (i
+ 1)) + s
->record_first
) % s
->record_count
;
1178 if (s
->record
[where
]->mid
== 0) continue;
1179 if (s
->record
[where
]->mid
<= start_id
) break;
1183 if (i
>= s
->record_count
)
1187 for (i
= 0; i
< query
->count
; i
++) asl_memory_record_free(s
, qp
[i
]);
1192 return ASL_STATUS_OK
;
1198 * loop through records
1200 for (i
= 0; i
< s
->record_count
; i
++)
1202 status
= ASL_STATUS_INVALID_ID
;
1203 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
);
1204 if (status
!= ASL_STATUS_OK
)
1209 if (where
>= s
->record_count
) where
= 0;
1213 if (where
== 0) where
= s
->record_count
- 1;
1217 if (where
== s
->record_first
) break;
1221 s
->record
[where
]->flags
&= ASL_MSG_FLAG_SEARCH_CLEAR
;
1222 *last_id
= s
->record
[where
]->mid
;
1229 for (j
= 0; (j
< query
->count
) && (did_match
== 0); j
++)
1231 if (qtype
[j
] == ASL_QUERY_MATCH_TRUE
)
1235 else if (qtype
[j
] == ASL_QUERY_MATCH_FALSE
)
1239 else if (qtype
[j
] == ASL_QUERY_MATCH_SLOW
)
1241 did_match
= asl_memory_slow_match(s
, s
->record
[where
], (aslmsg
)query
->msg
[j
]);
1245 did_match
= asl_memory_fast_match(s
, s
->record
[where
], qtype
[j
], qp
[j
]);
1252 s
->record
[where
]->flags
|= ASL_MSG_FLAG_SEARCH_MATCH
;
1254 if ((count
!= 0) && (rescount
>= count
)) break;
1260 if (where
>= s
->record_count
) where
= 0;
1264 if (where
== 0) where
= s
->record_count
- 1;
1268 if (where
== s
->record_first
) break;
1273 for (i
= 0; i
< query
->count
; i
++) asl_memory_record_free(s
, qp
[i
]);
1279 if (rescount
== 0) return ASL_STATUS_OK
;
1281 *res
= (asl_msg_list_t
*)calloc(1, sizeof(asl_msg_list_t
));
1282 if (*res
== NULL
) return ASL_STATUS_NO_MEMORY
;
1284 (*res
)->count
= rescount
;
1286 (*res
)->msg
= (asl_msg_t
**)calloc(rescount
, sizeof(asl_msg_t
*));
1287 if ((*res
)->msg
== NULL
)
1291 return ASL_STATUS_NO_MEMORY
;
1297 if (s
->record
[where
]->flags
& ASL_MSG_FLAG_SEARCH_MATCH
)
1299 s
->record
[where
]->flags
&= ASL_MSG_FLAG_SEARCH_CLEAR
;
1301 status
= asl_memory_message_decode(s
, s
->record
[where
], &m
);
1302 if (status
!= ASL_STATUS_OK
)
1304 aslresponse_free(*res
);
1309 (*res
)->msg
[(*res
)->curr
++] = (asl_msg_t
*)m
;
1310 if ((*res
)->curr
== rescount
) break;
1316 if (where
>= s
->record_count
) where
= 0;
1320 if (where
== 0) where
= s
->record_count
- 1;
1324 if (where
== s
->record_first
) break;
1328 return ASL_STATUS_OK
;