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>
24 extern e2fsck_t e2fsck_global_ctx; /* Try your very best not to use this! */
32 static void alloc_string(struct string *s, int len)
35 /* e2fsck_allocate_memory(ctx, len, "logfile name"); */
40 static void append_string(struct string *s, const char *a, int len)
47 needlen = s->end + len + 1;
48 if (needlen > s->len) {
51 if (s->len * 2 > needlen)
53 n = realloc(s->s, needlen);
59 /* Don't append if we ran out of memory */
63 memcpy(s->s + s->end, a, len);
68 #define FLAG_UTC 0x0001
70 static void expand_percent_expression(e2fsck_t ctx, char ch,
71 struct string *s, int *flags)
73 struct tm *tm = NULL, tm_struct;
74 struct passwd *pw = NULL, pw_struct;
78 if ((ch == 'D') || (ch == 'd') || (ch == 'm') || (ch == 'y') ||
80 (ch == 'T') || (ch == 'H') || (ch == 'M') || (ch == 'S')) {
82 tm = (*flags & FLAG_UTC) ? gmtime_r(&ctx->now, &tm_struct) :
83 localtime_r(&ctx->now, &tm_struct);
88 append_string(s, "%", 1);
91 sprintf(buf, "%02d", tm->tm_mday);
94 sprintf(buf, "%d%02d%02d", tm->tm_year + 1900, tm->tm_mon + 1,
99 strcpy(buf, "server");
102 gethostname(buf, sizeof(buf));
103 buf[sizeof(buf)-1] = 0;
107 sprintf(buf, "%02d", tm->tm_hour);
110 sprintf(buf, "%02d", tm->tm_mon + 1);
113 sprintf(buf, "%02d", tm->tm_min);
115 case 'N': /* block device name */
116 cp = strrchr(ctx->filesystem_name, '/');
120 cp = ctx->filesystem_name;
121 append_string(s, cp, 0);
124 sprintf(buf, "%lu", (unsigned long) getpid());
127 sprintf(buf, "%lu", (unsigned long) ctx->now);
130 sprintf(buf, "%02d", tm->tm_sec);
133 sprintf(buf, "%02d%02d%02d", tm->tm_hour, tm->tm_min,
138 strcpy(buf, "tytso");
141 #ifdef HAVE_GETPWUID_R
142 getpwuid_r(getuid(), &pw_struct, buf, sizeof(buf), &pw);
144 pw = getpwuid(getuid());
147 append_string(s, pw->pw_name, 0);
154 sprintf(buf, "%02d", tm->tm_year % 100);
157 sprintf(buf, "%d", tm->tm_year + 1900);
160 append_string(s, buf, 0);
163 static void expand_logfn(e2fsck_t ctx, const char *log_fn, struct string *s)
169 alloc_string(s, 100);
170 for (cp = log_fn; *cp; cp++) {
173 expand_percent_expression(ctx, *cp, s, &flags);
176 for (i = 0; cp[i]; i++)
179 append_string(s, cp, i);
184 static int outbufsize;
187 static int do_read(int fd)
193 c = read(fd, buffer, sizeof(buffer)-1);
197 n = realloc(outbuf, outbufsize + c);
200 memcpy(((char *)outbuf)+outbufsize, buffer, c);
207 * Fork a child process to save the output of the logfile until the
208 * appropriate file system is mounted read/write.
210 static FILE *save_output(const char *s0, const char *s1, const char *s2)
224 /* At least one potential output file name is valid */
225 if (!s0 && !s1 && !s2)
239 if (e2fsck_global_ctx && e2fsck_global_ctx->progress_fd)
240 close(e2fsck_global_ctx->progress_fd);
241 if (daemon(0, 0) < 0) {
246 * Grab the output from our parent
249 while (do_read(fds[0]) > 0)
253 /* OK, now let's try to open the output file */
257 fd = open(s0, O_WRONLY|O_CREAT|O_TRUNC, 0644);
259 fd = open(s1, O_WRONLY|O_CREAT|O_TRUNC, 0644);
261 fd = open(s2, O_WRONLY|O_CREAT|O_TRUNC, 0644);
268 while (outbufsize > 0) {
269 c = write(fd, cp, outbufsize);
271 if ((errno == EAGAIN) || (errno == EINTR))
282 ret = fdopen(fds[1], "w");
289 static FILE *set_up_log_file(e2fsck_t ctx, const char *key, const char *fn)
292 struct string s, s1, s2;
293 char *s0 = 0, *log_dir = 0, *log_fn = 0;
294 int log_dir_wait = 0;
296 char string_index[10];
298 s.s = s1.s = s2.s = 0;
300 profile_get_boolean(ctx->profile, "options", "log_dir_wait", 0, 0,
303 log_fn = string_copy(ctx, fn, 0);
305 profile_get_string(ctx->profile, "options", key,
307 profile_get_string(ctx->profile, "options", "log_dir", 0, 0, &log_dir);
309 if (!log_fn || !log_fn[0])
312 expand_logfn(ctx, log_fn, &s);
314 if (ctx->global_ctx) {
315 sprintf(string_index, "%d",
316 ctx->thread_info.et_thread_index);
317 append_string(&s, ".", 1);
318 append_string(&s, string_index, 0);
322 if ((log_fn[0] == '/') || !log_dir || !log_dir[0])
325 if (log_dir && log_dir[0]) {
326 alloc_string(&s1, strlen(log_dir) + strlen(s.s) + 2);
327 append_string(&s1, log_dir, 0);
328 append_string(&s1, "/", 1);
329 append_string(&s1, s.s, 0);
333 profile_get_string(ctx->profile, "options", "log_dir_fallback", 0, 0,
335 if (log_dir && log_dir[0]) {
336 alloc_string(&s2, strlen(log_dir) + strlen(s.s) + 2);
337 append_string(&s2, log_dir, 0);
338 append_string(&s2, "/", 1);
339 append_string(&s2, s.s, 0);
345 f = fopen(s1.s, "w");
347 f = fopen(s2.s, "w");
348 if (!f && log_dir_wait)
349 f = save_output(s0, s1.s, s2.s);
360 void set_up_logging(e2fsck_t ctx)
362 ctx->logf = set_up_log_file(ctx, "log_filename", ctx->log_fn);
363 ctx->problem_logf = set_up_log_file(ctx, "problem_log_filename",
364 ctx->problem_log_fn);
367 void *e2fsck_allocate_memory(e2fsck_t ctx, unsigned long size,
368 const char *description)
375 sprintf(buf, "Can't allocate %s\n", description);
378 memset(ret, 0, size);
382 errcode_t e2fsck_allocate_context(e2fsck_t *ret)
388 context = malloc(sizeof(struct e2fsck_struct));
392 memset(context, 0, sizeof(struct e2fsck_struct));
394 context->now = 1332006474;
396 context->filesystem_name = "/dev/sda3";
397 context->device_name = "fslabel";
403 int main(int argc, char **argv)
408 putenv("TZ=EST+5:00");
409 e2fsck_allocate_context(&ctx);
410 expand_logfn(ctx, "e2fsck-%N.%h.%u.%D-%T", &s);
413 expand_logfn(ctx, "e2fsck-%N.%h.%u.%Y%m%d-%H%M%S", &s);