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_mini_memory.h"
29 #include <sys/errno.h>
31 #include <sys/types.h>
33 #include <asl_private.h>
36 #define DEFAULT_MAX_RECORDS 256
37 #define MEM_STRING_HEADER_SIZE 8
38 #define CFLOG_LOCAL_TIME_KEY "CFLog Local Time"
39 #define CFLOG_THREAD_KEY "CFLog Thread"
41 #define forever for(;;)
42 extern time_t asl_parse_time(const char *str
);
43 extern int asl_msg_cmp(asl_msg_t
*a
, asl_msg_t
*b
);
46 asl_mini_memory_statistics(asl_mini_memory_t
*s
, aslmsg
*msg
)
53 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
54 if (msg
== NULL
) return ASL_STATUS_INVALID_ARG
;
56 out
= asl_new(ASL_TYPE_MSG
);
57 if (out
== NULL
) return ASL_STATUS_NO_MEMORY
;
59 size
= sizeof(asl_mini_memory_t
);
60 size
+= ((s
->record_count
+ 1) * sizeof(mini_mem_record_t
));
62 for (i
= 0; i
< s
->string_count
; i
++)
64 size
+= MEM_STRING_HEADER_SIZE
;
65 if (((mini_mem_string_t
*)s
->string_cache
[i
])->str
!= NULL
) size
+= (strlen(((mini_mem_string_t
*)s
->string_cache
[i
])->str
) + 1);
68 snprintf(str
, sizeof(str
), "%llu", size
);
69 asl_set(out
, "Size", str
);
72 for (i
= 0; i
< s
->record_count
; i
++) if (s
->record
[i
]->mid
!= 0) n
++;
74 snprintf(str
, sizeof(str
), "%u", n
);
75 asl_set(out
, "RecordCount", str
);
77 snprintf(str
, sizeof(str
), "%u", s
->string_count
);
78 asl_set(out
, "StringCount", str
);
85 asl_mini_memory_close(asl_mini_memory_t
*s
)
89 if (s
== NULL
) return ASL_STATUS_OK
;
91 if (s
->record
!= NULL
)
93 for (i
= 0; i
< s
->record_count
; i
++)
95 if (s
->record
[i
] != NULL
) free(s
->record
[i
]);
103 if (s
->buffer_record
!= NULL
) free(s
->buffer_record
);
105 if (s
->string_cache
!= NULL
)
107 for (i
= 0; i
< s
->string_count
; i
++)
109 if (s
->string_cache
[i
] != NULL
) free(s
->string_cache
[i
]);
110 s
->string_cache
[i
] = NULL
;
113 free(s
->string_cache
);
114 s
->string_cache
= NULL
;
119 return ASL_STATUS_OK
;
123 asl_mini_memory_open(uint32_t max_records
, asl_mini_memory_t
**s
)
125 asl_mini_memory_t
*out
;
128 if (s
== NULL
) return ASL_STATUS_INVALID_ARG
;
130 if (max_records
== 0) max_records
= DEFAULT_MAX_RECORDS
;
132 out
= calloc(1, sizeof(asl_mini_memory_t
));
133 if (out
== NULL
) return ASL_STATUS_NO_MEMORY
;
135 out
->record_count
= max_records
;
136 out
->record
= (mini_mem_record_t
**)calloc(max_records
, sizeof(mini_mem_record_t
*));
137 if (out
->record
== NULL
)
140 return ASL_STATUS_NO_MEMORY
;
143 for (i
= 0; i
< max_records
; i
++)
145 out
->record
[i
] = (mini_mem_record_t
*)calloc(1, sizeof(mini_mem_record_t
));
146 if (out
->record
[i
] == NULL
)
148 asl_mini_memory_close(out
);
149 return ASL_STATUS_NO_MEMORY
;
153 out
->buffer_record
= (mini_mem_record_t
*)calloc(1, sizeof(mini_mem_record_t
));
154 if (out
->buffer_record
== NULL
)
156 asl_mini_memory_close(out
);
157 return ASL_STATUS_NO_MEMORY
;
163 return ASL_STATUS_OK
;
166 static mini_mem_string_t
*
167 mem_string_new(const char *str
, uint32_t len
, uint32_t hash
)
169 mini_mem_string_t
*out
;
172 if (str
== NULL
) return NULL
;
174 ss
= MEM_STRING_HEADER_SIZE
+ len
+ 1;
175 out
= (mini_mem_string_t
*)calloc(1, ss
);
176 if (out
== NULL
) return NULL
;
180 memcpy(out
->str
, str
, len
);
186 * Find the first hash greater than or equal to a given hash in the string cache.
187 * Return s->string_count if hash is greater that or equal to last hash in the string cache.
188 * Caller must check if the hashes match or not.
190 * This routine is used both to find strings in the cache and to determine where to insert
191 * new strings. Note that the caller needs to do extra work after calling this routine.
194 asl_mini_memory_string_cache_search_hash(asl_mini_memory_t
*s
, uint32_t hash
)
196 uint32_t top
, bot
, mid
, range
;
197 mini_mem_string_t
*ms
;
199 if (s
->string_count
== 0) return 0;
200 if (s
->string_count
== 1)
202 ms
= (mini_mem_string_t
*)s
->string_cache
[0];
203 if (hash
< ms
->hash
) return 0;
207 range
= top
= s
->string_count
- 1;
213 ms
= (mini_mem_string_t
*)s
->string_cache
[mid
];
215 if (hash
== ms
->hash
)
219 ms
= (mini_mem_string_t
*)s
->string_cache
[mid
- 1];
220 if (hash
!= ms
->hash
) break;
228 ms
= (mini_mem_string_t
*)s
->string_cache
[mid
];
229 if (hash
< ms
->hash
) top
= mid
;
234 mid
= bot
+ (range
/ 2);
237 ms
= (mini_mem_string_t
*)s
->string_cache
[bot
];
238 if (hash
<= ms
->hash
) return bot
;
240 ms
= (mini_mem_string_t
*)s
->string_cache
[top
];
241 if (hash
<= ms
->hash
) return top
;
243 return s
->string_count
;
247 * Search the string cache.
248 * If the string is in the cache, increment refcount and return it.
249 * If the string is not in cache and create flag is on, create a new string.
250 * Otherwise, return NULL.
252 static mini_mem_string_t
*
253 asl_mini_memory_string_retain(asl_mini_memory_t
*s
, const char *str
, int create
)
255 uint32_t i
, where
, hash
, len
;
256 mini_mem_string_t
*new;
258 if (s
== NULL
) return NULL
;
259 if (str
== NULL
) return NULL
;
262 /* check the cache */
263 hash
= asl_core_string_hash(str
, len
);
264 where
= asl_mini_memory_string_cache_search_hash(s
, hash
);
266 /* asl_mini_memory_string_cache_search_hash just tells us where to look */
267 if (where
< s
->string_count
)
269 while (((mini_mem_string_t
*)(s
->string_cache
[where
]))->hash
== hash
)
271 if (!strcmp(str
, ((mini_mem_string_t
*)(s
->string_cache
[where
]))->str
))
273 ((mini_mem_string_t
*)(s
->string_cache
[where
]))->refcount
++;
274 return s
->string_cache
[where
];
282 if (create
== 0) return NULL
;
284 /* create a new mini_mem_string_t and insert into the cache at index 'where' */
285 if (s
->string_count
== 0)
287 s
->string_cache
= (void **)calloc(1, sizeof(void *));
291 s
->string_cache
= (void **)reallocf(s
->string_cache
, (s
->string_count
+ 1) * sizeof(void *));
292 for (i
= s
->string_count
; i
> where
; i
--) s
->string_cache
[i
] = s
->string_cache
[i
- 1];
295 if (s
->string_cache
== NULL
)
301 new = mem_string_new(str
, len
, hash
);
302 if (new == NULL
) return NULL
;
304 s
->string_cache
[where
] = new;
307 return s
->string_cache
[where
];
311 asl_mini_memory_string_release(asl_mini_memory_t
*s
, mini_mem_string_t
*m
)
315 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
316 if (m
== NULL
) return ASL_STATUS_OK
;
318 if (m
->refcount
> 0) m
->refcount
--;
319 if (m
->refcount
> 0) return ASL_STATUS_OK
;
321 where
= asl_mini_memory_string_cache_search_hash(s
, m
->hash
);
322 if (((mini_mem_string_t
*)(s
->string_cache
[where
]))->hash
!= m
->hash
) return ASL_STATUS_OK
;
324 while (s
->string_cache
[where
] != m
)
326 if (((mini_mem_string_t
*)(s
->string_cache
[where
]))->hash
!= m
->hash
) return ASL_STATUS_OK
;
329 if (where
>= s
->string_count
) return ASL_STATUS_OK
;
332 for (i
= where
+ 1; i
< s
->string_count
; i
++) s
->string_cache
[i
- 1] = s
->string_cache
[i
];
337 if (s
->string_count
== 0)
339 free(s
->string_cache
);
340 s
->string_cache
= NULL
;
341 return ASL_STATUS_OK
;
344 s
->string_cache
= (void **)reallocf(s
->string_cache
, s
->string_count
* sizeof(void *));
345 if (s
->string_cache
== NULL
)
348 return ASL_STATUS_NO_MEMORY
;
351 return ASL_STATUS_OK
;
355 * Release all a record's strings and reset it's values
358 asl_mini_memory_record_clear(asl_mini_memory_t
*s
, mini_mem_record_t
*r
)
362 if (s
== NULL
) return;
363 if (r
== NULL
) return;
365 asl_mini_memory_string_release(s
, r
->sender
);
366 asl_mini_memory_string_release(s
, r
->sender_mach_uuid
);
367 asl_mini_memory_string_release(s
, r
->facility
);
368 asl_mini_memory_string_release(s
, r
->message
);
370 for (i
= 0; i
< r
->kvcount
; i
++) asl_mini_memory_string_release(s
, r
->kvlist
[i
]);
372 if (r
->kvlist
!= NULL
) free(r
->kvlist
);
373 memset(r
, 0, sizeof(mini_mem_record_t
));
377 asl_mini_memory_record_free(asl_mini_memory_t
*s
, mini_mem_record_t
*r
)
379 asl_mini_memory_record_clear(s
, r
);
384 * Encode an aslmsg as a record structure.
385 * Creates and caches strings.
388 asl_mini_memory_message_encode(asl_mini_memory_t
*s
, aslmsg msg
)
391 mini_mem_string_t
*k
, *v
;
392 mini_mem_record_t
*r
;
393 const char *key
, *val
;
395 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
396 if (s
->buffer_record
== NULL
) return ASL_STATUS_INVALID_STORE
;
397 if (msg
== NULL
) return ASL_STATUS_INVALID_MESSAGE
;
399 r
= s
->buffer_record
;
401 memset(r
, 0, sizeof(mini_mem_record_t
));
404 r
->level
= ASL_LEVEL_DEBUG
;
408 r
->time
= (uint64_t)-1;
409 r
->nano
= (uint32_t)-1;
414 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
))
416 if (key
== NULL
) continue;
418 else if (!strcmp(key
, ASL_KEY_TIME
))
420 if (val
!= NULL
) r
->time
= asl_parse_time(val
);
422 else if (!strcmp(key
, ASL_KEY_TIME_NSEC
))
424 if (val
!= NULL
) r
->nano
= atoi(val
);
426 else if (!strcmp(key
, ASL_KEY_SENDER
))
428 if (val
!= NULL
) r
->sender
= asl_mini_memory_string_retain(s
, val
, 1);
430 else if (!strcmp(key
, ASL_KEY_SENDER_MACH_UUID
))
432 if (val
!= NULL
) r
->sender_mach_uuid
= asl_mini_memory_string_retain(s
, val
, 1);
434 else if (!strcmp(key
, ASL_KEY_PID
))
436 if (val
!= NULL
) r
->pid
= atoi(val
);
438 else if (!strcmp(key
, ASL_KEY_LEVEL
))
440 if (val
!= NULL
) r
->level
= atoi(val
);
442 else if (!strcmp(key
, ASL_KEY_MSG
))
444 if (val
!= NULL
) r
->message
= asl_mini_memory_string_retain(s
, val
, 1);
446 else if (!strcmp(key
, ASL_KEY_FACILITY
))
448 if (val
!= NULL
) r
->facility
= asl_mini_memory_string_retain(s
, val
, 1);
450 else if (!strcmp(key
, ASL_KEY_MSG_ID
))
455 else if (!strcmp(key
, ASL_KEY_TIME_NSEC
))
460 else if (!strcmp(key
, ASL_KEY_HOST
))
465 else if (!strcmp(key
, ASL_KEY_REF_PID
))
470 else if (!strcmp(key
, ASL_KEY_REF_PROC
))
475 else if (!strcmp(key
, ASL_KEY_SESSION
))
480 else if (!strcmp(key
, ASL_KEY_UID
))
485 else if (!strcmp(key
, ASL_KEY_GID
))
490 else if (!strcmp(key
, ASL_KEY_READ_UID
))
492 if (((r
->flags
& ASL_MSG_FLAG_READ_UID_SET
) == 0) && (val
!= NULL
))
495 r
->flags
|= ASL_MSG_FLAG_READ_UID_SET
;
498 else if (!strcmp(key
, ASL_KEY_READ_GID
))
500 if (((r
->flags
& ASL_MSG_FLAG_READ_GID_SET
) == 0) && (val
!= NULL
))
503 r
->flags
|= ASL_MSG_FLAG_READ_GID_SET
;
506 else if (!strcmp(key
, CFLOG_LOCAL_TIME_KEY
))
511 else if (!strcmp(key
, CFLOG_THREAD_KEY
))
518 k
= asl_mini_memory_string_retain(s
, key
, 1);
519 if (k
== NULL
) continue;
522 if (val
!= NULL
) v
= asl_mini_memory_string_retain(s
, val
, 1);
526 r
->kvlist
= (mini_mem_string_t
**)calloc(2, sizeof(mini_mem_string_t
*));
530 r
->kvlist
= (mini_mem_string_t
**)reallocf(r
->kvlist
, (r
->kvcount
+ 2) * sizeof(mini_mem_string_t
*));
533 if (r
->kvlist
== NULL
)
535 asl_mini_memory_record_clear(s
, r
);
536 return ASL_STATUS_NO_MEMORY
;
539 r
->kvlist
[r
->kvcount
++] = k
;
540 r
->kvlist
[r
->kvcount
++] = v
;
544 return ASL_STATUS_OK
;
548 asl_mini_memory_save(asl_mini_memory_t
*s
, aslmsg msg
, uint64_t *mid
)
551 mini_mem_record_t
*t
;
553 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
554 if (s
->buffer_record
== NULL
) return ASL_STATUS_INVALID_STORE
;
556 /* asl_mini_memory_message_encode creates and caches strings */
557 status
= asl_mini_memory_message_encode(s
, msg
);
558 if (status
!= ASL_STATUS_OK
) return status
;
560 s
->buffer_record
->mid
= s
->next_id
;
563 /* clear the first record */
564 t
= s
->record
[s
->record_first
];
565 asl_mini_memory_record_clear(s
, t
);
567 /* add the new record to the record list (swap in the buffer record) */
568 s
->record
[s
->record_first
] = s
->buffer_record
;
569 s
->buffer_record
= t
;
571 /* record list is a circular queue */
573 if (s
->record_first
>= s
->record_count
) s
->record_first
= 0;
575 *mid
= s
->buffer_record
->mid
;
581 * Decodes a record structure.
584 asl_mini_memory_message_decode(asl_mini_memory_t
*s
, mini_mem_record_t
*r
, aslmsg
*out
)
589 const char *key
, *val
;
591 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
592 if (r
== NULL
) return ASL_STATUS_INVALID_ARG
;
593 if (out
== NULL
) return ASL_STATUS_INVALID_ARG
;
597 msg
= asl_new(ASL_TYPE_MSG
);
598 if (msg
== NULL
) return ASL_STATUS_NO_MEMORY
;
601 snprintf(tmp
, sizeof(tmp
), "%u", r
->mid
);
602 asl_set(msg
, ASL_KEY_MSG_ID
, tmp
);
605 snprintf(tmp
, sizeof(tmp
), "%u", r
->level
);
606 asl_set(msg
, ASL_KEY_LEVEL
, tmp
);
609 if (r
->time
!= (uint64_t)-1)
611 snprintf(tmp
, sizeof(tmp
), "%llu", r
->time
);
612 asl_set(msg
, ASL_KEY_TIME
, tmp
);
616 if (r
->nano
!= (uint32_t)-1)
618 snprintf(tmp
, sizeof(tmp
), "%u", r
->nano
);
619 asl_set(msg
, ASL_KEY_TIME_NSEC
, tmp
);
623 if (r
->sender
!= NULL
)
625 asl_set(msg
, ASL_KEY_SENDER
, r
->sender
->str
);
628 /* Sender mach UUID */
629 if (r
->sender_mach_uuid
!= NULL
)
631 asl_set(msg
, ASL_KEY_SENDER_MACH_UUID
, r
->sender_mach_uuid
->str
);
635 if (r
->facility
!= NULL
)
637 asl_set(msg
, ASL_KEY_FACILITY
, r
->facility
->str
);
643 snprintf(tmp
, sizeof(tmp
), "%d", r
->pid
);
644 asl_set(msg
, ASL_KEY_PID
, tmp
);
648 if (r
->message
!= NULL
)
650 asl_set(msg
, ASL_KEY_MSG
, r
->message
->str
);
654 if (r
->flags
& ASL_MSG_FLAG_READ_UID_SET
)
656 snprintf(tmp
, sizeof(tmp
), "%d", r
->ruid
);
657 asl_set(msg
, ASL_KEY_READ_UID
, tmp
);
661 if (r
->flags
& ASL_MSG_FLAG_READ_GID_SET
)
663 snprintf(tmp
, sizeof(tmp
), "%d", r
->rgid
);
664 asl_set(msg
, ASL_KEY_READ_GID
, tmp
);
667 /* Key - Value List */
668 for (i
= 0; i
< r
->kvcount
; i
++)
673 if ((r
->kvlist
[i
] != NULL
) && (r
->kvlist
[i
]->str
!= NULL
)) key
= r
->kvlist
[i
]->str
;
675 if ((r
->kvlist
[i
] != NULL
) && (r
->kvlist
[i
]->str
!= NULL
)) val
= r
->kvlist
[i
]->str
;
677 if (key
!= NULL
) asl_set(msg
, key
, val
);
681 return ASL_STATUS_OK
;
685 asl_mini_memory_fetch(asl_mini_memory_t
*s
, uint64_t mid
, aslmsg
*msg
, int32_t ruid
, int32_t rgid
)
689 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
690 if (msg
== NULL
) return ASL_STATUS_INVALID_ARG
;
692 for (i
= 0; i
< s
->record_count
; i
++)
694 if (s
->record
[i
]->mid
== 0) break;
696 if (s
->record
[i
]->mid
== mid
)
698 status
= asl_core_check_access(s
->record
[i
]->ruid
, s
->record
[i
]->rgid
, ruid
, rgid
, s
->record
[i
]->flags
);
699 if (status
!= ASL_STATUS_OK
) return status
;
700 return asl_mini_memory_message_decode(s
, s
->record
[i
], msg
);
704 return ASL_STATUS_INVALID_ID
;
707 static mini_mem_record_t
*
708 asl_mini_memory_query_to_record(asl_mini_memory_t
*s
, asl_msg_t
*q
, uint32_t *type
)
710 mini_mem_record_t
*out
;
712 mini_mem_string_t
*mkey
, *mval
;
713 const char *key
, *val
;
715 if (type
== NULL
) return NULL
;
719 *type
= ASL_QUERY_MATCH_ERROR
;
723 /* NULL query matches anything */
724 *type
= ASL_QUERY_MATCH_TRUE
;
725 if (q
== NULL
) return NULL
;
726 if (asl_msg_count((asl_msg_t
*)q
) == 0) return NULL
;
729 /* we can only do fast match on equality tests */
730 *type
= ASL_QUERY_MATCH_SLOW
;
732 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
))
734 if (op
!= ASL_QUERY_OP_EQUAL
) return NULL
;
737 out
= (mini_mem_record_t
*)calloc(1, sizeof(mini_mem_record_t
));
740 *type
= ASL_QUERY_MATCH_ERROR
;
744 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
))
746 if (key
== NULL
) continue;
748 else if (!strcmp(key
, ASL_KEY_MSG_ID
))
750 if (val
== NULL
) continue;
752 if (*type
& ASL_QUERY_MATCH_MSG_ID
)
754 asl_mini_memory_record_free(s
, out
);
755 *type
= ASL_QUERY_MATCH_SLOW
;
759 *type
|= ASL_QUERY_MATCH_MSG_ID
;
760 out
->mid
= atoll(val
);
762 else if (!strcmp(key
, ASL_KEY_TIME
))
764 if (val
== NULL
) continue;
766 if (*type
& ASL_QUERY_MATCH_TIME
)
768 asl_mini_memory_record_free(s
, out
);
769 *type
= ASL_QUERY_MATCH_SLOW
;
773 *type
|= ASL_QUERY_MATCH_TIME
;
774 out
->time
= asl_parse_time(val
);
776 else if (!strcmp(key
, ASL_KEY_TIME_NSEC
))
778 if (val
== NULL
) continue;
780 if (*type
& ASL_QUERY_MATCH_NANO
)
782 asl_mini_memory_record_free(s
, out
);
783 *type
= ASL_QUERY_MATCH_SLOW
;
787 *type
|= ASL_QUERY_MATCH_NANO
;
788 out
->nano
= atoll(val
);
790 else if (!strcmp(key
, ASL_KEY_LEVEL
))
792 if (val
== NULL
) continue;
794 if (*type
& ASL_QUERY_MATCH_LEVEL
)
796 asl_mini_memory_record_free(s
, out
);
797 *type
= ASL_QUERY_MATCH_SLOW
;
801 *type
|= ASL_QUERY_MATCH_LEVEL
;
802 out
->level
= atoi(val
);
804 else if (!strcmp(key
, ASL_KEY_PID
))
806 if (val
== NULL
) continue;
808 if (*type
& ASL_QUERY_MATCH_PID
)
810 asl_mini_memory_record_free(s
, out
);
811 *type
= ASL_QUERY_MATCH_SLOW
;
815 *type
|= ASL_QUERY_MATCH_PID
;
816 out
->pid
= atoi(val
);
818 else if (!strcmp(key
, ASL_KEY_READ_UID
))
820 if (val
== NULL
) continue;
822 if (*type
& ASL_QUERY_MATCH_RUID
)
824 asl_mini_memory_record_free(s
, out
);
825 *type
= ASL_QUERY_MATCH_SLOW
;
829 *type
|= ASL_QUERY_MATCH_RUID
;
830 out
->ruid
= atoi(val
);
832 else if (!strcmp(key
, ASL_KEY_READ_GID
))
834 if (val
== NULL
) continue;
836 if (*type
& ASL_QUERY_MATCH_RGID
)
838 asl_mini_memory_record_free(s
, out
);
839 *type
= ASL_QUERY_MATCH_SLOW
;
843 *type
|= ASL_QUERY_MATCH_RGID
;
844 out
->rgid
= atoi(val
);
846 else if (!strcmp(key
, ASL_KEY_SENDER
))
848 if (val
== NULL
) continue;
850 if (*type
& ASL_QUERY_MATCH_SENDER
)
852 asl_mini_memory_record_free(s
, out
);
853 *type
= ASL_QUERY_MATCH_SLOW
;
857 *type
|= ASL_QUERY_MATCH_SENDER
;
858 out
->sender
= asl_mini_memory_string_retain(s
, val
, 0);
859 if (out
->sender
== NULL
)
861 asl_mini_memory_record_free(s
, out
);
862 *type
= ASL_QUERY_MATCH_FALSE
;
866 else if (!strcmp(key
, ASL_KEY_SENDER_MACH_UUID
))
868 if (val
== NULL
) continue;
870 if (*type
& ASL_QUERY_MATCH_SMUUID
)
872 asl_mini_memory_record_free(s
, out
);
873 *type
= ASL_QUERY_MATCH_SLOW
;
877 *type
|= ASL_QUERY_MATCH_SMUUID
;
878 out
->sender_mach_uuid
= asl_mini_memory_string_retain(s
, val
, 0);
879 if (out
->sender_mach_uuid
== NULL
)
881 asl_mini_memory_record_free(s
, out
);
882 *type
= ASL_QUERY_MATCH_FALSE
;
886 else if (!strcmp(key
, ASL_KEY_FACILITY
))
888 if (val
== NULL
) continue;
890 if (*type
& ASL_QUERY_MATCH_FACILITY
)
892 asl_mini_memory_record_free(s
, out
);
893 *type
= ASL_QUERY_MATCH_SLOW
;
897 *type
|= ASL_QUERY_MATCH_FACILITY
;
898 out
->facility
= asl_mini_memory_string_retain(s
, val
, 0);
899 if (out
->facility
== NULL
)
901 asl_mini_memory_record_free(s
, out
);
902 *type
= ASL_QUERY_MATCH_FALSE
;
906 else if (!strcmp(key
, ASL_KEY_MSG
))
908 if (val
== NULL
) continue;
910 if (*type
& ASL_QUERY_MATCH_MESSAGE
)
912 asl_mini_memory_record_free(s
, out
);
913 *type
= ASL_QUERY_MATCH_SLOW
;
917 *type
|= ASL_QUERY_MATCH_MESSAGE
;
918 out
->message
= asl_mini_memory_string_retain(s
, val
, 0);
919 if (out
->message
== NULL
)
921 asl_mini_memory_record_free(s
, out
);
922 *type
= ASL_QUERY_MATCH_FALSE
;
928 mkey
= asl_mini_memory_string_retain(s
, key
, 0);
931 asl_mini_memory_record_free(s
, out
);
932 *type
= ASL_QUERY_MATCH_FALSE
;
936 for (i
= 0; i
< out
->kvcount
; i
+= 2)
938 if (out
->kvlist
[i
] == mkey
)
940 asl_mini_memory_record_free(s
, out
);
941 *type
= ASL_QUERY_MATCH_SLOW
;
946 mval
= asl_mini_memory_string_retain(s
, val
, 0);
948 if (out
->kvcount
== 0)
950 out
->kvlist
= (mini_mem_string_t
**)calloc(2, sizeof(mini_mem_string_t
*));
954 out
->kvlist
= (mini_mem_string_t
**)reallocf(out
->kvlist
, (out
->kvcount
+ 2) * sizeof(mini_mem_string_t
*));
957 if (out
->kvlist
== NULL
)
959 asl_mini_memory_record_free(s
, out
);
960 *type
= ASL_QUERY_MATCH_ERROR
;
964 out
->kvlist
[out
->kvcount
++] = mkey
;
965 out
->kvlist
[out
->kvcount
++] = mval
;
973 asl_mini_memory_fast_match(asl_mini_memory_t
*s
, mini_mem_record_t
*r
, uint32_t qtype
, mini_mem_record_t
*q
)
977 if (s
== NULL
) return 0;
978 if (r
== NULL
) return 0;
979 if (q
== NULL
) return 1;
981 if ((qtype
& ASL_QUERY_MATCH_MSG_ID
) && (q
->mid
!= r
->mid
)) return 0;
982 if ((qtype
& ASL_QUERY_MATCH_TIME
) && (q
->time
!= r
->time
)) return 0;
983 if ((qtype
& ASL_QUERY_MATCH_NANO
) && (q
->nano
!= r
->nano
)) return 0;
984 if ((qtype
& ASL_QUERY_MATCH_LEVEL
) && (q
->level
!= r
->level
)) return 0;
985 if ((qtype
& ASL_QUERY_MATCH_PID
) && (q
->pid
!= r
->pid
)) return 0;
986 if ((qtype
& ASL_QUERY_MATCH_RUID
) && (q
->ruid
!= r
->ruid
)) return 0;
987 if ((qtype
& ASL_QUERY_MATCH_RGID
) && (q
->rgid
!= r
->rgid
)) return 0;
988 if ((qtype
& ASL_QUERY_MATCH_SENDER
) && (q
->sender
!= r
->sender
)) return 0;
989 if ((qtype
& ASL_QUERY_MATCH_SMUUID
) && (q
->sender_mach_uuid
!= r
->sender_mach_uuid
)) return 0;
990 if ((qtype
& ASL_QUERY_MATCH_FACILITY
) && (q
->facility
!= r
->facility
)) return 0;
991 if ((qtype
& ASL_QUERY_MATCH_MESSAGE
) && (q
->message
!= r
->message
)) return 0;
993 for (i
= 0; i
< q
->kvcount
; i
+= 2)
995 for (j
= 0; j
< r
->kvcount
; j
+= 2)
997 if (q
->kvlist
[i
] == r
->kvlist
[j
])
999 if (q
->kvlist
[i
+ 1] == r
->kvlist
[j
+ 1]) break;
1004 if (j
>= r
->kvcount
) return 0;
1011 asl_mini_memory_slow_match(asl_mini_memory_t
*s
, mini_mem_record_t
*r
, mini_mem_record_t
*q
, aslmsg rawq
)
1017 status
= asl_mini_memory_message_decode(s
, r
, &rawm
);
1018 if (status
!= ASL_STATUS_OK
) return 0;
1021 if (asl_msg_cmp((asl_msg_t
*)rawq
, (asl_msg_t
*)rawm
) != 0) status
= 1;
1027 asl_mini_memory_match_restricted_uuid(asl_mini_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
, const char *uuid_str
)
1029 uint32_t status
, i
, where
, start
, j
, do_match
, did_match
, rescount
, *qtype
;
1030 mini_mem_record_t
**qp
;
1033 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
1034 if (res
== NULL
) return ASL_STATUS_INVALID_ARG
;
1040 if ((query
== NULL
) || ((query
!= NULL
) && (query
->count
== 0)))
1046 qp
= (mini_mem_record_t
**)calloc(query
->count
, sizeof(mini_mem_record_t
*));
1047 if (qp
== NULL
) return ASL_STATUS_NO_MEMORY
;
1049 qtype
= (uint32_t *)calloc(query
->count
, sizeof(uint32_t));
1053 return ASL_STATUS_NO_MEMORY
;
1057 for (i
= 0; i
< query
->count
; i
++)
1059 qp
[i
] = asl_mini_memory_query_to_record(s
, query
->msg
[i
], &(qtype
[i
]));
1060 if (qtype
[i
] == ASL_QUERY_MATCH_ERROR
)
1062 for (j
= 0; j
< i
; j
++) asl_mini_memory_record_free(s
, qp
[j
]);
1065 return ASL_STATUS_FAILED
;
1068 if (qtype
[i
] != ASL_QUERY_MATCH_TRUE
) do_match
= 1;
1072 for (i
= 0; i
< s
->record_count
; i
++)
1076 where
= (s
->record_first
+ i
) % s
->record_count
;
1077 if (s
->record
[where
]->mid
== 0) continue;
1078 if (s
->record
[where
]->mid
>= start_id
) break;
1082 where
= ((s
->record_count
- (i
+ 1)) + s
->record_first
) % s
->record_count
;
1083 if (s
->record
[where
]->mid
== 0) continue;
1084 if (s
->record
[where
]->mid
<= start_id
) break;
1088 if (i
>= s
->record_count
)
1092 for (i
= 0; i
< query
->count
; i
++) asl_mini_memory_record_free(s
, qp
[i
]);
1097 return ASL_STATUS_OK
;
1103 * loop through records
1105 for (i
= 0; i
< s
->record_count
; i
++)
1107 status
= ASL_STATUS_INVALID_ID
;
1108 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
);
1110 if ((status
== ASL_STATUS_OK
) && (uuid_str
!= NULL
))
1112 if (s
->record
[where
]->sender_mach_uuid
== NULL
) status
= ASL_STATUS_INVALID_ID
;
1113 else if (strcmp(s
->record
[where
]->sender_mach_uuid
->str
, uuid_str
) != 0) status
= ASL_STATUS_INVALID_ID
;
1116 if (status
!= ASL_STATUS_OK
)
1121 if (where
>= s
->record_count
) where
= 0;
1125 if (where
== 0) where
= s
->record_count
- 1;
1129 if (where
== s
->record_first
) break;
1133 s
->record
[where
]->flags
&= ASL_MINI_MSG_FLAG_SEARCH_CLEAR
;
1134 *last_id
= s
->record
[where
]->mid
;
1141 for (j
= 0; (j
< query
->count
) && (did_match
== 0); j
++)
1143 if (qtype
[j
] == ASL_QUERY_MATCH_TRUE
)
1147 else if (qtype
[j
] == ASL_QUERY_MATCH_FALSE
)
1151 else if (qtype
[j
] == ASL_QUERY_MATCH_SLOW
)
1153 did_match
= asl_mini_memory_slow_match(s
, s
->record
[where
], qp
[j
], (aslmsg
)query
->msg
[j
]);
1157 did_match
= asl_mini_memory_fast_match(s
, s
->record
[where
], qtype
[j
], qp
[j
]);
1164 s
->record
[where
]->flags
|= ASL_MINI_MSG_FLAG_SEARCH_MATCH
;
1166 if ((count
!= 0) && (rescount
>= count
)) break;
1172 if (where
>= s
->record_count
) where
= 0;
1176 if (where
== 0) where
= s
->record_count
- 1;
1180 if (where
== s
->record_first
) break;
1185 for (i
= 0; i
< query
->count
; i
++) asl_mini_memory_record_free(s
, qp
[i
]);
1191 if (rescount
== 0) return ASL_STATUS_OK
;
1193 *res
= (asl_msg_list_t
*)calloc(1, sizeof(asl_msg_list_t
));
1194 if (*res
== NULL
) return ASL_STATUS_NO_MEMORY
;
1196 (*res
)->count
= rescount
;
1198 (*res
)->msg
= (asl_msg_t
**)calloc(rescount
, sizeof(asl_msg_t
*));
1199 if ((*res
)->msg
== NULL
)
1203 return ASL_STATUS_NO_MEMORY
;
1209 if (s
->record
[where
]->flags
& ASL_MINI_MSG_FLAG_SEARCH_MATCH
)
1211 s
->record
[where
]->flags
&= ASL_MINI_MSG_FLAG_SEARCH_CLEAR
;
1213 status
= asl_mini_memory_message_decode(s
, s
->record
[where
], &m
);
1214 if (status
!= ASL_STATUS_OK
)
1216 aslresponse_free(*res
);
1221 (*res
)->msg
[(*res
)->curr
++] = (asl_msg_t
*)m
;
1222 if ((*res
)->curr
== rescount
) break;
1228 if (where
>= s
->record_count
) where
= 0;
1232 if (where
== 0) where
= s
->record_count
- 1;
1236 if (where
== s
->record_first
) break;
1240 return ASL_STATUS_OK
;
1244 asl_mini_memory_match(asl_mini_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
)
1246 return asl_mini_memory_match_restricted_uuid(s
, query
, res
, last_id
, start_id
, count
, direction
, ruid
, rgid
, NULL
);