2 * Copyright (c) 2007-2008 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * "Portions Copyright (c) 2007 Apple Inc. All Rights
7 * Reserved. This file contains Original Code and/or Modifications of
8 * Original Code as defined in and that are subject to the Apple Public
9 * Source License Version 1.0 (the 'License'). You may not use this file
10 * except in compliance with the License. Please obtain a copy of the
11 * License at http://www.apple.com/publicsource and read it before using
14 * The Original Code and all software distributed under the License are
15 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
16 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
17 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
19 * License for the specific language governing rights and limitations
22 * @APPLE_LICENSE_HEADER_END@
32 #include <sys/errno.h>
37 #include <asl_private.h>
38 #include <asl_legacy1.h>
40 extern time_t asl_parse_time(const char *str
);
41 extern int asl_msg_cmp(asl_msg_t
*a
, asl_msg_t
*b
);
43 #define forever for(;;)
44 #define MILLION 1000000
47 * MSG and STR records have (at least) a type (uint16_t) and a length (uint32_t)
48 * type and level are both 16 bit fields so that alignment isn't a pain.
50 #define RECORD_COMMON_LEN 6
51 #define RECORD_TYPE_LEN 2
52 #define RECORD_OFFSET_FLAGS 30
53 #define RECORD_OFFSET_RUID 44
54 #define RECORD_OFFSET_RGID 48
56 #define SCRATCH_BUFFER_SIZE (MSG_RECORD_FIXED_LENGTH + (20 * sizeof(uint64_t)))
84 asl_file_list_t
*list
;
86 } asl_file_match_token_t
;
98 _asl_put_16(uint16_t i
, char *h
)
116 _asl_put_32(uint32_t i
, char *h
)
130 return asl_core_ntohq(x
);
134 _asl_put_64(uint64_t i
, char *h
)
138 x
= asl_core_htonq(i
);
143 asl_file_read_uint32(asl_file_t
*s
, off_t off
, uint32_t *out
)
145 uint32_t status
, val
;
147 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
148 if (s
->store
== NULL
) return ASL_STATUS_INVALID_STORE
;
150 status
= fseeko(s
->store
, off
, SEEK_SET
);
151 if (status
!= 0) return ASL_STATUS_READ_FAILED
;
155 status
= fread(&val
, sizeof(uint32_t), 1, s
->store
);
156 if (status
!= 1) return ASL_STATUS_READ_FAILED
;
158 if (out
!= NULL
) *out
= ntohl(val
);
159 return ASL_STATUS_OK
;
163 asl_file_read_uint64(asl_file_t
*s
, off_t off
, uint64_t *out
)
168 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
169 if (s
->store
== NULL
) return ASL_STATUS_INVALID_STORE
;
171 status
= fseeko(s
->store
, off
, SEEK_SET
);
172 if (status
!= 0) return ASL_STATUS_READ_FAILED
;
176 status
= fread(&val
, sizeof(uint64_t), 1, s
->store
);
177 if (status
!= 1) return ASL_STATUS_READ_FAILED
;
179 if (out
!= NULL
) *out
= asl_core_ntohq(val
);
180 return ASL_STATUS_OK
;
184 asl_file_close(asl_file_t
*s
)
188 if (s
== NULL
) return ASL_STATUS_OK
;
192 return asl_legacy1_close((asl_legacy1_t
*)s
->legacy
);
195 while (s
->string_list
!= NULL
)
197 x
= s
->string_list
->next
;
198 free(s
->string_list
);
202 if (s
->store
!= NULL
) fclose(s
->store
);
204 memset(s
, 0, sizeof(asl_file_t
));
207 return ASL_STATUS_OK
;
211 asl_file_open_write(const char *path
, mode_t mode
, uid_t uid
, gid_t gid
, asl_file_t
**s
)
216 char buf
[DB_HEADER_LEN
];
218 uint32_t aslstatus
, vers
;
220 memset(&sb
, 0, sizeof(struct stat
));
222 status
= stat(path
, &sb
);
225 /* XXX Check that mode, uid, and gid are correct */
226 out
= (asl_file_t
*)calloc(1, sizeof(asl_file_t
));
227 if (out
== NULL
) return ASL_STATUS_NO_MEMORY
;
229 out
->store
= fopen(path
, "r+");
230 if (out
->store
== NULL
)
233 return ASL_STATUS_FAILED
;
236 out
->file_size
= sb
.st_size
;
238 i
= fread(buf
, DB_HEADER_LEN
, 1, out
->store
);
242 return ASL_STATUS_READ_FAILED
;
246 vers
= _asl_get_32(buf
+ DB_HEADER_VERS_OFFSET
);
247 if (vers
!= DB_VERSION
)
250 return ASL_STATUS_INVALID_STORE
;
253 out
->dob
= _asl_get_64(buf
+ DB_HEADER_TIME_OFFSET
);
254 out
->first
= _asl_get_64(buf
+ DB_HEADER_FIRST_OFFSET
);
255 out
->last
= _asl_get_64(buf
+ DB_HEADER_LAST_OFFSET
);
257 aslstatus
= asl_file_read_set_position(out
, ASL_FILE_POSITION_LAST
);
258 if (aslstatus
!= ASL_STATUS_OK
)
264 out
->prev
= out
->cursor
;
265 status
= fseeko(out
->store
, 0, SEEK_END
);
269 return ASL_STATUS_READ_FAILED
;
272 out
->file_size
= ftello(out
->store
);
274 /* scratch buffer for file writes (we test for NULL before using it) */
275 out
->scratch
= malloc(SCRATCH_BUFFER_SIZE
);
279 return ASL_STATUS_OK
;
282 if (errno
!= ENOENT
) return ASL_STATUS_FAILED
;
284 fd
= open(path
, O_RDWR
| O_CREAT
| O_EXCL
, mode
);
285 if (fd
< 0) return ASL_STATUS_FAILED
;
287 status
= fchown(fd
, uid
, gid
);
292 return ASL_STATUS_FAILED
;
295 out
= (asl_file_t
*)calloc(1, sizeof(asl_file_t
));
296 if (out
== NULL
) return ASL_STATUS_NO_MEMORY
;
298 out
->store
= fdopen(fd
, "w+");
299 if (out
->store
== NULL
)
302 return ASL_STATUS_FAILED
;
305 memset(buf
, 0, sizeof(buf
));
306 memcpy(buf
, ASL_DB_COOKIE
, ASL_DB_COOKIE_LEN
);
308 _asl_put_32(DB_VERSION
, buf
+ DB_HEADER_VERS_OFFSET
);
312 _asl_put_64(out
->dob
, buf
+ DB_HEADER_TIME_OFFSET
);
314 _asl_put_32(CACHE_SIZE
, buf
+ DB_HEADER_CSIZE_OFFSET
);
316 status
= fwrite(buf
, sizeof(buf
), 1, out
->store
);
322 return ASL_STATUS_FAILED
;
325 out
->file_size
= sizeof(buf
);
329 return ASL_STATUS_OK
;
333 asl_file_compact(asl_file_t
*s
, const char *path
, mode_t mode
, uid_t uid
, gid_t gid
)
341 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
342 if (path
== NULL
) return ASL_STATUS_INVALID_ARG
;
344 if (s
->version
== 1) return ASL_STATUS_FAILED
;
346 memset(&sb
, 0, sizeof(struct stat
));
348 if (stat(path
, &sb
) == 0) return ASL_STATUS_FAILED
;
349 if (errno
!= ENOENT
) return ASL_STATUS_FAILED
;
351 status
= asl_file_read_set_position(s
, ASL_FILE_POSITION_FIRST
);
352 if (status
!= ASL_STATUS_OK
) return status
;
355 status
= asl_file_open_write(path
, mode
, uid
, gid
, &new);
356 if (status
!= ASL_STATUS_OK
) return status
;
357 new->flags
= ASL_FILE_FLAG_UNLIMITED_CACHE
| ASL_FILE_FLAG_PRESERVE_MSG_ID
;
359 while ((status
== ASL_STATUS_OK
) && (s
->cursor
!= 0))
362 status
= asl_file_fetch_next(s
, &m
);
363 if (status
!= ASL_STATUS_OK
) break;
366 status
= asl_file_save(new, m
, &xid
);
375 asl_file_string_encode(asl_file_t
*s
, const char *str
, uint64_t *out
)
377 uint32_t i
, hash
, len
, x32
;
378 file_string_t
*sp
, *sx
, *sl
;
385 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
386 if (str
== NULL
) return ASL_STATUS_INVALID_ARG
;
400 memcpy(p
+ 1, str
, len
);
401 *out
= asl_core_ntohq(x64
);
402 return ASL_STATUS_OK
;
405 /* check the cache */
406 hash
= asl_core_string_hash(str
, len
);
409 for (sx
= s
->string_list
; sx
!= NULL
; sx
= sx
->next
)
411 if ((hash
== sx
->hash
) && (!strcmp(str
, sx
->str
)))
413 /* Move this string to the head of the list */
423 return ASL_STATUS_OK
;
429 off
= ftello(s
->store
);
432 type
= htons(ASL_FILE_TYPE_STR
);
433 i
= fwrite(&type
, sizeof(uint16_t), 1, s
->store
);
434 if (i
!= 1) return ASL_STATUS_WRITE_FAILED
;
435 s
->file_size
+= sizeof(uint16_t);
437 /* Length (includes trailing nul) */
438 x32
= htonl(len
+ 1);
439 i
= fwrite(&x32
, sizeof(uint32_t), 1, s
->store
);
440 if (i
!= 1) return ASL_STATUS_WRITE_FAILED
;
441 s
->file_size
+= sizeof(uint32_t);
443 /* String data (nul terminated) */
444 i
= fwrite(str
, len
+ 1, 1, s
->store
);
445 if (i
!= 1) return ASL_STATUS_WRITE_FAILED
;
448 /* create file_string_t and insert into the cache */
449 sx
= (file_string_t
*)calloc(1, offsetof(file_string_t
, str
) + len
+ 1);
450 if (sx
== NULL
) return ASL_STATUS_NO_MEMORY
;
454 sx
->next
= s
->string_list
;
455 memcpy(sx
->str
, str
, len
);
459 if (((s
->flags
& ASL_FILE_FLAG_UNLIMITED_CACHE
) == 0) && (s
->string_count
== CACHE_SIZE
))
461 /* drop last (lru) string from cache */
465 /* NB CACHE_SIZE must be > 1 */
466 while (sx
->next
!= NULL
)
481 return ASL_STATUS_OK
;
485 * Encode an aslmsg as a record structure.
486 * Creates and caches strings.
489 asl_file_save(asl_file_t
*s
, aslmsg msg
, uint64_t *mid
)
492 uint32_t len
, i
, status
;
498 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
499 if (msg
== NULL
) return ASL_STATUS_INVALID_MESSAGE
;
501 if (s
->flags
& ASL_FILE_FLAG_READ_ONLY
) return ASL_STATUS_READ_ONLY
;
503 memset(&r
, 0, sizeof(file_record_t
));
506 r
.level
= ASL_LEVEL_DEBUG
;
517 for (i
= 0; i
< msg
->count
; i
++)
519 if (msg
->key
[i
] == NULL
)
523 else if (!strcmp(msg
->key
[i
], ASL_KEY_TIME
))
525 if (msg
->val
[i
] != NULL
) r
.time
= asl_parse_time(msg
->val
[i
]);
527 else if (!strcmp(msg
->key
[i
], ASL_KEY_TIME_NSEC
))
529 if (msg
->val
[i
] != NULL
) r
.nano
= atoi(msg
->val
[i
]);
531 else if (!strcmp(msg
->key
[i
], ASL_KEY_HOST
))
533 if (msg
->val
[i
] != NULL
)
535 status
= asl_file_string_encode(s
, msg
->val
[i
], &(r
.host
));
536 if (status
!= ASL_STATUS_OK
)
538 if (kvlist
!= NULL
) free(kvlist
);
543 else if (!strcmp(msg
->key
[i
], ASL_KEY_SENDER
))
545 if (msg
->val
[i
] != NULL
)
547 status
= asl_file_string_encode(s
, msg
->val
[i
], &(r
.sender
));
548 if (status
!= ASL_STATUS_OK
)
550 if (kvlist
!= NULL
) free(kvlist
);
555 else if (!strcmp(msg
->key
[i
], ASL_KEY_PID
))
557 if (msg
->val
[i
] != NULL
) r
.pid
= atoi(msg
->val
[i
]);
559 else if (!strcmp(msg
->key
[i
], ASL_KEY_REF_PID
))
561 if (msg
->val
[i
] != NULL
) r
.refpid
= atoi(msg
->val
[i
]);
563 else if (!strcmp(msg
->key
[i
], ASL_KEY_UID
))
565 if (msg
->val
[i
] != NULL
) r
.uid
= atoi(msg
->val
[i
]);
567 else if (!strcmp(msg
->key
[i
], ASL_KEY_GID
))
569 if (msg
->val
[i
] != NULL
) r
.gid
= atoi(msg
->val
[i
]);
571 else if (!strcmp(msg
->key
[i
], ASL_KEY_LEVEL
))
573 if (msg
->val
[i
] != NULL
) r
.level
= atoi(msg
->val
[i
]);
575 else if (!strcmp(msg
->key
[i
], ASL_KEY_MSG
))
577 if (msg
->val
[i
] != NULL
)
579 status
= asl_file_string_encode(s
, msg
->val
[i
], &(r
.message
));
580 if (status
!= ASL_STATUS_OK
)
582 if (kvlist
!= NULL
) free(kvlist
);
587 else if (!strcmp(msg
->key
[i
], ASL_KEY_FACILITY
))
589 if (msg
->val
[i
] != NULL
)
591 status
= asl_file_string_encode(s
, msg
->val
[i
], &(r
.facility
));
592 if (status
!= ASL_STATUS_OK
)
594 if (kvlist
!= NULL
) free(kvlist
);
599 else if (!strcmp(msg
->key
[i
], ASL_KEY_REF_PROC
))
601 if (msg
->val
[i
] != NULL
)
603 status
= asl_file_string_encode(s
, msg
->val
[i
], &(r
.refproc
));
604 if (status
!= ASL_STATUS_OK
)
606 if (kvlist
!= NULL
) free(kvlist
);
611 else if (!strcmp(msg
->key
[i
], ASL_KEY_SESSION
))
613 if (msg
->val
[i
] != NULL
)
615 status
= asl_file_string_encode(s
, msg
->val
[i
], &(r
.session
));
616 if (status
!= ASL_STATUS_OK
)
618 if (kvlist
!= NULL
) free(kvlist
);
623 else if (!strcmp(msg
->key
[i
], ASL_KEY_READ_UID
))
625 if (((r
.flags
& ASL_MSG_FLAG_READ_UID_SET
) == 0) && (msg
->val
[i
] != NULL
))
627 r
.ruid
= atoi(msg
->val
[i
]);
628 r
.flags
|= ASL_MSG_FLAG_READ_UID_SET
;
631 else if (!strcmp(msg
->key
[i
], ASL_KEY_READ_GID
))
633 if (((r
.flags
& ASL_MSG_FLAG_READ_GID_SET
) == 0) && (msg
->val
[i
] != NULL
))
635 r
.rgid
= atoi(msg
->val
[i
]);
636 r
.flags
|= ASL_MSG_FLAG_READ_GID_SET
;
639 else if (!strcmp(msg
->key
[i
], ASL_KEY_MSG_ID
))
641 if (s
->flags
& ASL_FILE_FLAG_PRESERVE_MSG_ID
) *mid
= atoll(msg
->val
[i
]);
645 status
= asl_file_string_encode(s
, msg
->key
[i
], &k
);
646 if (status
!= ASL_STATUS_OK
)
648 if (kvlist
!= NULL
) free(kvlist
);
653 if (msg
->val
[i
] != NULL
)
655 status
= asl_file_string_encode(s
, msg
->val
[i
], &v
);
656 if (status
!= ASL_STATUS_OK
)
658 if (kvlist
!= NULL
) free(kvlist
);
665 kvlist
= (uint64_t *)calloc(2, sizeof(uint64_t));
669 kvlist
= (uint64_t *)reallocf(kvlist
, (r
.kvcount
+ 2) * sizeof(uint64_t));
674 return ASL_STATUS_NO_MEMORY
;
677 kvlist
[r
.kvcount
++] = k
;
678 kvlist
[r
.kvcount
++] = v
;
682 len
= MSG_RECORD_FIXED_LENGTH
+ (r
.kvcount
* sizeof(uint64_t));
685 /* use the scratch buffer if it exists and is large enough */
686 if ((s
->scratch
!= NULL
) && (len
<= SCRATCH_BUFFER_SIZE
))
688 memset(s
->scratch
, 0, SCRATCH_BUFFER_SIZE
);
693 buf
= calloc(1, len
);
696 if (buf
== NULL
) return ASL_STATUS_NO_MEMORY
;
704 r
.mid
= asl_core_new_msg_id(0);
711 _asl_put_16(ASL_FILE_TYPE_MSG
, p
);
712 p
+= sizeof(uint16_t);
714 /* Length of message (excludes type and length fields) */
715 _asl_put_32(len
- RECORD_COMMON_LEN
, p
);
716 p
+= sizeof(uint32_t);
718 /* Message data... */
720 _asl_put_64(r
.next
, p
);
721 p
+= sizeof(uint64_t);
723 _asl_put_64(r
.mid
, p
);
724 p
+= sizeof(uint64_t);
726 _asl_put_64(r
.time
, p
);
727 p
+= sizeof(uint64_t);
729 _asl_put_32(r
.nano
, p
);
730 p
+= sizeof(uint32_t);
732 _asl_put_16(r
.level
, p
);
733 p
+= sizeof(uint16_t);
735 _asl_put_16(r
.flags
, p
);
736 p
+= sizeof(uint16_t);
738 _asl_put_32(r
.pid
, p
);
739 p
+= sizeof(uint32_t);
741 _asl_put_32(r
.uid
, p
);
742 p
+= sizeof(uint32_t);
744 _asl_put_32(r
.gid
, p
);
745 p
+= sizeof(uint32_t);
747 _asl_put_32(r
.ruid
, p
);
748 p
+= sizeof(uint32_t);
750 _asl_put_32(r
.rgid
, p
);
751 p
+= sizeof(uint32_t);
753 _asl_put_32(r
.refpid
, p
);
754 p
+= sizeof(uint32_t);
756 _asl_put_32(r
.kvcount
, p
);
757 p
+= sizeof(uint32_t);
759 _asl_put_64(r
.host
, p
);
760 p
+= sizeof(uint64_t);
762 _asl_put_64(r
.sender
, p
);
763 p
+= sizeof(uint64_t);
765 _asl_put_64(r
.facility
, p
);
766 p
+= sizeof(uint64_t);
768 _asl_put_64(r
.message
, p
);
769 p
+= sizeof(uint64_t);
771 _asl_put_64(r
.refproc
, p
);
772 p
+= sizeof(uint64_t);
774 _asl_put_64(r
.session
, p
);
775 p
+= sizeof(uint64_t);
777 for (i
= 0; i
< r
.kvcount
; i
++)
779 _asl_put_64(kvlist
[i
], p
);
780 p
+= sizeof(uint64_t);
783 _asl_put_64(r
.prev
, p
);
784 p
+= sizeof(uint64_t);
789 if (status
!= 0) return ASL_STATUS_WRITE_FAILED
;
791 /* write record at end of file */
792 status
= fseeko(s
->store
, 0, SEEK_END
);
793 if (status
!= 0) return ASL_STATUS_WRITE_FAILED
;
795 s
->last
= (uint64_t)ftello(s
->store
);
796 v
= asl_core_htonq(s
->last
);
798 status
= fwrite(buf
, len
, 1, s
->store
);
801 /* free the buffer if it was allocated here */
802 if (buf
!= s
->scratch
) free(buf
);
804 /* seek to "next" field of previous record, write last offset */
805 off
= s
->prev
+ RECORD_COMMON_LEN
;
806 if (s
->prev
== 0) off
= DB_HEADER_FIRST_OFFSET
;
808 status
= fseeko(s
->store
, off
, SEEK_SET
);
809 if (status
!= 0) return ASL_STATUS_WRITE_FAILED
;
811 status
= fwrite(&v
, sizeof(uint64_t), 1, s
->store
);
812 if (status
!= 1) return ASL_STATUS_WRITE_FAILED
;
814 /* seek to DB_HEADER_LAST_OFFSET, write last record offset */
815 off
= DB_HEADER_LAST_OFFSET
;
817 status
= fseeko(s
->store
, off
, SEEK_SET
);
818 if (status
!= 0) return ASL_STATUS_WRITE_FAILED
;
820 status
= fwrite(&v
, sizeof(uint64_t), 1, s
->store
);
821 if (status
!= 1) return ASL_STATUS_WRITE_FAILED
;
823 /* return to the end of the store (this is expected by other routines) */
824 status
= fseeko(s
->store
, 0, SEEK_END
);
825 if (status
!= 0) return ASL_STATUS_WRITE_FAILED
;
829 return ASL_STATUS_OK
;
833 asl_file_fetch_object(asl_file_t
*s
, uint64_t where
, char **out
)
844 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
845 if (out
== NULL
) return ASL_STATUS_INVALID_ARG
;
846 if (where
== 0) return ASL_STATUS_INVALID_ARG
;
851 x64
= asl_core_htonq(where
);
852 memcpy(&inls
, &x64
, 1);
856 memset(ils
, 0, sizeof(ils
));
858 p
= 1 + (char *)&x64
;
859 memcpy(ils
, p
, inls
);
862 if (*out
== NULL
) return ASL_STATUS_NO_MEMORY
;
863 return ASL_STATUS_OK
;
867 status
= fseeko(s
->store
, off
, SEEK_SET
);
868 if (status
!= 0) return ASL_STATUS_READ_FAILED
;
871 status
= fread(&type
, sizeof(uint16_t), 1, s
->store
);
872 if (status
!= 1) return ASL_STATUS_READ_FAILED
;
876 status
= fread(&len
, sizeof(uint32_t), 1, s
->store
);
877 if (status
!= 1) return ASL_STATUS_READ_FAILED
;
880 *out
= calloc(1, len
);
881 if (*out
== NULL
) return ASL_STATUS_NO_MEMORY
;
883 status
= fread(*out
, len
, 1, s
->store
);
887 return ASL_STATUS_READ_FAILED
;
890 return ASL_STATUS_OK
;
894 asl_file_fetch_helper_16(asl_file_t
*s
, char **p
, aslmsg m
, const char *key
)
899 out
= _asl_get_16(*p
);
900 *p
+= sizeof(uint16_t);
902 if ((m
== NULL
) || (key
== NULL
)) return out
;
904 snprintf(str
, sizeof(str
), "%hu", out
);
905 asl_set(m
, key
, str
);
911 asl_file_fetch_helper_32(asl_file_t
*s
, char **p
, aslmsg m
, const char *key
, int ignore
, uint32_t ignoreval
)
916 out
= _asl_get_32(*p
);
917 *p
+= sizeof(uint32_t);
919 if ((m
== NULL
) || (key
== NULL
)) return out
;
922 if ((ignore
!= 0) && (out
== ignoreval
)) doit
= 0;
925 snprintf(str
, sizeof(str
), "%u", out
);
926 asl_set(m
, key
, str
);
933 asl_file_fetch_helper_64(asl_file_t
*s
, char **p
, aslmsg m
, const char *key
)
938 out
= _asl_get_64(*p
);
939 *p
+= sizeof(uint64_t);
941 if ((m
== NULL
) || (key
== NULL
)) return out
;
943 snprintf(str
, sizeof(str
), "%llu", out
);
944 asl_set(m
, key
, str
);
950 asl_file_fetch_helper_str(asl_file_t
*s
, char **p
, aslmsg m
, const char *key
)
956 out
= _asl_get_64(*p
);
957 *p
+= sizeof(uint64_t);
960 status
= asl_file_fetch_object(s
, out
, &val
);
961 if ((status
== ASL_STATUS_OK
) && (val
!= NULL
))
963 asl_set(m
, key
, val
);
971 asl_file_fetch_pos(asl_file_t
*s
, uint64_t where
, int dir
, aslmsg
*msg
)
973 char *buf
, *p
, *k
, *v
;
980 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
981 if (msg
== NULL
) return ASL_STATUS_INVALID_ARG
;
982 if ((s
->flags
& ASL_FILE_FLAG_READ_ONLY
) == 0) return ASL_STATUS_WRITE_ONLY
;
985 status
= asl_file_fetch_object(s
, where
, &buf
);
986 if (buf
== NULL
) return status
;
988 out
= asl_new(ASL_TYPE_MSG
);
989 if (out
== NULL
) return ASL_STATUS_NO_MEMORY
;
991 memset(&r
, 0, sizeof(file_record_t
));
994 r
.next
= asl_file_fetch_helper_64(s
, &p
, NULL
, NULL
);
995 r
.mid
= asl_file_fetch_helper_64(s
, &p
, out
, ASL_KEY_MSG_ID
);
996 r
.time
= asl_file_fetch_helper_64(s
, &p
, out
, ASL_KEY_TIME
);
997 r
.nano
= asl_file_fetch_helper_32(s
, &p
, out
, ASL_KEY_TIME_NSEC
, 0, 0);
998 r
.level
= asl_file_fetch_helper_16(s
, &p
, out
, ASL_KEY_LEVEL
);
999 r
.flags
= asl_file_fetch_helper_16(s
, &p
, NULL
, NULL
);
1000 r
.pid
= asl_file_fetch_helper_32(s
, &p
, out
, ASL_KEY_PID
, 0, 0);
1001 r
.uid
= asl_file_fetch_helper_32(s
, &p
, out
, ASL_KEY_UID
, 1, (uint32_t)-1);
1002 r
.gid
= asl_file_fetch_helper_32(s
, &p
, out
, ASL_KEY_GID
, 1, (uint32_t)-1);
1003 r
.ruid
= asl_file_fetch_helper_32(s
, &p
, out
, ASL_KEY_READ_UID
, 1, (uint32_t)-1);
1004 r
.rgid
= asl_file_fetch_helper_32(s
, &p
, out
, ASL_KEY_READ_GID
, 1, (uint32_t)-1);
1005 r
.refpid
= asl_file_fetch_helper_32(s
, &p
, out
, ASL_KEY_REF_PID
, 1, 0);
1006 r
.kvcount
= asl_file_fetch_helper_32(s
, &p
, NULL
, NULL
, 0, 0);
1007 r
.host
= asl_file_fetch_helper_str(s
, &p
, out
, ASL_KEY_HOST
);
1008 r
.sender
= asl_file_fetch_helper_str(s
, &p
, out
, ASL_KEY_SENDER
);
1009 r
.facility
= asl_file_fetch_helper_str(s
, &p
, out
, ASL_KEY_FACILITY
);
1010 r
.message
= asl_file_fetch_helper_str(s
, &p
, out
, ASL_KEY_MSG
);
1011 r
.refproc
= asl_file_fetch_helper_str(s
, &p
, out
, ASL_KEY_REF_PROC
);
1012 r
.session
= asl_file_fetch_helper_str(s
, &p
, out
, ASL_KEY_SESSION
);
1014 for (i
= 0; i
< r
.kvcount
/ 2; i
++)
1016 kv
= _asl_get_64(p
);
1017 p
+= sizeof(uint64_t);
1019 status
= asl_file_fetch_object(s
, kv
, &k
);
1021 kv
= _asl_get_64(p
);
1022 p
+= sizeof(uint64_t);
1024 status
= asl_file_fetch_object(s
, kv
, &v
);
1026 if ((status
== ASL_STATUS_OK
) && (k
!= NULL
))
1029 if (v
!= NULL
) free(v
);
1034 r
.prev
= asl_file_fetch_helper_64(s
, &p
, NULL
, NULL
);
1038 if (dir
>= 0) s
->cursor
= r
.next
;
1039 else s
->cursor
= r
.prev
;
1045 off
= s
->cursor
+ RECORD_COMMON_LEN
+ sizeof(uint64_t);
1046 status
= fseeko(s
->store
, off
, SEEK_SET
);
1047 if (status
!= 0) return ASL_STATUS_READ_FAILED
;
1049 status
= fread(&x64
, sizeof(uint64_t), 1, s
->store
);
1050 if (status
!= 1) return ASL_STATUS_READ_FAILED
;
1052 s
->cursor_xid
= asl_core_ntohq(x64
);
1056 return ASL_STATUS_OK
;
1060 asl_file_open_read(const char *path
, asl_file_t
**s
)
1065 uint32_t status
, vers
;
1066 char buf
[DB_HEADER_LEN
];
1068 asl_legacy1_t
*legacy
;
1070 f
= fopen(path
, "r");
1073 if (errno
== EACCES
) return ASL_STATUS_ACCESS_DENIED
;
1074 return ASL_STATUS_FAILED
;
1077 i
= fread(buf
, DB_HEADER_LEN
, 1, f
);
1081 return ASL_STATUS_INVALID_STORE
;
1084 /* validate header */
1085 if (strncmp(buf
, ASL_DB_COOKIE
, ASL_DB_COOKIE_LEN
))
1088 return ASL_STATUS_INVALID_STORE
;
1093 vers
= _asl_get_32(buf
+ DB_HEADER_VERS_OFFSET
);
1094 if (vers
== DB_VERSION_LEGACY_1
)
1097 status
= asl_legacy1_open(path
, &legacy
);
1098 if (status
!= ASL_STATUS_OK
) return status
;
1101 out
= (asl_file_t
*)calloc(1, sizeof(asl_file_t
));
1105 return ASL_STATUS_NO_MEMORY
;
1108 out
->flags
= ASL_FILE_FLAG_READ_ONLY
;
1109 out
->version
= vers
;
1113 out
->flags
|= ASL_FILE_FLAG_LEGACY_STORE
;
1114 out
->legacy
= (void *)legacy
;
1117 return ASL_STATUS_OK
;
1120 out
->first
= _asl_get_64(buf
+ DB_HEADER_FIRST_OFFSET
);
1121 out
->last
= _asl_get_64(buf
+ DB_HEADER_LAST_OFFSET
);
1125 out
->cursor
= out
->first
;
1126 if (out
->cursor
!= 0)
1128 off
= out
->cursor
+ RECORD_COMMON_LEN
+ sizeof(uint64_t);
1129 status
= asl_file_read_uint64(out
, off
, &(out
->cursor_xid
));
1130 if (status
!= ASL_STATUS_OK
)
1138 return ASL_STATUS_OK
;
1142 asl_file_read_set_position_first(asl_file_t
*s
)
1147 s
->cursor
= s
->first
;
1150 if (s
->cursor
== 0) return ASL_STATUS_OK
;
1152 /* read ID of the first record */
1153 off
= s
->cursor
+ RECORD_COMMON_LEN
+ sizeof(uint64_t);
1154 status
= asl_file_read_uint64(s
, off
, &(s
->cursor_xid
));
1159 asl_file_read_set_position_last(asl_file_t
*s
)
1166 * If the file has the offset of the last record, we just go there.
1167 * The last record offset was added to improve performance, so it may
1168 * or may not be there. If we don't have the last record offset, we
1169 * just iterate down the record links to find the last one.
1171 * Note that s->last may be zero if the file is empty.
1176 s
->cursor
= s
->last
;
1177 off
= s
->last
+ RECORD_COMMON_LEN
+ sizeof(uint64_t);
1179 /* read ID of the last record */
1180 status
= asl_file_read_uint64(s
, off
, &(s
->cursor_xid
));
1184 /* start at the first record and iterate */
1185 s
->cursor
= s
->first
;
1190 off
= s
->cursor
+ RECORD_COMMON_LEN
;
1193 /* read next offset */
1194 status
= asl_file_read_uint64(s
, off
, &next
);
1195 if (status
!= ASL_STATUS_OK
) return status
;
1199 if (s
->cursor
== 0) return ASL_STATUS_OK
;
1201 off
= s
->cursor
+ RECORD_COMMON_LEN
+ sizeof(uint64_t);
1202 status
= asl_file_read_uint64(s
, off
, &(s
->cursor_xid
));
1203 return ASL_STATUS_OK
;
1211 asl_file_read_set_position(asl_file_t
*s
, uint32_t pos
)
1213 uint32_t len
, status
;
1216 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
1217 if (s
->version
== 1) return ASL_STATUS_FAILED
;
1219 if (pos
== ASL_FILE_POSITION_FIRST
) return asl_file_read_set_position_first(s
);
1220 if (pos
== ASL_FILE_POSITION_LAST
) return asl_file_read_set_position_last(s
);
1224 if (pos
== ASL_FILE_POSITION_PREVIOUS
)
1226 if (s
->cursor
== s
->first
) return ASL_STATUS_NO_RECORDS
;
1227 if (s
->cursor
== 0) return ASL_STATUS_NO_RECORDS
;
1229 off
= s
->cursor
+ RECORD_TYPE_LEN
;
1230 status
= asl_file_read_uint32(s
, off
, &len
);
1231 if (status
!= ASL_STATUS_OK
) return status
;
1233 /* set offset to read the "previous" field at the end of the record */
1234 off
= s
->cursor
+ RECORD_COMMON_LEN
+ len
- sizeof(uint64_t);
1236 else if (pos
== ASL_FILE_POSITION_NEXT
)
1238 if (s
->cursor
== s
->last
) return ASL_STATUS_NO_RECORDS
;
1239 if (s
->cursor
== 0) return ASL_STATUS_NO_RECORDS
;
1241 off
= s
->cursor
+ RECORD_COMMON_LEN
;
1243 else return ASL_STATUS_INVALID_ARG
;
1248 * read offset of next / previous
1250 status
= asl_file_read_uint64(s
, off
, &(s
->cursor
));
1251 if (status
!= ASL_STATUS_OK
) return ASL_STATUS_READ_FAILED
;
1253 if (s
->cursor
== 0) return ASL_STATUS_NO_RECORDS
;
1255 /* read ID of the record */
1256 off
= s
->cursor
+ RECORD_COMMON_LEN
+ sizeof(uint64_t);
1257 status
= asl_file_read_uint64(s
, off
, &(s
->cursor_xid
));
1262 asl_file_fetch_next(asl_file_t
*s
, aslmsg
*msg
)
1264 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
1265 if (s
->version
== 1) return ASL_STATUS_FAILED
;
1267 return asl_file_fetch_pos(s
, s
->cursor
, 1, msg
);
1271 asl_file_fetch_previous(asl_file_t
*s
, aslmsg
*msg
)
1273 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
1274 if (s
->version
== 1) return ASL_STATUS_FAILED
;
1276 return asl_file_fetch_pos(s
, s
->cursor
, -1, msg
);
1280 asl_file_fetch(asl_file_t
*s
, uint64_t mid
, aslmsg
*msg
)
1284 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
1285 if (msg
== NULL
) return ASL_STATUS_INVALID_ARG
;
1286 if ((s
->flags
& ASL_FILE_FLAG_READ_ONLY
) == 0) return ASL_STATUS_WRITE_ONLY
;
1288 if (s
->version
== 1)
1290 return asl_legacy1_fetch((asl_legacy1_t
*)s
->legacy
, mid
, msg
);
1293 if (s
->cursor_xid
== 0)
1295 status
= asl_file_read_set_position(s
, ASL_FILE_POSITION_FIRST
);
1296 if (status
!= ASL_STATUS_OK
) return status
;
1297 if (s
->cursor_xid
== 0) return ASL_STATUS_INVALID_ID
;
1300 while (s
->cursor_xid
< mid
)
1302 status
= asl_file_read_set_position(s
, ASL_FILE_POSITION_NEXT
);
1303 if (status
!= ASL_STATUS_OK
) return status
;
1304 if (s
->cursor_xid
> mid
) return ASL_STATUS_INVALID_ID
;
1305 if (s
->cursor_xid
== 0) return ASL_STATUS_INVALID_ID
;
1308 while (s
->cursor_xid
> mid
)
1310 status
= asl_file_read_set_position(s
, ASL_FILE_POSITION_PREVIOUS
);
1311 if (status
!= ASL_STATUS_OK
) return status
;
1312 if (s
->cursor_xid
< mid
) return ASL_STATUS_INVALID_ID
;
1313 if (s
->cursor_xid
== 0) return ASL_STATUS_INVALID_ID
;
1316 if (s
->cursor_xid
!= mid
) return ASL_STATUS_INVALID_ID
;
1318 return asl_file_fetch_pos(s
, s
->cursor
, 1, msg
);
1322 asl_file_cursor(asl_file_t
*s
)
1324 if (s
== NULL
) return 0;
1325 if ((s
->flags
& ASL_FILE_FLAG_READ_ONLY
) == 0) return 0;
1326 if (s
->version
== 1) return 0;
1328 return s
->cursor_xid
;
1332 asl_file_match_start(asl_file_t
*s
, uint64_t start_id
, int32_t direction
)
1336 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
1337 if (s
->version
== 1) return ASL_STATUS_INVALID_STORE
;
1338 if ((s
->flags
& ASL_FILE_FLAG_READ_ONLY
) == 0) return ASL_STATUS_WRITE_ONLY
;
1340 d
= ASL_FILE_POSITION_NEXT
;
1341 if (direction
< 0) d
= ASL_FILE_POSITION_PREVIOUS
;
1344 * find starting point
1346 status
= ASL_STATUS_OK
;
1347 if (direction
>= 0) status
= asl_file_read_set_position(s
, ASL_FILE_POSITION_FIRST
);
1348 else status
= asl_file_read_set_position(s
, ASL_FILE_POSITION_LAST
);
1349 if (status
!= ASL_STATUS_OK
) return status
;
1351 while ((status
== ASL_STATUS_OK
) && (((direction
>= 0) && (s
->cursor_xid
< start_id
)) || ((direction
< 0) && (s
->cursor_xid
> start_id
))))
1353 status
= asl_file_read_set_position(s
, d
);
1360 asl_file_match_next(asl_file_t
*s
, aslresponse query
, asl_msg_t
**msg
, uint64_t *last_id
, int32_t direction
)
1362 uint32_t status
, d
, i
, do_match
, did_match
;
1365 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
1366 if (msg
== NULL
) return ASL_STATUS_INVALID_ARG
;
1367 if (s
->version
== 1) return ASL_STATUS_INVALID_STORE
;
1368 if ((s
->flags
& ASL_FILE_FLAG_READ_ONLY
) == 0) return ASL_STATUS_WRITE_ONLY
;
1369 if (s
->cursor
== 0) return ASL_STATUS_NO_RECORDS
;
1374 d
= ASL_FILE_POSITION_NEXT
;
1375 if (direction
< 0) d
= ASL_FILE_POSITION_PREVIOUS
;
1377 if ((query
== NULL
) || ((query
!= NULL
) && (query
->count
== 0))) do_match
= 0;
1381 *last_id
= s
->cursor_xid
;
1383 status
= asl_file_fetch_pos(s
, s
->cursor
, direction
, &m
);
1384 if (status
== ASL_STATUS_ACCESS_DENIED
) return ASL_STATUS_MATCH_FAILED
;
1385 if ((status
== ASL_STATUS_INVALID_ARG
) && (s
->cursor
== 0)) return ASL_STATUS_NO_RECORDS
;
1386 if (status
!= ASL_STATUS_OK
) return status
;
1394 for (i
= 0; (i
< query
->count
) && (did_match
== 0); i
++)
1396 did_match
= asl_msg_cmp(query
->msg
[i
], m
);
1403 return ASL_STATUS_OK
;
1407 return ASL_STATUS_MATCH_FAILED
;
1411 asl_file_match(asl_file_t
*s
, aslresponse query
, aslresponse
*res
, uint64_t *last_id
, uint64_t start_id
, uint32_t count
, int32_t direction
)
1413 uint32_t status
, d
, i
, do_match
, did_match
, rescount
;
1416 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
1417 if (res
== NULL
) return ASL_STATUS_INVALID_ARG
;
1418 if ((s
->flags
& ASL_FILE_FLAG_READ_ONLY
) == 0) return ASL_STATUS_WRITE_ONLY
;
1420 if (s
->version
== 1)
1422 return asl_legacy1_match((asl_legacy1_t
*)s
->legacy
, query
, res
, last_id
, start_id
, count
, direction
);
1428 d
= ASL_FILE_POSITION_NEXT
;
1429 if (direction
< 0) d
= ASL_FILE_POSITION_PREVIOUS
;
1431 if ((query
== NULL
) || ((query
!= NULL
) && (query
->count
== 0))) do_match
= 0;
1434 * find starting point
1436 status
= ASL_STATUS_OK
;
1437 if (direction
>= 0) status
= asl_file_read_set_position(s
, ASL_FILE_POSITION_FIRST
);
1438 else status
= asl_file_read_set_position(s
, ASL_FILE_POSITION_LAST
);
1439 if (status
!= ASL_STATUS_OK
) return status
;
1441 while ((status
== ASL_STATUS_OK
) && (((direction
>= 0) && (s
->cursor_xid
< start_id
)) || ((direction
< 0) && (s
->cursor_xid
> start_id
))))
1443 status
= asl_file_read_set_position(s
, d
);
1447 * loop through records
1452 status
= asl_file_fetch_pos(s
, s
->cursor
, direction
, &m
);
1453 if (status
== ASL_STATUS_ACCESS_DENIED
) continue;
1454 if (status
!= ASL_STATUS_OK
) break;
1456 *last_id
= s
->cursor_xid
;
1464 for (i
= 0; (i
< query
->count
) && (did_match
== 0); i
++)
1466 did_match
= asl_msg_cmp(query
->msg
[i
], m
);
1472 /* append m to res */
1475 *res
= (aslresponse
)calloc(1, sizeof(aslresponse
));
1476 if (*res
== NULL
) return ASL_STATUS_NO_MEMORY
;
1477 (*res
)->msg
= (asl_msg_t
**)calloc(1, sizeof(asl_msg_t
*));
1478 if ((*res
)->msg
== NULL
)
1481 return ASL_STATUS_NO_MEMORY
;
1486 (*res
)->msg
= (asl_msg_t
**)realloc((*res
)->msg
, ((*res
)->count
+ 1) * sizeof(asl_msg_t
*));
1487 if ((*res
)->msg
== NULL
)
1490 return ASL_STATUS_NO_MEMORY
;
1494 (*res
)->msg
[(*res
)->count
] = m
;
1498 if ((count
!= 0) && (rescount
>= count
)) break;
1507 return ASL_STATUS_OK
;
1511 asl_file_size(asl_file_t
*s
)
1513 if (s
== NULL
) return 0;
1514 return s
->file_size
;
1518 asl_file_ctime(asl_file_t
*s
)
1520 if (s
== NULL
) return 0;
1525 asl_file_list_close(asl_file_list_t
*head
)
1527 asl_file_list_t
*next
;
1529 while (head
!= NULL
)
1532 asl_file_close(head
->file
);
1539 asl_file_list_free(asl_file_list_t
*head
)
1541 asl_file_list_t
*next
;
1543 while (head
!= NULL
)
1552 asl_file_list_insert(asl_file_list_t
*list
, asl_file_t
*f
, int32_t dir
)
1554 asl_file_list_t
*a
, *b
, *tmp
;
1556 if (f
== NULL
) return list
;
1558 tmp
= (asl_file_list_t
*)calloc(1, sizeof(asl_file_list_t
));
1559 if (tmp
== NULL
) return NULL
;
1562 if (list
== NULL
) return tmp
;
1565 if (((dir
< 0) && (f
->cursor_xid
> a
->file
->cursor_xid
)) || ((dir
>= 0) && (f
->cursor_xid
< a
->file
->cursor_xid
)))
1574 if (((dir
< 0) && (f
->cursor_xid
> b
->file
->cursor_xid
)) || ((dir
>= 0) && (f
->cursor_xid
< b
->file
->cursor_xid
)))
1590 asl_file_list_add(asl_file_list_t
*list
, asl_file_t
*f
)
1592 asl_file_list_t
*tmp
;
1594 if (f
== NULL
) return list
;
1595 if (f
->version
== 1) return list
;
1597 tmp
= (asl_file_list_t
*)calloc(1, sizeof(asl_file_list_t
));
1598 if (tmp
== NULL
) return NULL
;
1606 asl_file_list_match_start(asl_file_list_t
*list
, uint64_t start_id
, int32_t direction
)
1610 asl_file_match_token_t
*out
;
1612 if (list
== NULL
) return NULL
;
1614 out
= (asl_file_match_token_t
*)calloc(1, sizeof(asl_file_match_token_t
));
1615 if (out
== NULL
) return NULL
;
1617 for (n
= list
; n
!= NULL
; n
= n
->next
)
1619 /* init file for the search */
1620 status
= asl_file_match_start(n
->file
, start_id
, direction
);
1621 if (status
!= ASL_STATUS_OK
) continue;
1622 if (n
->file
->cursor_xid
== 0) continue;
1624 out
->list
= asl_file_list_insert(out
->list
, n
->file
, direction
);
1627 out
->dir
= direction
;
1632 asl_file_list_match_next(void *token
, aslresponse query
, aslresponse
*res
, uint32_t count
)
1634 uint32_t status
, rescount
;
1637 asl_file_match_token_t
*work
;
1640 if (token
== NULL
) return ASL_STATUS_OK
;
1641 if (res
== NULL
) return ASL_STATUS_INVALID_ARG
;
1643 work
= (asl_file_match_token_t
*)token
;
1648 while ((work
->list
!= NULL
) && ((rescount
< count
) || (count
== 0)))
1651 status
= asl_file_match_next(work
->list
->file
, query
, &m
, &last_id
, work
->dir
);
1654 if (*res
== NULL
) *res
= (aslresponse
)calloc(1, sizeof(asl_search_result_t
));
1657 asl_file_list_free(work
->list
);
1659 return ASL_STATUS_NO_MEMORY
;
1662 if ((*res
)->msg
== NULL
) (*res
)->msg
= (asl_msg_t
**)calloc(1, sizeof(asl_msg_t
*));
1663 else (*res
)->msg
= (asl_msg_t
**)reallocf((*res
)->msg
, ((*res
)->count
+ 1) * sizeof(asl_msg_t
*));
1664 if ((*res
)->msg
== NULL
)
1668 asl_file_list_free(work
->list
);
1670 return ASL_STATUS_NO_MEMORY
;
1673 (*res
)->msg
[(*res
)->count
] = m
;
1678 if (work
->list
->file
->cursor_xid
== 0)
1680 n
= work
->list
->next
;
1685 if (work
->list
!= NULL
)
1687 n
= work
->list
->next
;
1690 if (((work
->dir
< 0) && (work
->list
->file
->cursor_xid
<= n
->file
->cursor_xid
)) || ((work
->dir
>= 0) && (work
->list
->file
->cursor_xid
> n
->file
->cursor_xid
)))
1693 work
->list
= work
->list
->next
;
1695 work
->list
= asl_file_list_insert(work
->list
, n
->file
, work
->dir
);
1702 return ASL_STATUS_OK
;
1706 asl_file_list_match_end(void *token
)
1708 asl_file_match_token_t
*work
;
1710 if (token
== NULL
) return;
1712 work
= (asl_file_match_token_t
*)token
;
1713 asl_file_list_free(work
->list
);
1720 asl_file_list_match_timeout(asl_file_list_t
*list
, aslresponse query
, aslresponse
*res
, uint64_t *last_id
, uint64_t start_id
, uint32_t count
, int32_t direction
, uint32_t usec
)
1722 uint32_t status
, rescount
;
1723 asl_file_list_t
*files
, *n
;
1725 struct timeval now
, finish
;
1727 if (list
== NULL
) return ASL_STATUS_INVALID_ARG
;
1728 if (res
== NULL
) return ASL_STATUS_INVALID_ARG
;
1729 if (last_id
== NULL
) return ASL_STATUS_INVALID_ARG
;
1733 for (n
= list
; n
!= NULL
; n
= n
->next
)
1735 /* init file for the search */
1736 status
= asl_file_match_start(n
->file
, start_id
, direction
);
1737 if (status
!= ASL_STATUS_OK
) continue;
1738 if (n
->file
->cursor_xid
== 0) continue;
1740 files
= asl_file_list_insert(files
, n
->file
, direction
);
1745 asl_file_list_free(files
);
1746 return ASL_STATUS_OK
;
1749 /* start the timer if a timeout was specified */
1750 memset(&finish
, 0, sizeof(struct timeval
));
1753 if (gettimeofday(&finish
, NULL
) == 0)
1755 finish
.tv_sec
+= (usec
/ MILLION
);
1756 finish
.tv_usec
+= (usec
% MILLION
);
1757 if (finish
.tv_usec
> MILLION
)
1759 finish
.tv_usec
-= MILLION
;
1765 /* shouldn't happen, but if gettimeofday failed we just run without a timeout */
1766 memset(&finish
, 0, sizeof(struct timeval
));
1771 while ((files
!= NULL
) && ((rescount
< count
) || (count
== 0)))
1774 status
= asl_file_match_next(files
->file
, query
, &m
, last_id
, direction
);
1777 if (*res
== NULL
) *res
= (aslresponse
)calloc(1, sizeof(asl_search_result_t
));
1780 asl_file_list_free(files
);
1781 return ASL_STATUS_NO_MEMORY
;
1784 if ((*res
)->msg
== NULL
) (*res
)->msg
= (asl_msg_t
**)calloc(1, sizeof(asl_msg_t
*));
1785 else (*res
)->msg
= (asl_msg_t
**)reallocf((*res
)->msg
, ((*res
)->count
+ 1) * sizeof(asl_msg_t
*));
1786 if ((*res
)->msg
== NULL
)
1790 asl_file_list_free(files
);
1791 return ASL_STATUS_NO_MEMORY
;
1794 (*res
)->msg
[(*res
)->count
] = m
;
1799 if (files
->file
->cursor_xid
== 0)
1811 if (((direction
< 0) && (files
->file
->cursor_xid
<= n
->file
->cursor_xid
)) || ((direction
>= 0) && (files
->file
->cursor_xid
> n
->file
->cursor_xid
)))
1814 files
= files
->next
;
1816 files
= asl_file_list_insert(files
, n
->file
, direction
);
1822 /* check the timer */
1823 if ((finish
.tv_sec
!= 0) && (gettimeofday(&now
, NULL
) == 0))
1825 if ((now
.tv_sec
> finish
.tv_sec
) || ((now
.tv_sec
== finish
.tv_sec
) && (now
.tv_usec
> finish
.tv_usec
))) break;
1829 asl_file_list_free(files
);
1830 return ASL_STATUS_OK
;
1834 asl_file_list_match(asl_file_list_t
*list
, aslresponse query
, aslresponse
*res
, uint64_t *last_id
, uint64_t start_id
, uint32_t count
, int32_t direction
)
1836 return asl_file_list_match_timeout(list
, query
, res
, last_id
, start_id
, count
, direction
, 0);