blob: 20b8fd0741420e57fa5ab5257704eefd9deb1165 [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/format-manager.h"
#include <glib.h>
#include <map>
#include <string>
#include <base/file_util.h>
#include <base/logging.h>
#include <chromeos/process.h>
#include "cros-disks/cros-disks-server-impl.h"
namespace {
// Expected locations of an external format program
const char* kFormatProgramPaths[] = {
"/usr/sbin/mkfs.", "/bin/mkfs.", "/sbin/mkfs.", "/usr/bin/mkfs.",
};
// Supported file systems
const char* kSupportedFilesystems[] = {
"vfat"
};
void OnFormatProcessExit(pid_t pid, gint status, gpointer data) {
cros_disks::FormatManager* format_manager =
reinterpret_cast<cros_disks::FormatManager*>(data);
format_manager->FormattingFinished(pid, status);
}
} // annoymous namespace
namespace cros_disks {
FormatManager::FormatManager() {
}
FormatManager::~FormatManager() {
}
bool FormatManager::StartFormatting(const std::string& device_path,
const std::string& filesystem) {
// Check if the file system is supported for formatting
if (!IsFilesystemSupported(filesystem)) {
LOG(WARNING) << filesystem
<< " filesystem is not supported for formatting";
return false;
}
// Localize mkfs on disk
std::string format_program = GetFormatProgramPath(filesystem);
if (format_program.empty()) {
LOG(WARNING) << "Could not find an external format program "
"for filesystem" << filesystem;
return false;
}
if (format_process_.find(device_path) != format_process_.end()) {
LOG(WARNING) << "Device '" << device_path
<< "' is already being formatted";
return false;
}
chromeos::ProcessImpl* process = &format_process_[device_path];
process->AddArg(format_program);
process->AddArg(device_path);
if (!process->Start()) {
LOG(WARNING) << "Cannot start a process for formatting '"
<< device_path << "' as filesystem '" << filesystem << "'";
format_process_.erase(device_path);
return false;
}
pid_to_device_path_[process->pid()] = device_path;
g_child_watch_add(process->pid(),
&OnFormatProcessExit,
this);
return true;
}
void FormatManager::FormattingFinished(pid_t pid, int status) {
std::string device_path = pid_to_device_path_[pid];
format_process_.erase(device_path);
pid_to_device_path_.erase(pid);
if (parent_)
parent_->SignalFormattingFinished(device_path, status);
}
bool FormatManager::StopFormatting(const std::string& device_path) {
// TODO(sidor): implement
// When the cancel button is hit
return false;
}
void FormatManager::set_parent(CrosDisksServer* parent) {
parent_ = parent;
}
std::string FormatManager::GetFormatProgramPath(
const std::string& filesystem) const {
for (size_t i = 0; i < arraysize(kFormatProgramPaths); ++i) {
std::string path = kFormatProgramPaths[i] + filesystem;
if (file_util::PathExists(FilePath(path)))
return path;
}
return std::string();
}
bool FormatManager::IsFilesystemSupported(
const std::string& filesystem) const {
for (size_t i = 0; i < arraysize(kSupportedFilesystems); ++i) {
if (filesystem == kSupportedFilesystems[i])
return true;
}
return false;
}
} // namespace cros_disks