diff --git a/Documentation/Books/Users/ModuleFs/README.mdpp b/Documentation/Books/Users/ModuleFs/README.mdpp index e7c5217d53..e375b7ecc3 100644 --- a/Documentation/Books/Users/ModuleFs/README.mdpp +++ b/Documentation/Books/Users/ModuleFs/README.mdpp @@ -227,21 +227,24 @@ the file contents will be returned as a string. Supported encodings are: If no `encoding` is specified, the file contents will be returned in a Buffer object. - -!SUBSUBSECTION save - - -writes to a file +!SUBSUBSECTION write `fs.write(filename, content)` -Writes the content into a file. Content can be a string or a Buffer object. - +Writes the content into a file. Content can be a string or a Buffer +object. If the file already exists, it is truncated. !SUBSUBSECTION writeFileSync `fs.writeFileSync(filename, content)` This is an alias for `fs.write(filename, content)`. +!SUBSUBSECTION append +`fs.append(filename, content)` + +Writes the content into a file. Content can be a string or a Buffer +object. If the file already exists, the content is appended at the +end. + !SECTION Recursive Manipulation !SUBSUBSECTION copyRecursive diff --git a/js/common/bootstrap/modules/fs.js b/js/common/bootstrap/modules/fs.js index 71d18ea67f..4a479f6ca1 100644 --- a/js/common/bootstrap/modules/fs.js +++ b/js/common/bootstrap/modules/fs.js @@ -528,13 +528,22 @@ if (global.FS_UNZIP_FILE) { delete global.FS_UNZIP_FILE; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief append +//////////////////////////////////////////////////////////////////////////////// + +if (global.SYS_APPEND) { + exports.append = global.SYS_APPEND; + delete global.SYS_APPEND; +} + //////////////////////////////////////////////////////////////////////////////// /// @brief write //////////////////////////////////////////////////////////////////////////////// -if (global.SYS_SAVE) { - exports.write = global.SYS_SAVE; - delete global.SYS_SAVE; +if (global.SYS_WRITE) { + exports.write = global.SYS_WRITE; + delete global.SYS_WRITE; } //////////////////////////////////////////////////////////////////////////////// diff --git a/lib/V8/v8-utils.cpp b/lib/V8/v8-utils.cpp index 48ac3b8b59..492970dd26 100644 --- a/lib/V8/v8-utils.cpp +++ b/lib/V8/v8-utils.cpp @@ -2354,10 +2354,69 @@ static void JS_Read64(v8::FunctionCallbackInfo const& args) { } //////////////////////////////////////////////////////////////////////////////// -/// @brief was docuBlock JS_Save +/// @brief append to a file //////////////////////////////////////////////////////////////////////////////// -static void JS_Save(v8::FunctionCallbackInfo const& args) { +static void JS_Append(v8::FunctionCallbackInfo const& args) { + TRI_V8_TRY_CATCH_BEGIN(isolate) + v8::HandleScope scope(isolate); + + if (args.Length() != 2) { + TRI_V8_THROW_EXCEPTION_USAGE("write(, )"); + } + + TRI_Utf8ValueNFC name(TRI_UNKNOWN_MEM_ZONE, args[0]); + + if (*name == nullptr) { + TRI_V8_THROW_TYPE_ERROR(" must be a string"); + } + + if (args[1]->IsObject() && V8Buffer::hasInstance(isolate, args[1])) { + // content is a buffer + char const* data = V8Buffer::data(args[1].As()); + size_t size = V8Buffer::length(args[1].As()); + + if (data == nullptr) { + TRI_V8_THROW_EXCEPTION_MESSAGE(TRI_ERROR_BAD_PARAMETER, + "invalid buffer value"); + } + + ofstream file; + + file.open(*name, ios::out | ios::binary | ios::app); + + if (file.is_open()) { + file.write(data, size); + file.close(); + TRI_V8_RETURN_TRUE(); + } + } else { + TRI_Utf8ValueNFC content(TRI_UNKNOWN_MEM_ZONE, args[1]); + + if (*content == nullptr) { + TRI_V8_THROW_TYPE_ERROR(" must be a string"); + } + + ofstream file; + + file.open(*name, ios::out | ios::binary | ios::app); + + if (file.is_open()) { + file << *content; + file.close(); + TRI_V8_RETURN_TRUE(); + } + } + + TRI_V8_THROW_EXCEPTION_SYS("cannot write file"); + TRI_V8_TRY_CATCH_END +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief write to a file +//////////////////////////////////////////////////////////////////////////////// + +static void JS_Write(v8::FunctionCallbackInfo const& args) { TRI_V8_TRY_CATCH_BEGIN(isolate) v8::HandleScope scope(isolate); @@ -4110,6 +4169,8 @@ void TRI_InitV8Utils(v8::Isolate* isolate, v8::Handle context, TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("FS_ZIP_FILE"), JS_ZipFile); + TRI_AddGlobalFunctionVocbase(isolate, context, + TRI_V8_ASCII_STRING("SYS_APPEND"), JS_Append); TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("SYS_BASE64DECODE"), JS_Base64Decode); @@ -4179,8 +4240,6 @@ void TRI_InitV8Utils(v8::Isolate* isolate, v8::Handle context, TRI_V8_ASCII_STRING("SYS_READ64"), JS_Read64); TRI_AddGlobalFunctionVocbase( isolate, context, TRI_V8_ASCII_STRING("SYS_READ_BUFFER"), JS_ReadBuffer); - TRI_AddGlobalFunctionVocbase(isolate, context, - TRI_V8_ASCII_STRING("SYS_SAVE"), JS_Save); TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("SYS_SHA1"), JS_Sha1); TRI_AddGlobalFunctionVocbase(isolate, context, @@ -4204,9 +4263,12 @@ void TRI_InitV8Utils(v8::Isolate* isolate, v8::Handle context, TRI_V8_ASCII_STRING("SYS_TIME"), JS_Time); TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("SYS_WAIT"), JS_Wait); + TRI_AddGlobalFunctionVocbase(isolate, context, + TRI_V8_ASCII_STRING("SYS_WRITE"), JS_Write); TRI_AddGlobalFunctionVocbase(isolate, context, TRI_V8_ASCII_STRING("SYS_DEBUG_CAN_USE_FAILAT"), JS_DebugCanUseFailAt); + // ............................................................................. // create the global variables // .............................................................................