diff options
author | Alan Coopersmith <alan.coopersmith@oracle.com> | 2016-01-01 18:11:14 -0800 |
---|---|---|
committer | Adam Jackson <ajax@redhat.com> | 2016-01-05 14:51:16 -0500 |
commit | edcb6426f20c3be5dd5f50b76a686754aef2f64e (patch) | |
tree | ec4f49adfaa843d43195f3cf50502849f7df14db | |
parent | fe8562f5316d8c74ca074ad145295c65ddff5fc2 (diff) |
Use unique logfile names when starting server with -displayfd
Fixes https://bugs.freedesktop.org/show_bug.cgi?id=93212
Previously all X servers started with -displayfd would overwrite
Xorg.0.log - now a temporary name of Xorg.pid-<pid>.log is used
until after -displayfd finds an open display - then it is renamed
to the traditional Xorg.<display>.log name.
Reviewed-by: Adam Jackson <ajax@redhat.com>
Signed-off-by: Alan Coopersmith <alan.coopersmith@oracle.com>
-rw-r--r-- | include/os.h | 2 | ||||
-rw-r--r-- | os/connection.c | 1 | ||||
-rw-r--r-- | os/log.c | 126 |
3 files changed, 101 insertions, 28 deletions
diff --git a/include/os.h b/include/os.h index e7c193669..461d5d6ce 100644 --- a/include/os.h +++ b/include/os.h @@ -626,6 +626,8 @@ typedef enum { extern _X_EXPORT const char * LogInit(const char *fname, const char *backup); +extern void +LogSetDisplay(void); extern _X_EXPORT void LogClose(enum ExitCode error); extern _X_EXPORT Bool diff --git a/os/connection.c b/os/connection.c index 8d866f61c..8e7513902 100644 --- a/os/connection.c +++ b/os/connection.c @@ -431,6 +431,7 @@ CreateWellKnownSockets(void) FatalError("Failed to find a socket to listen on"); snprintf(dynamic_display, sizeof(dynamic_display), "%d", i); display = dynamic_display; + LogSetDisplay(); } ListenTransFds = xallocarray(ListenTransCount, sizeof (int)); @@ -85,6 +85,7 @@ OR PERFORMANCE OF THIS SOFTWARE. #include <sys/stat.h> #include <stdarg.h> #include <stdlib.h> /* for malloc() */ +#include <errno.h> #include "input.h" #include "site.h" @@ -181,16 +182,64 @@ strlen_sigsafe(const char *s) } /* + * LogFilePrep is called to setup files for logging, including getting + * an old file out of the way, but it doesn't actually open the file, + * since it may be used for renaming a file we're already logging to. + */ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" + +static char * +LogFilePrep(const char *fname, const char *backup, const char *idstring) +{ + char *logFileName = NULL; + + if (asprintf(&logFileName, fname, idstring) == -1) + FatalError("Cannot allocate space for the log file name\n"); + + if (backup && *backup) { + struct stat buf; + + if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) { + char *suffix; + char *oldLog; + + if ((asprintf(&suffix, backup, idstring) == -1) || + (asprintf(&oldLog, "%s%s", logFileName, suffix) == -1)) { + FatalError("Cannot allocate space for the log file name\n"); + } + free(suffix); + + if (rename(logFileName, oldLog) == -1) { + FatalError("Cannot move old log file \"%s\" to \"%s\"\n", + logFileName, oldLog); + } + free(oldLog); + } + } + else { + if (remove(logFileName) != 0) { + FatalError("Cannot remove old log file \"%s\": %s\n", + logFileName, strerror(errno)); + } + } + + return logFileName; +} +#pragma GCC diagnostic pop + +/* * LogInit is called to start logging to a file. It is also called (with * NULL arguments) when logging to a file is not wanted. It must always be * called, otherwise log messages will continue to accumulate in a buffer. * * %s, if present in the fname or backup strings, is expanded to the display - * string. + * string (or to a string containing the pid if the display is not yet set). */ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-nonliteral" +static char *saved_log_fname; +static char *saved_log_backup; +static char *saved_log_tempname; const char * LogInit(const char *fname, const char *backup) @@ -198,30 +247,22 @@ LogInit(const char *fname, const char *backup) char *logFileName = NULL; if (fname && *fname) { - if (asprintf(&logFileName, fname, display) == -1) - FatalError("Cannot allocate space for the log file name\n"); - - if (backup && *backup) { - struct stat buf; - - if (!stat(logFileName, &buf) && S_ISREG(buf.st_mode)) { - char *suffix; - char *oldLog; - - if ((asprintf(&suffix, backup, display) == -1) || - (asprintf(&oldLog, "%s%s", logFileName, suffix) == -1)) - FatalError("Cannot allocate space for the log file name\n"); - free(suffix); - if (rename(logFileName, oldLog) == -1) { - FatalError("Cannot move old log file \"%s\" to \"%s\"\n", - logFileName, oldLog); - } - free(oldLog); - } - } - else { - unlink(logFileName); - } + if (displayfd != -1) { + /* Display isn't set yet, so we can't use it in filenames yet. */ + char pidstring[32]; + snprintf(pidstring, sizeof(pidstring), "pid-%ld", + (unsigned long) getpid()); + logFileName = LogFilePrep(fname, backup, pidstring); + saved_log_tempname = logFileName; + + /* Save the patterns for use when the display is named. */ + saved_log_fname = strdup(fname); + if (backup == NULL) + saved_log_backup = NULL; + else + saved_log_backup = strdup(backup); + } else + logFileName = LogFilePrep(fname, backup, display); if ((logFile = fopen(logFileName, "w")) == NULL) FatalError("Cannot open log file \"%s\"\n", logFileName); setvbuf(logFile, NULL, _IONBF, 0); @@ -251,7 +292,36 @@ LogInit(const char *fname, const char *backup) return logFileName; } -#pragma GCC diagnostic pop + +void +LogSetDisplay(void) +{ + if (saved_log_fname) { + char *logFileName; + + logFileName = LogFilePrep(saved_log_fname, saved_log_backup, display); + + if (rename(saved_log_tempname, logFileName) == 0) { + LogMessageVerb(X_PROBED, 0, + "Log file renamed from \"%s\" to \"%s\"\n", + saved_log_tempname, logFileName); + + if (strlen(saved_log_tempname) >= strlen(logFileName)) + strncpy(saved_log_tempname, logFileName, + strlen(saved_log_tempname)); + } + else { + ErrorF("Failed to rename log file \"%s\" to \"%s\": %s\n", + saved_log_tempname, logFileName, strerror(errno)); + } + + /* free newly allocated string - can't free old one since existing + pointers to it may exist in DDX callers. */ + free(logFileName); + free(saved_log_fname); + free(saved_log_backup); + } +} void LogClose(enum ExitCode error) |