From 297e727a59b2e08f8c414739325f8df390b567c4 Mon Sep 17 00:00:00 2001 From: Klaus Schmidinger Date: Sat, 13 Jan 2001 15:36:31 +0100 Subject: Implemented safe writing of config files --- tools.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) (limited to 'tools.c') diff --git a/tools.c b/tools.c index 1caaa9fd..cd2c60f8 100644 --- a/tools.c +++ b/tools.c @@ -4,7 +4,7 @@ * See the main source file 'vdr.c' for copyright information and * how to reach the author. * - * $Id: tools.c 1.26 2001/01/13 12:17:30 kls Exp $ + * $Id: tools.c 1.27 2001/01/13 15:35:02 kls Exp $ */ #define _GNU_SOURCE @@ -247,6 +247,27 @@ bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks) return true; } +char *ReadLink(const char *FileName) +{ + char RealName[_POSIX_PATH_MAX]; + const char *TargetName = NULL; + int n = readlink(FileName, RealName, sizeof(RealName) - 1); + if (n < 0) { + if (errno == ENOENT || errno == EINVAL) // file doesn't exist or is not a symlink + TargetName = FileName; + else { // some other error occurred + LOG_ERROR_STR(FileName); + } + } + else if (n < int(sizeof(RealName))) { // got it! + RealName[n] = 0; + TargetName = RealName; + } + else + esyslog(LOG_ERR, "ERROR: symlink's target name too long: %s", FileName); + return TargetName ? strdup(TargetName) : NULL; +} + // --- cFile ----------------------------------------------------------------- bool cFile::files[FD_SETSIZE] = { false }; @@ -367,6 +388,45 @@ bool cFile::FileReady(int FileDes, int TimeoutMs) return select(FD_SETSIZE, &set, NULL, NULL, &timeout) > 0 && FD_ISSET(FileDes, &set); } +// --- cSafeFile ------------------------------------------------------------- + +cSafeFile::cSafeFile(const char *FileName) +{ + f = NULL; + fileName = ReadLink(FileName); + tempName = fileName ? new char[strlen(fileName) + 5] : NULL; + if (tempName) + strcat(strcpy(tempName, fileName), ".$$$"); +} + +cSafeFile::~cSafeFile() +{ + if (f) + fclose(f); + unlink(tempName); + delete fileName; + delete tempName; +} + +bool cSafeFile::Open(void) +{ + if (!f && fileName && tempName) { + f = fopen(tempName, "w"); + if (!f) + LOG_ERROR_STR(tempName); + } + return f != NULL; +} + +void cSafeFile::Close(void) +{ + if (f) { + fclose(f); + f = NULL; + rename(tempName, fileName); + } +} + // --- cListObject ----------------------------------------------------------- cListObject::cListObject(void) -- cgit v1.2.3