Implemented safe writing of config files

This commit is contained in:
Klaus Schmidinger 2001-01-13 15:36:31 +01:00
parent ba2c25d183
commit 297e727a59
5 changed files with 90 additions and 18 deletions

View File

@ -340,3 +340,5 @@ Video Disk Recorder Revision History
- Changed the value for Diseqc to '0' in the default 'channels.conf'.
- Fixed displaying channels and recording status in the RCU's LED display when
a recording is interrupted due to higher priority.
- Implemented safe writing of config files (first writes into a temporary file
and then renames it).

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: config.c 1.37 2001/01/13 12:36:32 kls Exp $
* $Id: config.c 1.38 2001/01/13 15:36:31 kls Exp $
*/
#include "config.h"
@ -119,10 +119,9 @@ bool cKeys::Load(const char *FileName)
bool cKeys::Save(void)
{
//TODO make backup copies???
bool result = true;
FILE *f = fopen(fileName, "w");
if (f) {
cSafeFile f(fileName);
if (f.Open()) {
if (fprintf(f, "Code\t%c\nAddress\t%04X\n", code, address) > 0) {
for (tKey *k = keys; k->type != kNone; k++) {
if (fprintf(f, "%s\t%08X\n", k->name, k->code) <= 0) {
@ -133,7 +132,7 @@ bool cKeys::Save(void)
}
else
result = false;
fclose(f);
f.Close();
}
else
result = false;
@ -782,8 +781,8 @@ bool cSetup::Save(const char *FileName)
if (!FileName)
FileName = fileName;
if (FileName) {
FILE *f = fopen(FileName, "w");
if (f) {
cSafeFile f(FileName);
if (f.Open()) {
fprintf(f, "# VDR Setup\n");
fprintf(f, "OSDLanguage = %d\n", OSDLanguage);
fprintf(f, "PrimaryDVB = %d\n", PrimaryDVB);
@ -796,7 +795,7 @@ bool cSetup::Save(const char *FileName)
fprintf(f, "MarginStart = %d\n", MarginStart);
fprintf(f, "MarginStop = %d\n", MarginStop);
fprintf(f, "EPGScanTimeout = %d\n", EPGScanTimeout);
fclose(f);
f.Close();
isyslog(LOG_INFO, "saved setup to %s", FileName);
return true;
}

View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: config.h 1.36 2000/12/25 14:20:09 kls Exp $
* $Id: config.h 1.37 2001/01/13 14:56:29 kls Exp $
*/
#ifndef __CONFIG_H
@ -202,11 +202,10 @@ public:
}
bool Save(void)
{
//TODO make backup copies???
bool result = true;
T *l = (T *)First();
FILE *f = fopen(fileName, "w");
if (f) {
cSafeFile f(fileName);
if (f.Open()) {
while (l) {
if (!l->Save(f)) {
result = false;
@ -214,12 +213,10 @@ public:
}
l = (T *)l->Next();
}
fclose(f);
f.Close();
}
else {
LOG_ERROR_STR(fileName);
else
result = false;
}
return result;
}
};

62
tools.c
View File

@ -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)

16
tools.h
View File

@ -4,7 +4,7 @@
* See the main source file 'vdr.c' for copyright information and
* how to reach the author.
*
* $Id: tools.h 1.22 2000/12/10 11:49:42 kls Exp $
* $Id: tools.h 1.23 2001/01/13 15:36:00 kls Exp $
*/
#ifndef __TOOLS_H
@ -48,6 +48,7 @@ uint FreeDiskSpaceMB(const char *Directory);
bool DirectoryOk(const char *DirName, bool LogErrors = false);
bool MakeDirs(const char *FileName, bool IsDirectory = false);
bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks = false);
char *ReadLink(const char *FileName);
class cFile {
private:
@ -68,6 +69,19 @@ public:
static bool FileReady(int FileDes, int TimeoutMs = 1000);
};
class cSafeFile {
private:
FILE *f;
char *fileName;
char *tempName;
public:
cSafeFile(const char *FileName);
~cSafeFile();
operator FILE* () { return f; }
bool Open(void);
void Close(void);
};
class cListObject {
private:
cListObject *prev, *next;