2 * logfile.c --- set up e2fsck log files
4 * Copyright 1996, 1997 by Theodore Ts'o
7 * This file may be redistributed under the terms of the GNU Public
16 #include <sys/types.h>
23 extern e2fsck_t e2fsck_global_ctx
; /* Try your very best not to use this! */
31 static void alloc_string(struct string
*s
, int len
)
34 /* e2fsck_allocate_memory(ctx, len, "logfile name"); */
39 static void append_string(struct string
*s
, const char *a
, int len
)
46 needlen
= s
->end
+ len
+ 1;
47 if (needlen
> s
->len
) {
50 if (s
->len
* 2 > needlen
)
52 n
= realloc(s
->s
, needlen
);
58 /* Don't append if we ran out of memory */
62 memcpy(s
->s
+ s
->end
, a
, len
);
67 #define FLAG_UTC 0x0001
69 static void expand_percent_expression(e2fsck_t ctx
, char ch
,
70 struct string
*s
, int *flags
)
72 struct tm
*tm
= NULL
, tm_struct
;
73 struct passwd
*pw
= NULL
, pw_struct
;
77 if ((ch
== 'D') || (ch
== 'd') || (ch
== 'm') || (ch
== 'y') ||
79 (ch
== 'T') || (ch
== 'H') || (ch
== 'M') || (ch
== 'S')) {
81 tm
= (*flags
& FLAG_UTC
) ? gmtime_r(&ctx
->now
, &tm_struct
) :
82 localtime_r(&ctx
->now
, &tm_struct
);
87 append_string(s
, "%", 1);
90 sprintf(buf
, "%02d", tm
->tm_mday
);
93 sprintf(buf
, "%d%02d%02d", tm
->tm_year
+ 1900, tm
->tm_mon
+ 1,
98 strcpy(buf
, "server");
101 gethostname(buf
, sizeof(buf
));
102 buf
[sizeof(buf
)-1] = 0;
106 sprintf(buf
, "%02d", tm
->tm_hour
);
109 sprintf(buf
, "%02d", tm
->tm_mon
+ 1);
112 sprintf(buf
, "%02d", tm
->tm_min
);
114 case 'N': /* block device name */
115 cp
= strrchr(ctx
->filesystem_name
, '/');
119 cp
= ctx
->filesystem_name
;
120 append_string(s
, cp
, 0);
123 sprintf(buf
, "%lu", (unsigned long) getpid());
126 sprintf(buf
, "%lu", (unsigned long) ctx
->now
);
129 sprintf(buf
, "%02d", tm
->tm_sec
);
132 sprintf(buf
, "%02d%02d%02d", tm
->tm_hour
, tm
->tm_min
,
137 strcpy(buf
, "tytso");
140 #ifdef HAVE_GETPWUID_R
141 getpwuid_r(getuid(), &pw_struct
, buf
, sizeof(buf
), &pw
);
143 pw
= getpwuid(getuid());
146 append_string(s
, pw
->pw_name
, 0);
153 sprintf(buf
, "%02d", tm
->tm_year
% 100);
156 sprintf(buf
, "%d", tm
->tm_year
+ 1900);
159 append_string(s
, buf
, 0);
162 static void expand_logfn(e2fsck_t ctx
, const char *log_fn
, struct string
*s
)
168 alloc_string(s
, 100);
169 for (cp
= log_fn
; *cp
; cp
++) {
172 expand_percent_expression(ctx
, *cp
, s
, &flags
);
175 for (i
= 0; cp
[i
]; i
++)
178 append_string(s
, cp
, i
);
183 static int outbufsize
;
186 static int do_read(int fd
)
192 c
= read(fd
, buffer
, sizeof(buffer
)-1);
196 n
= realloc(outbuf
, outbufsize
+ c
);
199 memcpy(((char *)outbuf
)+outbufsize
, buffer
, c
);
206 * Fork a child process to save the output of the logfile until the
207 * appropriate file system is mounted read/write.
209 static FILE *save_output(const char *s0
, const char *s1
, const char *s2
)
223 /* At least one potential output file name is valid */
224 if (!s0
&& !s1
&& !s2
)
238 if (e2fsck_global_ctx
&& e2fsck_global_ctx
->progress_fd
)
239 close(e2fsck_global_ctx
->progress_fd
);
240 if (daemon(0, 0) < 0) {
245 * Grab the output from our parent
248 while (do_read(fds
[0]) > 0)
252 /* OK, now let's try to open the output file */
256 fd
= open(s0
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0644);
258 fd
= open(s1
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0644);
260 fd
= open(s2
, O_WRONLY
|O_CREAT
|O_TRUNC
, 0644);
267 while (outbufsize
> 0) {
268 c
= write(fd
, cp
, outbufsize
);
270 if ((errno
== EAGAIN
) || (errno
== EINTR
))
281 ret
= fdopen(fds
[1], "w");
288 static FILE *set_up_log_file(e2fsck_t ctx
, const char *key
, const char *fn
)
291 struct string s
, s1
, s2
;
292 char *s0
= 0, *log_dir
= 0, *log_fn
= 0;
293 int log_dir_wait
= 0;
295 s
.s
= s1
.s
= s2
.s
= 0;
297 profile_get_boolean(ctx
->profile
, "options", "log_dir_wait", 0, 0,
300 log_fn
= string_copy(ctx
, fn
, 0);
302 profile_get_string(ctx
->profile
, "options", key
,
304 profile_get_string(ctx
->profile
, "options", "log_dir", 0, 0, &log_dir
);
306 if (!log_fn
|| !log_fn
[0])
309 expand_logfn(ctx
, log_fn
, &s
);
310 if ((log_fn
[0] == '/') || !log_dir
|| !log_dir
[0])
313 if (log_dir
&& log_dir
[0]) {
314 alloc_string(&s1
, strlen(log_dir
) + strlen(s
.s
) + 2);
315 append_string(&s1
, log_dir
, 0);
316 append_string(&s1
, "/", 1);
317 append_string(&s1
, s
.s
, 0);
321 profile_get_string(ctx
->profile
, "options", "log_dir_fallback", 0, 0,
323 if (log_dir
&& log_dir
[0]) {
324 alloc_string(&s2
, strlen(log_dir
) + strlen(s
.s
) + 2);
325 append_string(&s2
, log_dir
, 0);
326 append_string(&s2
, "/", 1);
327 append_string(&s2
, s
.s
, 0);
328 printf("%s\n", s2
.s
);
334 f
= fopen(s1
.s
, "w");
336 f
= fopen(s2
.s
, "w");
337 if (!f
&& log_dir_wait
)
338 f
= save_output(s0
, s1
.s
, s2
.s
);
349 void set_up_logging(e2fsck_t ctx
)
351 ctx
->logf
= set_up_log_file(ctx
, "log_filename", ctx
->log_fn
);
352 ctx
->problem_logf
= set_up_log_file(ctx
, "problem_log_filename",
353 ctx
->problem_log_fn
);
356 void *e2fsck_allocate_memory(e2fsck_t ctx
, unsigned int size
,
357 const char *description
)
364 sprintf(buf
, "Can't allocate %s\n", description
);
367 memset(ret
, 0, size
);
371 errcode_t
e2fsck_allocate_context(e2fsck_t
*ret
)
377 context
= malloc(sizeof(struct e2fsck_struct
));
381 memset(context
, 0, sizeof(struct e2fsck_struct
));
383 context
->now
= 1332006474;
385 context
->filesystem_name
= "/dev/sda3";
386 context
->device_name
= "fslabel";
392 int main(int argc
, char **argv
)
397 putenv("TZ=EST+5:00");
398 e2fsck_allocate_context(&ctx
);
399 expand_logfn(ctx
, "e2fsck-%N.%h.%u.%D-%T", &s
);
402 expand_logfn(ctx
, "e2fsck-%N.%h.%u.%Y%m%d-%H%M%S", &s
);