]> git.saurik.com Git - apple/syslog.git/blob - aslmanager.tproj/aslmanager.c
a524421bf214a9221efd9f1f91e9dc69e8489fe8
[apple/syslog.git] / aslmanager.tproj / aslmanager.c
1 /*
2 * Copyright (c) 2007-2009 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <stdio.h>
25 #include <dirent.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <stdint.h>
30 #include <errno.h>
31 #include <time.h>
32 #include <sys/time.h>
33 #include <sys/stat.h>
34 #include <copyfile.h>
35 #include <asl.h>
36 #include <asl_private.h>
37 #include <asl_core.h>
38 #include <asl_file.h>
39 #include <asl_store.h>
40
41 #define SECONDS_PER_DAY 86400
42 #define DEFAULT_MAX_SIZE 150000000
43 #define DEFAULT_TTL 7
44
45 #define _PATH_ASL_CONF "/etc/asl.conf"
46
47 /* global */
48 static char *archive = NULL;
49 static char *store_dir = PATH_ASL_STORE;
50 static time_t ttl;
51 static size_t max_size;
52 static mode_t archive_mode = 0400;
53 static int debug;
54
55 typedef struct name_list_s
56 {
57 char *name;
58 size_t size;
59 struct name_list_s *next;
60 } name_list_t;
61
62 name_list_t *
63 add_to_list(name_list_t *l, const char *name, size_t size)
64 {
65 name_list_t *e, *x;
66
67 if (name == NULL) return l;
68
69 e = (name_list_t *)calloc(1, sizeof(name_list_t));
70 if (e == NULL) return NULL;
71
72 e->name = strdup(name);
73 if (e->name == NULL)
74 {
75 free(e);
76 return NULL;
77 }
78
79 e->size = size;
80
81 /* list is sorted by name (i.e. primarily by timestamp) */
82 if (l == NULL) return e;
83
84 if (strcmp(e->name, l->name) <= 0)
85 {
86 e->next = l;
87 return e;
88 }
89
90 for (x = l; (x->next != NULL) && (strcmp(e->name, x->next->name) > 0) ; x = x->next);
91
92 e->next = x->next;
93 x->next = e;
94 return l;
95 }
96
97 void
98 free_list(name_list_t *l)
99 {
100 name_list_t *e;
101
102 while (l != NULL)
103 {
104 e = l;
105 l = l->next;
106 free(e->name);
107 free(e);
108 }
109
110 free(l);
111 }
112
113 uint32_t
114 do_copy(const char *infile, const char *outfile, mode_t mode)
115 {
116 asl_search_result_t *res;
117 asl_file_t *f;
118 uint32_t status, i;
119 uint64_t mid;
120
121 if (infile == NULL) return ASL_STATUS_INVALID_ARG;
122 if (outfile == NULL) return ASL_STATUS_INVALID_ARG;
123
124 f = NULL;
125 status = asl_file_open_read(infile, &f);
126 if (status != ASL_STATUS_OK) return status;
127
128 res = NULL;
129 mid = 0;
130
131 status = asl_file_match(f, NULL, &res, &mid, 0, 0, 1);
132 asl_file_close(f);
133
134 if (status != ASL_STATUS_OK) return status;
135 if (res->count == 0)
136 {
137 aslresponse_free(res);
138 return ASL_STATUS_OK;
139 }
140
141 f = NULL;
142 status = asl_file_open_write(outfile, mode, -1, -1, &f);
143 if (status != ASL_STATUS_OK) return status;
144 if (f == ASL_STATUS_OK) return ASL_STATUS_FAILED;
145
146 f->flags = ASL_FILE_FLAG_UNLIMITED_CACHE | ASL_FILE_FLAG_PRESERVE_MSG_ID;
147
148 for (i = 0; i < res->count; i++)
149 {
150 mid = 0;
151 status = asl_file_save(f, (aslmsg)(res->msg[i]), &mid);
152 if (status != ASL_STATUS_OK) break;
153 }
154
155 asl_file_close(f);
156 return status;
157 }
158
159 int
160 do_dir_archive(const char *indir, const char *outdir)
161 {
162 return copyfile(indir, outdir, NULL, COPYFILE_ALL | COPYFILE_RECURSIVE);
163 }
164
165 int
166 remove_directory(const char *path)
167 {
168 DIR *dp;
169 struct dirent *dent;
170 char *str;
171 int status;
172
173 dp = opendir(path);
174 if (dp == NULL) return 0;
175
176 while ((dent = readdir(dp)) != NULL)
177 {
178 if ((!strcmp(dent->d_name, ".")) || (!strcmp(dent->d_name, ".."))) continue;
179 asprintf(&str, "%s/%s", path, dent->d_name);
180 if (str != NULL)
181 {
182 status = unlink(str);
183 free(str);
184 str = NULL;
185 }
186 }
187
188 closedir(dp);
189 status = rmdir(path);
190
191 return status;
192 }
193
194
195 static char **
196 _insertString(char *s, char **l, uint32_t x)
197 {
198 int i, len;
199
200 if (s == NULL) return l;
201 if (l == NULL)
202 {
203 l = (char **)malloc(2 * sizeof(char *));
204 if (l == NULL) return NULL;
205
206 l[0] = strdup(s);
207 if (l[0] == NULL)
208 {
209 free(l);
210 return NULL;
211 }
212
213 l[1] = NULL;
214 return l;
215 }
216
217 for (i = 0; l[i] != NULL; i++);
218 len = i + 1; /* count the NULL on the end of the list too! */
219
220 l = (char **)reallocf(l, (len + 1) * sizeof(char *));
221 if (l == NULL) return NULL;
222
223 if ((x >= (len - 1)) || (x == IndexNull))
224 {
225 l[len - 1] = strdup(s);
226 if (l[len - 1] == NULL)
227 {
228 free(l);
229 return NULL;
230 }
231
232 l[len] = NULL;
233 return l;
234 }
235
236 for (i = len; i > x; i--) l[i] = l[i - 1];
237 l[x] = strdup(s);
238 if (l[x] == NULL) return NULL;
239
240 return l;
241 }
242
243 char **
244 explode(const char *s, const char *delim)
245 {
246 char **l = NULL;
247 const char *p;
248 char *t, quote;
249 int i, n;
250
251 if (s == NULL) return NULL;
252
253 quote = '\0';
254
255 p = s;
256 while (p[0] != '\0')
257 {
258 /* scan forward */
259 for (i = 0; p[i] != '\0'; i++)
260 {
261 if (quote == '\0')
262 {
263 /* not inside a quoted string: check for delimiters and quotes */
264 if (strchr(delim, p[i]) != NULL) break;
265 else if (p[i] == '\'') quote = p[i];
266 else if (p[i] == '"') quote = p[i];
267 }
268 else
269 {
270 /* inside a quoted string - look for matching quote */
271 if (p[i] == quote) quote = '\0';
272 }
273 }
274
275 n = i;
276 t = malloc(n + 1);
277 if (t == NULL) return NULL;
278
279 for (i = 0; i < n; i++) t[i] = p[i];
280 t[n] = '\0';
281 l = _insertString(t, l, IndexNull);
282 free(t);
283 t = NULL;
284 if (p[i] == '\0') return l;
285 if (p[i + 1] == '\0') l = _insertString("", l, IndexNull);
286 p = p + i + 1;
287 }
288
289 return l;
290 }
291
292 void
293 freeList(char **l)
294 {
295 int i;
296
297 if (l == NULL) return;
298 for (i = 0; l[i] != NULL; i++) free(l[i]);
299 free(l);
300 }
301
302 /*
303 * Used to sed config parameters.
304 * Line format "= name value"
305 */
306 static void
307 _parse_set_param(char *s)
308 {
309 char **l;
310 uint32_t count;
311
312 if (s == NULL) return;
313 if (s[0] == '\0') return;
314
315 /* skip '=' and whitespace */
316 s++;
317 while ((*s == ' ') || (*s == '\t')) s++;
318
319 l = explode(s, " \t");
320 if (l == NULL) return;
321
322 for (count = 0; l[count] != NULL; count++);
323
324 /* name is required */
325 if (count == 0)
326 {
327 freeList(l);
328 return;
329 }
330
331 /* value is required */
332 if (count == 1)
333 {
334 freeList(l);
335 return;
336 }
337
338 if (!strcasecmp(l[0], "aslmanager_debug"))
339 {
340 /* = debug {0|1} */
341 debug = atoi(l[1]);
342 }
343 else if (!strcasecmp(l[0], "store_ttl"))
344 {
345 /* = store_ttl days */
346 ttl = SECONDS_PER_DAY * (time_t)atoll(l[1]);
347 }
348 else if (!strcasecmp(l[0], "max_store_size"))
349 {
350 /* = max_file_size bytes */
351 max_size = atoi(l[1]);
352 }
353 else if (!strcasecmp(l[0], "archive"))
354 {
355 /* = archive {0|1} path */
356 if (!strcmp(l[1], "1"))
357 {
358 if (l[2] == NULL) archive = PATH_ASL_ARCHIVE;
359 else archive = strdup(l[2]); /* never freed */
360 }
361 else archive = NULL;
362 }
363 else if (!strcasecmp(l[0], "store_path"))
364 {
365 /* = archive path */
366 store_dir = strdup(l[1]); /* never freed */
367 }
368 else if (!strcasecmp(l[0], "archive_mode"))
369 {
370 archive_mode = strtol(l[1], NULL, 0);
371 if ((archive_mode == 0) && (errno == EINVAL)) archive_mode = 0400;
372 }
373
374 freeList(l);
375 }
376
377 static void
378 _parse_line(char *s)
379 {
380 if (s == NULL) return;
381 while ((*s == ' ') || (*s == '\t')) s++;
382
383 /*
384 * First non-whitespace char is the rule type.
385 * aslmanager only checks "=" (set parameter) rules.
386 */
387 if (*s == '=') _parse_set_param(s);
388 }
389
390 char *
391 get_line_from_file(FILE *f)
392 {
393 char *s, *out;
394 size_t len;
395
396 out = fgetln(f, &len);
397 if (out == NULL) return NULL;
398 if (len == 0) return NULL;
399
400 s = malloc(len + 1);
401 if (s == NULL) return NULL;
402
403 memcpy(s, out, len);
404
405 s[len - 1] = '\0';
406 return s;
407 }
408
409 static int
410 _parse_config_file(const char *name)
411 {
412 FILE *cf;
413 char *line;
414
415 cf = fopen(name, "r");
416 if (cf == NULL) return 1;
417
418 while (NULL != (line = get_line_from_file(cf)))
419 {
420 _parse_line(line);
421 free(line);
422 }
423
424 fclose(cf);
425
426 return 0;
427 }
428
429 size_t
430 directory_size(const char *path)
431 {
432 DIR *dp;
433 struct dirent *dent;
434 struct stat sb;
435 size_t size;
436 char *str;
437
438 dp = opendir(path);
439 if (dp == NULL) return 0;
440
441 size = 0;
442 while ((dent = readdir(dp)) != NULL)
443 {
444 if ((!strcmp(dent->d_name, ".")) || (!strcmp(dent->d_name, ".."))) continue;
445
446 memset(&sb, 0, sizeof(struct stat));
447 str = NULL;
448 asprintf(&str, "%s/%s", path, dent->d_name);
449
450 if ((str != NULL) && (stat(str, &sb) == 0) && S_ISREG(sb.st_mode))
451 {
452 size += sb.st_size;
453 free(str);
454 }
455 }
456
457 closedir(dp);
458 return size;
459 }
460
461 int
462 main(int argc, const char *argv[])
463 {
464 int i, today_ymd_stringlen, expire_ymd_stringlen;
465 time_t now, ymd_expire;
466 struct tm ctm;
467 char today_ymd_string[32], expire_ymd_string[32], *str;
468 DIR *dp;
469 struct dirent *dent;
470 name_list_t *ymd_list, *bb_list, *aux_list, *bb_aux_list, *e;
471 uint32_t status;
472 size_t file_size, store_size;
473 struct stat sb;
474
475 ymd_list = NULL;
476 bb_list = NULL;
477 aux_list = NULL;
478 bb_aux_list = NULL;
479
480 ttl = DEFAULT_TTL * SECONDS_PER_DAY;
481 max_size = DEFAULT_MAX_SIZE;
482 store_size = 0;
483 debug = 0;
484
485 for (i = 1; i < argc; i++)
486 {
487 if (!strcmp(argv[i], "-a"))
488 {
489 if (((i + 1) < argc) && (argv[i + 1][0] != '-')) archive = (char *)argv[++i];
490 else archive = PATH_ASL_ARCHIVE;
491 }
492 else if (!strcmp(argv[i], "-s"))
493 {
494 if (((i + 1) < argc) && (argv[i + 1][0] != '-')) store_dir = (char *)argv[++i];
495 }
496 else if (!strcmp(argv[i], "-ttl"))
497 {
498 if (((i + 1) < argc) && (argv[i + 1][0] != '-')) ttl = atoi(argv[++i]) * SECONDS_PER_DAY;
499 }
500 else if (!strcmp(argv[i], "-size"))
501 {
502 if (((i + 1) < argc) && (argv[i + 1][0] != '-')) max_size = atoi(argv[++i]);
503 }
504 else if (!strcmp(argv[i], "-d"))
505 {
506 debug = 1;
507 }
508 }
509
510 _parse_config_file(_PATH_ASL_CONF);
511
512 if (debug == 1) printf("aslmanager starting\n");
513
514 /* check archive */
515 if (archive != NULL)
516 {
517 memset(&sb, 0, sizeof(struct stat));
518 if (stat(archive, &sb) == 0)
519 {
520 /* must be a directory */
521 if (!S_ISDIR(sb.st_mode))
522 {
523 fprintf(stderr, "aslmanager error: archive %s is not a directory", archive);
524 return -1;
525 }
526 }
527 else
528 {
529 if (errno == ENOENT)
530 {
531 /* archive doesn't exist - create it */
532 if (mkdir(archive, 0755) != 0)
533 {
534 fprintf(stderr, "aslmanager error: can't create archive %s: %s\n", archive, strerror(errno));
535 return -1;
536 }
537 }
538 else
539 {
540 /* stat failed for some other reason */
541 fprintf(stderr, "aslmanager error: can't stat archive %s: %s\n", archive, strerror(errno));
542 return -1;
543 }
544 }
545 }
546
547 chdir(store_dir);
548
549 /* determine current time */
550 now = time(NULL);
551
552 /* ttl 0 means files never expire */
553 ymd_expire = 0;
554 if (ttl > 0) ymd_expire = now - ttl;
555
556 /* construct today's date as YYYY.MM.DD */
557 memset(&ctm, 0, sizeof(struct tm));
558 if (localtime_r((const time_t *)&now, &ctm) == NULL) return -1;
559
560 snprintf(today_ymd_string, sizeof(today_ymd_string), "%d.%02d.%02d.", ctm.tm_year + 1900, ctm.tm_mon + 1, ctm.tm_mday);
561 today_ymd_stringlen = strlen(today_ymd_string);
562
563 /* construct regular file expiry date as YYYY.MM.DD */
564 memset(&ctm, 0, sizeof(struct tm));
565 if (localtime_r((const time_t *)&ymd_expire, &ctm) == NULL) return -1;
566
567 snprintf(expire_ymd_string, sizeof(expire_ymd_string), "%d.%02d.%02d.", ctm.tm_year + 1900, ctm.tm_mon + 1, ctm.tm_mday);
568 expire_ymd_stringlen = strlen(expire_ymd_string);
569
570 if (debug == 1) printf("Expiry Date %s\n", expire_ymd_string);
571
572 dp = opendir(store_dir);
573 if (dp == NULL) return -1;
574
575 /* gather a list of YMD files, AUX dirs, BB.AUX dirs, and BB files */
576 while ((dent = readdir(dp)) != NULL)
577 {
578 memset(&sb, 0, sizeof(struct stat));
579 file_size = 0;
580 if (stat(dent->d_name, &sb) == 0) file_size = sb.st_size;
581
582 if ((dent->d_name[0] >= '0') && (dent->d_name[0] <= '9'))
583 {
584 ymd_list = add_to_list(ymd_list, dent->d_name, file_size);
585 store_size += file_size;
586 }
587 else if (!strncmp(dent->d_name, "AUX.", 4) && (dent->d_name[4] >= '0') && (dent->d_name[4] <= '9') && S_ISDIR(sb.st_mode))
588 {
589 file_size = directory_size(dent->d_name);
590 aux_list = add_to_list(aux_list, dent->d_name, file_size);
591 store_size += file_size;
592 }
593 else if (!strncmp(dent->d_name, "BB.AUX.", 7) && (dent->d_name[7] >= '0') && (dent->d_name[7] <= '9') && S_ISDIR(sb.st_mode))
594 {
595 file_size = directory_size(dent->d_name);
596 bb_aux_list = add_to_list(bb_aux_list, dent->d_name, file_size);
597 store_size += file_size;
598 }
599 else if (!strncmp(dent->d_name, "BB.", 3) && (dent->d_name[3] >= '0') && (dent->d_name[3] <= '9'))
600 {
601 bb_list = add_to_list(bb_list, dent->d_name, file_size);
602 store_size += file_size;
603 }
604 else if ((!strcmp(dent->d_name, ".")) || (!strcmp(dent->d_name, "..")))
605 {}
606 else if ((!strcmp(dent->d_name, "StoreData")) || (!strcmp(dent->d_name, "SweepStore")))
607 {}
608 else
609 {
610 fprintf(stderr, "aslmanager: unexpected file %s in ASL data store\n", dent->d_name);
611 }
612 }
613
614 closedir(dp);
615
616 if (debug == 1)
617 {
618 printf("Data Store Size = %lu\n", store_size);
619 printf("Data Store YMD Files\n");
620 for (e = ymd_list; e != NULL; e = e->next) printf(" %s %lu\n", e->name, e->size);
621 printf("Data Store AUX Directories\n");
622 for (e = aux_list; e != NULL; e = e->next) printf(" %s %lu\n", e->name, e->size);
623 printf("Data Store BB.AUX Directories\n");
624 for (e = bb_aux_list; e != NULL; e = e->next) printf(" %s %lu\n", e->name, e->size);
625 printf("Data Store BB Files\n");
626 for (e = bb_list; e != NULL; e = e->next) printf(" %s %lu\n", e->name, e->size);
627 }
628
629 /* Delete/achive expired YMD files */
630 if (debug == 1) printf("Start YMD File Scan\n");
631
632 e = ymd_list;
633 while (e != NULL)
634 {
635 /* stop when a file name/date is after the expire date */
636 if (strncmp(e->name, expire_ymd_string, expire_ymd_stringlen) > 0) break;
637
638 if (archive != NULL)
639 {
640 str = NULL;
641 asprintf(&str, "%s/%s", archive, e->name);
642 if (str == NULL) return -1;
643
644 if (debug == 1) printf(" copy %s ---> %s\n", e->name, str);
645 status = do_copy(e->name, str, archive_mode);
646 free(str);
647 }
648
649 if (debug == 1) printf(" unlink %s\n", e->name);
650 unlink(e->name);
651
652 store_size -= e->size;
653 e->size = 0;
654
655 e = e->next;
656 }
657
658 if (debug == 1) printf("Finished YMD FILE Scan\n");
659
660 /* Delete/achive expired YMD AUX directories */
661 if (debug == 1) printf("Start AUX Directory Scan\n");
662
663 e = aux_list;
664 while (e != NULL)
665 {
666 /* stop when a file name/date is after the expire date */
667 if (strncmp(e->name + 4, expire_ymd_string, expire_ymd_stringlen) > 0) break;
668
669 if (archive != NULL)
670 {
671 str = NULL;
672 asprintf(&str, "%s/%s", archive, e->name);
673 if (str == NULL) return -1;
674
675 if (debug == 1) printf(" copy %s ---> %s\n", e->name, str);
676 do_dir_archive(e->name, str);
677 free(str);
678 }
679
680 if (debug == 1) printf(" Remove %s\n", e->name);
681 remove_directory(e->name);
682
683 store_size -= e->size;
684 e->size = 0;
685
686 e = e->next;
687 }
688
689 if (debug == 1) printf("Finished AUX Directory Scan\n");
690
691 /* Delete/achive expired BB.AUX directories */
692 if (debug == 1) printf("Start BB.AUX Directory Scan\n");
693
694 e = bb_aux_list;
695 while (e != NULL)
696 {
697 /* stop when a file name/date is after the expire date */
698 if (strncmp(e->name + 7, today_ymd_string, today_ymd_stringlen) > 0) break;
699
700 if (archive != NULL)
701 {
702 str = NULL;
703 asprintf(&str, "%s/%s", archive, e->name);
704 if (str == NULL) return -1;
705
706 if (debug == 1) printf(" copy %s ---> %s\n", e->name, str);
707 do_dir_archive(e->name, str);
708 free(str);
709 }
710
711 if (debug == 1) printf(" remove %s\n", e->name);
712 remove_directory(e->name);
713
714 store_size -= e->size;
715 e->size = 0;
716
717 e = e->next;
718 }
719
720 if (debug == 1) printf("Finished BB.AUX Directory Scan\n");
721
722 /* Delete/achive expired BB files */
723 if (debug == 1) printf("Start BB Scan\n");
724
725 e = bb_list;
726 while (e != NULL)
727 {
728 /* stop when a file name/date is after the expire date */
729 if (strncmp(e->name + 3, today_ymd_string, today_ymd_stringlen) > 0) break;
730
731 if (archive != NULL)
732 {
733 str = NULL;
734 asprintf(&str, "%s/%s", archive, e->name);
735 if (str == NULL) return -1;
736
737 /* syslog -x [str] -f [e->name] */
738 if (debug == 1) printf(" copy %s ---> %s\n", e->name, str);
739 status = do_copy(e->name, str, archive_mode);
740 free(str);
741 }
742
743 if (debug == 1) printf(" unlink %s\n", e->name);
744 unlink(e->name);
745
746 store_size -= e->size;
747 e->size = 0;
748
749 e = e->next;
750 }
751
752 if (debug == 1) printf("Finished BB Scan\n");
753
754 /* if data store is over max_size, delete/archive more YMD files */
755 if ((debug == 1) && (store_size > max_size)) printf("Additional YMD Scan\n");
756
757 e = ymd_list;
758 while ((e != NULL) && (store_size > max_size))
759 {
760 if (e->size != 0)
761 {
762 /* stop when we get to today's files */
763 if (strncmp(e->name, today_ymd_string, today_ymd_stringlen) == 0) break;
764
765 if (archive != NULL)
766 {
767 str = NULL;
768 asprintf(&str, "%s/%s", archive, e->name);
769 if (str == NULL) return -1;
770
771 /* syslog -x [str] -f [e->name] */
772 if (debug == 1) printf(" copy %s ---> %s\n", e->name, str);
773 status = do_copy(e->name, str, archive_mode);
774 free(str);
775 }
776
777 if (debug == 1) printf(" unlink %s\n", e->name);
778 unlink(e->name);
779
780 store_size -= e->size;
781 e->size = 0;
782 }
783
784 e = e->next;
785 }
786
787 /* if data store is over max_size, delete/archive more BB files */
788 if ((debug == 1) && (store_size > max_size)) printf("Additional BB Scan\n");
789
790 e = bb_list;
791 while ((e != NULL) && (store_size > max_size))
792 {
793 if (e->size != 0)
794 {
795 if (archive != NULL)
796 {
797 str = NULL;
798 asprintf(&str, "%s/%s", archive, e->name);
799 if (str == NULL) return -1;
800
801 /* syslog -x [str] -f [e->name] */
802 if (debug == 1) printf(" copy %s ---> %s\n", e->name, str);
803 status = do_copy(e->name, str, archive_mode);
804 free(str);
805 }
806
807 if (debug == 1) printf(" unlink %s\n", e->name);
808 unlink(e->name);
809
810 store_size -= e->size;
811 e->size = 0;
812 }
813
814 e = e->next;
815 }
816
817 free_list(ymd_list);
818 free_list(bb_list);
819
820 if (debug == 1)
821 {
822 printf("Data Store Size = %lu\n", store_size);
823 printf("aslmanager finished\n");
824 }
825
826 return 0;
827 }
828