blob: 01ce2fee0283284f8c5bbb4947628cdbbb2b6d93 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#pragma once
#include <fcntl.h>
#include <mutex>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fbl/string.h>
#include <fbl/unique_fd.h>
#include <fbl/vector.h>
#include <zircon/types.h>
#include <fs-host/file_size_recorder.h>
// The "manifest" command is only being retained here for backwards compatibility.
//TODO(planders): Once all clients have switched create/add with --manifest, remove this command.
enum class Command {
kNone,
kMkfs,
kFsck,
kLs,
kAdd,
kCp,
kManifest,
kMkdir,
};
enum class Option {
kDepfile,
kReadonly,
kOffset,
kLength,
kCompress,
kSizes,
kHelp,
};
enum class Argument {
kManifest,
kBlob,
};
enum class ArgType {
kNone,
kOne,
kTwo,
kMany,
kOptional,
};
// An abstract class which defines an interface for processing and running commands for file system
// host-side tools. This includes parsing all command line options, pre-processing any files to be
// copied, and resizing the file system image as necessary. Child classes must implement any
// commands they wish to support, as well as providing their own space calculations for files to be
// added.
class FsCreator {
public:
DISALLOW_COPY_ASSIGN_AND_MOVE(FsCreator);
FsCreator(uint64_t data_blocks) : data_blocks_(data_blocks) {}
virtual ~FsCreator() {}
// Process the command line arguments and run the specified command.
zx_status_t ProcessAndRun(int argc, char** argv);
// If a depfile was requested, |str| will be appended (followed by a space)
// to the depfile. |str| must be less than PATH_MAX.
zx_status_t AppendDepfile(const char* str);
protected:
// Print usage information for all options, commands, and arguments valid for this fs.
virtual zx_status_t Usage();
// Returns the command name of the child fs.
virtual const char* GetToolName() = 0;
// Tells whether a given |command|, |option|, or |argument| are valid for this fs.
virtual bool IsCommandValid(Command command) = 0;
virtual bool IsOptionValid(Option option) = 0;
virtual bool IsArgumentValid(Argument argument) = 0;
// Processes the manifest at |manifest_path| and adds all relevant source/destination files to
// the child's internal processing lists.
zx_status_t ProcessManifest(char* manifest_path);
// Parses the next line in the |manifest| file located at |dir_path|,
// and returns the |dst| and |src| paths (if found).
zx_status_t ParseManifestLine(FILE* manifest, const char* dir_path, char* src, char* dst);
// Processes one line in |manifest|, storing files to copy and calculating total space required.
// Returns "ZX_ERR_OUT_OF_RANGE" when manifest has reached EOF.
virtual zx_status_t ProcessManifestLine(FILE* manifest, const char* dir_path) = 0;
// Process custom arguments specific to the child fs. Returns the number of processed arguments
// in |processed|.
virtual zx_status_t ProcessCustom(int argc, char** argv, uint8_t* processed) {
return ZX_ERR_NOT_SUPPORTED;
}
// Calculates the minimum fs size required for all files processed up to this point.
virtual zx_status_t CalculateRequiredSize(off_t* out) = 0;
// Commands.
// Creates the fs at fd_.
virtual zx_status_t Mkfs() { return ZX_ERR_NOT_SUPPORTED; }
// Runs fsck on the fs at fd_.
virtual zx_status_t Fsck() { return ZX_ERR_NOT_SUPPORTED; }
// Adds all files specified in manifests or other command line arguments to the fs.
virtual zx_status_t Add() { return ZX_ERR_NOT_SUPPORTED; }
// Runs ls on the fs at fd_, at the specified path (if any).
virtual zx_status_t Ls() { return ZX_ERR_NOT_SUPPORTED; }
Command GetCommand() const { return command_; }
off_t GetOffset() const { return offset_; }
off_t GetLength() const { return length_; }
bool ShouldCompress() const { return compress_; }
FileSizeRecorder* size_recorder() { return &size_recorder_; }
fbl::unique_fd fd_;
off_t data_blocks_;
private:
// Process all options/arguments and open fd to device.
zx_status_t ProcessArgs(int argc, char** argv);
// Perform the specified command.
zx_status_t RunCommand();
// Parses the size specification (if any) from the |device| string, and returns the result in
// |*out|. The size argument is only valid for the "create" command.
zx_status_t ParseSize(char* device, size_t* out);
// Resizes the file on "create" if a different size was specified, or the file is not as
// large as it needs to be to contain all specified files (specifiles).
zx_status_t ResizeFile(off_t requested_size, struct stat stats);
Command command_{Command::kNone};
off_t offset_{0};
off_t length_{0};
bool read_only_{false};
bool compress_{false};
std::mutex depfile_lock_;
fbl::unique_fd depfile_;
FileSizeRecorder size_recorder_;
};