0
0
mirror of https://github.com/mongodb/mongo.git synced 2024-11-21 20:49:10 +01:00

SERVER-93800: Implement appendFile() in mongo shell extensions (#26325)

GitOrigin-RevId: 733b6eacf1cda8199440ac0ceeb963f4d155c3a6
This commit is contained in:
William L Qian 2024-08-21 14:55:59 -04:00 committed by MongoDB Bot
parent c984354d72
commit c6b0d0aff6
2 changed files with 64 additions and 0 deletions

View File

@ -153,6 +153,7 @@ globals:
# likely could be replaced with `path`
_copyFileRange: true
appendFile: true
copyFile: true
writeFile: true
fileExists: true

View File

@ -475,6 +475,68 @@ BSONObj writeBsonArrayToFile(const BSONObj& args, void* data) {
return undefinedReturn;
}
BSONObj appendFile(const BSONObj& args, void* data) {
// Parse the arguments.
uassert(9380001,
"appendFile requires at least 2 arguments: appendFile(filePath, content, "
"[useBinaryMode])",
args.nFields() >= 2);
BSONObjIterator it(args);
auto filePathElem = it.next();
uassert(9380002,
"the first argument to appendFile() must be a string containing the path to the file",
filePathElem.type() == mongo::String);
auto fileContentElem = it.next();
uassert(9380003,
"the second argument to appendFile() must be a string to append to the file",
fileContentElem.type() == mongo::String);
// Limit the capability to appending to only existing files.
const boost::filesystem::path originalFilePath{filePathElem.String()};
const boost::filesystem::path normalizedFilePath{originalFilePath.lexically_normal()};
const boost::filesystem::path absoluteFilePath{boost::filesystem::absolute(normalizedFilePath)};
uassert(9380004,
"appendFile() can onlyappend to a file in a directory that already exists",
boost::filesystem::exists(absoluteFilePath.parent_path()));
uassert(9380005,
"appendFile() can only append to a file that does not yet exist",
boost::filesystem::exists(absoluteFilePath));
uassert(9380006,
"the file name must be compatible with POSIX and Windows",
boost::filesystem::portable_name(absoluteFilePath.filename().string()));
std::ios::openmode mode = std::ios::out;
auto useBinary = it.next();
if (!useBinary.eoo()) {
uassert(9380007,
"the third argument to appendFile(), must be a boolean indicating whether "
"or not to read the file in binary mode. If omitted, the default is 'false'.",
useBinary.type() == mongo::Bool);
if (useBinary.Bool())
mode |= std::ios::binary;
}
boost::filesystem::ofstream ofs{absoluteFilePath, mode | std::ios::app};
uassert(9380008,
str::stream() << "failed to open file " << absoluteFilePath.string()
<< " for appending",
ofs);
ofs << fileContentElem.String();
uassert(
9380009, str::stream() << "failed to append to file " << absoluteFilePath.string(), ofs);
return undefinedReturn;
}
BSONObj getHostName(const BSONObj& a, void* data) {
uassert(13411, "getHostName accepts no arguments", a.nFields() == 0);
char buf[260]; // HOST_NAME_MAX is usually 255
@ -648,6 +710,7 @@ void installShellUtilsExtended(Scope& scope) {
scope.injectNative("getHostName", getHostName);
scope.injectNative("removeFile", removeFile);
scope.injectNative("copyFile", copyFile);
scope.injectNative("appendFile", appendFile);
scope.injectNative("writeFile", writeFile);
scope.injectNative("listFiles", listFiles);
scope.injectNative("ls", ls);