summaryrefslogtreecommitdiffstats
path: root/base
diff options
context:
space:
mode:
authoryoshiki@chromium.org <yoshiki@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-11 01:24:02 +0000
committeryoshiki@chromium.org <yoshiki@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-11 01:24:02 +0000
commit5085e4487f4b1d6c92075e1a1434b8d422adbecc (patch)
treec1ec6d98d3656565a912f802750bb5604a7b45c3 /base
parenta51ea457256f8cd7249f9c0c363845371494ac60 (diff)
downloadchromium_src-5085e4487f4b1d6c92075e1a1434b8d422adbecc.zip
chromium_src-5085e4487f4b1d6c92075e1a1434b8d422adbecc.tar.gz
chromium_src-5085e4487f4b1d6c92075e1a1434b8d422adbecc.tar.bz2
Add the methods to change and get a posix file permission to file_util.
BUG=134821, 134820 TEST=both base_unittests:FileUtilTest.*, VerifyPathControlledByUserTest.* and unit_tests:Gdata* pass Review URL: https://chromiumcodereview.appspot.com/10756020 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@146020 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'base')
-rw-r--r--base/file_util.h30
-rw-r--r--base/file_util_posix.cc34
-rw-r--r--base/file_util_unittest.cc191
3 files changed, 229 insertions, 26 deletions
diff --git a/base/file_util.h b/base/file_util.h
index 7564df3..dec95d6 100644
--- a/base/file_util.h
+++ b/base/file_util.h
@@ -101,7 +101,7 @@ BASE_EXPORT int64 ComputeFilesSize(const FilePath& directory,
// Returns true if successful, false otherwise.
//
// In posix environment and if |path| is a symbolic link, this deletes only
-// the symlink. (even if the symlink deferences to a non-existent file)
+// the symlink. (even if the symlink points to a non-existent file)
//
// WARNING: USING THIS WITH recursive==true IS EQUIVALENT
// TO "rm -rf", SO USE WITH CAUTION.
@@ -196,6 +196,34 @@ BASE_EXPORT bool CreateSymbolicLink(const FilePath& target,
// Reads the given |symlink| and returns where it points to in |target|.
// Returns false upon failure.
BASE_EXPORT bool ReadSymbolicLink(const FilePath& symlink, FilePath* target);
+
+// Bits ans masks of the file permission.
+enum FilePermissionBits {
+ FILE_PERMISSION_MASK = S_IRWXU | S_IRWXG | S_IRWXO,
+ FILE_PERMISSION_USER_MASK = S_IRWXU,
+ FILE_PERMISSION_GROUP_MASK = S_IRWXG,
+ FILE_PERMISSION_OTHERS_MASK = S_IRWXO,
+
+ FILE_PERMISSION_READ_BY_USER = S_IRUSR,
+ FILE_PERMISSION_WRITE_BY_USER = S_IWUSR,
+ FILE_PERMISSION_EXECUTE_BY_USER = S_IXUSR,
+ FILE_PERMISSION_READ_BY_GROUP = S_IRGRP,
+ FILE_PERMISSION_WRITE_BY_GROUP = S_IWGRP,
+ FILE_PERMISSION_EXECUTE_BY_GROUP = S_IXGRP,
+ FILE_PERMISSION_READ_BY_OTHERS = S_IROTH,
+ FILE_PERMISSION_WRITE_BY_OTHERS = S_IWOTH,
+ FILE_PERMISSION_EXECUTE_BY_OTHERS = S_IXOTH,
+};
+
+// Reads the permission of the given |path|, storing the file permission
+// bits in |mode|. If |path| is symbolic link, |mode| is the permission of
+// a file which the symlink points to.
+BASE_EXPORT bool GetPosixFilePermissions(const FilePath& path,
+ int* mode);
+// Sets the permission of the given |path|. If |path| is symbolic link, sets
+// the permission of a file which the symlink points to.
+BASE_EXPORT bool SetPosixFilePermissions(const FilePath& path,
+ int mode);
#endif // defined(OS_POSIX)
#if defined(OS_WIN)
diff --git a/base/file_util_posix.cc b/base/file_util_posix.cc
index 18e515f..56dc8501 100644
--- a/base/file_util_posix.cc
+++ b/base/file_util_posix.cc
@@ -460,6 +460,40 @@ bool ReadSymbolicLink(const FilePath& symlink_path,
return true;
}
+bool GetPosixFilePermissions(const FilePath& path, int* mode) {
+ base::ThreadRestrictions::AssertIOAllowed();
+ DCHECK(mode);
+
+ stat_wrapper_t file_info;
+ // Uses stat(), because on symbolic link, lstat() does not return valid
+ // permission bits in st_mode
+ if (CallStat(path.value().c_str(), &file_info) != 0)
+ return false;
+
+ *mode = file_info.st_mode & FILE_PERMISSION_MASK;
+ return true;
+}
+
+bool SetPosixFilePermissions(const FilePath& path,
+ int mode) {
+ base::ThreadRestrictions::AssertIOAllowed();
+ DCHECK((mode & ~FILE_PERMISSION_MASK) == 0);
+
+ // Calls stat() so that we can preserve the higher bits like S_ISGID.
+ stat_wrapper_t stat_buf;
+ if (CallStat(path.value().c_str(), &stat_buf) != 0)
+ return false;
+
+ // Clears the existing permission bits, and adds the new ones.
+ mode_t updated_mode_bits = stat_buf.st_mode & ~FILE_PERMISSION_MASK;
+ updated_mode_bits |= mode & FILE_PERMISSION_MASK;
+
+ if (HANDLE_EINTR(chmod(path.value().c_str(), updated_mode_bits)) != 0)
+ return false;
+
+ return true;
+}
+
// Creates and opens a temporary file in |directory|, returning the
// file descriptor. |path| is set to the temporary file path.
// This function does NOT unlink() the file.
diff --git a/base/file_util_unittest.cc b/base/file_util_unittest.cc
index 55f2039..25e2f40 100644
--- a/base/file_util_unittest.cc
+++ b/base/file_util_unittest.cc
@@ -115,19 +115,16 @@ bool DeleteReparsePoint(HANDLE source) {
// ASSERT failures will return, but not stop the test. Caller should wrap
// calls to this function in ASSERT_NO_FATAL_FAILURE().
void ChangePosixFilePermissions(const FilePath& path,
- mode_t mode_bits_to_set,
- mode_t mode_bits_to_clear) {
+ int mode_bits_to_set,
+ int mode_bits_to_clear) {
ASSERT_FALSE(mode_bits_to_set & mode_bits_to_clear)
<< "Can't set and clear the same bits.";
- struct stat stat_buf;
- ASSERT_EQ(0, stat(path.value().c_str(), &stat_buf));
-
- mode_t updated_mode_bits = stat_buf.st_mode;
- updated_mode_bits |= mode_bits_to_set;
- updated_mode_bits &= ~mode_bits_to_clear;
-
- ASSERT_EQ(0, chmod(path.value().c_str(), updated_mode_bits));
+ int mode = 0;
+ ASSERT_TRUE(file_util::GetPosixFilePermissions(path, &mode));
+ mode |= mode_bits_to_set;
+ mode &= ~mode_bits_to_clear;
+ ASSERT_TRUE(file_util::SetPosixFilePermissions(path, mode));
}
#endif // defined(OS_POSIX)
@@ -667,7 +664,6 @@ TEST_F(FileUtilTest, CreateAndReadSymlinks) {
ASSERT_FALSE(file_util::ReadSymbolicLink(missing, &result));
}
-
// The following test of NormalizeFilePath() require that we create a symlink.
// This can not be done on Windows before Vista. On Vista, creating a symlink
// requires privilege "SeCreateSymbolicLinkPrivilege".
@@ -746,44 +742,186 @@ TEST_F(FileUtilTest, DeleteFile) {
#if defined(OS_POSIX)
TEST_F(FileUtilTest, DeleteSymlinkToExistentFile) {
- // Create a file
+ // Create a file.
FilePath file_name = temp_dir_.path().Append(FPL("Test DeleteFile 2.txt"));
CreateTextFile(file_name, bogus_content);
ASSERT_TRUE(file_util::PathExists(file_name));
- // Create a symlink to the file
+ // Create a symlink to the file.
FilePath file_link = temp_dir_.path().Append("file_link_2");
ASSERT_TRUE(file_util::CreateSymbolicLink(file_name, file_link))
<< "Failed to create symlink.";
- // Delete the symbolic link
+ // Delete the symbolic link.
EXPECT_TRUE(file_util::Delete(file_link, false));
- // Make sure original file is not deleted
+ // Make sure original file is not deleted.
EXPECT_FALSE(file_util::PathExists(file_link));
EXPECT_TRUE(file_util::PathExists(file_name));
}
TEST_F(FileUtilTest, DeleteSymlinkToNonExistentFile) {
- // Create a non-existent file path
+ // Create a non-existent file path.
FilePath non_existent = temp_dir_.path().Append(FPL("Test DeleteFile 3.txt"));
EXPECT_FALSE(file_util::PathExists(non_existent));
- // Create a symlink to the non-existent file
+ // Create a symlink to the non-existent file.
FilePath file_link = temp_dir_.path().Append("file_link_3");
ASSERT_TRUE(file_util::CreateSymbolicLink(non_existent, file_link))
<< "Failed to create symlink.";
- // Make sure the symbolic link is exist
+ // Make sure the symbolic link is exist.
EXPECT_TRUE(file_util::IsLink(file_link));
EXPECT_FALSE(file_util::PathExists(file_link));
- // Delete the symbolic link
+ // Delete the symbolic link.
EXPECT_TRUE(file_util::Delete(file_link, false));
- // Make sure the symbolic link is deleted
+ // Make sure the symbolic link is deleted.
EXPECT_FALSE(file_util::IsLink(file_link));
}
+
+TEST_F(FileUtilTest, ChangeFilePermissionsAndRead) {
+ // Create a file path.
+ FilePath file_name = temp_dir_.path().Append(FPL("Test Readable File.txt"));
+ EXPECT_FALSE(file_util::PathExists(file_name));
+
+ const std::string kData("hello");
+
+ int buffer_size = kData.length();
+ char* buffer = new char[buffer_size];
+
+ // Write file.
+ EXPECT_EQ(static_cast<int>(kData.length()),
+ file_util::WriteFile(file_name, kData.data(), kData.length()));
+ EXPECT_TRUE(file_util::PathExists(file_name));
+
+ // Make sure the file is readable.
+ int32 mode = 0;
+ EXPECT_TRUE(file_util::GetPosixFilePermissions(file_name, &mode));
+ EXPECT_TRUE(mode & file_util::FILE_PERMISSION_READ_BY_USER);
+
+ // Get rid of the read permission.
+ EXPECT_TRUE(file_util::SetPosixFilePermissions(file_name, 0u));
+ EXPECT_TRUE(file_util::GetPosixFilePermissions(file_name, &mode));
+ EXPECT_FALSE(mode & file_util::FILE_PERMISSION_READ_BY_USER);
+ // Make sure the file can't be read.
+ EXPECT_EQ(-1, file_util::ReadFile(file_name, buffer, buffer_size));
+
+ // Give the read permission.
+ EXPECT_TRUE(file_util::SetPosixFilePermissions(
+ file_name,
+ file_util::FILE_PERMISSION_READ_BY_USER));
+ EXPECT_TRUE(file_util::GetPosixFilePermissions(file_name, &mode));
+ EXPECT_TRUE(mode & file_util::FILE_PERMISSION_READ_BY_USER);
+ // Make sure the file can be read.
+ EXPECT_EQ(static_cast<int>(kData.length()),
+ file_util::ReadFile(file_name, buffer, buffer_size));
+
+ // Delete the file.
+ EXPECT_TRUE(file_util::Delete(file_name, false));
+ EXPECT_FALSE(file_util::PathExists(file_name));
+
+ delete[] buffer;
+}
+
+TEST_F(FileUtilTest, ChangeFilePermissionsAndWrite) {
+ // Create a file path.
+ FilePath file_name = temp_dir_.path().Append(FPL("Test Readable File.txt"));
+ EXPECT_FALSE(file_util::PathExists(file_name));
+
+ const std::string kData("hello");
+
+ // Write file.
+ EXPECT_EQ(static_cast<int>(kData.length()),
+ file_util::WriteFile(file_name, kData.data(), kData.length()));
+ EXPECT_TRUE(file_util::PathExists(file_name));
+
+ // Make sure the file is writable.
+ int mode = 0;
+ EXPECT_TRUE(file_util::GetPosixFilePermissions(file_name, &mode));
+ EXPECT_TRUE(mode & file_util::FILE_PERMISSION_WRITE_BY_USER);
+ EXPECT_TRUE(file_util::PathIsWritable(file_name));
+
+ // Get rid of the write permission.
+ EXPECT_TRUE(file_util::SetPosixFilePermissions(file_name, 0u));
+ EXPECT_TRUE(file_util::GetPosixFilePermissions(file_name, &mode));
+ EXPECT_FALSE(mode & file_util::FILE_PERMISSION_WRITE_BY_USER);
+ // Make sure the file can't be write.
+ EXPECT_EQ(-1,
+ file_util::WriteFile(file_name, kData.data(), kData.length()));
+ EXPECT_FALSE(file_util::PathIsWritable(file_name));
+
+ // Give read permission.
+ EXPECT_TRUE(file_util::SetPosixFilePermissions(
+ file_name,
+ file_util::FILE_PERMISSION_WRITE_BY_USER));
+ EXPECT_TRUE(file_util::GetPosixFilePermissions(file_name, &mode));
+ EXPECT_TRUE(mode & file_util::FILE_PERMISSION_WRITE_BY_USER);
+ // Make sure the file can be write.
+ EXPECT_EQ(static_cast<int>(kData.length()),
+ file_util::WriteFile(file_name, kData.data(), kData.length()));
+ EXPECT_TRUE(file_util::PathIsWritable(file_name));
+
+ // Delete the file.
+ EXPECT_TRUE(file_util::Delete(file_name, false));
+ EXPECT_FALSE(file_util::PathExists(file_name));
+}
+
+TEST_F(FileUtilTest, ChangeDirectoryPermissionsAndEnumerate) {
+ // Create a directory path.
+ FilePath subdir_path =
+ temp_dir_.path().Append(FPL("PermissionTest1"));
+ file_util::CreateDirectory(subdir_path);
+ ASSERT_TRUE(file_util::PathExists(subdir_path));
+
+ // Create a dummy file to enumerate.
+ FilePath file_name = subdir_path.Append(FPL("Test Readable File.txt"));
+ EXPECT_FALSE(file_util::PathExists(file_name));
+ const std::string kData("hello");
+ EXPECT_EQ(static_cast<int>(kData.length()),
+ file_util::WriteFile(file_name, kData.data(), kData.length()));
+ EXPECT_TRUE(file_util::PathExists(file_name));
+
+ // Make sure the directory has the all permissions.
+ int mode = 0;
+ EXPECT_TRUE(file_util::GetPosixFilePermissions(subdir_path, &mode));
+ EXPECT_EQ(file_util::FILE_PERMISSION_USER_MASK,
+ mode & file_util::FILE_PERMISSION_USER_MASK);
+
+ // Get rid of the permissions from the directory.
+ EXPECT_TRUE(file_util::SetPosixFilePermissions(subdir_path, 0u));
+ EXPECT_TRUE(file_util::GetPosixFilePermissions(subdir_path, &mode));
+ EXPECT_FALSE(mode & file_util::FILE_PERMISSION_USER_MASK);
+
+ // Make sure the file in the directory can't be enumerated.
+ file_util::FileEnumerator f1(subdir_path, true,
+ file_util::FileEnumerator::FILES);
+ EXPECT_TRUE(file_util::PathExists(subdir_path));
+ FindResultCollector c1(f1);
+ EXPECT_EQ(c1.size(), 0);
+ EXPECT_FALSE(file_util::GetPosixFilePermissions(file_name, &mode));
+
+ // Give the permissions to the directory.
+ EXPECT_TRUE(file_util::SetPosixFilePermissions(
+ subdir_path,
+ file_util::FILE_PERMISSION_USER_MASK));
+ EXPECT_TRUE(file_util::GetPosixFilePermissions(subdir_path, &mode));
+ EXPECT_EQ(file_util::FILE_PERMISSION_USER_MASK,
+ mode & file_util::FILE_PERMISSION_USER_MASK);
+
+ // Make sure the file in the directory can be enumerated.
+ file_util::FileEnumerator f2(subdir_path, true,
+ file_util::FileEnumerator::FILES);
+ FindResultCollector c2(f2);
+ EXPECT_TRUE(c2.HasFile(file_name));
+ EXPECT_EQ(c2.size(), 1);
+
+ // Delete the file.
+ EXPECT_TRUE(file_util::Delete(subdir_path, true));
+ EXPECT_FALSE(file_util::PathExists(subdir_path));
+}
+
#endif // defined(OS_POSIX)
#if defined(OS_WIN)
@@ -1997,11 +2135,14 @@ class VerifyPathControlledByUserTest : public FileUtilTest {
// of permissions to be different from what we expect, explicitly
// set permissions on the directories we create.
// Make all files and directories non-world-writable.
- mode_t enabled_permissions =
- S_IRWXU | // User can read, write, traverse
- S_IRWXG; // Group can read, write, traverse
- mode_t disabled_permissions =
- S_IRWXO; // Other users can't read, write, traverse.
+
+ // Users and group can read, write, traverse
+ int enabled_permissions =
+ file_util::FILE_PERMISSION_USER_MASK |
+ file_util::FILE_PERMISSION_GROUP_MASK;
+ // Other users can't read, write, traverse
+ int disabled_permissions =
+ file_util::FILE_PERMISSION_OTHERS_MASK;
ASSERT_NO_FATAL_FAILURE(
ChangePosixFilePermissions(