1 /* 2 * Access a filesystem. 3 * 4 * Copyright (C) 2019, 2022 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <stdio.h> 23 #include <string.h> 24 #include <unistd.h> 25 26 #include <ext2fs/ext2fs.h> 27 28 #include "input.h" 29 #include "ops.h" 30 #include "session.h" 31 32 33 34 /* Copy buffer size. */ 35 36 extern int BUFSIZE; 37 38 /* Maximum number of arguments in scripts. */ 39 40 const int MAX_ARGS = 32; 41 42 43 44 /* Read operations from a script file. */ 45 46 enum op_results 47 { 48 OP_SUCCESS = 0, 49 OP_FAILED = 1, 50 OP_UNKNOWN = 2, 51 }; 52 53 int handle_op_result(const char *operation, enum op_results op_result) 54 { 55 if (op_result == OP_UNKNOWN) 56 { 57 fprintf(stderr, "Operation not recognised: %s\n", operation); 58 return 1; 59 } 60 else if (op_result == OP_FAILED) 61 { 62 fprintf(stderr, "Operation failed: %s\n", operation); 63 return 1; 64 } 65 else 66 return 0; 67 } 68 69 enum op_results run_operation(ext2_filsys fs, const char *operation, int argc, char *argv[]); 70 71 int run_script(ext2_filsys fs, int argc, char *argv[]) 72 { 73 FILE *fp; 74 char buffer[BUFSIZE]; 75 struct read_line_state state; 76 enum op_results op_result; 77 int num_args; 78 char *args[MAX_ARGS]; 79 int i; 80 81 for (i = 0; i < argc; i++) 82 { 83 fp = fopen(argv[i], "r"); 84 85 state.buffer = buffer; 86 state.start = buffer; 87 state.end = buffer; 88 state.buffer_size = BUFSIZE; 89 state.remaining = BUFSIZE - 1; 90 91 while (read_line(fp, &state) != NULL) 92 { 93 parse_line(state.start, state.eolp, &num_args, args, MAX_ARGS); 94 95 if (num_args > 1) 96 { 97 op_result = run_operation(fs, args[0], num_args - 1, &args[1]); 98 99 if (handle_op_result(args[0], op_result)) 100 return 1; 101 } 102 103 state.start = state.eolp + 1; 104 } 105 106 fclose(fp); 107 } 108 109 return 0; 110 } 111 112 113 114 /* Help message. */ 115 116 char help_text[] = "\ 117 Usage: %s [ <options> ] <image file> <operation> <filename>...\n\ 118 \n\ 119 File ownership options:\n\ 120 \n\ 121 -g GID Set group identifier for new files\n\ 122 -u UID Set user identifier for new files\n\ 123 \n\ 124 File permission options:\n\ 125 \n\ 126 -m MASK Set mode/permissions mask for new directories\n\ 127 \n\ 128 Transfer operations:\n\ 129 \n\ 130 copy-in Copy files into a directory within the image\n\ 131 copy-out Copy files from the image into a directory\n\ 132 \n\ 133 Image operations:\n\ 134 \n\ 135 ls List files and directories within the image\n\ 136 mkdir Make directories within the image\n\ 137 rm Remove non-directory objects from the image\n\ 138 rmdir Remove directories from the image\n\ 139 stat Show statistics for files and directories\n\ 140 \n\ 141 Script operations:\n\ 142 \n\ 143 script Read operations from a script file\n\ 144 "; 145 146 /* Operations exposed by the program. */ 147 148 struct operation 149 { 150 const char *name; 151 int (*fn)(ext2_filsys, int, char *[]); 152 }; 153 154 static struct operation operations[] = { 155 {"copy-in", copy_in}, 156 {"copy-out", copy_out}, 157 {"ls", list}, 158 {"mkdir", make_dirs}, 159 {"rm", remove_non_dirs}, 160 {"rmdir", remove_dirs}, 161 {"script", run_script}, 162 {"stat", stat_objects}, 163 {NULL, NULL}, 164 }; 165 166 /* Invocation of operations. */ 167 168 enum op_results run_operation(ext2_filsys fs, const char *operation, int argc, char *argv[]) 169 { 170 struct operation *op; 171 int exitcode; 172 173 for (op = &operations[0]; op->name != NULL; op++) 174 { 175 if (!strcmp(operation, op->name)) 176 { 177 exitcode = op->fn(fs, argc, argv); 178 if (exitcode) 179 return OP_FAILED; 180 break; 181 } 182 } 183 184 if (op->name == NULL) 185 return OP_UNKNOWN; 186 187 return OP_SUCCESS; 188 } 189 190 /* Main program. */ 191 192 int main(int argc, char *argv[]) 193 { 194 int flags = EXT2_FLAG_RW; // | EXT2_FLAG_SOFTSUPP_FEATURES | EXT2_FLAG_64BITS; 195 ext2_filsys fs = NULL; 196 errcode_t retval; 197 int exitcode = 0; 198 199 /* Program argument details. */ 200 201 char **args; 202 char *fsname, *filename; 203 int num_args; 204 enum op_results op_result; 205 206 /* Parse program options and initialise the argument details. */ 207 208 if (parse_options(argc, argv)) 209 return 1; 210 211 args = &argv[optind]; 212 num_args = argc - optind; 213 214 if (num_args < 3) 215 { 216 fprintf(stderr, help_text, argv[0]); 217 return 1; 218 } 219 220 /* Open the filesystem image using the POSIX file access mechanism. */ 221 222 fsname = args[0]; 223 224 retval = ext2fs_open(fsname, flags, 0, 0, unix_io_manager, &fs); 225 if (retval) 226 { 227 fprintf(stderr, "Could not open filesystem: %s\n", fsname); 228 return 1; 229 } 230 231 //fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE; 232 233 retval = ext2fs_read_bitmaps(fs); 234 if (retval) 235 { 236 fprintf(stderr, "Could not read bitmaps: %s\n", fsname); 237 return 1; 238 } 239 240 /* Perform the requested operation. */ 241 242 op_result = run_operation(fs, args[1], num_args - 2, &args[2]); 243 exitcode = handle_op_result(args[1], op_result); 244 245 /* Close the filesystem image. */ 246 247 retval = ext2fs_flush(fs); 248 if (retval) 249 { 250 fprintf(stderr, "Error flushing filesystem: %s\n", fsname); 251 exitcode = 1; 252 } 253 254 retval = ext2fs_close(fs); 255 if (retval) 256 { 257 fprintf(stderr, "Error closing filesystem: %s\n", fsname); 258 exitcode = 1; 259 } 260 261 ext2fs_free(fs); 262 return exitcode; 263 } 264 265 /* vim: tabstop=4 expandtab shiftwidth=4 266 */