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:
parent
c984354d72
commit
c6b0d0aff6
@ -153,6 +153,7 @@ globals:
|
||||
|
||||
# likely could be replaced with `path`
|
||||
_copyFileRange: true
|
||||
appendFile: true
|
||||
copyFile: true
|
||||
writeFile: true
|
||||
fileExists: true
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user