summaryrefslogtreecommitdiff
path: root/tools.c
diff options
context:
space:
mode:
authorKlaus Schmidinger <vdr@tvdr.de>2001-01-13 15:36:31 +0100
committerKlaus Schmidinger <vdr@tvdr.de>2001-01-13 15:36:31 +0100
commit297e727a59b2e08f8c414739325f8df390b567c4 (patch)
tree0eb697cc5be0968b3fbcc7151f87e2fc5b8ac647 /tools.c
parentba2c25d1835dae0030b12e35b814c2b0ab9406fb (diff)
downloadvdr-297e727a59b2e08f8c414739325f8df390b567c4.tar.gz
vdr-297e727a59b2e08f8c414739325f8df390b567c4.tar.bz2
Implemented safe writing of config files
Diffstat (limited to 'tools.c')
-rw-r--r--tools.c62
1 files changed, 61 insertions, 1 deletions
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)