summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIngo Huerner <ingo.huerner@xse.de>2013-04-08 23:49:35 +0200
committerIngo Huerner <ingo.huerner@xse.de>2013-04-08 23:49:35 +0200
commitcc01613b747e0ec2fbdad19b4ae3e97ea4d2fd14 (patch)
tree687eb2004f15438b55c08a63e180adc3a6fddee9
parent9f0a5460f1d7b62b4588dcd1538f3ae8f4802e41 (diff)
downloadpersistence-client-library-cc01613b747e0ec2fbdad19b4ae3e97ea4d2fd14.tar.gz
Added backup file and checksum creation for files
-rw-r--r--configure.ac4
-rw-r--r--include/persistence_client_library_key.h18
-rw-r--r--include_protected/persistence_client_library_data_organization.h4
-rw-r--r--include_protected/persistence_client_library_db_access.h2
-rw-r--r--include_protected/persistence_client_library_rc_table.h18
-rw-r--r--persistence_client_library.pc.in4
-rw-r--r--src/persistence_client_library_data_organization.c2
-rw-r--r--src/persistence_client_library_db_access.c46
-rw-r--r--src/persistence_client_library_dbus_service.c2
-rw-r--r--src/persistence_client_library_file.c409
-rw-r--r--src/persistence_client_library_handle.c10
-rw-r--r--src/persistence_client_library_handle.h26
-rw-r--r--src/persistence_client_library_key.c60
-rw-r--r--src/persistence_client_library_pas_interface.c2
-rw-r--r--test/persistence_client_library_dbus_test.c3
-rw-r--r--test/persistence_client_library_test.c35
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, &notifyStruct.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