blob: 0cd9812a41b5ad2fc8eec5bdfff960b7e10d9ad0 [file] [log] [blame]
// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "cros-disks/mount_info.h"
#include <base/strings/string_split.h>
#include <base/logging.h>
#include "cros-disks/file_reader.h"
using base::FilePath;
using std::string;
using std::vector;
namespace {
bool IsOctalDigit(char digit) {
return digit >= '0' && digit <= '7';
}
} // namespace
namespace cros_disks {
// A data structure for holding information of a mount point.
struct MountPoint {
string source_path;
string mount_path;
string filesystem_type;
};
MountInfo::MountInfo() {
}
MountInfo::~MountInfo() {
}
int MountInfo::ConvertOctalStringToInt(const string& octal) const {
if (octal.size() == 3 && IsOctalDigit(octal[0]) &&
IsOctalDigit(octal[1]) && IsOctalDigit(octal[2])) {
return (octal[0] - '0') * 64 + (octal[1] - '0') * 8 + (octal[2] - '0');
}
return -1;
}
string MountInfo::DecodePath(const string& encoded_path) const {
size_t encoded_path_size = encoded_path.size();
string decoded_path;
decoded_path.reserve(encoded_path_size);
for (size_t index = 0; index < encoded_path_size; ++index) {
char path_char = encoded_path[index];
if ((path_char == '\\') && (index + 3 < encoded_path_size)) {
int decimal = ConvertOctalStringToInt(encoded_path.substr(index + 1, 3));
if (decimal != -1) {
decoded_path.push_back(static_cast<char>(decimal));
index += 3;
continue;
}
}
decoded_path.push_back(path_char);
}
return decoded_path;
}
vector<string> MountInfo::GetMountPaths(const string& source_path) const {
vector<string> mount_paths;
for (vector<MountPoint>::const_iterator iter = mount_points_.begin();
iter != mount_points_.end(); ++iter) {
if (iter->source_path == source_path)
mount_paths.push_back(iter->mount_path);
}
return mount_paths;
}
bool MountInfo::HasMountPath(const string& mount_path) const {
for (vector<MountPoint>::const_iterator iter = mount_points_.begin();
iter != mount_points_.end(); ++iter) {
if (iter->mount_path == mount_path)
return true;
}
return false;
}
bool MountInfo::RetrieveFromFile(const string& path) {
mount_points_.clear();
FileReader reader;
if (!reader.Open(FilePath(path))) {
LOG(ERROR) << "Failed to retrieve mount info from '" << path << "'";
return false;
}
string line;
while (reader.ReadLine(&line)) {
vector<string> tokens;
base::SplitString(line, ' ', &tokens);
size_t num_tokens = tokens.size();
if (num_tokens >= 10 && tokens[num_tokens - 4] == "-") {
MountPoint mount_point;
mount_point.source_path = DecodePath(tokens[num_tokens - 2]);
mount_point.mount_path = DecodePath(tokens[4]);
mount_point.filesystem_type = tokens[num_tokens - 3];
mount_points_.push_back(mount_point);
}
}
return true;
}
bool MountInfo::RetrieveFromCurrentProcess() {
return RetrieveFromFile("/proc/self/mountinfo");
}
} // namespace cros_disks