1.1 --- a/libe2access/host/e2access.c Sun Mar 06 01:06:30 2022 +0100
1.2 +++ b/libe2access/host/e2access.c Sun Mar 06 01:30:32 2022 +0100
1.3 @@ -20,28 +20,20 @@
1.4 */
1.5
1.6 #include <stdio.h>
1.7 -#include <stdlib.h>
1.8 #include <string.h>
1.9 #include <unistd.h>
1.10
1.11 -#include <sys/types.h>
1.12 -#include <sys/stat.h>
1.13 -#include <sys/sysmacros.h> /* major, minor */
1.14 -
1.15 #include <ext2fs/ext2fs.h>
1.16
1.17 -#include "file.h"
1.18 -#include "format.h"
1.19 -#include "image.h"
1.20 #include "input.h"
1.21 -#include "path.h"
1.22 -#include "utils.h"
1.23 +#include "ops.h"
1.24 +#include "session.h"
1.25
1.26
1.27
1.28 /* Copy buffer size. */
1.29
1.30 -const int BUFSIZE = 4096;
1.31 +extern int BUFSIZE;
1.32
1.33 /* Maximum number of arguments in scripts. */
1.34
1.35 @@ -49,590 +41,6 @@
1.36
1.37
1.38
1.39 -/* Alternative metadata set by options. */
1.40 -
1.41 -struct metadata
1.42 -{
1.43 - uid_t uid;
1.44 - gid_t gid;
1.45 - mode_t mask;
1.46 - int have_uid, have_gid;
1.47 -};
1.48 -
1.49 -struct metadata md;
1.50 -
1.51 -/* Parse program options. */
1.52 -
1.53 -static int parse_options(int argc, char *argv[])
1.54 -{
1.55 - int opt;
1.56 -
1.57 - md.have_uid = 0;
1.58 - md.have_gid = 0;
1.59 - md.mask = 0000;
1.60 -
1.61 - while ((opt = getopt(argc, argv, "g:m:u:")) != -1)
1.62 - {
1.63 - switch (opt)
1.64 - {
1.65 - case 'g':
1.66 - md.gid = atoi(optarg);
1.67 - md.have_gid = 1;
1.68 - break;
1.69 -
1.70 - case 'm':
1.71 - md.mask = strtol(optarg, NULL, 0);
1.72 - break;
1.73 -
1.74 - case 'u':
1.75 - md.uid = atoi(optarg);
1.76 - md.have_uid = 1;
1.77 - break;
1.78 -
1.79 - default:
1.80 - fprintf(stderr, "Option not recognised: %s\n", argv[optind]);
1.81 - return -1;
1.82 - }
1.83 - }
1.84 -
1.85 - return 0;
1.86 -}
1.87 -
1.88 -
1.89 -
1.90 -/* Copy a file into the filesystem image. */
1.91 -
1.92 -int copy_file_in(const char *filename, ext2_filsys fs, ext2_ino_t ino_file, int flags)
1.93 -{
1.94 - int retval = 0;
1.95 - ext2_file_t file;
1.96 -
1.97 - /* Copying details. */
1.98 -
1.99 - FILE *fp;
1.100 - char buf[BUFSIZE];
1.101 - size_t got;
1.102 - unsigned int written;
1.103 -
1.104 - /* Open a file in the target directory. */
1.105 -
1.106 - if (ext2fs_file_open(fs, ino_file, flags, &file))
1.107 - return 1;
1.108 -
1.109 - /* Open the file in the source directory. */
1.110 -
1.111 - fp = fopen(filename, "r");
1.112 -
1.113 - /* Copy the file content. */
1.114 -
1.115 - if (fp != NULL)
1.116 - {
1.117 - while (got = fread(buf, sizeof(char), BUFSIZE, fp))
1.118 - {
1.119 - while (got)
1.120 - {
1.121 - if (ext2fs_file_write(file, buf, got, &written))
1.122 - {
1.123 - retval = 1;
1.124 - goto close_files;
1.125 - }
1.126 - got -= written;
1.127 - }
1.128 - }
1.129 - }
1.130 -
1.131 -close_files:
1.132 - fclose(fp);
1.133 - ext2fs_file_flush(file);
1.134 - ext2fs_file_close(file);
1.135 -
1.136 - return retval;
1.137 -}
1.138 -
1.139 -/* Copy a file out of the filesystem image. */
1.140 -
1.141 -int copy_file_out(const char *target, const char *filename, int target_is_file,
1.142 - ext2_filsys fs, ext2_ino_t ino_file)
1.143 -{
1.144 - int retval = 0;
1.145 - ext2_file_t file;
1.146 -
1.147 - /* Copying details. */
1.148 -
1.149 - FILE *fp;
1.150 - char buf[BUFSIZE];
1.151 - unsigned int got;
1.152 - size_t written;
1.153 -
1.154 - /* Open the file in the source directory. */
1.155 -
1.156 - if (ext2fs_file_open(fs, ino_file, 0, &file))
1.157 - return 1;
1.158 -
1.159 - /* Open a file in the target directory. */
1.160 -
1.161 - if (target_is_file)
1.162 - fp = fopen(target, "w");
1.163 - else
1.164 - fp = open_file_in_dir(target, path_basename(filename), "w");
1.165 -
1.166 - /* Copy the file content. */
1.167 -
1.168 - if (fp != NULL)
1.169 - {
1.170 - do
1.171 - {
1.172 - if (ext2fs_file_read(file, buf, BUFSIZE, &got))
1.173 - {
1.174 - retval = 1;
1.175 - goto close_files;
1.176 - }
1.177 -
1.178 - while (got)
1.179 - {
1.180 - written = fwrite(buf, sizeof(char), got, fp);
1.181 - got -= written;
1.182 - }
1.183 -
1.184 - } while (got);
1.185 - }
1.186 -
1.187 -close_files:
1.188 - fclose(fp);
1.189 - ext2fs_file_close(file);
1.190 -
1.191 - return retval;
1.192 -}
1.193 -
1.194 -
1.195 -
1.196 -/* Make a new directory in the external environment. */
1.197 -
1.198 -static int _make_directory(const char *target, const char *basename,
1.199 - ext2_filsys fs, ext2_ino_t ino)
1.200 -{
1.201 - errcode_t retval;
1.202 - struct ext2_inode inode;
1.203 - char target_path[strlen(target) + strlen(basename) + 2];
1.204 -
1.205 - sprintf(target_path, "%s/%s", target, basename);
1.206 -
1.207 - retval = ext2fs_read_inode(fs, ino, &inode);
1.208 -
1.209 - if (retval)
1.210 - return retval;
1.211 -
1.212 - return mkdir(target_path, inode.i_mode);
1.213 -}
1.214 -
1.215 -/* Make a new object using the given function. */
1.216 -
1.217 -static int _make_object(ext2_filsys fs, const char *filename,
1.218 - ext2_ino_t ino_parent, const char *basename,
1.219 - ext2_ino_t *ino_target,
1.220 - errcode_t (*fn)(ext2_filsys, ext2_ino_t, const char *,
1.221 - __u16, __u16, __u16, ext2_ino_t *))
1.222 -{
1.223 - errcode_t retval;
1.224 - struct stat st;
1.225 -
1.226 - /* Obtain the metadata. */
1.227 -
1.228 - if (lstat(filename, &st))
1.229 - {
1.230 - fprintf(stderr, "Failed to read object metadata: %s\n", filename);
1.231 - return 1;
1.232 - }
1.233 -
1.234 - retval = fn(fs, ino_parent, basename, st.st_mode & ~md.mask,
1.235 - md.have_uid ? md.uid : st.st_uid,
1.236 - md.have_gid ? md.gid : st.st_gid,
1.237 - ino_target);
1.238 -
1.239 - if (retval)
1.240 - {
1.241 - fprintf(stderr, "Failed to create object: %s\n", filename);
1.242 - return 1;
1.243 - }
1.244 -
1.245 - return 0;
1.246 -}
1.247 -
1.248 -/* Copy a source file from the external environment into the filesystem. */
1.249 -
1.250 -static int _copy_in(ext2_filsys fs, const char *filename, ext2_ino_t ino_target,
1.251 - const char *basename)
1.252 -{
1.253 - errcode_t retval;
1.254 - int flags;
1.255 -
1.256 - /* By default, treat the target as a new object. */
1.257 -
1.258 - ext2_ino_t ino_parent = ino_target;
1.259 - int target_is_new = 1;
1.260 -
1.261 - /* Source file details. */
1.262 -
1.263 - struct stat st;
1.264 -
1.265 - /* Without a basename, the target exists and is either a directory, into
1.266 - which the source file shall be copied, or it is a file that shall be
1.267 - overwritten. */
1.268 -
1.269 - if (basename == NULL)
1.270 - {
1.271 - basename = path_basename(filename);
1.272 - target_is_new = image_isdir_by_inode(fs, ino_target);
1.273 - }
1.274 -
1.275 - /* Directories are created with the same metadata. */
1.276 -
1.277 - if (isdir(filename))
1.278 - {
1.279 - if (!target_is_new)
1.280 - {
1.281 - fprintf(stderr, "Directory cannot be copied as it already exists: %s\n", filename);
1.282 - return 1;
1.283 - }
1.284 -
1.285 - if (_make_object(fs, filename, ino_parent, basename, &ino_target,
1.286 - image_make_dir))
1.287 - return 1;
1.288 - }
1.289 -
1.290 - /* Files are copied. */
1.291 -
1.292 - else if (isfile(filename))
1.293 - {
1.294 - flags = EXT2_FILE_WRITE;
1.295 -
1.296 - /* Obtain the inode for the target file. */
1.297 -
1.298 - if (target_is_new)
1.299 - {
1.300 - if (_make_object(fs, filename, ino_parent, basename, &ino_target,
1.301 - image_create_file))
1.302 - return 1;
1.303 -
1.304 - flags |= EXT2_FILE_CREATE;
1.305 - }
1.306 -
1.307 - /* NOTE: Overwrite/update metadata where appropriate. */
1.308 -
1.309 - if (copy_file_in(filename, fs, ino_target, flags))
1.310 - {
1.311 - fprintf(stderr, "Failed to copy file: %s\n", filename);
1.312 - return 1;
1.313 - }
1.314 - }
1.315 -}
1.316 -
1.317 -/* Copy source files from the external environment into the filesystem image. */
1.318 -
1.319 -int copy_in(ext2_filsys fs, int argc, char *argv[])
1.320 -{
1.321 - errcode_t retval;
1.322 - int i;
1.323 -
1.324 - /* Target filename details. */
1.325 -
1.326 - const char *target = argv[argc - 1];
1.327 - const char *target_remaining = target;
1.328 - const char *basename;
1.329 -
1.330 - /* Target file and directory details. */
1.331 -
1.332 - int target_is_file;
1.333 - ext2_ino_t ino_target;
1.334 -
1.335 - /* Locate the target and test whether it is a file or a directory. */
1.336 -
1.337 - if (image_resolve_by_path(fs, &target_remaining, &ino_target))
1.338 - {
1.339 - /* Only a non-existent file in an existing directory is permitted. */
1.340 -
1.341 - if (!image_isdir_by_inode(fs, ino_target) || !path_is_leafname(target_remaining))
1.342 - {
1.343 - fprintf(stderr, "Target not found: %s\n", target);
1.344 - return 1;
1.345 - }
1.346 -
1.347 - /* Any absent target leaves the basename remaining.
1.348 - The resolved target is the parent directory. */
1.349 -
1.350 - target_is_file = 0;
1.351 - basename = target_remaining;
1.352 - }
1.353 - else
1.354 - {
1.355 - /* Any present target can be a file or directory.
1.356 - The resolved target is the actual target. */
1.357 -
1.358 - target_is_file = image_isfile_by_inode(fs, ino_target);
1.359 - basename = NULL;
1.360 - }
1.361 -
1.362 - /* Only permit a target file when one source file is given. */
1.363 -
1.364 - if (target_is_file)
1.365 - {
1.366 - if (argc > 2)
1.367 - {
1.368 - fprintf(stderr, "Target can only be a file when copying a single file: %s\n", target);
1.369 - return 1;
1.370 - }
1.371 - }
1.372 - else if (!image_isdir_by_inode(fs, ino_target))
1.373 - {
1.374 - fprintf(stderr, "Target is not a directory: %s\n", target);
1.375 - return 1;
1.376 - }
1.377 -
1.378 - /* Copy each source object to the target directory. */
1.379 -
1.380 - for (i = 0; i < argc - 1; i++)
1.381 - if (_copy_in(fs, argv[i], ino_target, basename))
1.382 - return 1;
1.383 -
1.384 - return 0;
1.385 -}
1.386 -
1.387 -/* Copy a file from the filesystem into the external environment. */
1.388 -
1.389 -static int _copy_out(ext2_filsys fs, const char *source, const char *target,
1.390 - int target_is_file)
1.391 -{
1.392 - ext2_ino_t ino_source;
1.393 -
1.394 - if (image_find_by_path(fs, source, &ino_source))
1.395 - {
1.396 - fprintf(stderr, "Failed to find file: %s\n", source);
1.397 - return 1;
1.398 - }
1.399 -
1.400 - /* Test whether the filename references a file. */
1.401 -
1.402 - if (image_isdir_by_path(fs, source))
1.403 - {
1.404 - if (_make_directory(target, path_basename(source), fs, ino_source))
1.405 - {
1.406 - fprintf(stderr, "Failed to make directory: %s/%s\n", target,
1.407 - path_basename(source));
1.408 - return 1;
1.409 - }
1.410 - }
1.411 - else if (image_isfile_by_path(fs, source))
1.412 - {
1.413 - if (copy_file_out(target, source, target_is_file, fs, ino_source))
1.414 - {
1.415 - fprintf(stderr, "Failed to read from file: %s\n", source);
1.416 - return 1;
1.417 - }
1.418 - }
1.419 - else
1.420 - {
1.421 - fprintf(stderr, "Object type not supported: %s\n", source);
1.422 - return 1;
1.423 - }
1.424 -
1.425 - /* NOTE: Overwrite/update metadata where appropriate. */
1.426 -
1.427 - return 0;
1.428 -}
1.429 -
1.430 -/* Copy source files out of the filesystem image into the external environment. */
1.431 -
1.432 -int copy_out(ext2_filsys fs, int argc, char *argv[])
1.433 -{
1.434 - int i;
1.435 -
1.436 - /* Target filename details. */
1.437 -
1.438 - char *target = argv[argc - 1];
1.439 - int target_is_file;
1.440 -
1.441 - /* Locate the target and test whether it is a directory. */
1.442 -
1.443 - if (!isdir(target))
1.444 - {
1.445 - /* Only a new or existing file in an existing directory is permitted. */
1.446 -
1.447 - if (isfile(target) || isdir_dirname(target))
1.448 - target_is_file = 1;
1.449 - else
1.450 - {
1.451 - fprintf(stderr, "Target is not a directory: %s\n", target);
1.452 - return 1;
1.453 - }
1.454 -
1.455 - /* Only permit a target file when one source file is given. */
1.456 -
1.457 - if (argc > 2)
1.458 - {
1.459 - fprintf(stderr, "Target can only be a file when copying a single file: %s\n", target);
1.460 - return 1;
1.461 - }
1.462 - }
1.463 - else
1.464 - target_is_file = 0;
1.465 -
1.466 - /* Copy each source file to the target directory. */
1.467 -
1.468 - for (i = 0; i < argc - 1; i++)
1.469 - if (_copy_out(fs, argv[i], target, target_is_file))
1.470 - return 1;
1.471 -
1.472 - return 0;
1.473 -}
1.474 -
1.475 -/* List objects in the filesystem image. */
1.476 -
1.477 -int list(ext2_filsys fs, int argc, char *argv[])
1.478 -{
1.479 - int i;
1.480 - char *path;
1.481 -
1.482 - for (i = 0; i < argc; i++)
1.483 - {
1.484 - path = argv[i];
1.485 -
1.486 - /* Emit each object. */
1.487 -
1.488 - puts(path);
1.489 -
1.490 - /* List individual files or directories. */
1.491 -
1.492 - if (utils_list_dir(fs, path))
1.493 - {
1.494 - fprintf(stderr, "Failed to list object: %s\n", path);
1.495 - return 1;
1.496 - }
1.497 - }
1.498 -
1.499 - return 0;
1.500 -}
1.501 -
1.502 -/* Make directories in the filesystem image. */
1.503 -
1.504 -int make_dirs(ext2_filsys fs, int argc, char *argv[])
1.505 -{
1.506 - int i;
1.507 - const char *path;
1.508 - ext2_ino_t ino;
1.509 -
1.510 - /* Make each directory component in the given pathname. */
1.511 -
1.512 - for (i = 0; i < argc; i++)
1.513 - {
1.514 - path = argv[i];
1.515 -
1.516 - /* Search for the remaining components. */
1.517 -
1.518 - if ((!*path) || !image_resolve_by_path(fs, &path, &ino))
1.519 - {
1.520 - fprintf(stderr, "Path exists: %s\n", argv[i]);
1.521 - return 1;
1.522 - }
1.523 -
1.524 - /* From the first unrecognised component, make the remaining
1.525 - directories. */
1.526 -
1.527 - if (image_make_dirs(fs, &path, ino,
1.528 - 0777 & ~md.mask,
1.529 - md.have_uid ? md.uid : 0,
1.530 - md.have_gid ? md.gid : 0))
1.531 - {
1.532 - fprintf(stderr, "Failed to make directory: %s\n", argv[i]);
1.533 - return 1;
1.534 - }
1.535 - }
1.536 -
1.537 - return 0;
1.538 -}
1.539 -
1.540 -/* Remove objects from the filesystem image. */
1.541 -
1.542 -int _remove(ext2_filsys fs, int argc, char *argv[], int dir_only)
1.543 -{
1.544 - int i;
1.545 - const char *path;
1.546 - ext2_ino_t ino;
1.547 -
1.548 - /* Remove each directory with the given pathname. */
1.549 -
1.550 - for (i = 0; i < argc; i++)
1.551 - {
1.552 - path = argv[i];
1.553 -
1.554 - /* Detect missing objects. */
1.555 -
1.556 - if ((!*path) || image_find_by_path(fs, path, &ino))
1.557 - {
1.558 - fprintf(stderr, "Not found: %s\n", path);
1.559 - return 1;
1.560 - }
1.561 -
1.562 - /* Insist on a directory if specified. */
1.563 -
1.564 - if (dir_only)
1.565 - {
1.566 - if (!image_isdir_by_inode(fs, ino))
1.567 - {
1.568 - fprintf(stderr, "Not a directory: %s\n", path);
1.569 - return 1;
1.570 - }
1.571 -
1.572 - /* Test for an empty directory. */
1.573 -
1.574 - if (image_dir_empty_by_inode(fs, ino))
1.575 - {
1.576 - fprintf(stderr, "Directory not empty: %s\n", path);
1.577 - return 1;
1.578 - }
1.579 - }
1.580 -
1.581 - /* Otherwise, insist on a non-directory. */
1.582 -
1.583 - else if (image_isdir_by_inode(fs, ino))
1.584 - {
1.585 - fprintf(stderr, "Cannot remove a directory: %s\n", path);
1.586 - return 1;
1.587 - }
1.588 -
1.589 - /* Unlink the object. */
1.590 -
1.591 - if (image_unlink_by_path(fs, path))
1.592 - {
1.593 - fprintf(stderr, "Could not unlink object: %s\n", path);
1.594 - return 1;
1.595 - }
1.596 -
1.597 - /* Remove the object. */
1.598 -
1.599 - if (image_remove_by_inode(fs, ino))
1.600 - {
1.601 - fprintf(stderr, "Could not remove object: %s\n", path);
1.602 - return 1;
1.603 - }
1.604 - }
1.605 -
1.606 - return 0;
1.607 -}
1.608 -
1.609 -/* Remove directories from the filesystem image. */
1.610 -
1.611 -int remove_dirs(ext2_filsys fs, int argc, char *argv[])
1.612 -{
1.613 - return _remove(fs, argc, argv, 1);
1.614 -}
1.615 -
1.616 -/* Remove non-directories from the filesystem image. */
1.617 -
1.618 -int remove_non_dirs(ext2_filsys fs, int argc, char *argv[])
1.619 -{
1.620 - return _remove(fs, argc, argv, 0);
1.621 -}
1.622 -
1.623 /* Read operations from a script file. */
1.624
1.625 enum op_results
1.626 @@ -701,61 +109,6 @@
1.627 return 0;
1.628 }
1.629
1.630 -/* Show statistics for files and directories. */
1.631 -
1.632 -int stat_objects(ext2_filsys fs, int argc, char *argv[])
1.633 -{
1.634 - int i;
1.635 - const char *path;
1.636 - ext2_ino_t ino;
1.637 - struct stat st;
1.638 -
1.639 - for (i = 0; i < argc; i++)
1.640 - {
1.641 - path = argv[i];
1.642 -
1.643 - /* Detect missing objects. */
1.644 -
1.645 - if (image_find_by_path(fs, path, &ino))
1.646 - {
1.647 - fprintf(stderr, "Not found: %s\n", path);
1.648 - return 1;
1.649 - }
1.650 -
1.651 - /* Even though the statistics could be read directly out of ext2 data
1.652 - structures, it is convenient to use the standard stat structure. */
1.653 -
1.654 - if (image_stat_inode(fs, ino, &st))
1.655 - {
1.656 - fprintf(stderr, "Cannot stat object: %s\n", path);
1.657 - return 1;
1.658 - }
1.659 -
1.660 - /* Terse stat output:
1.661 - %n %s %b %f %u %g %D %i %h %t %T %X %Y %Z %W %o %C */
1.662 -
1.663 - printf("%s %ld %ld %x %d %d ",
1.664 - path, st.st_size, st.st_blocks, st.st_mode, st.st_uid, st.st_gid);
1.665 -
1.666 - printf("%d %d %d %x %x ",
1.667 - st.st_dev, st.st_ino, st.st_nlink,
1.668 - major(st.st_rdev), minor(st.st_rdev));
1.669 -
1.670 - printf("%d %d %d ",
1.671 - st.st_atim, st.st_mtim, st.st_ctim);
1.672 -
1.673 - /* NOTE: Arbitrary values:
1.674 - %W (creation time) given as 0
1.675 - %o (I/O transfer size hint) given as 0
1.676 - %C (SELinux security context) given as empty string */
1.677 -
1.678 - printf("%d %d %s\n",
1.679 - 0, 0, "");
1.680 - }
1.681 -
1.682 - return 0;
1.683 -}
1.684 -
1.685
1.686
1.687 /* Help message. */