mirror of
https://github.com/VDR4Arch/vdr.git
synced 2023-10-10 13:36:52 +02:00
Implemented safe writing of config files
This commit is contained in:
parent
ba2c25d183
commit
297e727a59
2
HISTORY
2
HISTORY
@ -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).
|
||||
|
15
config.c
15
config.c
@ -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;
|
||||
}
|
||||
|
13
config.h
13
config.h
@ -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
62
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)
|
||||
|
16
tools.h
16
tools.h
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user