1 // Copyright 2018 The Fuchsia Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include <fcntl.h> 6 #include <mutex> 7 #include <stdio.h> 8 #include <stdlib.h> 9 #include <string.h> 10 #include <unistd.h> 11 12 #include <fbl/string.h> 13 #include <fbl/unique_fd.h> 14 #include <fbl/vector.h> 15 #include <zircon/types.h> 16 17 // The "manifest" command is only being retained here for backwards compatibility. 18 //TODO(planders): Once all clients have switched create/add with --manifest, remove this command. 19 enum class Command { 20 kNone, 21 kMkfs, 22 kFsck, 23 kLs, 24 kAdd, 25 kCp, 26 kManifest, 27 kMkdir, 28 }; 29 30 enum class Option { 31 kDepfile, 32 kReadonly, 33 kOffset, 34 kLength, 35 kCompress, 36 kHelp, 37 }; 38 39 enum class Argument { 40 kManifest, 41 kBlob, 42 }; 43 44 enum class ArgType { 45 kNone, 46 kOne, 47 kTwo, 48 kMany, 49 kOptional, 50 }; 51 52 // An abstract class which defines an interface for processing and running commands for file system 53 // host-side tools. This includes parsing all command line options, pre-processing any files to be 54 // copied, and resizing the file system image as necessary. Child classes must implement any 55 // commands they wish to support, as well as providing their own space calculations for files to be 56 // added. 57 class FsCreator { 58 public: 59 DISALLOW_COPY_ASSIGN_AND_MOVE(FsCreator); 60 FsCreator(uint64_t data_blocks)61 FsCreator(uint64_t data_blocks) : data_blocks_(data_blocks),command_(Command::kNone), 62 offset_(0), length_(0), read_only_(false), compress_(false), 63 depfile_lock_() {} ~FsCreator()64 virtual ~FsCreator() {} 65 66 // Process the command line arguments and run the specified command. 67 zx_status_t ProcessAndRun(int argc, char** argv); 68 69 // If a depfile was requested, |str| will be appended (followed by a space) 70 // to the depfile. |str| must be less than PATH_MAX. 71 zx_status_t AppendDepfile(const char* str); 72 73 protected: 74 // Print usage information for all options, commands, and arguments valid for this fs. 75 virtual zx_status_t Usage(); 76 77 // Returns the command name of the child fs. 78 virtual const char* GetToolName() = 0; 79 80 // Tells whether a given |command|, |option|, or |argument| are valid for this fs. 81 virtual bool IsCommandValid(Command command) = 0; 82 virtual bool IsOptionValid(Option option) = 0; 83 virtual bool IsArgumentValid(Argument argument) = 0; 84 85 // Processes the manifest at |manifest_path| and adds all relevant source/destination files to 86 // the child's internal processing lists. 87 zx_status_t ProcessManifest(char* manifest_path); 88 89 // Parses the next line in the |manifest| file located at |dir_path|, 90 // and returns the |dst| and |src| paths (if found). 91 zx_status_t ParseManifestLine(FILE* manifest, const char* dir_path, char* src, char* dst); 92 93 // Processes one line in |manifest|, storing files to copy and calculating total space required. 94 // Returns "ZX_ERR_OUT_OF_RANGE" when manifest has reached EOF. 95 virtual zx_status_t ProcessManifestLine(FILE* manifest, const char* dir_path) = 0; 96 97 // Process custom arguments specific to the child fs. Returns the number of processed arguments 98 // in |processed|. ProcessCustom(int argc,char ** argv,uint8_t * processed)99 virtual zx_status_t ProcessCustom(int argc, char** argv, uint8_t* processed) { 100 return ZX_ERR_NOT_SUPPORTED; 101 } 102 103 // Calculates the minimum fs size required for all files processed up to this point. 104 virtual zx_status_t CalculateRequiredSize(off_t* out) = 0; 105 106 // Commands. 107 // Creates the fs at fd_. Mkfs()108 virtual zx_status_t Mkfs() { return ZX_ERR_NOT_SUPPORTED; } 109 // Runs fsck on the fs at fd_. Fsck()110 virtual zx_status_t Fsck() { return ZX_ERR_NOT_SUPPORTED; } 111 // Adds all files specified in manifests or other command line arguments to the fs. Add()112 virtual zx_status_t Add() { return ZX_ERR_NOT_SUPPORTED; } 113 // Runs ls on the fs at fd_, at the specified path (if any). Ls()114 virtual zx_status_t Ls() { return ZX_ERR_NOT_SUPPORTED; } 115 GetCommand()116 Command GetCommand() const { return command_; } GetOffset()117 off_t GetOffset() const { return offset_; } GetLength()118 off_t GetLength() const { return length_; } ShouldCompress()119 bool ShouldCompress() const { return compress_; } 120 121 fbl::unique_fd fd_; 122 123 off_t data_blocks_; 124 125 private: 126 // Process all options/arguments and open fd to device. 127 zx_status_t ProcessArgs(int argc, char** argv); 128 129 // Perform the specified command. 130 zx_status_t RunCommand(); 131 132 // Parses the size specification (if any) from the |device| string, and returns the result in 133 // |*out|. The size argument is only valid for the "create" command. 134 zx_status_t ParseSize(char* device, size_t* out); 135 136 // Resizes the file on "create" if a different size was specified, or the file is not as 137 // large as it needs to be to contain all specified files (specifiles). 138 zx_status_t ResizeFile(off_t requested_size, struct stat stats); 139 140 Command command_; 141 off_t offset_; 142 off_t length_; 143 bool read_only_; 144 bool compress_; 145 std::mutex depfile_lock_; 146 fbl::unique_fd depfile_; 147 }; 148