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'.
|
- 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
|
- Fixed displaying channels and recording status in the RCU's LED display when
|
||||||
a recording is interrupted due to higher priority.
|
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
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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"
|
#include "config.h"
|
||||||
@ -119,10 +119,9 @@ bool cKeys::Load(const char *FileName)
|
|||||||
|
|
||||||
bool cKeys::Save(void)
|
bool cKeys::Save(void)
|
||||||
{
|
{
|
||||||
//TODO make backup copies???
|
|
||||||
bool result = true;
|
bool result = true;
|
||||||
FILE *f = fopen(fileName, "w");
|
cSafeFile f(fileName);
|
||||||
if (f) {
|
if (f.Open()) {
|
||||||
if (fprintf(f, "Code\t%c\nAddress\t%04X\n", code, address) > 0) {
|
if (fprintf(f, "Code\t%c\nAddress\t%04X\n", code, address) > 0) {
|
||||||
for (tKey *k = keys; k->type != kNone; k++) {
|
for (tKey *k = keys; k->type != kNone; k++) {
|
||||||
if (fprintf(f, "%s\t%08X\n", k->name, k->code) <= 0) {
|
if (fprintf(f, "%s\t%08X\n", k->name, k->code) <= 0) {
|
||||||
@ -133,7 +132,7 @@ bool cKeys::Save(void)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = false;
|
result = false;
|
||||||
fclose(f);
|
f.Close();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
result = false;
|
result = false;
|
||||||
@ -782,8 +781,8 @@ bool cSetup::Save(const char *FileName)
|
|||||||
if (!FileName)
|
if (!FileName)
|
||||||
FileName = fileName;
|
FileName = fileName;
|
||||||
if (FileName) {
|
if (FileName) {
|
||||||
FILE *f = fopen(FileName, "w");
|
cSafeFile f(FileName);
|
||||||
if (f) {
|
if (f.Open()) {
|
||||||
fprintf(f, "# VDR Setup\n");
|
fprintf(f, "# VDR Setup\n");
|
||||||
fprintf(f, "OSDLanguage = %d\n", OSDLanguage);
|
fprintf(f, "OSDLanguage = %d\n", OSDLanguage);
|
||||||
fprintf(f, "PrimaryDVB = %d\n", PrimaryDVB);
|
fprintf(f, "PrimaryDVB = %d\n", PrimaryDVB);
|
||||||
@ -796,7 +795,7 @@ bool cSetup::Save(const char *FileName)
|
|||||||
fprintf(f, "MarginStart = %d\n", MarginStart);
|
fprintf(f, "MarginStart = %d\n", MarginStart);
|
||||||
fprintf(f, "MarginStop = %d\n", MarginStop);
|
fprintf(f, "MarginStop = %d\n", MarginStop);
|
||||||
fprintf(f, "EPGScanTimeout = %d\n", EPGScanTimeout);
|
fprintf(f, "EPGScanTimeout = %d\n", EPGScanTimeout);
|
||||||
fclose(f);
|
f.Close();
|
||||||
isyslog(LOG_INFO, "saved setup to %s", FileName);
|
isyslog(LOG_INFO, "saved setup to %s", FileName);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
13
config.h
13
config.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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
|
#ifndef __CONFIG_H
|
||||||
@ -202,11 +202,10 @@ public:
|
|||||||
}
|
}
|
||||||
bool Save(void)
|
bool Save(void)
|
||||||
{
|
{
|
||||||
//TODO make backup copies???
|
|
||||||
bool result = true;
|
bool result = true;
|
||||||
T *l = (T *)First();
|
T *l = (T *)First();
|
||||||
FILE *f = fopen(fileName, "w");
|
cSafeFile f(fileName);
|
||||||
if (f) {
|
if (f.Open()) {
|
||||||
while (l) {
|
while (l) {
|
||||||
if (!l->Save(f)) {
|
if (!l->Save(f)) {
|
||||||
result = false;
|
result = false;
|
||||||
@ -214,12 +213,10 @@ public:
|
|||||||
}
|
}
|
||||||
l = (T *)l->Next();
|
l = (T *)l->Next();
|
||||||
}
|
}
|
||||||
fclose(f);
|
f.Close();
|
||||||
}
|
}
|
||||||
else {
|
else
|
||||||
LOG_ERROR_STR(fileName);
|
|
||||||
result = false;
|
result = false;
|
||||||
}
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
62
tools.c
62
tools.c
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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
|
#define _GNU_SOURCE
|
||||||
@ -247,6 +247,27 @@ bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks)
|
|||||||
return true;
|
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 -----------------------------------------------------------------
|
// --- cFile -----------------------------------------------------------------
|
||||||
|
|
||||||
bool cFile::files[FD_SETSIZE] = { false };
|
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);
|
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::cListObject(void)
|
cListObject::cListObject(void)
|
||||||
|
16
tools.h
16
tools.h
@ -4,7 +4,7 @@
|
|||||||
* See the main source file 'vdr.c' for copyright information and
|
* See the main source file 'vdr.c' for copyright information and
|
||||||
* how to reach the author.
|
* 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
|
#ifndef __TOOLS_H
|
||||||
@ -48,6 +48,7 @@ uint FreeDiskSpaceMB(const char *Directory);
|
|||||||
bool DirectoryOk(const char *DirName, bool LogErrors = false);
|
bool DirectoryOk(const char *DirName, bool LogErrors = false);
|
||||||
bool MakeDirs(const char *FileName, bool IsDirectory = false);
|
bool MakeDirs(const char *FileName, bool IsDirectory = false);
|
||||||
bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks = false);
|
bool RemoveFileOrDir(const char *FileName, bool FollowSymlinks = false);
|
||||||
|
char *ReadLink(const char *FileName);
|
||||||
|
|
||||||
class cFile {
|
class cFile {
|
||||||
private:
|
private:
|
||||||
@ -68,6 +69,19 @@ public:
|
|||||||
static bool FileReady(int FileDes, int TimeoutMs = 1000);
|
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 {
|
class cListObject {
|
||||||
private:
|
private:
|
||||||
cListObject *prev, *next;
|
cListObject *prev, *next;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user