int verbose;
const char *szLogRoot;
int truncate;
+ const char *linkfile;
};
typedef struct rotate_status rotate_status_t;
fprintf(stderr, "%s\n", reason);
}
fprintf(stderr,
- "Usage: %s [-v] [-l] [-f] [-t] <logfile> "
+ "Usage: %s [-v] [-l] [-L linkname] [-f] [-t] <logfile> "
"{<rotation time in seconds>|<rotation size>(B|K|M|G)} "
"[offset minutes from UTC]\n\n",
argv0);
"when the file size\nis reached a new log is started. If the "
"-t option is specified, the specified\nfile will be truncated "
"instead of rotated, and is useful where tail is used to\n"
- "process logs in real time.\n");
+ "process logs in real time. If the -L option is specified, "
+ "a hard link will be\nmade from the current log file to the "
+ "specified filename.\n");
exit(1);
}
if (config->verbose) {
apr_finfo_t finfo;
apr_int32_t wanted = APR_FINFO_NAME;
- if (apr_file_info_get(&finfo, wanted, file) == APR_SUCCESS) {
- fprintf(stderr, "Closing file %s (%s)\n", finfo.name, finfo.fname);
+ apr_status_t rv = apr_file_info_get(&finfo, wanted, file);
+ if ((rv == APR_SUCCESS) || (rv == APR_INCOMPLETE)) {
+ if (finfo.valid & APR_FINFO_NAME) {
+ fprintf(stderr, "Closing file %s (%s)\n", finfo.name, finfo.fname);
+ } else {
+ fprintf(stderr, "Closing file %s\n", finfo.fname);
+ }
}
}
apr_file_close(file);
}
else {
if (config->truncate) {
- snprintf(status->filename, sizeof(status->filename), "%s", config->szLogRoot);
+ apr_snprintf(status->filename, sizeof(status->filename), "%s", config->szLogRoot);
}
else {
- snprintf(status->filename, sizeof(status->filename), "%s.%010d", config->szLogRoot,
+ apr_snprintf(status->filename, sizeof(status->filename), "%s.%010d", config->szLogRoot,
tLogStart);
}
}
status->pfile_prev = NULL;
}
status->nMessCount = 0;
+ if (config->linkfile) {
+ apr_file_remove(config->linkfile, status->pfile);
+ if (config->verbose) {
+ fprintf(stderr,"Linking %s to %s\n", status->filename, config->linkfile);
+ }
+ rv = apr_file_link(status->filename, config->linkfile);
+ if (rv != APR_SUCCESS) {
+ char error[120];
+ apr_strerror(rv, error, sizeof error);
+ fprintf(stderr, "Error linking file %s to %s (%s)\n",
+ status->filename, config->linkfile, error);
+ exit(2);
+ }
+ }
}
/*
apr_getopt_t *opt;
apr_status_t rv;
char c;
- const char *optarg;
+ const char *opt_arg;
const char *err = NULL;
apr_app_initialize(&argc, &argv, NULL);
apr_pool_create(&status.pool, NULL);
apr_getopt_init(&opt, status.pool, argc, argv);
- while ((rv = apr_getopt(opt, "lftv", &c, &optarg)) == APR_SUCCESS) {
+ while ((rv = apr_getopt(opt, "lL:ftv", &c, &opt_arg)) == APR_SUCCESS) {
switch (c) {
case 'l':
config.use_localtime = 1;
break;
+ case 'L':
+ config.linkfile = opt_arg;
+ break;
case 'f':
config.force_open = 1;
break;