diff --git a/microscript/ILibDuktape_SimpleDataStore.c b/microscript/ILibDuktape_SimpleDataStore.c index 42d7ab8..eb9a515 100644 --- a/microscript/ILibDuktape_SimpleDataStore.c +++ b/microscript/ILibDuktape_SimpleDataStore.c @@ -193,6 +193,8 @@ duk_ret_t ILibDuktape_SimpleDataStore_Create(duk_context *ctx) { ILibSimpleDataStore dataStore; char *filePath; + int nargs = duk_get_top(ctx); + int rdonly = (nargs > 1 && duk_is_object(ctx, 1)) ? Duktape_GetIntPropertyValue(ctx, 1, "readOnly", 0) : 0; duk_push_this(ctx); // [DataStore] duk_push_object(ctx); // [DataStore][RetVal] @@ -216,7 +218,7 @@ duk_ret_t ILibDuktape_SimpleDataStore_Create(duk_context *ctx) else { filePath = (char*)duk_require_string(ctx, 0); - dataStore = ILibSimpleDataStore_Create(filePath); + dataStore = ILibSimpleDataStore_CreateEx2(filePath, 0, rdonly); duk_pop_2(ctx); // [DataStore][RetVal] ILibDuktape_CreateFinalizer(ctx, ILibDuktape_SimpleDataStore_Finalizer); } @@ -224,11 +226,14 @@ duk_ret_t ILibDuktape_SimpleDataStore_Create(duk_context *ctx) duk_push_pointer(ctx, dataStore); // [DataStore][RetVal][ds] duk_put_prop_string(ctx, -2, ILibDuktape_DataStore_PTR);// [DataStore][RetVal] - ILibDuktape_CreateInstanceMethod(ctx, "Delete", ILibDuktape_SimpleDataStore_Delete, 1); - ILibDuktape_CreateInstanceMethod(ctx, "Put", ILibDuktape_SimpleDataStore_Put, 2); + if (rdonly == 0) + { + ILibDuktape_CreateInstanceMethod(ctx, "Delete", ILibDuktape_SimpleDataStore_Delete, 1); + ILibDuktape_CreateInstanceMethod(ctx, "Put", ILibDuktape_SimpleDataStore_Put, 2); + ILibDuktape_CreateInstanceMethod(ctx, "Compact", ILibDuktape_SimpleDataStore_Compact, 0); + } ILibDuktape_CreateInstanceMethod(ctx, "Get", ILibDuktape_SimpleDataStore_Get, DUK_VARARGS); ILibDuktape_CreateInstanceMethod(ctx, "GetBuffer", ILibDuktape_SimpleDataStore_GetRaw, DUK_VARARGS); - ILibDuktape_CreateInstanceMethod(ctx, "Compact", ILibDuktape_SimpleDataStore_Compact, 0); ILibDuktape_CreateEventWithGetter(ctx, "Keys", ILibDuktape_SimpleDataStore_Keys); return 1; @@ -237,7 +242,7 @@ duk_ret_t ILibDuktape_SimpleDataStore_Create(duk_context *ctx) void ILibDuktape_SimpleDataStore_PUSH(duk_context *ctx, void *chain) { duk_push_object(ctx); // [DataStore] - ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "_shared", 0, "Create", ILibDuktape_SimpleDataStore_Create, 1); + ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "_shared", 0, "Create", ILibDuktape_SimpleDataStore_Create, DUK_VARARGS); ILibDuktape_CreateInstanceMethodWithIntProperty(ctx, "_shared", 1, "Shared", ILibDuktape_SimpleDataStore_Create, 0); } diff --git a/microstack/ILibSimpleDataStore.c b/microstack/ILibSimpleDataStore.c index 9bcec79..8f36177 100644 --- a/microstack/ILibSimpleDataStore.c +++ b/microstack/ILibSimpleDataStore.c @@ -21,6 +21,7 @@ limitations under the License. #include #else #include +#include #endif #if defined(WIN32) && !defined(_WIN32_WCE) && !defined(_MINCORE) @@ -321,28 +322,63 @@ void ILibSimpleDataStore_RebuildKeyTable(ILibSimpleDataStore_Root *root) } // Open the data store file -FILE* ILibSimpleDataStore_OpenFileEx(char* filePath, int forceTruncateIfNonZero) +FILE* ILibSimpleDataStore_OpenFileEx2(char* filePath, int forceTruncateIfNonZero, int readonly) { FILE* f = NULL; #ifdef WIN32 - if (forceTruncateIfNonZero !=0 || fopen_s(&f, filePath, "rb+N") != 0) + if (readonly == 0) { - fopen_s(&f, filePath, "wb+N"); + HANDLE h = NULL; + if (forceTruncateIfNonZero != 0) + { + h = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) + { + h = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + } + } + else + { + h = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE && GetLastError() == ERROR_FILE_NOT_FOUND) + { + h = CreateFile(filePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL); + } + } + int fd = _open_osfhandle((intptr_t)h, _O_RDWR); + if (fd == -1) { CloseHandle(h); return(NULL); } + f = _fdopen(fd, "wb+N"); + if (f == NULL) { CloseHandle(h); return(NULL); } + } + else + { + HANDLE h = CreateFile(filePath, GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (h == INVALID_HANDLE_VALUE) + { + int err = GetLastError(); + return(NULL); + } + int fd = _open_osfhandle((intptr_t)h, _O_RDONLY); + if (fd == -1) { CloseHandle(h); return(NULL); } + f = _fdopen(fd, "rb"); + if (f == NULL) { CloseHandle(h); return(NULL); } } #else - if (forceTruncateIfNonZero != 0 || (f = fopen(filePath, "rb+")) == NULL) + char *flag = readonly == 0 ? "rb+": "rb"; + + if (forceTruncateIfNonZero != 0 || (f = fopen(filePath, flag)) == NULL) { f = fopen(filePath, "wb+"); } if (f == NULL) { return NULL; } // If we failed to open the file, stop now. - if (flock(fileno(f), LOCK_EX | LOCK_NB) != 0) { fclose(f); return NULL; } // Request exclusive lock on this file, no blocking. + if (readonly == 0 && flock(fileno(f), LOCK_EX | LOCK_NB) != 0) { fclose(f); return NULL; } // Request exclusive lock on this file, no blocking. #endif return f; } -#define ILibSimpleDataStore_OpenFile(filePath) ILibSimpleDataStore_OpenFileEx(filePath, 0) - +#define ILibSimpleDataStore_OpenFile(filePath) ILibSimpleDataStore_OpenFileEx2(filePath, 0, 0) +#define ILibSimpleDataStore_OpenFileEx(filePath, forceTruncate) ILibSimpleDataStore_OpenFileEx2(filePath, forceTruncate, 0) int ILibSimpleDataStore_Exists(char *filePath) { #ifdef WIN32 @@ -352,12 +388,12 @@ int ILibSimpleDataStore_Exists(char *filePath) #endif } // Open the data store file. Optionally allocate spare user memory -__EXPORT_TYPE ILibSimpleDataStore ILibSimpleDataStore_CreateEx(char* filePath, int userExtraMemorySize) +__EXPORT_TYPE ILibSimpleDataStore ILibSimpleDataStore_CreateEx2(char* filePath, int userExtraMemorySize, int readonly) { ILibSimpleDataStore_Root* retVal = (ILibSimpleDataStore_Root*)ILibMemory_Allocate(ILibMemory_SimpleDataStore_CONTAINERSIZE, userExtraMemorySize, NULL, NULL); retVal->filePath = ILibString_Copy(filePath, (int)strnlen_s(filePath, ILibSimpleDataStore_MaxFilePath)); - retVal->dataFile = ILibSimpleDataStore_OpenFile(retVal->filePath); + retVal->dataFile = ILibSimpleDataStore_OpenFileEx2(retVal->filePath, 0, readonly); if (retVal->dataFile == NULL) { diff --git a/microstack/ILibSimpleDataStore.h b/microstack/ILibSimpleDataStore.h index 5faf1ac..cd08c24 100644 --- a/microstack/ILibSimpleDataStore.h +++ b/microstack/ILibSimpleDataStore.h @@ -41,8 +41,10 @@ const extern int ILibMemory_SimpleDataStore_CONTAINERSIZE; typedef void(*ILibSimpleDataStore_KeyEnumerationHandler)(ILibSimpleDataStore sender, char* Key, int KeyLen, void *user); // Create the data store. -__EXPORT_TYPE ILibSimpleDataStore ILibSimpleDataStore_CreateEx(char* filePath, int userExtraMemorySize); -#define ILibSimpleDataStore_Create(filePath) ILibSimpleDataStore_CreateEx(filePath, 0) +__EXPORT_TYPE ILibSimpleDataStore ILibSimpleDataStore_CreateEx2(char* filePath, int userExtraMemorySize, int readonly); +#define ILibSimpleDataStore_Create(filePath) ILibSimpleDataStore_CreateEx2(filePath, 0, 0) +#define ILibSimpleDataStore_CreateEx(filePath, userExtraMemorySize) ILibSimpleDataStore_CreateEx2(filePath, userExtraMemorySize, 0) + // Check if the data store exists int ILibSimpleDataStore_Exists(char *filePath); diff --git a/modules/dbTool.js b/modules/dbTool.js index 67d232b..5729623 100644 --- a/modules/dbTool.js +++ b/modules/dbTool.js @@ -16,13 +16,29 @@ limitations under the License. var db; +var readonlyDb = true; + +if (process.argv.length > 1) +{ + switch (process.argv[1]) + { + case 'compact': + case 'put': + case 'putx': + case 'delete': + case 'import': + readonlyDb = false; + break; + } +} + if (process.platform == 'win32') { - db = require('SimpleDataStore').Create(process.execPath.replace('.exe', '.db')); + db = require('SimpleDataStore').Create(process.execPath.replace('.exe', '.db'), { readOnly: readonlyDb }); } else { - db = require('SimpleDataStore').Create(process.execPath + '.db'); + db = require('SimpleDataStore').Create(process.execPath + '.db', { readOnly: readonlyDb }); }