Turn on utf8 flag with necessary to support non-ASCII file names on certain file systems.
BUG=chromium-os:15358
TEST=Checked that non-ASCII file names are shown correctly in file browser.
Change-Id: Idce832dc75c6d9e052be79e4f30a3c07fb56dbb2
Reviewed-on: http://gerrit.chromium.org/gerrit/3265
Reviewed-by: Darin Petkov <petkov@chromium.org>
Reviewed-by: Ben Chan <benchan@chromium.org>
Tested-by: Ben Chan <benchan@chromium.org>
diff --git a/disk-manager.cc b/disk-manager.cc
index e9d57f3..55c1710 100644
--- a/disk-manager.cc
+++ b/disk-manager.cc
@@ -6,6 +6,7 @@
#include "disk.h"
#include "udev-device.h"
+#include <base/basictypes.h>
#include <base/logging.h>
#include <base/scoped_ptr.h>
#include <base/string_number_conversions.h>
@@ -17,7 +18,6 @@
#include <unistd.h>
#include <algorithm>
#include <fstream>
-#include <sstream>
#include <vector>
@@ -39,11 +39,13 @@
static const char kFallbackMountPath[] = "/media/disk";
static const unsigned kMaxNumMountTrials = 10000;
static const unsigned kFallbackPasswordBufferSize = 16384;
+static const char* const kFilesystemsWithUTF8Flag[] = {
+ "vfat", "ntfs", "iso9660", "udf",
+};
static const char* const kFilesystemsWithMountUserAndGroupId[] = {
"fat", "vfat", "msdos", "ntfs",
"iso9660", "udf",
"hfs", "hfsplus", "hpfs",
- NULL
};
DiskManager::DiskManager()
@@ -358,31 +360,51 @@
return true;
}
-bool DiskManager::IsMountUserAndGroupIdSupportedByFilesystem(
- const std::string& filesystem_type) const {
- for (const char* const* filesystem = kFilesystemsWithMountUserAndGroupId;
- *filesystem; ++filesystem) {
- if (strcmp(filesystem_type.c_str(), *filesystem) == 0) {
+bool DiskManager::IsStringInStringArray(const std::string& str,
+ const char* const* str_array, size_t str_array_len) const {
+ for (size_t i = 0; i < str_array_len; ++i) {
+ if (str == str_array[i]) {
return true;
}
}
return false;
}
+bool DiskManager::IsMountUserAndGroupIdSupportedByFilesystem(
+ const std::string& filesystem_type) const {
+ return IsStringInStringArray(filesystem_type,
+ kFilesystemsWithMountUserAndGroupId,
+ arraysize(kFilesystemsWithMountUserAndGroupId));
+}
+
+bool DiskManager::IsUTF8FlagSupportedByFilesystem(
+ const std::string& filesystem_type) const {
+ return IsStringInStringArray(filesystem_type,
+ kFilesystemsWithUTF8Flag,
+ arraysize(kFilesystemsWithUTF8Flag));
+}
+
std::string DiskManager::ModifyMountOptionsForFilesystem(
const std::string& filesystem_type, const std::string& options) const {
- std::stringstream extended_options(options);
+ std::vector<std::string> extended_options;
+ if (!options.empty()) {
+ extended_options.push_back(options);
+ }
if (IsMountUserAndGroupIdSupportedByFilesystem(filesystem_type)) {
uid_t uid;
gid_t gid;
if (GetUserAndGroupId(kMountDefaultUser, &uid, &gid)) {
- if (!options.empty()) {
- extended_options << ",";
- }
- extended_options << "uid=" << uid << ",gid=" << gid;
+ extended_options.push_back(StringPrintf("uid=%d", uid));
+ extended_options.push_back(StringPrintf("gid=%d", gid));
}
}
- return extended_options.str();
+ if (IsUTF8FlagSupportedByFilesystem(filesystem_type)) {
+ extended_options.push_back("utf8");
+ }
+ if (filesystem_type == "vfat") {
+ extended_options.push_back("shortname=mixed");
+ }
+ return JoinString(extended_options, ',');
}
bool DiskManager::DoMount(const std::string& device_file,
diff --git a/disk-manager.h b/disk-manager.h
index 96c8732..eef2de6 100644
--- a/disk-manager.h
+++ b/disk-manager.h
@@ -59,10 +59,18 @@
// /proc/filesystems.
std::vector<std::string> GetFilesystems(std::istream& stream) const;
+ // Returns true if a string is found in an array of strings.
+ bool IsStringInStringArray(const std::string& str,
+ const char* const* str_array, size_t str_array_len) const;
+
// Checks if a filesystem supports user ID and group ID in mount options.
bool IsMountUserAndGroupIdSupportedByFilesystem(
const std::string& filesystem_type) const;
+ // Checks if a filesystem supports the utf8 flag in mount options.
+ bool IsUTF8FlagSupportedByFilesystem(
+ const std::string& filesystem_type) const;
+
// Gets the user ID and group ID for a given username.
bool GetUserAndGroupId(const std::string& username,
uid_t *uid, gid_t *gid) const;
diff --git a/disk-manager_unittest.cc b/disk-manager_unittest.cc
index 9866c2a..15ae749 100644
--- a/disk-manager_unittest.cc
+++ b/disk-manager_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include <base/logging.h>
+#include <base/string_util.h>
#include <gtest/gtest.h>
#include <sys/mount.h>
@@ -94,6 +95,20 @@
}
}
+TEST_F(DiskManagerTest, IsStringInStringArray) {
+ DiskManager manager;
+ const char* str_array[] = {
+ "this", "is", "a", "string", "array"
+ };
+ size_t len = arraysize(str_array);
+ EXPECT_TRUE(manager.IsStringInStringArray("this", str_array, len));
+ EXPECT_TRUE(manager.IsStringInStringArray("is", str_array, len));
+ EXPECT_TRUE(manager.IsStringInStringArray("a", str_array, len));
+ EXPECT_TRUE(manager.IsStringInStringArray("string", str_array, len));
+ EXPECT_TRUE(manager.IsStringInStringArray("array", str_array, len));
+ EXPECT_FALSE(manager.IsStringInStringArray("nonexistent", str_array, len));
+}
+
TEST_F(DiskManagerTest, IsMountUserAndGroupIdSupportedByFilesystem) {
DiskManager manager;
EXPECT_FALSE(manager.IsMountUserAndGroupIdSupportedByFilesystem("ext2"));
@@ -110,6 +125,59 @@
EXPECT_TRUE(manager.IsMountUserAndGroupIdSupportedByFilesystem("hpfs"));
}
+TEST_F(DiskManagerTest, IsUTF8FlagSupportedByFilesystem) {
+ DiskManager manager;
+ EXPECT_FALSE(manager.IsUTF8FlagSupportedByFilesystem("ext2"));
+ EXPECT_FALSE(manager.IsUTF8FlagSupportedByFilesystem("ext3"));
+ EXPECT_FALSE(manager.IsUTF8FlagSupportedByFilesystem("ext4"));
+ EXPECT_FALSE(manager.IsUTF8FlagSupportedByFilesystem("fat"));
+ EXPECT_TRUE(manager.IsUTF8FlagSupportedByFilesystem("vfat"));
+ EXPECT_FALSE(manager.IsUTF8FlagSupportedByFilesystem("msdos"));
+ EXPECT_TRUE(manager.IsUTF8FlagSupportedByFilesystem("ntfs"));
+ EXPECT_TRUE(manager.IsUTF8FlagSupportedByFilesystem("iso9660"));
+ EXPECT_TRUE(manager.IsUTF8FlagSupportedByFilesystem("udf"));
+ EXPECT_FALSE(manager.IsUTF8FlagSupportedByFilesystem("hfs"));
+ EXPECT_FALSE(manager.IsUTF8FlagSupportedByFilesystem("hfsplus"));
+ EXPECT_FALSE(manager.IsUTF8FlagSupportedByFilesystem("hpfs"));
+}
+
+TEST_F(DiskManagerTest, ModifyMountOptionsForFilesystem) {
+ DiskManager manager;
+ uid_t uid;
+ gid_t gid;
+ bool found_uid_gid = manager.GetUserAndGroupId("chronos", &uid, &gid);
+
+ std::string expected_options, modified_options;
+
+ // Test the case when both the uid/gid, utf8 and shortname options are added
+ expected_options = (found_uid_gid) ?
+ StringPrintf("ro,uid=%d,gid=%d,utf8,shortname=mixed", uid, gid) :
+ "ro,utf8,shortname=mixed";
+ modified_options = manager.ModifyMountOptionsForFilesystem("vfat", "ro");
+ EXPECT_EQ(expected_options, modified_options);
+
+ // Test the case when both the uid/gid and utf8 options are added
+ expected_options = (found_uid_gid) ?
+ StringPrintf("ro,uid=%d,gid=%d,utf8", uid, gid) : "ro,utf8";
+ modified_options = manager.ModifyMountOptionsForFilesystem("udf", "ro");
+ EXPECT_EQ(expected_options, modified_options);
+
+ // Test the case when only the uid/gid option is added
+ expected_options = (found_uid_gid) ?
+ StringPrintf("ro,uid=%d,gid=%d", uid, gid) : "ro";
+ modified_options = manager.ModifyMountOptionsForFilesystem("fat", "ro");
+ EXPECT_EQ(expected_options, modified_options);
+
+ // Test the case when no option is added
+ expected_options = "ro";
+ modified_options = manager.ModifyMountOptionsForFilesystem("ext2", "ro");
+ EXPECT_EQ(expected_options, modified_options);
+
+ expected_options = "";
+ modified_options = manager.ModifyMountOptionsForFilesystem("ext2", "");
+ EXPECT_EQ(expected_options, modified_options);
+}
+
TEST_F(DiskManagerTest, GetUserAndGroupIdForRoot) {
DiskManager manager;
uid_t uid;