# HG changeset patch # User Paul Boddie # Date 1644796017 -3600 # Node ID 77b98aed9da89f04acf68d7a8c3c3bb98fc61b53 # Parent fedb83ec8daebd89cd417c0bbd587733e7b400fa Reorganised e2access, adding directory removal and single file listing support, also permitting the membership of new directories to be specified. diff -r fedb83ec8dae -r 77b98aed9da8 libe2access/host/e2access.c --- a/libe2access/host/e2access.c Mon Feb 14 00:44:19 2022 +0100 +++ b/libe2access/host/e2access.c Mon Feb 14 00:46:57 2022 +0100 @@ -93,12 +93,24 @@ /* Show directory entries when iterating. */ -static int image_list_dir_proc(struct ext2_dir_entry *dirent, int offset, - int blocksize, char *buf, void *priv_data) +struct _list_dir_data +{ + ext2_filsys fs; + char *filename; +}; + +static int _list_dir_proc(struct ext2_dir_entry *dirent, int offset, + int blocksize, char *buf, void *priv_data) { - ext2_filsys fs = (ext2_filsys) priv_data; + struct _list_dir_data *data = (struct _list_dir_data *) priv_data; + ext2_filsys fs = data->fs; struct ext2_inode inode; + /* Select any indicated filename. */ + + if ((data->filename != NULL) && (strcmp(dirent->name, data->filename))) + return 0; + /* Obtain the inode details for metadata. */ if (ext2fs_read_inode(fs, dirent->inode, &inode)) @@ -448,22 +460,32 @@ return 0; } -/* List directories in the filesystem image. */ +/* List objects in the filesystem image. */ -int list_dirs(ext2_filsys fs, int argc, char *argv[]) +int list(ext2_filsys fs, int argc, char *argv[]) { int i; - const char *path; + char *path; + struct _list_dir_data data; for (i = 0; i < argc; i++) { path = argv[i]; - /* List the directory contents. */ + /* Emit each object. */ puts(path); - if (image_list_dir(fs, path, image_list_dir_proc, fs)) + /* List individual files or directories. */ + + if (image_isfile(fs, path)) + data.filename = path_split(path); + else + data.filename = NULL; + + data.fs = fs; + + if (image_list_dir(fs, path, _list_dir_proc, &data)) return 1; } @@ -475,7 +497,6 @@ int make_dirs(ext2_filsys fs, int argc, char *argv[]) { int i; - char *path_end; const char *path; ext2_ino_t ino; @@ -495,14 +516,59 @@ /* From the first unrecognised component, make the remaining directories. */ - if (image_make_dirs(fs, &path, ino, 0777 & ~md.mask, 0, 0)) + if (image_make_dirs(fs, &path, ino, + 0777 & ~md.mask, + md.have_uid ? md.uid : 0, + md.have_gid ? md.gid : 0)) return 1; } return 0; } -/* Help message and main program. */ +/* Remove directories from the filesystem image. */ + +int remove_dirs(ext2_filsys fs, int argc, char *argv[]) +{ + int i; + const char *path; + ext2_ino_t ino; + + /* Remove each directory with the given pathname. */ + + for (i = 0; i < argc; i++) + { + path = argv[i]; + if (!*path) + continue; + + /* Ignore missing objects. */ + + if (!image_exists(fs, path)) + continue; + + /* Insist on a directory. */ + + if (!image_isdir(fs, path)) + return 1; + + /* Remove the directory. */ + + if (image_remove_by_path(fs, path)) + return 1; + + /* Unlink the directory. */ + + if (image_unlink_by_path(fs, path)) + return 1; + } + + return 0; +} + + + +/* Help message. */ char help_text[] = "\ Usage: %s [ ] ...\n\ @@ -515,8 +581,35 @@ File permission options:\n\ \n\ -m MASK Set mode/permissions mask for new directories\n\ +\n\ +Operations:\n\ +\n\ + copy-in Copy files into a directory within the image\n\ + copy-out Copy files from the image into a directory\n\ + ls List files and directories within the image\n\ + mkdir Make directories within the image\n\ + rmdir Remove directories from the image\n\ "; +/* Operations exposed by the program. */ + +struct operation +{ + const char *name; + int (*fn)(ext2_filsys, int, char *[]); +}; + +static struct operation operations[] = { + {"copy-in", copy_in}, + {"copy-out", copy_out}, + {"ls", list}, + {"mkdir", make_dirs}, + {"rmdir", remove_dirs}, + {NULL, NULL}, + }; + +/* Main program. */ + int main(int argc, char *argv[]) { int flags = EXT2_FLAG_RW; // | EXT2_FLAG_SOFTSUPP_FEATURES | EXT2_FLAG_64BITS; @@ -529,6 +622,7 @@ char **args; char *fsname, *operation, *filename; int num_args; + struct operation *op; /* Parse program options and initialise the argument details. */ @@ -570,23 +664,16 @@ args = &args[2]; num_args -= 2; - if (!strcmp(operation, "copy-out")) + for (op = &operations[0]; op->name != NULL; op++) { - exitcode = copy_out(fs, num_args, args); - } - else if (!strcmp(operation, "copy-in")) - { - exitcode = copy_in(fs, num_args, args); + if (!strcmp(operation, op->name)) + { + exitcode = op->fn(fs, num_args, args); + break; + } } - else if (!strcmp(operation, "list-dirs")) - { - exitcode = list_dirs(fs, num_args, args); - } - else if (!strcmp(operation, "make-dirs")) - { - exitcode = make_dirs(fs, num_args, args); - } - else + + if (op->name == NULL) { printf("Operation %s is not recognised.\n", operation); exitcode = 1; diff -r fedb83ec8dae -r 77b98aed9da8 test_files/mk_e2test.sh --- a/test_files/mk_e2test.sh Mon Feb 14 00:44:19 2022 +0100 +++ b/test_files/mk_e2test.sh Mon Feb 14 00:46:57 2022 +0100 @@ -1,7 +1,28 @@ #!/bin/sh +# Make a test filesystem. +# +# Copyright (C) 2021, 2022 Paul Boddie +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 2 of +# the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, +# Boston, MA 02110-1301, USA + PROGNAME=$(basename "$0") +# Handle program options. + if [ "$1" = '-q' ] ; then QUIET=$1 shift 1 @@ -31,9 +52,11 @@ OPTIONS='-u 1000 -g 1000' +# Define a convenience function for e2access invocation. + e2access() { - "$E2ACCESS" $OPTIONS $* + "$E2ACCESS" $OPTIONS "$TARGET" $* } # Make a filesystem for the example. @@ -102,8 +125,8 @@ # Add the directories and files to the image. for DIR in home/paulb/private home/paulb/public home/paulb/shared home/paulb/many home/paulb ; do - e2access "$TARGET" make-dirs "$DIR" - e2access "$TARGET" copy-in $(find "$DIR" -maxdepth 1 -type f | sort) "$DIR" + e2access mkdir "$DIR" + e2access copy-in $(find "$DIR" -maxdepth 1 -type f | sort) "$DIR" done # Leave the root of the filesystem. @@ -111,13 +134,13 @@ cd .. if [ ! "$QUIET" ] ; then - e2access "$TARGET" list-dirs '' - e2access "$TARGET" list-dirs 'home' - e2access "$TARGET" list-dirs 'home/paulb' - e2access "$TARGET" list-dirs 'home/paulb/many' - e2access "$TARGET" list-dirs 'home/paulb/private' - e2access "$TARGET" list-dirs 'home/paulb/public' - e2access "$TARGET" list-dirs 'home/paulb/shared' + e2access ls '' + e2access ls 'home' + e2access ls 'home/paulb' + e2access ls 'home/paulb/many' + e2access ls 'home/paulb/private' + e2access ls 'home/paulb/public' + e2access ls 'home/paulb/shared' fi rm -r tmp_e2test