From a756aac7ed08de6ab876fbfe88a46b07360a8922 Mon Sep 17 00:00:00 2001 From: Ingo Huerner Date: Fri, 24 Jan 2014 14:33:15 +0100 Subject: File backups on seperate partition; Fixed bug 146; created performance benchmark; minor optimization; disabled PAS interface by default, to enable use configure --enable-pasinterface --- src/persistence_client_library_backup_filelist.c | 457 +++++++++++++++++++++++ 1 file changed, 457 insertions(+) (limited to 'src/persistence_client_library_backup_filelist.c') diff --git a/src/persistence_client_library_backup_filelist.c b/src/persistence_client_library_backup_filelist.c index 24cf12b..168f30c 100644 --- a/src/persistence_client_library_backup_filelist.c +++ b/src/persistence_client_library_backup_filelist.c @@ -17,6 +17,7 @@ */ #include "persistence_client_library_backup_filelist.h" +#include "persistence_client_library_handle.h" #include "rbtree.h" #include "../include_protected/crc32.h" #include "../include_protected/persistence_client_library_data_organization.h" @@ -317,3 +318,459 @@ void key_val_rel(void *p ) } +int pclCreateFile(const char* path) +{ + const char* delimiters = "/\n"; // search for blank and end of line + char* tokenArray[24]; + char* thePath = (char*)path; + int numTokens = 0, i = 0, validPath = 1; + int handle = 0; + + tokenArray[numTokens++] = strtok(thePath, delimiters); + while(tokenArray[numTokens-1] != NULL ) + { + tokenArray[numTokens] = strtok(NULL, delimiters); + if(tokenArray[numTokens] != NULL) + { + numTokens++; + if(numTokens >= 24) + { + validPath = 0; + break; + } + } + else + { + break; + } + } + + if(validPath == 1) + { + char createPath[DbPathMaxLen] = {0}; + snprintf(createPath, DbPathMaxLen, "/%s",tokenArray[0] ); + for(i=1; i no valid path to create: "), DLT_STRING(path) ); + } + + return handle; +} + + +int pclVerifyConsistency(const char* origPath, const char* backupPath, const char* csumPath, int openFlags) +{ + int handle = 0, readSize = 0; + int backupAvail = 0, csumAvail = 0; + int fdCsum = 0, fdBackup = 0; + + char origCsumBuf[ChecksumBufSize] = {0}; + char backCsumBuf[ChecksumBufSize] = {0}; + char csumBuf[ChecksumBufSize] = {0}; + + // check if we have a backup and checksum file + backupAvail = access(backupPath, F_OK); + csumAvail = access(csumPath, F_OK); + + // ************************************************* + // there is a backup file and a checksum + // ************************************************* + if( (backupAvail == 0) && (csumAvail == 0) ) + { + DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclVerifyConsistency => there is a backup file AND a checksum")); + // calculate checksum form backup file + fdBackup = open(backupPath, O_RDONLY); + if(fdBackup != -1) + { + pclCalcCrc32Csum(fdBackup, backCsumBuf); + + fdCsum = open(csumPath, O_RDONLY); + if(fdCsum != -1) + { + readSize = read(fdCsum, csumBuf, ChecksumBufSize); + if(readSize > 0) + { + if(strcmp(csumBuf, backCsumBuf) == 0) + { + // checksum matches ==> replace with original file + handle = pclRecoverFromBackup(fdBackup, origPath); + } + else + { + // checksum does not match, check checksum with original file + handle = open(origPath, openFlags); + if(handle != -1) + { + pclCalcCrc32Csum(handle, origCsumBuf); + if(strcmp(csumBuf, origCsumBuf) != 0) + { + close(handle); + handle = -1; // error: file corrupt + } + // else case: checksum matches ==> keep original file ==> nothing to do + + } + else + { + close(handle); + handle = -1; // error: file corrupt + } + } + } + close(fdCsum); + } + else + { + close(fdCsum); + handle = -1; // error: file corrupt + } + } + else + { + handle = -1; + } + close(fdBackup); + } + // ************************************************* + // there is ONLY a checksum file + // ************************************************* + else if(csumAvail == 0) + { + DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclVerifyConsistency => there is ONLY a checksum file")); + + fdCsum = open(csumPath, O_RDONLY); + if(fdCsum != -1) + { + readSize = read(fdCsum, csumBuf, ChecksumBufSize); + if(readSize <= 0) + { + DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclVerifyConsistency => read checksum: invalid readSize")); + } + close(fdCsum); + + // calculate the checksum form the original file to see if it matches + handle = open(origPath, openFlags); + if(handle != -1) + { + pclCalcCrc32Csum(handle, origCsumBuf); + + if(strcmp(csumBuf, origCsumBuf) != 0) + { + close(handle); + handle = -1; // checksum does NOT match ==> error: file corrupt + } + // else case: checksum matches ==> keep original file ==> nothing to do + } + else + { + close(handle); + handle = -1; // error: file corrupt + } + } + else + { + close(fdCsum); + handle = -1; // error: file corrupt + } + } + // ************************************************* + // there is ONLY a backup file + // ************************************************* + else if(backupAvail == 0) + { + DLT_LOG(gDLTContext, DLT_LOG_INFO, DLT_STRING("pclVerifyConsistency => there is ONLY a backup file")); + + // calculate checksum form backup file + fdBackup = open(backupPath, O_RDONLY); + if(fdBackup != -1) + { + pclCalcCrc32Csum(fdBackup, backCsumBuf); + close(fdBackup); + + // calculate the checksum form the original file to see if it matches + handle = open(origPath, openFlags); + if(handle != -1) + { + pclCalcCrc32Csum(handle, origCsumBuf); + + if(strcmp(backCsumBuf, origCsumBuf) != 0) + { + close(handle); + handle = -1; // checksum does NOT match ==> error: file corrupt + } + // else case: checksum matches ==> keep original file ==> nothing to do + + } + else + { + close(handle); + handle = -1; // error: file corrupt + } + } + else + { + close(fdBackup); + handle = -1; // error: file corrupt + } + } + // for else case: nothing to do + + + // if we are in an inconsistent state: delete file, backup and checksum + if(handle == -1) + { + remove(origPath); + remove(backupPath); + remove(csumPath); + } + + return handle; +} + + + +int pclRecoverFromBackup(int backupFd, const char* original) +{ + int handle = 0; + int readSize = 0; + char buffer[RDRWBufferSize]; + + handle = open(original, O_TRUNC | O_RDWR); + if(handle != -1) + { + // copy data from one file to another + while((readSize = read(backupFd, buffer, RDRWBufferSize)) > 0) + { + if(write(handle, buffer, readSize) != readSize) + { + DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclRecoverFromBackup => couldn't write whole buffer")); + break; + } + } + + } + + return handle; +} + + + +int pclCreateBackup(const char* dstPath, int srcfd, const char* csumPath, const char* csumBuf) +{ + int dstFd = 0, csfd = 0; + int readSize = -1; + char buffer[RDRWBufferSize]; + + if(access(dstPath, F_OK) != 0) + { + char pathToCreate[DbPathMaxLen] = {0}; + strncpy(pathToCreate, dstPath, DbPathMaxLen); + pclCreateFileAndPath(pathToCreate); + } + + // create checksum file and and write checksum + csfd = open(csumPath, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); + if(csfd != -1) + { + int csumSize = strlen(csumBuf); + if(write(csfd, csumBuf, csumSize) != csumSize) + { + DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclCreateBackup => failed to write checksum to file")); + } + close(csfd); + } + else + { + DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclCreateBackup => failed to create checksum file:"), DLT_STRING(strerror(errno)) ); + } + + // create backup file, user and group has read/write permission, others have read permission + dstFd = open(dstPath, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); + if(dstFd != -1) + { + off_t curPos = 0; + // remember the current position + curPos = lseek(srcfd, 0, SEEK_CUR); + + // copy data from one file to another + while((readSize = read(srcfd, buffer, RDRWBufferSize)) > 0) + { + if(write(dstFd, buffer, readSize) != readSize) + { + DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclCreateBackup => couldn't write whole buffer")); + break; + } + } + + if(readSize == -1) + DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pcl_create_backup => error copying file")); + + if((readSize = close(dstFd)) == -1) + DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pcl_create_backup => error closing fd")); + + // set back to the position + lseek(srcfd, curPos, SEEK_SET); + } + else + { + DLT_LOG(gDLTContext, DLT_LOG_ERROR, DLT_STRING("pclCreateBackup => failed to open backup file"), + DLT_STRING(dstPath), DLT_STRING(strerror(errno))); + } + + return readSize; +} + + + +int pclCalcCrc32Csum(int fd, char crc32sum[]) +{ + int rval = 1; + + if(crc32sum != 0) + { + char* buf; + struct stat statBuf; + + fstat(fd, &statBuf); + buf = malloc((unsigned int)statBuf.st_size); + + if(buf != 0) + { + off_t curPos = 0; + // remember the current position + curPos = lseek(fd, 0, SEEK_CUR); + + if(curPos != 0) + { + // set to beginning of the file + lseek(fd, 0, SEEK_SET); + } + + while((rval = read(fd, buf, statBuf.st_size)) > 0) + { + unsigned int crc = 0; + crc = pclCrc32(crc, (unsigned char*)buf, statBuf.st_size); + snprintf(crc32sum, ChecksumBufSize-1, "%x", crc); + } + + // set back to the position + lseek(fd, curPos, SEEK_SET); + + free(buf); + } + } + return rval; +} + + + +int pclBackupNeeded(const char* path) +{ + return need_backup_key(pclCrc32(0, (const unsigned char*)path, strlen(path))); +} + + + +int pclCreateFileAndPath(const char* path) +{ + const char* delimiters = "/\n"; // search for blank and end of line + char* tokenArray[24]; + char* thePath = (char*)path; + char createPath[DbPathMaxLen] = {0}; + int numTokens = 0, i = 0, validPath = 1; + int rval = -1; + + tokenArray[numTokens++] = strtok(thePath, delimiters); + while(tokenArray[numTokens-1] != NULL ) + { + tokenArray[numTokens] = strtok(NULL, delimiters); + if(tokenArray[numTokens] != NULL) + { + numTokens++; + if(numTokens >= 24) + { + validPath = 0; + break; + } + } + else + { + break; + } + } + + if(validPath == 1) + { + snprintf(createPath, DbPathMaxLen, "/%s",tokenArray[0] ); + for(i=1; i no valid path to create:"), DLT_STRING(path)); + } + + return rval; +} + + + +int pclGetPosixPermission(PersistencePermission_e permission) +{ + int posixPerm = 0; + + switch( (int)permission) + { + case PersistencePermission_ReadWrite: + posixPerm = O_RDWR; + break; + case PersistencePermission_ReadOnly: + posixPerm = O_RDONLY; + break; + case PersistencePermission_WriteOnly: + posixPerm = O_WRONLY; + break; + default: + posixPerm = O_RDONLY; + break; + } + + return posixPerm; +} + + + -- cgit v1.2.1