Delete unused features of rtc::FilesystemInterface and related classes.
Deleted methods: DirectoryIterator::FileSize DirectoryIterator::IsDots DirectoryIterator::OlderThan FilesystemInterface::CleanAppTempFolder FilesystemInterface::CopyFileOrFolder FilesystemInterface::CopyFolder FilesystemInterface::CreatePrivateFile FilesystemInterface::DeleteFileOrFolder FilesystemInterface::GetAppPathname FilesystemInterface::GetCurrentDirectory FilesystemInterface::MoveFileOrFolder FilesystemInterface::MoveFolder Filesystem::CleanAppTempFolder Filesystem::CopyFolder Filesystem::CreatePrivateFile Filesystem::CreateUniqueFile Filesystem::DeleteEmptyFolder Filesystem::GetAppPathname Filesystem::GetCurrentDirectory Filesystem::MoveFolder BUG=webrtc:6424 Review-Url: https://codereview.webrtc.org/2445733002 Cr-Commit-Position: refs/heads/master@{#14800}
This commit is contained in:
parent
a101e560b9
commit
da35f3e3ce
@ -117,25 +117,6 @@ std::string DirectoryIterator::Name() const {
|
||||
#endif
|
||||
}
|
||||
|
||||
// returns the size of the file currently pointed to
|
||||
size_t DirectoryIterator::FileSize() const {
|
||||
#if !defined(WEBRTC_WIN)
|
||||
return stat_.st_size;
|
||||
#else
|
||||
return data_.nFileSizeLow;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool DirectoryIterator::OlderThan(int seconds) const {
|
||||
time_t file_modify_time;
|
||||
#if defined(WEBRTC_WIN)
|
||||
FileTimeToUnixTime(data_.ftLastWriteTime, &file_modify_time);
|
||||
#else
|
||||
file_modify_time = stat_.st_mtime;
|
||||
#endif
|
||||
return time(NULL) - file_modify_time >= seconds;
|
||||
}
|
||||
|
||||
FilesystemInterface* Filesystem::default_filesystem_ = NULL;
|
||||
|
||||
FilesystemInterface *Filesystem::EnsureDefaultFilesystem() {
|
||||
@ -153,37 +134,6 @@ DirectoryIterator* FilesystemInterface::IterateDirectory() {
|
||||
return new DirectoryIterator();
|
||||
}
|
||||
|
||||
bool FilesystemInterface::CopyFolder(const Pathname &old_path,
|
||||
const Pathname &new_path) {
|
||||
bool success = true;
|
||||
VERIFY(IsFolder(old_path));
|
||||
Pathname new_dir;
|
||||
new_dir.SetFolder(new_path.pathname());
|
||||
Pathname old_dir;
|
||||
old_dir.SetFolder(old_path.pathname());
|
||||
if (!CreateFolder(new_dir))
|
||||
return false;
|
||||
DirectoryIterator *di = IterateDirectory();
|
||||
if (!di)
|
||||
return false;
|
||||
if (di->Iterate(old_dir.pathname())) {
|
||||
do {
|
||||
if (di->Name() == "." || di->Name() == "..")
|
||||
continue;
|
||||
Pathname source;
|
||||
Pathname dest;
|
||||
source.SetFolder(old_dir.pathname());
|
||||
dest.SetFolder(new_path.pathname());
|
||||
source.SetFilename(di->Name());
|
||||
dest.SetFilename(di->Name());
|
||||
if (!CopyFileOrFolder(source, dest))
|
||||
success = false;
|
||||
} while (di->Next());
|
||||
}
|
||||
delete di;
|
||||
return success;
|
||||
}
|
||||
|
||||
bool FilesystemInterface::DeleteFolderContents(const Pathname &folder) {
|
||||
bool success = true;
|
||||
VERIFY(IsFolder(folder));
|
||||
@ -217,68 +167,4 @@ bool FilesystemInterface::DeleteFolderAndContents(const Pathname& folder) {
|
||||
return DeleteFolderContents(folder) && DeleteEmptyFolder(folder);
|
||||
}
|
||||
|
||||
bool FilesystemInterface::CleanAppTempFolder() {
|
||||
Pathname path;
|
||||
if (!GetAppTempFolder(&path))
|
||||
return false;
|
||||
if (IsAbsent(path))
|
||||
return true;
|
||||
if (!IsTemporaryPath(path)) {
|
||||
ASSERT(false);
|
||||
return false;
|
||||
}
|
||||
return DeleteFolderContents(path);
|
||||
}
|
||||
|
||||
Pathname Filesystem::GetCurrentDirectory() {
|
||||
return EnsureDefaultFilesystem()->GetCurrentDirectory();
|
||||
}
|
||||
|
||||
bool CreateUniqueFile(Pathname& path, bool create_empty) {
|
||||
LOG(LS_INFO) << "Path " << path.pathname() << std::endl;
|
||||
// If no folder is supplied, use the temporary folder
|
||||
if (path.folder().empty()) {
|
||||
Pathname temporary_path;
|
||||
if (!Filesystem::GetTemporaryFolder(temporary_path, true, NULL)) {
|
||||
printf("Get temp failed\n");
|
||||
return false;
|
||||
}
|
||||
path.SetFolder(temporary_path.pathname());
|
||||
}
|
||||
|
||||
// If no filename is supplied, use a temporary name
|
||||
if (path.filename().empty()) {
|
||||
std::string folder(path.folder());
|
||||
std::string filename = Filesystem::TempFilename(folder, "gt");
|
||||
path.SetPathname(filename);
|
||||
if (!create_empty) {
|
||||
Filesystem::DeleteFile(path.pathname());
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// Otherwise, create a unique name based on the given filename
|
||||
// foo.txt -> foo-N.txt
|
||||
const std::string basename = path.basename();
|
||||
const size_t MAX_VERSION = 100;
|
||||
size_t version = 0;
|
||||
while (version < MAX_VERSION) {
|
||||
std::string pathname = path.pathname();
|
||||
|
||||
if (!Filesystem::IsFile(pathname)) {
|
||||
if (create_empty) {
|
||||
FileStream* fs = Filesystem::OpenFile(pathname, "w");
|
||||
delete fs;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
version += 1;
|
||||
char version_base[MAX_PATH];
|
||||
sprintfn(version_base, arraysize(version_base), "%s-%u", basename.c_str(),
|
||||
version);
|
||||
path.SetBasename(version_base);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
@ -63,18 +63,6 @@ class DirectoryIterator {
|
||||
// returns the name of the file currently pointed to
|
||||
virtual std::string Name() const;
|
||||
|
||||
// returns the size of the file currently pointed to
|
||||
virtual size_t FileSize() const;
|
||||
|
||||
// returns true if the file is older than seconds
|
||||
virtual bool OlderThan(int seconds) const;
|
||||
|
||||
// checks whether current file is a special directory file "." or ".."
|
||||
bool IsDots() const {
|
||||
std::string filename(Name());
|
||||
return (filename.compare(".") == 0) || (filename.compare("..") == 0);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string directory_;
|
||||
#if defined(WEBRTC_WIN)
|
||||
@ -104,15 +92,6 @@ class FilesystemInterface {
|
||||
virtual FileStream *OpenFile(const Pathname &filename,
|
||||
const std::string &mode) = 0;
|
||||
|
||||
// Atomically creates an empty file accessible only to the current user if one
|
||||
// does not already exist at the given path, otherwise fails. This is the only
|
||||
// secure way to create a file in a shared temp directory (e.g., C:\Temp on
|
||||
// Windows or /tmp on Linux).
|
||||
// Note that if it is essential that a file be successfully created then the
|
||||
// app must generate random names and retry on failure, or else it will be
|
||||
// vulnerable to a trivial DoS.
|
||||
virtual bool CreatePrivateFile(const Pathname &filename) = 0;
|
||||
|
||||
// This will attempt to delete the path located at filename.
|
||||
// It ASSERTS and returns false if the path points to a folder or a
|
||||
// non-existent file.
|
||||
@ -133,16 +112,6 @@ class FilesystemInterface {
|
||||
// the folder itself.
|
||||
virtual bool DeleteFolderAndContents(const Pathname& folder);
|
||||
|
||||
// This will delete whatever is located at path, be it a file or a folder.
|
||||
// If it is a folder, it will delete it recursively by calling
|
||||
// DeleteFolderAndContents
|
||||
bool DeleteFileOrFolder(const Pathname &path) {
|
||||
if (IsFolder(path))
|
||||
return DeleteFolderAndContents(path);
|
||||
else
|
||||
return DeleteFile(path);
|
||||
}
|
||||
|
||||
// Creates a directory. This will call itself recursively to create /foo/bar
|
||||
// even if /foo does not exist. Returns true if the function succeeds.
|
||||
virtual bool CreateFolder(const Pathname &pathname) = 0;
|
||||
@ -152,41 +121,13 @@ class FilesystemInterface {
|
||||
// directory, and returns true if the function succeeds.
|
||||
// If the new path is on a different volume than the old path, this function
|
||||
// will attempt to copy and, if that succeeds, delete the old path.
|
||||
virtual bool MoveFolder(const Pathname &old_path,
|
||||
const Pathname &new_path) = 0;
|
||||
|
||||
// This moves a directory from old_path to new_path, where "old_path" is a
|
||||
// directory. This ASSERTs and returns false if old_path points to a plain
|
||||
// file, and returns true if the function succeeds.
|
||||
// If the new path is on a different volume, this function will attempt to
|
||||
// copy and if that succeeds, delete the old path.
|
||||
virtual bool MoveFile(const Pathname &old_path, const Pathname &new_path) = 0;
|
||||
|
||||
// This attempts to move whatever is located at old_path to new_path,
|
||||
// be it a file or folder.
|
||||
bool MoveFileOrFolder(const Pathname &old_path, const Pathname &new_path) {
|
||||
if (IsFile(old_path)) {
|
||||
return MoveFile(old_path, new_path);
|
||||
} else {
|
||||
return MoveFolder(old_path, new_path);
|
||||
}
|
||||
}
|
||||
|
||||
// This copies a file from old_path to new_path. This method ASSERTs and
|
||||
// returns false if old_path is a folder, and returns true if the copy
|
||||
// succeeds.
|
||||
virtual bool CopyFile(const Pathname &old_path, const Pathname &new_path) = 0;
|
||||
|
||||
// This copies a folder from old_path to new_path.
|
||||
bool CopyFolder(const Pathname &old_path, const Pathname &new_path);
|
||||
|
||||
bool CopyFileOrFolder(const Pathname &old_path, const Pathname &new_path) {
|
||||
if (IsFile(old_path))
|
||||
return CopyFile(old_path, new_path);
|
||||
else
|
||||
return CopyFolder(old_path, new_path);
|
||||
}
|
||||
|
||||
// Returns true if pathname refers to a directory
|
||||
virtual bool IsFolder(const Pathname& pathname) = 0;
|
||||
|
||||
@ -215,11 +156,6 @@ class FilesystemInterface {
|
||||
virtual bool GetFileTime(const Pathname& path, FileTimeType which,
|
||||
time_t* time) = 0;
|
||||
|
||||
// Returns the path to the running application.
|
||||
// Note: This is not guaranteed to work on all platforms. Be aware of the
|
||||
// limitations before using it, and robustly handle failure.
|
||||
virtual bool GetAppPathname(Pathname* path) = 0;
|
||||
|
||||
// Get a folder that is unique to the current application, which is suitable
|
||||
// for sharing data between executions of the app. If the per_user arg is
|
||||
// true, the folder is also specific to the current user.
|
||||
@ -231,14 +167,8 @@ class FilesystemInterface {
|
||||
// will be cleaned up when the program exits.
|
||||
virtual bool GetAppTempFolder(Pathname* path) = 0;
|
||||
|
||||
// Delete the contents of the folder returned by GetAppTempFolder
|
||||
bool CleanAppTempFolder();
|
||||
|
||||
virtual bool GetDiskFreeSpace(const Pathname& path, int64_t* freebytes) = 0;
|
||||
|
||||
// Returns the absolute path of the current directory.
|
||||
virtual Pathname GetCurrentDirectory() = 0;
|
||||
|
||||
// Note: These might go into some shared config section later, but they're
|
||||
// used by some methods in this interface, so we're leaving them here for now.
|
||||
void SetOrganizationName(const std::string& organization) {
|
||||
@ -292,18 +222,10 @@ class Filesystem {
|
||||
return EnsureDefaultFilesystem()->OpenFile(filename, mode);
|
||||
}
|
||||
|
||||
static bool CreatePrivateFile(const Pathname &filename) {
|
||||
return EnsureDefaultFilesystem()->CreatePrivateFile(filename);
|
||||
}
|
||||
|
||||
static bool DeleteFile(const Pathname &filename) {
|
||||
return EnsureDefaultFilesystem()->DeleteFile(filename);
|
||||
}
|
||||
|
||||
static bool DeleteEmptyFolder(const Pathname &folder) {
|
||||
return EnsureDefaultFilesystem()->DeleteEmptyFolder(folder);
|
||||
}
|
||||
|
||||
static bool DeleteFolderContents(const Pathname &folder) {
|
||||
return EnsureDefaultFilesystem()->DeleteFolderContents(folder);
|
||||
}
|
||||
@ -312,18 +234,10 @@ class Filesystem {
|
||||
return EnsureDefaultFilesystem()->DeleteFolderAndContents(folder);
|
||||
}
|
||||
|
||||
static bool MoveFolder(const Pathname &old_path, const Pathname &new_path) {
|
||||
return EnsureDefaultFilesystem()->MoveFolder(old_path, new_path);
|
||||
}
|
||||
|
||||
static bool MoveFile(const Pathname &old_path, const Pathname &new_path) {
|
||||
return EnsureDefaultFilesystem()->MoveFile(old_path, new_path);
|
||||
}
|
||||
|
||||
static bool CopyFolder(const Pathname &old_path, const Pathname &new_path) {
|
||||
return EnsureDefaultFilesystem()->CopyFolder(old_path, new_path);
|
||||
}
|
||||
|
||||
static bool CopyFile(const Pathname &old_path, const Pathname &new_path) {
|
||||
return EnsureDefaultFilesystem()->CopyFile(old_path, new_path);
|
||||
}
|
||||
@ -363,10 +277,6 @@ class Filesystem {
|
||||
return EnsureDefaultFilesystem()->GetFileTime(path, which, time);
|
||||
}
|
||||
|
||||
static bool GetAppPathname(Pathname* path) {
|
||||
return EnsureDefaultFilesystem()->GetAppPathname(path);
|
||||
}
|
||||
|
||||
static bool GetAppDataFolder(Pathname* path, bool per_user) {
|
||||
return EnsureDefaultFilesystem()->GetAppDataFolder(path, per_user);
|
||||
}
|
||||
@ -375,18 +285,10 @@ class Filesystem {
|
||||
return EnsureDefaultFilesystem()->GetAppTempFolder(path);
|
||||
}
|
||||
|
||||
static bool CleanAppTempFolder() {
|
||||
return EnsureDefaultFilesystem()->CleanAppTempFolder();
|
||||
}
|
||||
|
||||
static bool GetDiskFreeSpace(const Pathname& path, int64_t* freebytes) {
|
||||
return EnsureDefaultFilesystem()->GetDiskFreeSpace(path, freebytes);
|
||||
}
|
||||
|
||||
// Definition has to be in the .cc file due to returning forward-declared
|
||||
// Pathname by value.
|
||||
static Pathname GetCurrentDirectory();
|
||||
|
||||
static void SetOrganizationName(const std::string& organization) {
|
||||
EnsureDefaultFilesystem()->SetOrganizationName(organization);
|
||||
}
|
||||
@ -423,14 +325,6 @@ class FilesystemScope{
|
||||
RTC_DISALLOW_IMPLICIT_CONSTRUCTORS(FilesystemScope);
|
||||
};
|
||||
|
||||
// Generates a unique filename based on the input path. If no path component
|
||||
// is specified, it uses the temporary directory. If a filename is provided,
|
||||
// up to 100 variations of form basename-N.extension are tried. When
|
||||
// create_empty is true, an empty file of this name is created (which
|
||||
// decreases the chance of a temporary filename collision with another
|
||||
// process).
|
||||
bool CreateUniqueFile(Pathname& path, bool create_empty);
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
#endif // WEBRTC_BASE_FILEUTILS_H_
|
||||
|
||||
@ -150,10 +150,6 @@ class FakeFileSystem : public FilesystemInterface {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool CreatePrivateFile(const Pathname &filename) {
|
||||
EXPECT_TRUE(false) << "Unsupported operation";
|
||||
return false;
|
||||
}
|
||||
bool DeleteFile(const Pathname &filename) {
|
||||
EXPECT_TRUE(false) << "Unsupported operation";
|
||||
return false;
|
||||
@ -174,10 +170,6 @@ class FakeFileSystem : public FilesystemInterface {
|
||||
EXPECT_TRUE(false) << "Unsupported operation";
|
||||
return false;
|
||||
}
|
||||
bool MoveFolder(const Pathname &old_path, const Pathname &new_path) {
|
||||
EXPECT_TRUE(false) << "Unsupported operation";
|
||||
return false;
|
||||
}
|
||||
bool MoveFile(const Pathname &old_path, const Pathname &new_path) {
|
||||
EXPECT_TRUE(false) << "Unsupported operation";
|
||||
return false;
|
||||
@ -220,10 +212,6 @@ class FakeFileSystem : public FilesystemInterface {
|
||||
EXPECT_TRUE(false) << "Unsupported operation";
|
||||
return false;
|
||||
}
|
||||
bool GetAppPathname(Pathname *path) {
|
||||
EXPECT_TRUE(false) << "Unsupported operation";
|
||||
return false;
|
||||
}
|
||||
bool GetAppDataFolder(Pathname *path, bool per_user) {
|
||||
EXPECT_TRUE(per_user) << "Unsupported operation";
|
||||
#if defined(WEBRTC_WIN)
|
||||
@ -241,11 +229,8 @@ class FakeFileSystem : public FilesystemInterface {
|
||||
EXPECT_TRUE(false) << "Unsupported operation";
|
||||
return false;
|
||||
}
|
||||
Pathname GetCurrentDirectory() {
|
||||
return Pathname();
|
||||
}
|
||||
|
||||
private:
|
||||
private:
|
||||
const std::vector<File> all_files_;
|
||||
};
|
||||
} // namespace rtc
|
||||
|
||||
@ -70,28 +70,6 @@ TEST(MAYBE_FilesystemTest, TestOpenBadFile) {
|
||||
EXPECT_FALSE(fs != NULL);
|
||||
}
|
||||
|
||||
// Test that CreatePrivateFile fails for existing files and succeeds for
|
||||
// non-existent ones.
|
||||
TEST(MAYBE_FilesystemTest, TestCreatePrivateFile) {
|
||||
Pathname path;
|
||||
EXPECT_TRUE(Filesystem::GetTemporaryFolder(path, true, NULL));
|
||||
path.SetFilename("private_file_test");
|
||||
|
||||
// First call should succeed because the file doesn't exist yet.
|
||||
EXPECT_TRUE(Filesystem::CreatePrivateFile(path));
|
||||
// Next call should fail, because now it exists.
|
||||
EXPECT_FALSE(Filesystem::CreatePrivateFile(path));
|
||||
|
||||
// Verify that we have permission to open the file for reading and writing.
|
||||
std::unique_ptr<FileStream> fs(Filesystem::OpenFile(path, "wb"));
|
||||
EXPECT_TRUE(fs.get() != NULL);
|
||||
// Have to close the file on Windows before it will let us delete it.
|
||||
fs.reset();
|
||||
|
||||
// Verify that we have permission to delete the file.
|
||||
EXPECT_TRUE(Filesystem::DeleteFile(path));
|
||||
}
|
||||
|
||||
// Test checking for free disk space.
|
||||
TEST(MAYBE_FilesystemTest, TestGetDiskFreeSpace) {
|
||||
// Note that we should avoid picking any file/folder which could be located
|
||||
@ -125,16 +103,4 @@ TEST(MAYBE_FilesystemTest, TestGetDiskFreeSpace) {
|
||||
EXPECT_GT(free3, 0);
|
||||
}
|
||||
|
||||
// Tests that GetCurrentDirectory() returns something.
|
||||
TEST(MAYBE_FilesystemTest, TestGetCurrentDirectory) {
|
||||
EXPECT_FALSE(Filesystem::GetCurrentDirectory().empty());
|
||||
}
|
||||
|
||||
// Tests that GetAppPathname returns something.
|
||||
TEST(MAYBE_FilesystemTest, TestGetAppPathname) {
|
||||
Pathname path;
|
||||
EXPECT_TRUE(Filesystem::GetAppPathname(&path));
|
||||
EXPECT_FALSE(path.empty());
|
||||
}
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
@ -132,22 +132,6 @@ FileStream *UnixFilesystem::OpenFile(const Pathname &filename,
|
||||
return fs;
|
||||
}
|
||||
|
||||
bool UnixFilesystem::CreatePrivateFile(const Pathname &filename) {
|
||||
int fd = open(filename.pathname().c_str(),
|
||||
O_RDWR | O_CREAT | O_EXCL,
|
||||
S_IRUSR | S_IWUSR);
|
||||
if (fd < 0) {
|
||||
LOG_ERR(LS_ERROR) << "open() failed.";
|
||||
return false;
|
||||
}
|
||||
// Don't need to keep the file descriptor.
|
||||
if (close(fd) < 0) {
|
||||
LOG_ERR(LS_ERROR) << "close() failed.";
|
||||
// Continue.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnixFilesystem::DeleteFile(const Pathname &filename) {
|
||||
LOG(LS_INFO) << "Deleting file:" << filename.pathname();
|
||||
|
||||
@ -229,25 +213,6 @@ bool UnixFilesystem::MoveFile(const Pathname &old_path,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnixFilesystem::MoveFolder(const Pathname &old_path,
|
||||
const Pathname &new_path) {
|
||||
if (!IsFolder(old_path)) {
|
||||
ASSERT(IsFolder(old_path));
|
||||
return false;
|
||||
}
|
||||
LOG(LS_VERBOSE) << "Moving " << old_path.pathname()
|
||||
<< " to " << new_path.pathname();
|
||||
if (rename(old_path.pathname().c_str(), new_path.pathname().c_str()) != 0) {
|
||||
if (errno != EXDEV)
|
||||
return false;
|
||||
if (!CopyFolder(old_path, new_path))
|
||||
return false;
|
||||
if (!DeleteFolderAndContents(old_path))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnixFilesystem::IsFolder(const Pathname &path) {
|
||||
struct stat st;
|
||||
if (stat(path.pathname().c_str(), &st) < 0)
|
||||
@ -347,23 +312,6 @@ bool UnixFilesystem::GetFileTime(const Pathname& path, FileTimeType which,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UnixFilesystem::GetAppPathname(Pathname* path) {
|
||||
#if defined(__native_client__)
|
||||
return false;
|
||||
#elif defined(WEBRTC_MAC)
|
||||
AppleAppName(path);
|
||||
return true;
|
||||
#else // WEBRTC_MAC && !defined(WEBRTC_IOS)
|
||||
char buffer[PATH_MAX + 2];
|
||||
ssize_t len = readlink("/proc/self/exe", buffer, arraysize(buffer) - 1);
|
||||
if ((len <= 0) || (len == PATH_MAX + 1))
|
||||
return false;
|
||||
buffer[len] = '\0';
|
||||
path->SetPathname(buffer);
|
||||
return true;
|
||||
#endif // WEBRTC_MAC && !defined(WEBRTC_IOS)
|
||||
}
|
||||
|
||||
bool UnixFilesystem::GetAppDataFolder(Pathname* path, bool per_user) {
|
||||
// On macOS and iOS, there is no requirement that the path contains the
|
||||
// organization.
|
||||
@ -503,20 +451,6 @@ bool UnixFilesystem::GetDiskFreeSpace(const Pathname& path,
|
||||
#endif // !__native_client__
|
||||
}
|
||||
|
||||
Pathname UnixFilesystem::GetCurrentDirectory() {
|
||||
Pathname cwd;
|
||||
char buffer[PATH_MAX];
|
||||
char *path = getcwd(buffer, PATH_MAX);
|
||||
|
||||
if (!path) {
|
||||
LOG_ERR(LS_ERROR) << "getcwd() failed";
|
||||
return cwd; // returns empty pathname
|
||||
}
|
||||
cwd.SetFolder(std::string(path));
|
||||
|
||||
return cwd;
|
||||
}
|
||||
|
||||
char* UnixFilesystem::CopyString(const std::string& str) {
|
||||
size_t size = str.length() + 1;
|
||||
|
||||
|
||||
@ -39,10 +39,6 @@ class UnixFilesystem : public FilesystemInterface {
|
||||
FileStream* OpenFile(const Pathname& filename,
|
||||
const std::string& mode) override;
|
||||
|
||||
// Atomically creates an empty file accessible only to the current user if one
|
||||
// does not already exist at the given path, otherwise fails.
|
||||
bool CreatePrivateFile(const Pathname& filename) override;
|
||||
|
||||
// This will attempt to delete the file located at filename.
|
||||
// It will fail with VERIY if you pass it a non-existant file, or a directory.
|
||||
bool DeleteFile(const Pathname& filename) override;
|
||||
@ -65,7 +61,6 @@ class UnixFilesystem : public FilesystemInterface {
|
||||
// file or directory, which will be moved recursively.
|
||||
// Returns true if function succeeds.
|
||||
bool MoveFile(const Pathname& old_path, const Pathname& new_path) override;
|
||||
bool MoveFolder(const Pathname& old_path, const Pathname& new_path) override;
|
||||
|
||||
// This copies a file from old_path to _new_path where "file" can be a plain
|
||||
// file or directory, which will be copied recursively.
|
||||
@ -99,9 +94,6 @@ class UnixFilesystem : public FilesystemInterface {
|
||||
FileTimeType which,
|
||||
time_t* time) override;
|
||||
|
||||
// Returns the path to the running application.
|
||||
bool GetAppPathname(Pathname* path) override;
|
||||
|
||||
bool GetAppDataFolder(Pathname* path, bool per_user) override;
|
||||
|
||||
// Get a temporary folder that is unique to the current user and application.
|
||||
@ -109,9 +101,6 @@ class UnixFilesystem : public FilesystemInterface {
|
||||
|
||||
bool GetDiskFreeSpace(const Pathname& path, int64_t* freebytes) override;
|
||||
|
||||
// Returns the absolute path of the current directory.
|
||||
Pathname GetCurrentDirectory() override;
|
||||
|
||||
private:
|
||||
#if defined(WEBRTC_ANDROID) || defined(WEBRTC_MAC)
|
||||
static char* provided_app_data_folder_;
|
||||
|
||||
@ -72,114 +72,6 @@ FileStream *Win32Filesystem::OpenFile(const Pathname &filename,
|
||||
return fs;
|
||||
}
|
||||
|
||||
bool Win32Filesystem::CreatePrivateFile(const Pathname &filename) {
|
||||
// To make the file private to the current user, we first must construct a
|
||||
// SECURITY_DESCRIPTOR specifying an ACL. This code is mostly based upon
|
||||
// http://msdn.microsoft.com/en-us/library/ms707085%28VS.85%29.aspx
|
||||
|
||||
// Get the current process token.
|
||||
HANDLE process_token = INVALID_HANDLE_VALUE;
|
||||
if (!::OpenProcessToken(::GetCurrentProcess(),
|
||||
TOKEN_QUERY,
|
||||
&process_token)) {
|
||||
LOG_ERR(LS_ERROR) << "OpenProcessToken() failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the size of its TOKEN_USER structure. Return value is not checked
|
||||
// because we expect it to fail.
|
||||
DWORD token_user_size = 0;
|
||||
(void)::GetTokenInformation(process_token,
|
||||
TokenUser,
|
||||
NULL,
|
||||
0,
|
||||
&token_user_size);
|
||||
|
||||
// Get the TOKEN_USER structure.
|
||||
std::unique_ptr<char[]> token_user_bytes(new char[token_user_size]);
|
||||
PTOKEN_USER token_user = reinterpret_cast<PTOKEN_USER>(
|
||||
token_user_bytes.get());
|
||||
memset(token_user, 0, token_user_size);
|
||||
BOOL success = ::GetTokenInformation(process_token,
|
||||
TokenUser,
|
||||
token_user,
|
||||
token_user_size,
|
||||
&token_user_size);
|
||||
// We're now done with this.
|
||||
::CloseHandle(process_token);
|
||||
if (!success) {
|
||||
LOG_ERR(LS_ERROR) << "GetTokenInformation() failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!IsValidSid(token_user->User.Sid)) {
|
||||
LOG_ERR(LS_ERROR) << "Current process has invalid user SID";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Compute size needed for an ACL that allows access to just this user.
|
||||
int acl_size = sizeof(ACL) + sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) +
|
||||
GetLengthSid(token_user->User.Sid);
|
||||
|
||||
// Allocate it.
|
||||
std::unique_ptr<char[]> acl_bytes(new char[acl_size]);
|
||||
PACL acl = reinterpret_cast<PACL>(acl_bytes.get());
|
||||
memset(acl, 0, acl_size);
|
||||
if (!::InitializeAcl(acl, acl_size, ACL_REVISION)) {
|
||||
LOG_ERR(LS_ERROR) << "InitializeAcl() failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allow access to only the current user.
|
||||
if (!::AddAccessAllowedAce(acl,
|
||||
ACL_REVISION,
|
||||
GENERIC_READ | GENERIC_WRITE | STANDARD_RIGHTS_ALL,
|
||||
token_user->User.Sid)) {
|
||||
LOG_ERR(LS_ERROR) << "AddAccessAllowedAce() failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now make the security descriptor.
|
||||
SECURITY_DESCRIPTOR security_descriptor;
|
||||
if (!::InitializeSecurityDescriptor(&security_descriptor,
|
||||
SECURITY_DESCRIPTOR_REVISION)) {
|
||||
LOG_ERR(LS_ERROR) << "InitializeSecurityDescriptor() failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Put the ACL in it.
|
||||
if (!::SetSecurityDescriptorDacl(&security_descriptor,
|
||||
TRUE,
|
||||
acl,
|
||||
FALSE)) {
|
||||
LOG_ERR(LS_ERROR) << "SetSecurityDescriptorDacl() failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finally create the file.
|
||||
SECURITY_ATTRIBUTES security_attributes;
|
||||
security_attributes.nLength = sizeof(security_attributes);
|
||||
security_attributes.lpSecurityDescriptor = &security_descriptor;
|
||||
security_attributes.bInheritHandle = FALSE;
|
||||
HANDLE handle = ::CreateFile(
|
||||
ToUtf16(filename.pathname()).c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
&security_attributes,
|
||||
CREATE_NEW,
|
||||
0,
|
||||
NULL);
|
||||
if (INVALID_HANDLE_VALUE == handle) {
|
||||
LOG_ERR(LS_ERROR) << "CreateFile() failed";
|
||||
return false;
|
||||
}
|
||||
if (!::CloseHandle(handle)) {
|
||||
LOG_ERR(LS_ERROR) << "CloseFile() failed";
|
||||
// Continue.
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Win32Filesystem::DeleteFile(const Pathname &filename) {
|
||||
LOG(LS_INFO) << "Deleting file " << filename.pathname();
|
||||
if (!IsFile(filename)) {
|
||||
@ -241,28 +133,6 @@ bool Win32Filesystem::MoveFile(const Pathname &old_path,
|
||||
ToUtf16(new_path.pathname()).c_str()) != 0;
|
||||
}
|
||||
|
||||
bool Win32Filesystem::MoveFolder(const Pathname &old_path,
|
||||
const Pathname &new_path) {
|
||||
if (!IsFolder(old_path)) {
|
||||
ASSERT(IsFolder(old_path));
|
||||
return false;
|
||||
}
|
||||
LOG(LS_INFO) << "Moving " << old_path.pathname()
|
||||
<< " to " << new_path.pathname();
|
||||
if (::MoveFile(ToUtf16(old_path.pathname()).c_str(),
|
||||
ToUtf16(new_path.pathname()).c_str()) == 0) {
|
||||
if (::GetLastError() != ERROR_NOT_SAME_DEVICE) {
|
||||
LOG_GLE(LS_ERROR) << "Failed to move file";
|
||||
return false;
|
||||
}
|
||||
if (!CopyFolder(old_path, new_path))
|
||||
return false;
|
||||
if (!DeleteFolderAndContents(old_path))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Win32Filesystem::IsFolder(const Pathname &path) {
|
||||
WIN32_FILE_ATTRIBUTE_DATA data = {0};
|
||||
if (0 == ::GetFileAttributesEx(ToUtf16(path.pathname()).c_str(),
|
||||
@ -423,41 +293,4 @@ bool Win32Filesystem::GetDiskFreeSpace(const Pathname& path,
|
||||
}
|
||||
}
|
||||
|
||||
Pathname Win32Filesystem::GetCurrentDirectory() {
|
||||
Pathname cwd;
|
||||
int path_len = 0;
|
||||
std::unique_ptr<wchar_t[]> path;
|
||||
do {
|
||||
int needed = ::GetCurrentDirectory(path_len, path.get());
|
||||
if (needed == 0) {
|
||||
// Error.
|
||||
LOG_GLE(LS_ERROR) << "::GetCurrentDirectory() failed";
|
||||
return cwd; // returns empty pathname
|
||||
}
|
||||
if (needed <= path_len) {
|
||||
// It wrote successfully.
|
||||
break;
|
||||
}
|
||||
// Else need to re-alloc for "needed".
|
||||
path.reset(new wchar_t[needed]);
|
||||
path_len = needed;
|
||||
} while (true);
|
||||
cwd.SetFolder(ToUtf8(path.get()));
|
||||
return cwd;
|
||||
}
|
||||
|
||||
// TODO: Consider overriding DeleteFolderAndContents for speed and potentially
|
||||
// better OS integration (recycle bin?)
|
||||
/*
|
||||
std::wstring temp_path16 = ToUtf16(temp_path.pathname());
|
||||
temp_path16.append(1, '*');
|
||||
temp_path16.append(1, '\0');
|
||||
|
||||
SHFILEOPSTRUCT file_op = { 0 };
|
||||
file_op.wFunc = FO_DELETE;
|
||||
file_op.pFrom = temp_path16.c_str();
|
||||
file_op.fFlags = FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
|
||||
return (0 == SHFileOperation(&file_op));
|
||||
*/
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
@ -22,10 +22,6 @@ class Win32Filesystem : public FilesystemInterface {
|
||||
virtual FileStream *OpenFile(const Pathname &filename,
|
||||
const std::string &mode);
|
||||
|
||||
// Atomically creates an empty file accessible only to the current user if one
|
||||
// does not already exist at the given path, otherwise fails.
|
||||
virtual bool CreatePrivateFile(const Pathname &filename);
|
||||
|
||||
// This will attempt to delete the path located at filename.
|
||||
// If the path points to a folder, it will fail with VERIFY
|
||||
virtual bool DeleteFile(const Pathname &filename);
|
||||
@ -45,11 +41,6 @@ class Win32Filesystem : public FilesystemInterface {
|
||||
// Returns true if the file is successfully moved
|
||||
virtual bool MoveFile(const Pathname &old_path, const Pathname &new_path);
|
||||
|
||||
// Moves a folder from old_path to new_path. If the new path is on a different
|
||||
// volume from the old, it will attempt to Copy and then Delete the folder
|
||||
// Returns true if the folder is successfully moved
|
||||
virtual bool MoveFolder(const Pathname &old_path, const Pathname &new_path);
|
||||
|
||||
// This copies a file from old_path to _new_path
|
||||
// Returns true if function succeeds
|
||||
virtual bool CopyFile(const Pathname &old_path, const Pathname &new_path);
|
||||
@ -77,15 +68,12 @@ class Win32Filesystem : public FilesystemInterface {
|
||||
virtual bool GetFileSize(const Pathname& path, size_t* size);
|
||||
virtual bool GetFileTime(const Pathname& path, FileTimeType which,
|
||||
time_t* time);
|
||||
|
||||
|
||||
// A folder appropriate for storing temporary files (Contents are
|
||||
// automatically deleted when the program exists)
|
||||
virtual bool GetTemporaryFolder(Pathname &path, bool create,
|
||||
const std::string *append);
|
||||
|
||||
// Returns the path to the running application.
|
||||
virtual bool GetAppPathname(Pathname* path);
|
||||
|
||||
virtual bool GetAppDataFolder(Pathname* path, bool per_user);
|
||||
|
||||
// Get a temporary folder that is unique to the current user and application.
|
||||
@ -93,7 +81,9 @@ class Win32Filesystem : public FilesystemInterface {
|
||||
|
||||
virtual bool GetDiskFreeSpace(const Pathname& path, int64_t* free_bytes);
|
||||
|
||||
virtual Pathname GetCurrentDirectory();
|
||||
private:
|
||||
// Returns the path to the running application.
|
||||
bool GetAppPathname(Pathname* path);
|
||||
};
|
||||
|
||||
} // namespace rtc
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user