diff options
author | Ingo Huerner <ingo.huerner@xse.de> | 2013-04-08 23:49:35 +0200 |
---|---|---|
committer | Ingo Huerner <ingo.huerner@xse.de> | 2013-04-08 23:49:35 +0200 |
commit | cc01613b747e0ec2fbdad19b4ae3e97ea4d2fd14 (patch) | |
tree | 687eb2004f15438b55c08a63e180adc3a6fddee9 | |
parent | 9f0a5460f1d7b62b4588dcd1538f3ae8f4802e41 (diff) | |
download | persistence-client-library-cc01613b747e0ec2fbdad19b4ae3e97ea4d2fd14.tar.gz |
Added backup file and checksum creation for files
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | include/persistence_client_library_key.h | 18 | ||||
-rw-r--r-- | include_protected/persistence_client_library_data_organization.h | 4 | ||||
-rw-r--r-- | include_protected/persistence_client_library_db_access.h | 2 | ||||
-rw-r--r-- | include_protected/persistence_client_library_rc_table.h | 18 | ||||
-rw-r--r-- | persistence_client_library.pc.in | 4 | ||||
-rw-r--r-- | src/persistence_client_library_data_organization.c | 2 | ||||
-rw-r--r-- | src/persistence_client_library_db_access.c | 46 | ||||
-rw-r--r-- | src/persistence_client_library_dbus_service.c | 2 | ||||
-rw-r--r-- | src/persistence_client_library_file.c | 409 | ||||
-rw-r--r-- | src/persistence_client_library_handle.c | 10 | ||||
-rw-r--r-- | src/persistence_client_library_handle.h | 26 | ||||
-rw-r--r-- | src/persistence_client_library_key.c | 60 | ||||
-rw-r--r-- | src/persistence_client_library_pas_interface.c | 2 | ||||
-rw-r--r-- | test/persistence_client_library_dbus_test.c | 3 | ||||
-rw-r--r-- | test/persistence_client_library_test.c | 35 |
16 files changed, 539 insertions, 106 deletions
diff --git a/configure.ac b/configure.ac index 141e49f..b1dbcf8 100644 --- a/configure.ac +++ b/configure.ac @@ -16,8 +16,8 @@ AC_GNU_SOURCE() # create library version information -m4_define([pers_client_library_version_current], [3]) -m4_define([pers_client_library_version_revision], [2]) +m4_define([pers_client_library_version_current], [4]) +m4_define([pers_client_library_version_revision], [0]) m4_define([pers_client_library_version_age], [0]) m4_define([pers_client_library_version], [pers_client_library_version_current():pers_client_library_version_revision():pers_client_library_version_age()]) diff --git a/include/persistence_client_library_key.h b/include/persistence_client_library_key.h index 876d951..56c5c3c 100644 --- a/include/persistence_client_library_key.h +++ b/include/persistence_client_library_key.h @@ -32,12 +32,12 @@ extern "C" { #endif -#define PERSIST_KEYVALUEAPI_INTERFACE_VERSION (0x03000000U) +#define PERSIST_KEYVALUEAPI_INTERFACE_VERSION (0x04000000U) /** * status returned in notification structure */ -typedef enum _PersistenceNotifyStatus_e +typedef enum _pclNotifyStatus_e { pclNotifyStatus_no_changed = 0, pclNotifyStatus_created, @@ -45,23 +45,23 @@ typedef enum _PersistenceNotifyStatus_e pclNotifyStatus_deleted, /* insert new_ entries here .. */ pclNotifyStatus_lastEntry -} PersistenceNotifyStatus_e; +} pclNotifyStatus_e; /** * structure to return in case of notification */ -typedef struct _PersistenceNotification_s +typedef struct _pclNotification_s { - PersistenceNotifyStatus_e pclKeyNotify_Status; + pclNotifyStatus_e pclKeyNotify_Status; unsigned int ldbid; const char * resource_id; unsigned int user_no; unsigned int seat_no; -} PersistenceNotification_s; +} pclNotification_s; -typedef int(* changeNotifyCallback_t)(PersistenceNotification_s * notifyStruct); +typedef int(* pclChangeNotifyCallback_t)(pclNotification_s * notifyStruct); /** * @brief delete persistent data @@ -151,7 +151,7 @@ int pclKeyHandleReadData(int key_handle, unsigned char* buffer, int buffer_size) * * @return positive value: registration OK; On error a negative value will be returned with th follwoing error codes: */ -int pclKeyHandleRegisterNotifyOnChange(int key_handle, changeNotifyCallback_t callback); +int pclKeyHandleRegisterNotifyOnChange(int key_handle, pclChangeNotifyCallback_t callback); @@ -196,7 +196,7 @@ int pclKeyReadData(unsigned int ldbid, const char* resource_id, unsigned int use * * @return positive value: registration OK; On error a negative value will be returned with th follwoing error codes: */ -int pclKeyRegisterNotifyOnChange(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no, changeNotifyCallback_t callback); +int pclKeyRegisterNotifyOnChange(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no, pclChangeNotifyCallback_t callback); diff --git a/include_protected/persistence_client_library_data_organization.h b/include_protected/persistence_client_library_data_organization.h index 74a1aeb..3ed3a11 100644 --- a/include_protected/persistence_client_library_data_organization.h +++ b/include_protected/persistence_client_library_data_organization.h @@ -48,6 +48,8 @@ enum _PersistenceConstantDef NsmErrorStatus_OK = 1, NsmErrorStatus_Fail = -1, + ChecksumBufSize = 64, + PrctKeySize = 64, /// persistence resource config table max key size PrctValueSize = 256, /// persistence resource config table max value size PrctDbTableSize = 1024, /// number of persistence resource config tables to store @@ -131,7 +133,7 @@ extern char gAppId[MaxAppNameLen]; extern int gMaxKeyValDataSize; -extern int(* gChangeNotifyCallback)(PersistenceNotification_s * notifyStruct); +extern int(* gChangeNotifyCallback)(pclNotification_s * notifyStruct); #ifdef __cplusplus diff --git a/include_protected/persistence_client_library_db_access.h b/include_protected/persistence_client_library_db_access.h index 1958b0a..a105ac2 100644 --- a/include_protected/persistence_client_library_db_access.h +++ b/include_protected/persistence_client_library_db_access.h @@ -118,7 +118,7 @@ void pers_db_close_all(); * @return 0 of registration was successfull; -1 if registration failes */ int persistence_reg_notify_on_change(char* dbPath, char* key, unsigned int ldbid, unsigned int user_no, unsigned int seat_no, - changeNotifyCallback_t callback); + pclChangeNotifyCallback_t callback); diff --git a/include_protected/persistence_client_library_rc_table.h b/include_protected/persistence_client_library_rc_table.h index 054d23c..813638f 100644 --- a/include_protected/persistence_client_library_rc_table.h +++ b/include_protected/persistence_client_library_rc_table.h @@ -23,7 +23,9 @@ extern "C" { #endif -#define PERSIST_DATA_RC_TABLE_INTERFACE_VERSION (0x02000000U) +#include <fcntl.h> // needed for file open flags + +#define PERSIST_DATA_RC_TABLE_INTERFACE_VERSION (0x03000000U) #include "persistence_client_library_data_organization.h" @@ -77,13 +79,25 @@ typedef struct _PersistenceDbContext_s } PersistenceDbContext_s; +typedef enum PersistencePermission_e_ +{ + PersistencePermission_ReadWrite = O_RDWR, + PersistencePermission_ReadOnly = O_RDONLY, + PersistencePermission_WriteOnly = O_WRONLY, + + /** insert new entries here ... */ + PersistencePermission_LastEntry /**< last entry */ +} PersistencePermission_e; + + + /// structure used to manage the persistence configuration for a key typedef struct _PersistenceConfigurationKey_s { PersistencePolicy_e policy; /**< policy */ PersistenceStorage_e storage; /**< definition of storage to use */ PersistenceResourceType_e type; /**< type of the resource - since 4.0.0.0*/ - unsigned int permission; /**< access right, corresponds to UNIX */ + PersistencePermission_e permission; /**< file access flags*/ unsigned int max_size; /**< max size expected for the key */ char reponsible[MaxConfKeyLengthResp]; /**< name of responsible application */ char custom_name[MaxConfKeyLengthCusName]; /**< name of the customer plugin */ diff --git a/persistence_client_library.pc.in b/persistence_client_library.pc.in index 28b2e2b..2b40b17 100644 --- a/persistence_client_library.pc.in +++ b/persistence_client_library.pc.in @@ -9,5 +9,7 @@ Name: persistence client library Description: persistence client library Version: @VERSION@ Requires: automotive-dlt -Libs: -L${libdir} -lrt -ldl +Requires.private: libitzam dbus-1 +Libs: -L${libdir} -lpersistence_client_library -lrt -ldl +Libs.private: -lpersistence_client_library_common_data -ldbus Cflags: -I${includedir} diff --git a/src/persistence_client_library_data_organization.c b/src/persistence_client_library_data_organization.c index f88becb..0dd5118 100644 --- a/src/persistence_client_library_data_organization.c +++ b/src/persistence_client_library_data_organization.c @@ -77,6 +77,6 @@ char gAppId[MaxAppNameLen]; int gMaxKeyValDataSize = defaultMaxKeyValDataSize; -int(* gChangeNotifyCallback)(PersistenceNotification_s * notifyStruct); +int(* gChangeNotifyCallback)(pclNotification_s * notifyStruct); diff --git a/src/persistence_client_library_db_access.c b/src/persistence_client_library_db_access.c index ab0eac1..10cd3d5 100644 --- a/src/persistence_client_library_db_access.c +++ b/src/persistence_client_library_db_access.c @@ -186,11 +186,6 @@ int pers_db_read_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned { read_size = EPERS_NOKEY; } - - // - // workaround till lifecycle is working correctly - // - pers_db_close(info); } else { @@ -244,6 +239,10 @@ int pers_db_write_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned dataSize = (int)strlen( (const char*)buffer); if(dataSize < DbValueSize) { + // ----------------------------------------------------------------------------- + // transaction start + itzam_btree_transaction_start(btree); + // key memset(insert.m_key, 0, DbKeySize); memcpy(insert.m_key, key, keySize); @@ -267,6 +266,11 @@ int pers_db_write_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned write_size = EPERS_DB_ERROR_INTERNAL; } + + itzam_btree_transaction_commit(btree); + // transaction end + // ----------------------------------------------------------------------------- + if(PersistenceStorage_shared == info->configKey.storage) { // send changed notification @@ -312,11 +316,6 @@ int pers_db_write_key(char* dbPath, char* key, PersistenceInfo_s* info, unsigned fprintf(stderr, "\npersistence_set_data ==> set_value_to_table_itzam => data to long » size %d | maxSize: %d\n", dataSize, DbKeySize); write_size = EPERS_DB_VALUE_SIZE; } - - // - // workaround till lifecycle is working correctly - // - pers_db_close(info); } else { @@ -372,7 +371,7 @@ int pers_db_get_key_size(char* dbPath, char* key, PersistenceInfo_s* info) memcpy(search.m_key, key, keySize); if(itzam_true == itzam_btree_find(btree, key, &search)) { - read_size = strlen(search.m_data); + read_size = search.m_data_size; } else { @@ -384,10 +383,6 @@ int pers_db_get_key_size(char* dbPath, char* key, PersistenceInfo_s* info) fprintf(stderr, "persistence_get_data_size => key to long » size: %d | maxSize: %d\n", keySize, DbKeySize); read_size = EPERS_DB_KEY_SIZE; } - // - // workaround till lifecycle is working correctly - // - pers_db_close(info); } else { @@ -431,6 +426,10 @@ int pers_db_delete_key(char* dbPath, char* dbKey, PersistenceInfo_s* info) keySize = (int)strlen((const char*)dbKey); if(keySize < DbKeySize) { + // ----------------------------------------------------------------------------- + // transaction start + itzam_btree_transaction_start(btree); + itzam_state state; memset(delete.m_key,0, DbKeySize); @@ -441,16 +440,15 @@ int pers_db_delete_key(char* dbPath, char* dbKey, PersistenceInfo_s* info) fprintf(stderr, "persistence_delete_data ==> Remove Itzam problem: %s\n", STATE_MESSAGES[state]); ret = EPERS_DB_ERROR_INTERNAL; } + itzam_btree_transaction_commit(btree); + // transaction end + // ----------------------------------------------------------------------------- } else { fprintf(stderr, "persistence_delete_data => key to long » size: %d | maxSize: %d\n", keySize, DbKeySize); ret = EPERS_DB_KEY_SIZE; } - // - // workaround till lifecycle is working correctly - // - pers_db_close(info); } else { @@ -478,7 +476,7 @@ int pers_db_delete_key(char* dbPath, char* dbKey, PersistenceInfo_s* info) int persistence_reg_notify_on_change(char* dbPath, char* key, unsigned int ldbid, unsigned int user_no, unsigned int seat_no, - changeNotifyCallback_t callback) + pclChangeNotifyCallback_t callback) { int rval = -1; DBusError error; @@ -497,9 +495,9 @@ int persistence_reg_notify_on_change(char* dbPath, char* key, unsigned int ldbid // dbus_bus_add_match works only for type DBUS_TYPE_STRING as message arguments // this is the reason to use string instead of integer types directly - snprintf(ldbid_array, 12, "%d", ldbid); - snprintf(user_array, 12, "%d", user_no); - snprintf(seat_array, 12, "%d", seat_no); + snprintf(ldbid_array, 12, "%u", ldbid); + snprintf(user_array, 12, "%u", user_no); + snprintf(seat_array, 12, "%u", seat_no); snprintf(rule, 256, "type='signal',interface='org.genivi.persistence.adminconsumer',member='PersistenceValueChanged',path='/org/genivi/persistence/adminconsumer',arg0='%s',arg1='%s',arg2='%s',arg3='%s'", key, ldbid_array, user_array, seat_array); @@ -567,7 +565,7 @@ int pers_db_cursor_create(char* dbPath) if(handle < MaxPersHandle && handle >= 0) { // open database - state = itzam_btree_open(&gCursorArray[handle].m_btree, dbPath, itzam_comparator_string, error_handler, 0/*recover*/, 0/*read_only*/); + state = itzam_btree_open(&gCursorArray[handle].m_btree, dbPath, itzam_comparator_string, error_handler, 1/*recover*/, 0/*read_only*/); if (state != ITZAM_OKAY) { fprintf(stderr, "pers_db_open ==> Open Itzam problem: %s\n", STATE_MESSAGES[state]); diff --git a/src/persistence_client_library_dbus_service.c b/src/persistence_client_library_dbus_service.c index d82d2e7..8a1374c 100644 --- a/src/persistence_client_library_dbus_service.c +++ b/src/persistence_client_library_dbus_service.c @@ -140,7 +140,7 @@ static DBusHandlerResult handleObjectPathMessageFallback(DBusConnection * connec printf("PersistenceValueChanged signal\n"); // to do handle signal - PersistenceNotification_s notifyStruct; + pclNotification_s notifyStruct; notifyStruct.pclKeyNotify_Status = pclNotifyStatus_changed; if (!dbus_message_get_args (message, &error, DBUS_TYPE_STRING, ¬ifyStruct.resource_id, diff --git a/src/persistence_client_library_file.c b/src/persistence_client_library_file.c index 6c1e3fe..7421e65 100644 --- a/src/persistence_client_library_file.c +++ b/src/persistence_client_library_file.c @@ -20,6 +20,7 @@ #include "persistence_client_library_file.h" #include "../include_protected/persistence_client_library_data_organization.h" #include "../include_protected/persistence_client_library_db_access.h" +#include "../include_protected/crc32.h" #include "persistence_client_library_pas_interface.h" #include "persistence_client_library_handle.h" @@ -32,6 +33,18 @@ #include <sys/stat.h> #include <sys/types.h> #include <unistd.h> +#include <stdlib.h> + + +// header prototype definition of internal functions +int pcl_create_backup(const char* srcPath, int srcfd, const char* csumPath, const char* csumBuf); + +int pcl_recover_from_backup(int backupFd, const char* original); + +int pcl_calc_crc32_checksum(int fd, char crc32sum[]); + +int pcl_verify_consistency(const char* origPath, const char* backupPath, const char* csumPath, int flags); +//------------------------------------------------------------- @@ -41,6 +54,15 @@ int pclFileClose(int fd) if(fd < MaxPersHandle) { + // check if a backup and checksum file needs to bel deleted + if( gFileHandleArray[fd].permission != PersistencePermission_ReadOnly) + { + // remove bakup file + //rval = remove(gFileHandleArray[fd].backupPath ); + + // remove checksum file + rval = remove(gFileHandleArray[fd].csumPath); + } __sync_fetch_and_sub(&gOpenFdArray[fd], FileClosed); // set closed flag rval = close(fd); } @@ -86,8 +108,7 @@ void* pclFileMapData(void* addr, long size, long offset, int fd) int pclFileOpen(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no) { - int handle = -1, shared_DB = 0, flags = O_RDWR; - + int handle = -1, shared_DB = 0; PersistenceInfo_s dbContext; char dbKey[DbKeyMaxLen]; // database key @@ -106,12 +127,42 @@ int pclFileOpen(unsigned int ldbid, const char* resource_id, unsigned int user_n if( (shared_DB >= 0) // check valid database context && (dbContext.configKey.type == PersistenceResourceType_file) ) // check if type matches { - handle = open(dbPath, flags); + int flags = dbContext.configKey.permission; + char backupPath[DbKeyMaxLen]; // backup file + char csumPath[DbPathMaxLen]; // checksum file + + memset(backupPath, 0, DbKeyMaxLen); + memset(csumPath, 0, DbPathMaxLen); + + // file will be opend writable, so check about data consistency + if(dbContext.configKey.permission != PersistencePermission_ReadOnly) + { + snprintf(backupPath, DbPathMaxLen, "%s%s", dbPath, "~"); + snprintf(csumPath, DbPathMaxLen, "%s%s", dbPath, ".cs"); + + if((handle = pcl_verify_consistency(dbPath, backupPath, csumPath, flags)) == -1) + { + printf("pclFileOpen: error => file inconsistent, recovery N O T possible!\n"); + return -1; + } + } + + if(handle <= 0) // check if open is needed or already done in verifyConsistency + handle = open(dbPath, flags); + if(handle != -1) { if(handle < MaxPersHandle) { __sync_fetch_and_add(&gOpenFdArray[handle], FileOpen); // set open flag + + if(dbContext.configKey.permission != PersistencePermission_ReadOnly) + { + strcpy(gFileHandleArray[handle].backupPath, backupPath); + strcpy(gFileHandleArray[handle].csumPath, csumPath); + gFileHandleArray[handle].backupCreated = 0; + gFileHandleArray[handle].permission = dbContext.configKey.permission; + } } else { @@ -119,18 +170,15 @@ int pclFileOpen(unsigned int ldbid, const char* resource_id, unsigned int user_n handle = EPERS_MAXHANDLE; } } - else + else // file does not exist, create file and folder { - // file does not exist, create file and folder - const char* delimiters = "/\n"; // search for blank and end of line char* tokenArray[24]; + char* thePath = dbPath; char createPath[DbPathMaxLen]; - int numTokens = 0; - int i = 0; - int validPath = 1; + int numTokens = 0, i = 0, validPath = 1; - tokenArray[numTokens++] = strtok(dbPath, delimiters); + tokenArray[numTokens++] = strtok(thePath, delimiters); while(tokenArray[numTokens-1] != NULL ) { tokenArray[numTokens] = strtok(NULL, delimiters); @@ -290,7 +338,26 @@ int pclFileWriteData(int fd, const void * buffer, int buffer_size) if(AccessNoLock != isAccessLocked() ) // check if access to persistent data is locked { - size = write(fd, buffer, buffer_size); + if(fd < MaxPersHandle) + { + // check if a backup file has to be created + if( gFileHandleArray[fd].permission != PersistencePermission_ReadOnly + && gFileHandleArray[fd].backupCreated == 0) + { + char csumBuf[64]; + memset(csumBuf, 0, 64); + + // calculate checksum + pcl_calc_crc32_checksum(fd, csumBuf); + + // create checksum and backup file + pcl_create_backup(gFileHandleArray[fd].backupPath, fd, gFileHandleArray[fd].csumPath, csumBuf); + + gFileHandleArray[fd].backupCreated = 1; + } + + size = write(fd, buffer, buffer_size); + } } else { @@ -301,3 +368,323 @@ int pclFileWriteData(int fd, const void * buffer, int buffer_size) } + +/**************************************************************************************** + * Functions to create backup files + ****************************************************************************************/ + +int pcl_verify_consistency(const char* origPath, const char* backupPath, const char* csumPath, int flags) +{ + int handle = 0, readSize = 0; + int backupAvail = 0, csumAvail = 0; + int fdCsum = 0, fdBackup = 0; + + char origCsumBuf[64]; + char backCsumBuf[64]; + char csumBuf[64]; + + memset(origCsumBuf, 0, 64); + memset(backCsumBuf, 0, 64); + memset(csumBuf, 0, 64); + + // check if we have a backup and checksum file + backupAvail = access(backupPath, F_OK); + csumAvail = access(csumPath, F_OK); + + //printf("verifyConsistency ==> backup: %d | csum: %d \n", backupAvail, csumAvail); + + // ************************************************* + // there is a backup file and a checksum + // ************************************************* + if( (backupAvail == 0) && (csumAvail == 0) ) + { + printf("verifyConsistency => there is a backup file AND a checksum\n"); + // calculate checksum form backup file + fdBackup = open(backupPath, O_RDONLY); + if(fdBackup != -1) + { + pcl_calc_crc32_checksum(fdBackup, backCsumBuf); + + fdCsum = open(csumPath, O_RDONLY); + if(fdCsum != -1) + { + readSize = read(fdCsum, csumBuf, 64); + if(readSize > 0) + { + if(strcmp(csumBuf, backCsumBuf) == 0) + { + // checksum matches ==> replace with original file + handle = pcl_recover_from_backup(fdBackup, origPath); + } + else + { + // checksum does not match, check checksum with original file + handle = open(origPath, flags); + if(handle != -1) + { + pcl_calc_crc32_checksum(handle, origCsumBuf); + if(strcmp(csumBuf, origCsumBuf) == 0) + { + // checksum matches ==> keep original file + } + else + { + close(handle); + handle = -1; // error: file corrupt + } + } + else + { + close(handle); + handle = -1; // error: file corrupt + } + } + } + else + { + printf("verifyConsistency ==> checksum invalid size\n"); + } + 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) + { + //printf("verifyConsistency => there is ONLY a checksum file\n"); + + fdCsum = open(csumPath, O_RDONLY); + if(fdCsum != -1) + { + readSize = read(fdCsum, csumBuf, 64); + if(readSize != 64) + { + printf("verifyConsistency ==> read checksum: invalid readSize\n"); + } + close(fdCsum); + + // calculate the checksum form the original file + handle = open(origPath, flags); + if(handle != -1) + { + pcl_calc_crc32_checksum(handle, origCsumBuf); + + // checksum does NOT match ==> error: file corrupt + // checksum matches ==> keep original file + if(strcmp(csumBuf, origCsumBuf) != 0) + { + close(handle); + handle = -1; // error: file corrupt + } + } + 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) + { + //printf("verifyConsistency => there is ONLY a backup file\n"); + // calculate checksum form backup file + fdBackup = open(backupPath, O_RDONLY); + if(fdBackup != -1) + { + pcl_calc_crc32_checksum(fdBackup, backCsumBuf); + close(fdBackup); + + // calculate the checksum form the original file + handle = open(origPath, flags); + if(handle != -1) + { + pcl_calc_crc32_checksum(handle, origCsumBuf); + + // checksum does NOT match ==> error: file corrupt + // if checksum matches ==> keep original file + if(strcmp(backCsumBuf, origCsumBuf) != 0) + { + close(handle); + handle = -1; // error: file corrupt + } + /*else + { + printf(" original file is OK, keep it\n"); + }*/ + } + 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 pcl_recover_from_backup(int backupFd, const char* original) +{ + int handle = 0; + int readSize = 0; + char buffer[1024]; + + handle = open(original, O_TRUNC | O_RDWR); + if(handle != -1) + { + // copy data from one file to another + while((readSize = read(backupFd, buffer, 1024)) > 0) + { + if(write(handle, buffer, readSize) != readSize) + { + printf("pcl_recover_from_backup => couldn't write whole buffer\n"); + break; + } + } + + } + + return handle; +} + +int pcl_create_backup(const char* dstPath, int srcfd, const char* csumPath, const char* csumBuf) +{ + int dstFd = 0, csfd = 0; + int readSize = -1; + char buffer[1024]; + + // create checksum file and and write checksum + //printf(" pcl_create_backu => create checksum file: %s \n", csumPath); + 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) + { + printf("pcl_create_backup: failed to write checksum to file\n"); + } + close(csfd); + } + else + { + printf("pcl_create_backup => failed to create checksum file: %s | %s\n", csumPath, strerror(errno)); + } + + + // create backup file, user and group has read/write permission, others have read permission + //printf(" pclFileOpen => create a backup for file: %s\n", dstPath); + 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, 1024)) > 0) + { + if(write(dstFd, buffer, readSize) != readSize) + { + printf("pcl_create_backup => couldn't write whole buffer\n"); + break; + } + } + + if(readSize == -1) + printf("pcl_create_backup => error copying file\n"); + + if((readSize = close(dstFd)) == -1) + printf("pcl_create_backup => error closing fd\n"); + + // set back to the position + lseek(srcfd, curPos, SEEK_SET); + } + else + { + printf("pcl_create_backup => failed to open backup file: %s | %s \n", dstPath, strerror(errno)); + } + + return readSize; +} + + + +int pcl_calc_crc32_checksum(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 = crc32(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; +} + + + + diff --git a/src/persistence_client_library_handle.c b/src/persistence_client_library_handle.c index b45779e..7ccb9b3 100644 --- a/src/persistence_client_library_handle.c +++ b/src/persistence_client_library_handle.c @@ -31,8 +31,14 @@ static int gInitialized = 0; /// open file descriptor handle array int gOpenFdArray[MaxPersHandle]; -/// persistence handle array -PersistenceHandle_s gHandleArray[MaxPersHandle]; +/// persistence key handle array +PersistenceKeyHandle_s gKeyHandleArray[MaxPersHandle]; + + +/// persistence key handle array +PersistenceFileHandle_s gFileHandleArray[MaxPersHandle]; + + /// free handle array int gFreeHandleArray[MaxPersHandle]; diff --git a/src/persistence_client_library_handle.h b/src/persistence_client_library_handle.h index 12654c0..6d56c46 100644 --- a/src/persistence_client_library_handle.h +++ b/src/persistence_client_library_handle.h @@ -23,19 +23,35 @@ #include "../include_protected/persistence_client_library_data_organization.h" #include "../include_protected/persistence_client_library_rc_table.h" -/// handle structure definition -typedef struct _PersistenceHandle_s + +/// key handle structure definition +typedef struct _PersistenceKeyHandle_s { PersistenceInfo_s info; /// persistence info char dbPath[DbPathMaxLen]; /// path to the database char dbKey[DbKeyMaxLen]; /// database key char resourceID[DbResIDMaxLen]; /// resourceID } -PersistenceHandle_s; +PersistenceKeyHandle_s; + + +/// file handle structure definition +typedef struct _PersistenceFileHandle_s +{ + PersistencePermission_e permission; /// access permission read/write + int backupCreated; /// flag to indicate if a backup has already been created + char backupPath[DbPathMaxLen]; /// path to the backup file + char csumPath[DbPathMaxLen]; /// path to the checksum file +} +PersistenceFileHandle_s; + + +/// persistence key handle array +extern PersistenceKeyHandle_s gKeyHandleArray[MaxPersHandle]; -/// persistence handle array -extern PersistenceHandle_s gHandleArray[MaxPersHandle]; +/// persistence file handle array +extern PersistenceFileHandle_s gFileHandleArray[MaxPersHandle]; /// open file descriptor handle array diff --git a/src/persistence_client_library_key.c b/src/persistence_client_library_key.c index 172087b..4f58c68 100644 --- a/src/persistence_client_library_key.c +++ b/src/persistence_client_library_key.c @@ -81,12 +81,12 @@ int pclKeyHandleOpen(unsigned int ldbid, const char* resource_id, unsigned int u if(handle < MaxPersHandle && handle != -1) { // remember data in handle array - strncpy(gHandleArray[handle].dbPath, dbPath, DbPathMaxLen); - strncpy(gHandleArray[handle].dbKey, dbKey, DbKeyMaxLen); - strncpy(gHandleArray[handle].resourceID, resource_id, DbResIDMaxLen); - gHandleArray[handle].dbPath[DbPathMaxLen-1] = '\0'; // Ensures 0-Termination - gHandleArray[handle].dbKey[ DbPathMaxLen-1] = '\0'; // Ensures 0-Termination - gHandleArray[handle].info = dbContext; + strncpy(gKeyHandleArray[handle].dbPath, dbPath, DbPathMaxLen); + strncpy(gKeyHandleArray[handle].dbKey, dbKey, DbKeyMaxLen); + strncpy(gKeyHandleArray[handle].resourceID, resource_id, DbResIDMaxLen); + gKeyHandleArray[handle].dbPath[DbPathMaxLen-1] = '\0'; // Ensures 0-Termination + gKeyHandleArray[handle].dbKey[ DbPathMaxLen-1] = '\0'; // Ensures 0-Termination + gKeyHandleArray[handle].info = dbContext; } else { @@ -111,9 +111,9 @@ int pclKeyHandleClose(int key_handle) if(key_handle < MaxPersHandle) { - if(PersistenceStorage_custom == gHandleArray[key_handle].info.configKey.storage ) + if(PersistenceStorage_custom == gKeyHandleArray[key_handle].info.configKey.storage ) { - int idx = custom_client_name_to_id(gHandleArray[key_handle].dbPath, 1); + int idx = custom_client_name_to_id(gKeyHandleArray[key_handle].dbPath, 1); if( (idx < PersCustomLib_LastEntry) && (gPersCustomFuncs[idx].custom_plugin_handle_close) ) { @@ -130,9 +130,9 @@ int pclKeyHandleClose(int key_handle) } // invalidate entries - strncpy(gHandleArray[key_handle].dbPath, "", DbPathMaxLen); - strncpy(gHandleArray[key_handle].dbKey ,"", DbKeyMaxLen); - gHandleArray[key_handle].info.configKey.storage = -1; + strncpy(gKeyHandleArray[key_handle].dbPath, "", DbPathMaxLen); + strncpy(gKeyHandleArray[key_handle].dbKey ,"", DbKeyMaxLen); + gKeyHandleArray[key_handle].info.configKey.storage = -1; } else { @@ -150,13 +150,13 @@ int pclKeyHandleGetSize(int key_handle) if(key_handle < MaxPersHandle) { - if(PersistenceStorage_custom == gHandleArray[key_handle].info.configKey.storage) + if(PersistenceStorage_custom == gKeyHandleArray[key_handle].info.configKey.storage) { - int idx = custom_client_name_to_id(gHandleArray[key_handle].dbPath, 1); + int idx = custom_client_name_to_id(gKeyHandleArray[key_handle].dbPath, 1); if(idx < PersCustomLib_LastEntry && &(gPersCustomFuncs[idx].custom_plugin_get_size) != NULL) { - gPersCustomFuncs[idx].custom_plugin_get_size(gHandleArray[key_handle].dbPath); + gPersCustomFuncs[idx].custom_plugin_get_size(gKeyHandleArray[key_handle].dbPath); } else { @@ -165,8 +165,8 @@ int pclKeyHandleGetSize(int key_handle) } else { - size = pers_db_get_key_size(gHandleArray[key_handle].dbPath, gHandleArray[key_handle].dbKey, - &gHandleArray[key_handle].info); + size = pers_db_get_key_size(gKeyHandleArray[key_handle].dbPath, gKeyHandleArray[key_handle].dbKey, + &gKeyHandleArray[key_handle].info); } } @@ -180,9 +180,9 @@ int pclKeyHandleReadData(int key_handle, unsigned char* buffer, int buffer_size) int size = 0; if(key_handle < MaxPersHandle) { - if(PersistenceStorage_custom == gHandleArray[key_handle].info.configKey.storage) + if(PersistenceStorage_custom == gKeyHandleArray[key_handle].info.configKey.storage) { - int idx = custom_client_name_to_id(gHandleArray[key_handle].dbPath, 1); + int idx = custom_client_name_to_id(gKeyHandleArray[key_handle].dbPath, 1); if(idx < PersCustomLib_LastEntry && &(gPersCustomFuncs[idx].custom_plugin_handle_get_data) != NULL) { @@ -195,8 +195,8 @@ int pclKeyHandleReadData(int key_handle, unsigned char* buffer, int buffer_size) } else { - size = pers_db_read_key(gHandleArray[key_handle].dbPath, gHandleArray[key_handle].dbKey, - &gHandleArray[key_handle].info, buffer, buffer_size); + size = pers_db_read_key(gKeyHandleArray[key_handle].dbPath, gKeyHandleArray[key_handle].dbKey, + &gKeyHandleArray[key_handle].info, buffer, buffer_size); } } @@ -205,16 +205,16 @@ int pclKeyHandleReadData(int key_handle, unsigned char* buffer, int buffer_size) -int pclKeyHandleRegisterNotifyOnChange(int key_handle, changeNotifyCallback_t callback) +int pclKeyHandleRegisterNotifyOnChange(int key_handle, pclChangeNotifyCallback_t callback) { int rval = -1; if(key_handle < MaxPersHandle) { - pclKeyRegisterNotifyOnChange(gHandleArray[key_handle].info.context.ldbid, - gHandleArray[key_handle].resourceID, - gHandleArray[key_handle].info.context.user_no, - gHandleArray[key_handle].info.context.seat_no, callback); + pclKeyRegisterNotifyOnChange(gKeyHandleArray[key_handle].info.context.ldbid, + gKeyHandleArray[key_handle].resourceID, + gKeyHandleArray[key_handle].info.context.user_no, + gKeyHandleArray[key_handle].info.context.seat_no, callback); } return rval; @@ -232,9 +232,9 @@ int pclKeyHandleWriteData(int key_handle, unsigned char* buffer, int buffer_size { if(key_handle < MaxPersHandle) { - if(PersistenceStorage_custom == gHandleArray[key_handle].info.configKey.storage) + if(PersistenceStorage_custom == gKeyHandleArray[key_handle].info.configKey.storage) { - int idx = custom_client_name_to_id(gHandleArray[key_handle].dbPath, 1); + int idx = custom_client_name_to_id(gKeyHandleArray[key_handle].dbPath, 1); if(idx < PersCustomLib_LastEntry && *gPersCustomFuncs[idx].custom_plugin_handle_set_data != NULL) { @@ -247,8 +247,8 @@ int pclKeyHandleWriteData(int key_handle, unsigned char* buffer, int buffer_size } else { - size = pers_db_write_key(gHandleArray[key_handle].dbPath, gHandleArray[key_handle].dbKey, - &gHandleArray[key_handle].info, buffer, buffer_size); + size = pers_db_write_key(gKeyHandleArray[key_handle].dbPath, gKeyHandleArray[key_handle].dbKey, + &gKeyHandleArray[key_handle].info, buffer, buffer_size); } } else @@ -477,7 +477,7 @@ int pclKeyWriteData(unsigned int ldbid, const char* resource_id, unsigned int us } -int pclKeyRegisterNotifyOnChange(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no, changeNotifyCallback_t callback) +int pclKeyRegisterNotifyOnChange(unsigned int ldbid, const char* resource_id, unsigned int user_no, unsigned int seat_no, pclChangeNotifyCallback_t callback) { int rval = 0; PersistenceInfo_s dbContext; diff --git a/src/persistence_client_library_pas_interface.c b/src/persistence_client_library_pas_interface.c index e2db17e..3b50561 100644 --- a/src/persistence_client_library_pas_interface.c +++ b/src/persistence_client_library_pas_interface.c @@ -319,7 +319,7 @@ int send_pas_request(const char* method, unsigned int requestID, int status) "org.genivi.persistence.admin", // interface method); // method - printf(" =======****> send_pas_request: requestID: %u | status: %u \n", requestID, status); + printf(" =======****> send_pas_request: requestID: %u | status: %d \n", requestID, status); if(message != NULL) { diff --git a/test/persistence_client_library_dbus_test.c b/test/persistence_client_library_dbus_test.c index f276caf..36c6cab 100644 --- a/test/persistence_client_library_dbus_test.c +++ b/test/persistence_client_library_dbus_test.c @@ -25,7 +25,7 @@ -int myChangeCallback(PersistenceNotification_s * notifyStruct) +int myChangeCallback(pclNotification_s * notifyStruct) { printf(" ==> * - * myChangeCallback * - *\n"); printf("Notification received ==> lbid: %d | resource_id: %s | seat: %d | user: %d \n", notifyStruct->ldbid, @@ -41,7 +41,6 @@ int myChangeCallback(PersistenceNotification_s * notifyStruct) int main(int argc, char *argv[]) { int ret = 0; - PersistenceNotification_s notifyValue; printf("Dbus interface test application\n"); diff --git a/test/persistence_client_library_test.c b/test/persistence_client_library_test.c index 96b7ef5..83c0213 100644 --- a/test/persistence_client_library_test.c +++ b/test/persistence_client_library_test.c @@ -314,6 +314,7 @@ START_TEST(test_SetData) /*******************************************************************************************************************************************/ /*******************************************************************************************************************************************/ + /* * now read the data written in the previous steps to the keys * and verify data has been written correctly. @@ -458,12 +459,13 @@ END_TEST */ START_TEST(test_DataFile) { - int fd = 0, i = 0, idx = 0; + int fd = 0, i = 0, idx = 0, fd_RW = 0, fd_RO = 0; int size = 0, ret = 0; int writeSize = 16*1024; unsigned char buffer[READ_SIZE]; const char* refBuffer = "/Data/mnt-wt/lt-persistence_client_library_test/user/1/seat/1/media"; char* writeBuffer; + char* wBuffer = "This is a buffer to write"; char* fileMap = NULL; writeBuffer = malloc(writeSize); @@ -487,7 +489,7 @@ START_TEST(test_DataFile) O_CREAT|O_RDWR|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH); close(fd); - // open ---------------------------------------------------------- + // open ------------------------------------------------------------ fd = pclFileOpen(0xFF, "media/mediaDB.db", 1, 1); fail_unless(fd != -1, "Could not open file ==> /media/mediaDB.db"); @@ -495,14 +497,14 @@ START_TEST(test_DataFile) fail_unless(size == 68, "Wrong file size"); size = pclFileReadData(fd, buffer, READ_SIZE); - fail_unless(strncmp((char*)buffer, refBuffer, strlen(refBuffer)) == 0, "Buffer not correctly read"); + fail_unless(strncmp((char*)buffer, refBuffer, strlen(refBuffer)) == 0, "Buffer not correctly read => media/mediaDB.db"); fail_unless(size == (strlen(refBuffer)+1), "Wrong size returned"); // strlen + 1 ==> inlcude cr/lf ret = pclFileClose(fd); fail_unless(ret == 0, "Failed to close file"); - // open ---------------------------------------------------------- + // open ------------------------------------------------------------ fd = pclFileOpen(0xFF, "media/mediaDBWrite.db", 1, 1); fail_unless(fd != -1, "Could not open file ==> /media/mediaDBWrite.db"); @@ -517,17 +519,12 @@ START_TEST(test_DataFile) ret = pclFileRemove(0xFF, "media/mediaDBWrite.db", 1, 1); fail_unless(ret == 0, "File can't be removed ==> /media/mediaDBWrite.db"); - fd = pclFileOpen(0xFF, "media/mediaDBWrite.db", 1, 1); - fail_unless(fd != -1, "File can't be opend ==> /media/mediaDBWrite.db"); - - ret = pclFileRemove(0xFF, "media/mediaDBWrite.db", 1, 1); - fail_unless(ret == 0, "File can't be removed ==> /media/mediaDBWrite.db"); - - ret = pclFileClose(fd); - fail_unless(ret == 0, "Failed to close file"); + fd = open("/Data/mnt-wt/lt-persistence_client_library_test/user/1/seat/1/media/mediaDBWrite.db",O_RDWR); + fail_unless(fd == -1, "Failed to remove file, file still exists"); + close(fd); - // map file ------------------------------------------------------ + // map file -------------------------------------------------------- fd = pclFileOpen(0xFF, "media/mediaDB.db", 1, 1); size = pclFileGetSize(fd); @@ -544,6 +541,18 @@ START_TEST(test_DataFile) ret = pclFileClose(fd); fail_unless(ret == 0, "Failed to close file"); + + // test backup creation -------------------------------------------- + fd_RO = pclFileOpen(0xFF, "media/mediaDB_ReadOnly.db", 1, 1); + fail_unless(fd_RO != -1, "Could not open file ==> /media/mediaDB_ReadOnly.db"); + + fd_RW = pclFileOpen(0xFF, "media/mediaDB_ReadWrite.db", 1, 1); + fail_unless(fd_RW != -1, "Could not open file ==> /media/mediaDB_ReadWrite.db"); + pclFileWriteData(fd_RW, wBuffer, strlen(wBuffer)); + + ret = pclFileClose(fd_RW); + ret = pclFileClose(fd_RO); + free(writeBuffer); } END_TEST |