diff options
| author | Markus Mittendrein <git@maxmitti.tk> | 2019-08-31 13:51:07 +0200 |
|---|---|---|
| committer | Markus Mittendrein <git@maxmitti.tk> | 2019-08-31 13:51:07 +0200 |
| commit | d3ba5dcfd4f21e27c4ead7bde29374e66764179c (patch) | |
| tree | 768e83ed63b9cf6410cebaba80c897d50ef73fcb /src | |
| parent | 4fc01f7685ea96d5d3dce29ab467bae39255600d (diff) | |
| download | cc4group-d3ba5dcfd4f21e27c4ead7bde29374e66764179c.tar.gz cc4group-d3ba5dcfd4f21e27c4ead7bde29374e66764179c.zip | |
use a temporary file in saveOverwrite to avoid possible data loss in error cases (fixes SIGBUS in c4touch)
Diffstat (limited to 'src')
| -rw-r--r-- | src/cc4group.c | 75 |
1 files changed, 61 insertions, 14 deletions
diff --git a/src/cc4group.c b/src/cc4group.c index 93dbd3d..b086110 100644 --- a/src/cc4group.c +++ b/src/cc4group.c @@ -388,15 +388,30 @@ static void* cc4group_mapSizedWriteFd(CC4Group* const this, int fd, size_t size) } static const char tmpFileTemplate[] = "cc4grouptmpXXXXXX"; +#define tmpFileNameLength (sizeof(tmpFileTemplate) / sizeof(tmpFileTemplate[0])) typedef struct { void* addr; size_t size; - char fileName[sizeof(tmpFileTemplate) / sizeof(tmpFileTemplate[0])]; + char fileName[tmpFileNameLength]; bool unlinkLater; const CC4Group* group; } MunmapData; +// *fileNameTarget must be at least tmpFileNameLength long! +static int cc4group_createTmpFile(CC4Group* const this, char* const fileNameTarget) +{ + strncpy(fileNameTarget, tmpFileTemplate, tmpFileNameLength); + int tmpFile = mkstemp(fileNameTarget); + if(tmpFile == -1) + { + SET_ERRNO_ERROR("mkstemp: Creating and opening the tmp file"); + fileNameTarget[0] = '\0'; + } + + return tmpFile; +} + static void cc4group_tryWarnUnlink(const CC4Group* const this, const char* const fileName) { if(unlink(fileName) == -1) @@ -430,14 +445,10 @@ static void* cc4group_createTmpMemoryFile(CC4Group* const this, const size_t siz return NULL; } - strncpy(unmapData->fileName, tmpFileTemplate, sizeof(unmapData->fileName) / sizeof(unmapData->fileName[0])); - void* ret = NULL; - int tmpFile = mkstemp(unmapData->fileName); + int tmpFile = cc4group_createTmpFile(this, unmapData->fileName); if(tmpFile == -1) { - SET_ERRNO_ERROR("mkstemp: Creating and opening the tmp file"); - unmapData->fileName[0] = '\0'; goto ret; } @@ -2586,7 +2597,7 @@ static bool cc4group_saveToFd(CC4Group* const this, int fd) return cc4group_saveWithWriteCallback(this, cc4group_writeToFdCallback, &fd, 0); } -static bool cc4group_saveIt(CC4Group* const this, const char* const path, bool const overwrite) +static bool cc4group_save(CC4Group* const this, const char* const path) { assert(this); assert(path); @@ -2598,7 +2609,7 @@ static bool cc4group_saveIt(CC4Group* const this, const char* const path, bool c } bool success = false; - int file = open(path, O_WRONLY | O_BINARY | O_CREAT | (overwrite ? O_TRUNC : O_EXCL), 0644); + int file = open(path, O_WRONLY | O_BINARY | O_CREAT | O_EXCL, 0644); if(file == -1) { @@ -2627,14 +2638,50 @@ static bool cc4group_saveIt(CC4Group* const this, const char* const path, bool c return success; } -static bool cc4group_save(CC4Group* const this, const char* const path) -{ - return cc4group_saveIt(this, path, false); -} - static bool cc4group_saveOverwrite(CC4Group* const this, const char* const path) { - return cc4group_saveIt(this, path, true); + if(strcmp(path, "-") == 0) + { + return cc4group_save(this, path); + } + + char tmpFileName[tmpFileNameLength]; + int tmpFile = cc4group_createTmpFile(this, tmpFileName); + + if(tmpFile == -1) + { + return false; + } + + bool success = false; + if(!cc4group_saveWithWriteCallback(this, cc4group_writeToFdCallback, &tmpFile, 0)) + { + goto ret; + } + + if(rename(tmpFileName, path) == 0) + { + success = true; + } + else + { + SET_ERRNO_ERROR("rename: can't rename the temporary file to the target path"); + } + + if(close(tmpFile) == -1) + { + cc4group_warn(this, "close: Closing the target group file failed: %s", strerror(errno)); + } + +ret: + if(!success) + { + if(unlink(tmpFileName) == -1) + { + cc4group_warn(this, "unlink: Deleting the incomplete temporary group file \"%s\" failed: %s", tmpFileName, strerror(errno)); + } + } + return success; } static bool cc4group_getEntryInfoForEntry(CC4Group* const this, const C4GroupEntryData* const entry, CC4Group_EntryInfo* const info, bool const lazy) |
