blob: 872f5817a6f19ceb3ebc35da2f25528a91e256d1 [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/logging.h>
#include <base/strings/string_split.h>
#include "cros-disks/file_reader.h"
#include "cros-disks/quote.h"
namespace cros_disks {
namespace {
bool IsOctalDigit(char digit) {
return digit >= '0' && digit <= '7';
}
} // namespace
// A data structure for holding information of a mount point.
struct MountInfo::MountPointData {
std::string source_path;
std::string mount_path;
std::string filesystem_type;
};
MountInfo::MountInfo() = default;
MountInfo::~MountInfo() = default;
int MountInfo::ConvertOctalStringToInt(const std::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;
}
std::string MountInfo::DecodePath(const std::string& encoded_path) const {
size_t encoded_path_size = encoded_path.size();
std::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;
}
std::vector<std::string> MountInfo::GetMountPaths(
const std::string& source_path) const {
std::vector<std::string> mount_paths;
for (const auto& mount_point : mount_points_) {
if (mount_point.source_path == source_path)
mount_paths.push_back(mount_point.mount_path);
}
return mount_paths;
}
bool MountInfo::HasMountPath(const std::string& mount_path) const {
for (const auto& mount_point : mount_points_) {
if (mount_point.mount_path == mount_path)
return true;
}
return false;
}
bool MountInfo::RetrieveFromFile(const std::string& path) {
mount_points_.clear();
FileReader reader;
if (!reader.Open(base::FilePath(path))) {
LOG(ERROR) << "Cannot retrieve mount info from " << quote(path);
return false;
}
std::string line;
while (reader.ReadLine(&line)) {
std::vector<std::string> tokens = base::SplitString(
line, " ", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
size_t num_tokens = tokens.size();
if (num_tokens >= 10 && tokens[num_tokens - 4] == "-") {
MountPointData 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