]>
git.saurik.com Git - apple/syslog.git/blob - libsystem_asl.tproj/src/asl_store.c
0640d8ffe905e2759f1d41beecada62965e95423
2 * Copyright (c) 2007-2011 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@
29 #include <sys/types.h>
33 #include <asl_private.h>
35 #include <asl_store.h>
38 #include <TargetConditionals.h>
40 #if TARGET_IPHONE_SIMULATOR
41 #include <dispatch/dispatch.h>
45 extern time_t asl_parse_time(const char *str
);
46 extern uint64_t asl_file_cursor(asl_file_t
*s
);
47 extern uint32_t asl_file_match_start(asl_file_t
*s
, uint64_t start_id
, int32_t direction
);
48 extern uint32_t asl_file_match_next(asl_file_t
*s
, aslresponse query
, asl_msg_t
**msg
, uint64_t *last_id
, int32_t direction
, int32_t ruid
, int32_t rgid
);
49 extern int asl_file_create(const char *path
, uid_t uid
, gid_t gid
, mode_t mode
);
51 #define SECONDS_PER_DAY 86400
54 * The ASL Store is organized as a set of files in a common directory.
55 * Files are prefixed by the date (YYYY.MM.DD) of their contents.
57 * Messages with no access controls are saved in YYYY.MM.DD.asl
58 * Messages with access limited to UID uuu are saved in YYYY.MM.DD.Uuuu.asl
59 * Messages with access limited to GID ggg are saved in YYYY.MM.DD.Gggg.asl
60 * Messages with access limited to UID uuu and GID ggg are saved in YYYY.MM.DD.Uuuu.Gggg.asl
62 * Messages that have a value for ASLExpireTime are saved in BB.YYYY.MM.DD.asl
63 * where the timestamp is the "Best Before" date of the file. Access controls
64 * are implemented as above with Uuuu and Gggg in the file name. Note that the
65 * Best Before files are for the last day of the month, so a single file contains
66 * messages that expire in that month.
68 * An external tool runs daily and deletes "old" files.
77 memset(&ctm
, 0, sizeof(struct tm
));
80 if (localtime_r((const time_t *)&now
, &ctm
) == NULL
) return 0;
90 * The base directory contains a data file which stores
93 * | MAX_ID (uint64_t) |
97 asl_store_open_write(const char *basedir
, asl_store_t
**s
)
107 if (s
== NULL
) return ASL_STATUS_INVALID_ARG
;
109 start
= _asl_start_today();
110 if (start
== 0) return ASL_STATUS_FAILED
;
112 if (basedir
== NULL
) basedir
= PATH_ASL_STORE
;
114 memset(&sb
, 0, sizeof(struct stat
));
115 if (stat(basedir
, &sb
) != 0) return ASL_STATUS_INVALID_STORE
;
116 if (!S_ISDIR(sb
.st_mode
)) return ASL_STATUS_INVALID_STORE
;
119 asprintf(&path
, "%s/%s", basedir
, FILE_ASL_STORE_DATA
);
120 if (path
== NULL
) return ASL_STATUS_NO_MEMORY
;
124 memset(&sb
, 0, sizeof(struct stat
));
125 if (stat(path
, &sb
) != 0)
130 return ASL_STATUS_FAILED
;
133 sd
= fopen(path
, "w+");
136 if (sd
== NULL
) return ASL_STATUS_FAILED
;
140 /* Create new StoreData file (8 bytes ID + 4 bytes flags) */
142 if (fwrite(&last_id
, sizeof(uint64_t), 1, sd
) != 1)
145 return ASL_STATUS_WRITE_FAILED
;
149 if (fwrite(&flags
, sizeof(uint32_t), 1, sd
) != 1)
152 return ASL_STATUS_WRITE_FAILED
;
160 sd
= fopen(path
, "r+");
163 if (sd
== NULL
) return ASL_STATUS_FAILED
;
164 if (fread(&last_id
, sizeof(uint64_t), 1, sd
) != 1)
167 return ASL_STATUS_READ_FAILED
;
170 last_id
= asl_core_ntohq(last_id
);
173 out
= (asl_store_t
*)calloc(1, sizeof(asl_store_t
));
177 return ASL_STATUS_NO_MEMORY
;
180 if (basedir
== NULL
) out
->base_dir
= strdup(PATH_ASL_STORE
);
181 else out
->base_dir
= strdup(basedir
);
183 if (out
->base_dir
== NULL
)
187 return ASL_STATUS_NO_MEMORY
;
190 out
->start_today
= start
;
191 out
->start_tomorrow
= out
->start_today
+ SECONDS_PER_DAY
;
193 out
->next_id
= last_id
+ 1;
195 for (i
= 0; i
< FILE_CACHE_SIZE
; i
++)
197 memset(&out
->file_cache
[i
], 0, sizeof(asl_cached_file_t
));
198 out
->file_cache
[i
].u
= -1;
199 out
->file_cache
[i
].g
= -1;
203 return ASL_STATUS_OK
;
207 asl_store_statistics(asl_store_t
*s
, aslmsg
*msg
)
211 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
212 if (msg
== NULL
) return ASL_STATUS_INVALID_ARG
;
214 out
= asl_new(ASL_TYPE_MSG
);
215 if (out
== NULL
) return ASL_STATUS_NO_MEMORY
;
217 /* does nothing for now */
220 return ASL_STATUS_OK
;
224 asl_store_open_read(const char *basedir
, asl_store_t
**s
)
229 if (s
== NULL
) return ASL_STATUS_INVALID_ARG
;
231 if (basedir
== NULL
) basedir
= PATH_ASL_STORE
;
233 memset(&sb
, 0, sizeof(struct stat
));
234 if (stat(basedir
, &sb
) != 0) return ASL_STATUS_INVALID_STORE
;
235 if (!S_ISDIR(sb
.st_mode
)) return ASL_STATUS_INVALID_STORE
;
237 out
= (asl_store_t
*)calloc(1, sizeof(asl_store_t
));
238 if (out
== NULL
) return ASL_STATUS_NO_MEMORY
;
240 if (basedir
== NULL
) out
->base_dir
= strdup(PATH_ASL_STORE
);
241 else out
->base_dir
= strdup(basedir
);
243 if (out
->base_dir
== NULL
)
246 return ASL_STATUS_NO_MEMORY
;
250 return ASL_STATUS_OK
;
254 asl_store_max_file_size(asl_store_t
*s
, size_t max
)
256 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
258 s
->max_file_size
= max
;
259 return ASL_STATUS_OK
;
262 __private_extern__
void
263 asl_store_file_closeall(asl_store_t
*s
)
267 if (s
== NULL
) return;
269 for (i
= 0; i
< FILE_CACHE_SIZE
; i
++)
271 if (s
->file_cache
[i
].f
!= NULL
) asl_file_close(s
->file_cache
[i
].f
);
272 s
->file_cache
[i
].f
= NULL
;
273 if (s
->file_cache
[i
].path
!= NULL
) free(s
->file_cache
[i
].path
);
274 s
->file_cache
[i
].path
= NULL
;
275 s
->file_cache
[i
].u
= -1;
276 s
->file_cache
[i
].g
= -1;
277 s
->file_cache
[i
].bb
= 0;
278 s
->file_cache
[i
].ts
= 0;
283 asl_store_close(asl_store_t
*s
)
285 if (s
== NULL
) return ASL_STATUS_OK
;
287 if (s
->base_dir
!= NULL
) free(s
->base_dir
);
289 asl_store_file_closeall(s
);
290 if (s
->storedata
!= NULL
) fclose(s
->storedata
);
294 return ASL_STATUS_OK
;
298 * Sweep the file cache.
299 * Close any files that have not been used in the last FILE_CACHE_TTL seconds.
300 * Returns least recently used or unused cache slot.
303 asl_store_file_cache_lru(asl_store_t
*s
, time_t now
, uint32_t ignorex
)
308 if (s
== NULL
) return 0;
311 min
= now
- FILE_CACHE_TTL
;
313 for (i
= 0; i
< FILE_CACHE_SIZE
; i
++)
315 if ((i
!= ignorex
) && (s
->file_cache
[i
].ts
< min
))
317 asl_file_close(s
->file_cache
[i
].f
);
318 s
->file_cache
[i
].f
= NULL
;
319 if (s
->file_cache
[i
].path
!= NULL
) free(s
->file_cache
[i
].path
);
320 s
->file_cache
[i
].path
= NULL
;
321 s
->file_cache
[i
].u
= -1;
322 s
->file_cache
[i
].g
= -1;
323 s
->file_cache
[i
].bb
= 0;
324 s
->file_cache
[i
].ts
= 0;
327 if (s
->file_cache
[i
].ts
< s
->file_cache
[x
].ts
) x
= i
;
334 asl_store_sweep_file_cache(asl_store_t
*s
)
336 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
338 asl_store_file_cache_lru(s
, time(NULL
), FILE_CACHE_SIZE
);
339 return ASL_STATUS_OK
;
343 asl_store_make_ug_path(const char *dir
, const char *base
, const char *ext
, uid_t ruid
, gid_t rgid
, uid_t
*u
, gid_t
*g
, mode_t
*m
)
355 if (ext
== NULL
) asprintf(&path
, "%s/%s", dir
, base
);
356 else asprintf(&path
, "%s/%s.%s", dir
, base
, ext
);
362 if (ext
== NULL
) asprintf(&path
, "%s/%s.G%d", dir
, base
, *g
);
363 else asprintf(&path
, "%s/%s.G%d.%s", dir
, base
, *g
, ext
);
372 if (ext
== NULL
) asprintf(&path
, "%s/%s.U%d", dir
, base
, *u
);
373 else asprintf(&path
, "%s/%s.U%d.%s", dir
, base
, *u
, ext
);
379 if (ext
== NULL
) asprintf(&path
, "%s/%s.U%d.G%d", dir
, base
, *u
, *g
);
380 else asprintf(&path
, "%s/%s.U%d.G%u.%s", dir
, base
, *u
, *g
, ext
);
388 asl_store_file_open_write(asl_store_t
*s
, char *tstring
, int32_t ruid
, int32_t rgid
, time_t bb
, asl_file_t
**f
, time_t now
, uint32_t check_cache
)
398 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
400 /* see if the file is already open and in the cache */
401 for (i
= 0; i
< FILE_CACHE_SIZE
; i
++)
403 if ((s
->file_cache
[i
].u
== ruid
) && (s
->file_cache
[i
].g
== rgid
) && (s
->file_cache
[i
].bb
== bb
) && (s
->file_cache
[i
].f
!= NULL
))
405 s
->file_cache
[i
].ts
= now
;
406 *f
= s
->file_cache
[i
].f
;
407 if (check_cache
== 1) asl_store_file_cache_lru(s
, now
, i
);
408 return ASL_STATUS_OK
;
415 path
= asl_store_make_ug_path(s
->base_dir
, tstring
, "asl", (uid_t
)ruid
, (gid_t
)rgid
, &u
, &g
, &m
);
416 if (path
== NULL
) return ASL_STATUS_NO_MEMORY
;
419 status
= asl_file_open_write(path
, m
, u
, g
, &out
);
420 if (status
!= ASL_STATUS_OK
)
426 x
= asl_store_file_cache_lru(s
, now
, FILE_CACHE_SIZE
);
427 if (s
->file_cache
[x
].f
!= NULL
) asl_file_close(s
->file_cache
[x
].f
);
428 if (s
->file_cache
[x
].path
!= NULL
) free(s
->file_cache
[x
].path
);
430 s
->file_cache
[x
].f
= out
;
431 s
->file_cache
[x
].path
= path
;
432 s
->file_cache
[x
].u
= ruid
;
433 s
->file_cache
[x
].g
= rgid
;
434 s
->file_cache
[x
].bb
= bb
;
435 s
->file_cache
[x
].ts
= time(NULL
);
439 return ASL_STATUS_OK
;
442 __private_extern__
char *
443 asl_store_file_path(asl_store_t
*s
, asl_file_t
*f
)
447 if (s
== NULL
) return NULL
;
449 for (i
= 0; i
< FILE_CACHE_SIZE
; i
++)
451 if (s
->file_cache
[i
].f
== f
)
453 if (s
->file_cache
[i
].path
== NULL
) return NULL
;
454 return strdup(s
->file_cache
[i
].path
);
461 __private_extern__
void
462 asl_store_file_close(asl_store_t
*s
, asl_file_t
*f
)
466 if (s
== NULL
) return;
467 if (f
== NULL
) return;
469 for (i
= 0; i
< FILE_CACHE_SIZE
; i
++)
471 if (s
->file_cache
[i
].f
== f
)
473 asl_file_close(s
->file_cache
[i
].f
);
474 s
->file_cache
[i
].f
= NULL
;
475 if (s
->file_cache
[i
].path
!= NULL
) free(s
->file_cache
[i
].path
);
476 s
->file_cache
[i
].path
= NULL
;
477 s
->file_cache
[i
].u
= -1;
478 s
->file_cache
[i
].g
= -1;
479 s
->file_cache
[i
].bb
= 0;
480 s
->file_cache
[i
].ts
= 0;
487 asl_store_save(asl_store_t
*s
, aslmsg msg
)
490 time_t msg_time
, now
, bb
;
491 char *path
, *tmp_path
, *tstring
, *scratch
;
496 uint32_t status
, check_cache
, trigger_aslmanager
, len
;
500 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
501 if (msg
== NULL
) return ASL_STATUS_INVALID_ARG
;
506 if ((s
->last_write
+ FILE_CACHE_TTL
) <= now
) check_cache
= 1;
508 trigger_aslmanager
= 0;
511 val
= asl_get(msg
, ASL_KEY_TIME
);
512 if (val
== NULL
) msg_time
= now
;
513 else msg_time
= asl_parse_time(val
);
515 if (msg_time
>= s
->start_tomorrow
)
517 if (now
>= s
->start_tomorrow
)
521 asl_store_file_closeall(s
);
524 * _asl_start_today should never fail, but if it does,
525 * just push forward one day. That will probably be correct, and if
526 * it isn't, the next message that gets saved will push it ahead again
527 * until we get to the right date.
529 s
->start_today
= _asl_start_today();
530 if (s
->start_today
== 0) s
->start_today
= s
->start_tomorrow
;
532 s
->start_tomorrow
= s
->start_today
+ SECONDS_PER_DAY
;
536 val
= asl_get(msg
, ASL_KEY_READ_UID
);
538 if (val
!= NULL
) ruid
= atoi(val
);
540 val
= asl_get(msg
, ASL_KEY_READ_GID
);
542 if (val
!= NULL
) rgid
= atoi(val
);
545 val
= asl_get(msg
, ASL_KEY_EXPIRE_TIME
);
549 msg_time
= asl_parse_time(val
);
552 if (fseeko(s
->storedata
, 0, SEEK_SET
) != 0) return ASL_STATUS_WRITE_FAILED
;
554 xid
= asl_core_htonq(s
->next_id
);
555 if (fwrite(&xid
, sizeof(uint64_t), 1, s
->storedata
) != 1) return ASL_STATUS_WRITE_FAILED
;
558 fflush(s
->storedata
);
565 if (localtime_r((const time_t *)&msg_time
, &ctm
) == NULL
) return ASL_STATUS_FAILED
;
571 * This supports 12 monthly "Best Before" buckets.
572 * We advance the actual expiry time to day zero of the following month.
573 * mktime() is clever enough to know that you actually mean the last day
574 * of the previous month. What we get back from localtime is the last
575 * day of the month in which the message expires, which we use in the name.
585 if (localtime_r((const time_t *)&bb
, &ctm
) == NULL
) return ASL_STATUS_FAILED
;
586 asprintf(&tstring
, "BB.%d.%02d.%02d", ctm
.tm_year
+ 1900, ctm
.tm_mon
+ 1, ctm
.tm_mday
);
590 asprintf(&tstring
, "%d.%02d.%02d", ctm
.tm_year
+ 1900, ctm
.tm_mon
+ 1, ctm
.tm_mday
);
593 if (tstring
== NULL
) return ASL_STATUS_NO_MEMORY
;
595 status
= asl_store_file_open_write(s
, tstring
, ruid
, rgid
, bb
, &f
, now
, check_cache
);
599 if (status
!= ASL_STATUS_OK
) return status
;
601 status
= asl_file_save(f
, msg
, &xid
);
602 if (status
!= ASL_STATUS_OK
) return status
;
604 fsize
= asl_file_size(f
);
605 ftime
= asl_file_ctime(f
);
607 /* if file is larger than max_file_size, rename it and trigger aslmanager */
608 if ((s
->max_file_size
!= 0) && (fsize
> s
->max_file_size
))
610 trigger_aslmanager
= 1;
611 status
= ASL_STATUS_OK
;
613 path
= asl_store_file_path(s
, f
);
615 asl_store_file_close(s
, f
);
622 if ((len
>= 4) && (!strcmp(path
+ len
- 4, ".asl")))
624 /* rename xxxxxxx.asl to xxxxxxx.timestamp.asl */
625 scratch
= strdup(path
);
628 scratch
[len
- 4] = '\0';
629 asprintf(&tmp_path
, "%s.%llu.asl", scratch
, ftime
);
636 /* append timestamp */
637 asprintf(&tmp_path
, "%s.%llu", path
, ftime
);
640 if (tmp_path
== NULL
)
642 status
= ASL_STATUS_NO_MEMORY
;
646 if (rename(path
, tmp_path
) != 0) status
= ASL_STATUS_FAILED
;
654 if (trigger_aslmanager
!= 0) asl_trigger_aslmanager();
660 asl_store_mkdir(asl_store_t
*s
, const char *dir
, mode_t m
)
662 char *tstring
= NULL
;
666 asprintf(&tstring
, "%s/%s", s
->base_dir
, dir
);
667 if (tstring
== NULL
) return ASL_STATUS_NO_MEMORY
;
669 memset(&sb
, 0, sizeof(struct stat
));
670 status
= stat(tstring
, &sb
);
674 /* must be a directory */
675 if (!S_ISDIR(sb
.st_mode
))
678 return ASL_STATUS_INVALID_STORE
;
685 /* doesn't exist - create it */
686 if (mkdir(tstring
, m
) != 0)
689 return ASL_STATUS_WRITE_FAILED
;
694 /* stat failed for some other reason */
696 return ASL_STATUS_FAILED
;
701 return ASL_STATUS_OK
;
705 asl_store_open_aux(asl_store_t
*s
, aslmsg msg
, int *out_fd
, char **url
)
709 char *path
, *dir
, *tstring
;
718 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
719 if (msg
== NULL
) return ASL_STATUS_INVALID_ARG
;
720 if (out_fd
== NULL
) return ASL_STATUS_INVALID_ARG
;
721 if (url
== NULL
) return ASL_STATUS_INVALID_ARG
;
723 msg_time
= time(NULL
);
725 val
= asl_get(msg
, ASL_KEY_READ_UID
);
727 if (val
!= NULL
) ruid
= atoi(val
);
729 val
= asl_get(msg
, ASL_KEY_READ_GID
);
731 if (val
!= NULL
) rgid
= atoi(val
);
734 val
= asl_get(msg
, ASL_KEY_EXPIRE_TIME
);
738 msg_time
= asl_parse_time(val
);
741 if (localtime_r((const time_t *)&msg_time
, &ctm
) == NULL
) return ASL_STATUS_FAILED
;
747 * This supports 12 monthly "Best Before" buckets.
748 * We advance the actual expiry time to day zero of the following month.
749 * mktime() is clever enough to know that you actually mean the last day
750 * of the previous month. What we get back from localtime is the last
751 * day of the month in which the message expires, which we use in the name.
761 if (localtime_r((const time_t *)&bb
, &ctm
) == NULL
) return ASL_STATUS_FAILED
;
762 asprintf(&dir
, "BB.AUX.%d.%02d.%02d", ctm
.tm_year
+ 1900, ctm
.tm_mon
+ 1, ctm
.tm_mday
);
766 asprintf(&dir
, "AUX.%d.%02d.%02d", ctm
.tm_year
+ 1900, ctm
.tm_mon
+ 1, ctm
.tm_mday
);
769 if (dir
== NULL
) return ASL_STATUS_NO_MEMORY
;
771 status
= asl_store_mkdir(s
, dir
, 0755);
772 if (status
!= ASL_STATUS_OK
)
782 asprintf(&tstring
, "%s/%llu", dir
, fid
);
784 if (tstring
== NULL
) return ASL_STATUS_NO_MEMORY
;
789 path
= asl_store_make_ug_path(s
->base_dir
, tstring
, NULL
, ruid
, rgid
, &u
, &g
, &m
);
791 if (path
== NULL
) return ASL_STATUS_NO_MEMORY
;
793 fd
= asl_file_create(path
, u
, g
, m
);
798 return ASL_STATUS_WRITE_FAILED
;
801 /* URL is file://<path> */
803 asprintf(url
, "file://%s", path
);
812 asl_store_match_timeout(asl_store_t
*s
, aslresponse query
, aslresponse
*res
, uint64_t *last_id
, uint64_t start_id
, uint32_t count
, int32_t direction
, uint32_t usec
)
819 asl_file_list_t
*files
;
821 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
822 if (res
== NULL
) return ASL_STATUS_INVALID_ARG
;
827 * Open all readable files
829 dp
= opendir(s
->base_dir
);
830 if (dp
== NULL
) return ASL_STATUS_READ_FAILED
;
832 while ((dent
= readdir(dp
)) != NULL
)
834 if (dent
->d_name
[0] == '.') continue;
837 asprintf(&path
, "%s/%s", s
->base_dir
, dent
->d_name
);
839 /* NB asl_file_open_read will fail if path is NULL, if the file is not an ASL store file, or if it isn't readable */
840 status
= asl_file_open_read(path
, &f
);
841 if (path
!= NULL
) free(path
);
842 if ((status
!= ASL_STATUS_OK
) || (f
== NULL
)) continue;
844 files
= asl_file_list_add(files
, f
);
849 status
= asl_file_list_match_timeout(files
, query
, res
, last_id
, start_id
, count
, direction
, usec
);
850 asl_file_list_close(files
);
855 asl_store_match(asl_store_t
*s
, aslresponse query
, aslresponse
*res
, uint64_t *last_id
, uint64_t start_id
, uint32_t count
, int32_t direction
)
857 return asl_store_match_timeout(s
, query
, res
, last_id
, start_id
, count
, direction
, 0);
861 asl_store_match_start(asl_store_t
*s
, uint64_t start_id
, int32_t direction
)
868 asl_file_list_t
*files
;
870 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
872 if (s
->work
!= NULL
) asl_file_list_match_end(s
->work
);
878 * Open all readable files
880 dp
= opendir(s
->base_dir
);
881 if (dp
== NULL
) return ASL_STATUS_READ_FAILED
;
883 while ((dent
= readdir(dp
)) != NULL
)
885 if (dent
->d_name
[0] == '.') continue;
888 asprintf(&path
, "%s/%s", s
->base_dir
, dent
->d_name
);
890 /* NB asl_file_open_read will fail if path is NULL, if the file is not an ASL store file, or if it isn't readable */
891 status
= asl_file_open_read(path
, &f
);
892 if (path
!= NULL
) free(path
);
893 if ((status
!= ASL_STATUS_OK
) || (f
== NULL
)) continue;
895 files
= asl_file_list_add(files
, f
);
900 s
->work
= asl_file_list_match_start(files
, start_id
, direction
);
901 if (s
->work
== NULL
) return ASL_STATUS_FAILED
;
903 return ASL_STATUS_OK
;
907 asl_store_match_next(asl_store_t
*s
, aslresponse query
, aslresponse
*res
, uint32_t count
)
909 if (s
== NULL
) return ASL_STATUS_INVALID_STORE
;
910 if (s
->work
== NULL
) return ASL_STATUS_OK
;
912 return asl_file_list_match_next(s
->work
, query
, res
, count
);
915 #if TARGET_IPHONE_SIMULATOR
916 const char *_path_asl_store(void) {
918 static dispatch_once_t once
;
920 dispatch_once(&once
, ^{
921 char *sim_log_dir
= getenv("IPHONE_SIMULATOR_LOG_ROOT");
924 asprintf(&path
, "%s/asl", sim_log_dir
);
931 const char *_path_asl_archive(void) {
933 static dispatch_once_t once
;
935 dispatch_once(&once
, ^{
936 char *sim_log_dir
= getenv("IPHONE_SIMULATOR_LOG_ROOT");
939 asprintf(&path
, "%s/asl.archive", sim_log_dir
);