diff options
author | June McEnroe <june@causal.agency> | 2021-06-24 16:58:28 -0400 |
---|---|---|
committer | June McEnroe <june@causal.agency> | 2021-06-25 11:50:14 -0400 |
commit | fece6e6eb620068d352ceb0433c3d74d8c22f35b (patch) | |
tree | 1a325d74331aa6a55611cdf900a5b3376c2f556c | |
parent | Encourage packagers to patch in text macros (diff) | |
download | catgirl-fece6e6eb620068d352ceb0433c3d74d8c22f35b.tar.gz catgirl-fece6e6eb620068d352ceb0433c3d74d8c22f35b.zip |
Keep log directory open, use mkdirat(2) and openat(2)
-rw-r--r-- | chat.c | 7 | ||||
-rw-r--r-- | chat.h | 2 | ||||
-rw-r--r-- | log.c | 45 |
3 files changed, 37 insertions, 17 deletions
diff --git a/chat.c b/chat.c index a8940c3..71bfb7b 100644 --- a/chat.c +++ b/chat.c @@ -144,6 +144,7 @@ int main(int argc, char *argv[]) { const char *cert = NULL; const char *priv = NULL; + bool log = false; bool sasl = false; const char *pass = NULL; const char *nick = NULL; @@ -212,7 +213,7 @@ int main(int argc, char *argv[]) { break; case 'i': filterAdd(Ice, optarg); break; case 'j': self.join = optarg; break; case 'k': priv = optarg; - break; case 'l': logEnable = true; + break; case 'l': log = true; logOpen(); break; case 'm': self.mode = optarg; break; case 'n': nick = optarg; break; case 'o': insecure = true; printCert = true; @@ -277,7 +278,7 @@ int main(int argc, char *argv[]) { } #ifdef __OpenBSD__ - if (self.restricted && logEnable) { + if (self.restricted && log) { const char *logdir = dataMkdir(""); int error = unveil(logdir, "wc"); if (error) err(EX_OSERR, "unveil"); @@ -285,7 +286,7 @@ int main(int argc, char *argv[]) { char promises[64] = "stdio tty"; char *ptr = &promises[strlen(promises)], *end = &promises[sizeof(promises)]; - if (logEnable) ptr = seprintf(ptr, end, " wpath cpath"); + if (log) ptr = seprintf(ptr, end, " wpath cpath"); if (!self.restricted) ptr = seprintf(ptr, end, " proc exec"); char *promisesInitial = ptr; diff --git a/chat.h b/chat.h index 74c4abf..a4c7670 100644 --- a/chat.h +++ b/chat.h @@ -394,7 +394,7 @@ struct Filter filterAdd(enum Heat heat, const char *pattern); bool filterRemove(struct Filter filter); enum Heat filterCheck(enum Heat heat, uint id, const struct Message *msg); -extern bool logEnable; +void logOpen(void); void logFormat(uint id, const time_t *time, const char *format, ...) __attribute__((format(printf, 3, 4))); void logClose(void); diff --git a/log.c b/log.c index 2efb2e4..415e1dc 100644 --- a/log.c +++ b/log.c @@ -27,16 +27,32 @@ #include <assert.h> #include <err.h> +#include <errno.h> +#include <fcntl.h> #include <limits.h> #include <stdarg.h> #include <stdio.h> #include <stdlib.h> +#include <sys/stat.h> #include <sysexits.h> #include <time.h> +#include <unistd.h> #include "chat.h" -bool logEnable; +static int logDir = -1; + +void logOpen(void) { + dataMkdir(""); + const char *path = dataMkdir("log"); + logDir = open(path, O_RDONLY | O_CLOEXEC); + if (logDir < 0) err(EX_CANTCREAT, "%s", path); +} + +static void logMkdir(const char *path) { + int error = mkdirat(logDir, path, S_IRWXU); + if (error && errno != EEXIST) err(EX_CANTCREAT, "log/%s", path); +} static struct { int year; @@ -62,44 +78,47 @@ static FILE *logFile(uint id, const struct tm *tm) { logs[id].month = tm->tm_mon; logs[id].day = tm->tm_mday; - char path[PATH_MAX] = "log"; - size_t len = strlen(path); - dataMkdir(""); - dataMkdir(path); - - path[len++] = '/'; + size_t len = 0; + char path[PATH_MAX]; for (const char *ch = network.name; *ch; ++ch) { path[len++] = (*ch == '/' ? '_' : *ch); } path[len] = '\0'; - dataMkdir(path); + logMkdir(path); path[len++] = '/'; for (const char *ch = idNames[id]; *ch; ++ch) { path[len++] = (*ch == '/' ? '_' : *ch); } path[len] = '\0'; - dataMkdir(path); + logMkdir(path); strftime(&path[len], sizeof(path) - len, "/%F.log", tm); - logs[id].file = dataOpen(path, "ae"); - if (!logs[id].file) exit(EX_CANTCREAT); + int fd = openat( + logDir, path, + O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, + S_IRUSR | S_IWUSR + ); + if (fd < 0) err(EX_CANTCREAT, "log/%s", path); + logs[id].file = fdopen(fd, "a"); + if (!logs[id].file) err(EX_OSERR, "fdopen"); setlinebuf(logs[id].file); return logs[id].file; } void logClose(void) { - if (!logEnable) return; + if (logDir < 0) return; for (uint id = 0; id < IDCap; ++id) { if (!logs[id].file) continue; int error = fclose(logs[id].file); if (error) err(EX_IOERR, "%s", idNames[id]); } + close(logDir); } void logFormat(uint id, const time_t *src, const char *format, ...) { - if (!logEnable) return; + if (logDir < 0) return; time_t ts = (src ? *src : time(NULL)); struct tm *tm = localtime(&ts); |