1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/libe2access/host/Makefile Tue Dec 28 01:37:59 2021 +0100
1.3 @@ -0,0 +1,88 @@
1.4 +# Makefile - Build the filesystem access programs
1.5 +#
1.6 +# Copyright (C) 2019, 2021 Paul Boddie <paul@boddie.org.uk>
1.7 +#
1.8 +# This program is free software: you can redistribute it and/or modify
1.9 +# it under the terms of the GNU General Public License as published by
1.10 +# the Free Software Foundation, either version 3 of the License, or
1.11 +# (at your option) any later version.
1.12 +#
1.13 +# This program is distributed in the hope that it will be useful,
1.14 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
1.15 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.16 +# GNU General Public License for more details.
1.17 +#
1.18 +# You should have received a copy of the GNU General Public License
1.19 +# along with this program. If not, see <http://www.gnu.org/licenses/>.
1.20 +
1.21 +# Paths to library sources.
1.22 +
1.23 +INC = ../include/e2access
1.24 +SRC = ../lib/src
1.25 +
1.26 +# Tool definitions.
1.27 +
1.28 +RANLIB = ranlib
1.29 +
1.30 +# Compilation and linking flags.
1.31 +
1.32 +CFLAGS = -I$(INC) # -g
1.33 +LDFLAGS = -lext2fs -L. -le2access # -lcom_err
1.34 +
1.35 +# Output programs and libraries.
1.36 +
1.37 +E2ACCESS = e2access
1.38 +LIBE2ACCESS = libe2access.a
1.39 +LIBE2ACCESS_SHARED = libe2access.so
1.40 +
1.41 +TEST_LISTING = test_listing
1.42 +TEST_REMOVE = test_remove
1.43 +
1.44 +TARGETS = $(E2ACCESS) $(LIBE2ACCESS) $(LIBE2ACCESS_SHARED) $(TEST_LISTING) $(TEST_REMOVE)
1.45 +
1.46 +# Sources and objects.
1.47 +
1.48 +E2ACCESS_SRC = e2access.c file.c
1.49 +E2ACCESS_OBJ = $(E2ACCESS_SRC:.c=.o)
1.50 +
1.51 +TEST_LISTING_SRC = test_listing.c
1.52 +TEST_LISTING_OBJ = $(TEST_LISTING_SRC:.c=.o)
1.53 +
1.54 +TEST_REMOVE_SRC = test_remove.c
1.55 +TEST_REMOVE_OBJ = $(TEST_REMOVE_SRC:.c=.o)
1.56 +
1.57 +LIBE2ACCESS_SRC = $(foreach FILE,format.c image.c path.c,$(SRC)/$(FILE))
1.58 +LIBE2ACCESS_OBJ = $(LIBE2ACCESS_SRC:.c=.o)
1.59 +
1.60 +ALL_OBJ = $(E2ACCESS_OBJ) $(LIBE2ACCESS_OBJ) $(TEST_LISTING_OBJ) $(TEST_REMOVE_OBJ)
1.61 +
1.62 +# Rules.
1.63 +
1.64 +.PHONY: all clean distclean
1.65 +
1.66 +all: $(TARGETS)
1.67 +
1.68 +clean:
1.69 + rm -f $(ALL_OBJ) $(TARGETS)
1.70 +
1.71 +distclean: clean
1.72 + echo "Nothing else to clean."
1.73 +
1.74 +$(E2ACCESS): $(E2ACCESS_OBJ) $(LIBE2ACCESS_SHARED)
1.75 + $(CC) $(LDFLAGS) $(E2ACCESS_OBJ) -o $@
1.76 +
1.77 +$(LIBE2ACCESS): $(LIBE2ACCESS_OBJ)
1.78 + $(AR) rc $@ $(LIBE2ACCESS_OBJ)
1.79 + $(RANLIB) $@
1.80 +
1.81 +$(LIBE2ACCESS_SHARED): $(LIBE2ACCESS) $(LIBE2ACCESS_OBJ)
1.82 + $(LD) -shared $(LIBE2ACCESS_OBJ) -o $(LIBE2ACCESS_SHARED)
1.83 +
1.84 +$(TEST_LISTING): $(TEST_LISTING_OBJ) $(LIBE2ACCESS_SHARED)
1.85 + $(CC) $(LDFLAGS) $(TEST_LISTING_OBJ) -o $@
1.86 +
1.87 +$(TEST_REMOVE): $(TEST_REMOVE_OBJ) $(LIBE2ACCESS_SHARED)
1.88 + $(CC) $(LDFLAGS) $(TEST_REMOVE_OBJ) -o $@
1.89 +
1.90 +.c.o:
1.91 + $(CC) -c $(CFLAGS) $< -o $@
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
2.2 +++ b/libe2access/host/e2access.c Tue Dec 28 01:37:59 2021 +0100
2.3 @@ -0,0 +1,527 @@
2.4 +/*
2.5 + * Access a filesystem.
2.6 + *
2.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
2.8 + *
2.9 + * This program is free software; you can redistribute it and/or
2.10 + * modify it under the terms of the GNU General Public License as
2.11 + * published by the Free Software Foundation; either version 2 of
2.12 + * the License, or (at your option) any later version.
2.13 + *
2.14 + * This program is distributed in the hope that it will be useful,
2.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2.17 + * GNU General Public License for more details.
2.18 + *
2.19 + * You should have received a copy of the GNU General Public License
2.20 + * along with this program; if not, write to the Free Software
2.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
2.22 + * Boston, MA 02110-1301, USA
2.23 + */
2.24 +
2.25 +#include <stdio.h>
2.26 +#include <stdlib.h>
2.27 +#include <string.h>
2.28 +
2.29 +#include <sys/types.h>
2.30 +#include <sys/stat.h>
2.31 +
2.32 +#include <ext2fs/ext2fs.h>
2.33 +
2.34 +#include "file.h"
2.35 +#include "format.h"
2.36 +#include "image.h"
2.37 +#include "path.h"
2.38 +
2.39 +
2.40 +
2.41 +/* Copy buffer size. */
2.42 +
2.43 +const int BUFSIZE = 4096;
2.44 +
2.45 +
2.46 +
2.47 +/* Show directory entries when iterating. */
2.48 +
2.49 +static int image_list_dir_proc(struct ext2_dir_entry *dirent, int offset,
2.50 + int blocksize, char *buf, void *priv_data)
2.51 +{
2.52 + ext2_filsys fs = (ext2_filsys) priv_data;
2.53 + struct ext2_inode inode;
2.54 +
2.55 + /* Obtain the inode details for metadata. */
2.56 +
2.57 + if (ext2fs_read_inode(fs, dirent->inode, &inode))
2.58 + return DIRENT_ABORT;
2.59 +
2.60 + /* Output details in the style of "ls -l" showing directory, permissions,
2.61 + owner, group and size information. */
2.62 +
2.63 + printf("%s%s %5d %5d %6d ",
2.64 + _image_isdir(fs, dirent->inode) ? "d" : "-",
2.65 + get_permission_string(inode.i_mode),
2.66 + inode.i_uid,
2.67 + inode.i_gid,
2.68 + EXT2_I_SIZE(&inode));
2.69 +
2.70 + /* Output the name which is presumably not necessarily null-terminated. */
2.71 +
2.72 + fwrite(dirent->name, sizeof(char), ext2fs_dirent_name_len(dirent), stdout);
2.73 + fputc((int) '\n', stdout);
2.74 + return 0;
2.75 +}
2.76 +
2.77 +
2.78 +
2.79 +/* Copy a file into the filesystem image. */
2.80 +
2.81 +int copy_file_in(const char *filename, ext2_filsys fs, ext2_ino_t ino_file, int flags)
2.82 +{
2.83 + int retval = 0;
2.84 + ext2_file_t file;
2.85 +
2.86 + /* Copying details. */
2.87 +
2.88 + FILE *fp;
2.89 + char buf[BUFSIZE];
2.90 + size_t got;
2.91 + unsigned int written;
2.92 +
2.93 + /* Open a file in the target directory. */
2.94 +
2.95 + if (ext2fs_file_open(fs, ino_file, flags, &file))
2.96 + return 1;
2.97 +
2.98 + /* Open the file in the source directory. */
2.99 +
2.100 + fp = fopen(filename, "r");
2.101 +
2.102 + /* Copy the file content. */
2.103 +
2.104 + if (fp != NULL)
2.105 + {
2.106 + while (got = fread(buf, sizeof(char), BUFSIZE, fp))
2.107 + {
2.108 + while (got)
2.109 + {
2.110 + if (ext2fs_file_write(file, buf, got, &written))
2.111 + {
2.112 + retval = 1;
2.113 + goto close_files;
2.114 + }
2.115 + got -= written;
2.116 + }
2.117 + }
2.118 + }
2.119 +
2.120 +close_files:
2.121 + fclose(fp);
2.122 + ext2fs_file_flush(file);
2.123 + ext2fs_file_close(file);
2.124 +
2.125 + return retval;
2.126 +}
2.127 +
2.128 +/* Copy a file out of the filesystem image. */
2.129 +
2.130 +int copy_file_out(const char *target, const char *filename, int target_is_file,
2.131 + ext2_filsys fs, ext2_ino_t ino_file)
2.132 +{
2.133 + int retval = 0;
2.134 + ext2_file_t file;
2.135 +
2.136 + /* Copying details. */
2.137 +
2.138 + FILE *fp;
2.139 + char buf[BUFSIZE];
2.140 + unsigned int got;
2.141 + size_t written;
2.142 +
2.143 + /* Open the file in the source directory. */
2.144 +
2.145 + if (ext2fs_file_open(fs, ino_file, 0, &file))
2.146 + return 1;
2.147 +
2.148 + /* Open a file in the target directory. */
2.149 +
2.150 + if (target_is_file)
2.151 + fp = fopen(target, "w");
2.152 + else
2.153 + fp = open_file_in_dir(target, path_basename(filename), "w");
2.154 +
2.155 + /* Copy the file content. */
2.156 +
2.157 + if (fp != NULL)
2.158 + {
2.159 + do
2.160 + {
2.161 + if (ext2fs_file_read(file, buf, BUFSIZE, &got))
2.162 + {
2.163 + retval = 1;
2.164 + goto close_files;
2.165 + }
2.166 +
2.167 + while (got)
2.168 + {
2.169 + written = fwrite(buf, sizeof(char), got, fp);
2.170 + got -= written;
2.171 + }
2.172 +
2.173 + } while (got);
2.174 + }
2.175 +
2.176 +close_files:
2.177 + fclose(fp);
2.178 + ext2fs_file_close(file);
2.179 +
2.180 + return retval;
2.181 +}
2.182 +
2.183 +
2.184 +
2.185 +/* Copy source files from the external environment into the filesystem image. */
2.186 +
2.187 +int copy_in(ext2_filsys fs, int argc, char *argv[])
2.188 +{
2.189 + errcode_t retval;
2.190 +
2.191 + /* Target filename details. */
2.192 +
2.193 + const char *target = argv[argc - 1];
2.194 + const char *target_remaining = argv[argc - 1];
2.195 + const char *basename;
2.196 + int target_is_file;
2.197 +
2.198 + /* Target file and directory details. */
2.199 +
2.200 + int target_is_new;
2.201 + ext2_ino_t ino_file, ino_target;
2.202 + int flags;
2.203 +
2.204 + /* Source file details. */
2.205 +
2.206 + struct stat st;
2.207 + int i;
2.208 +
2.209 + /* Locate the target and test whether it is a file or a directory. */
2.210 +
2.211 + if (image_find_path(fs, &target_remaining, &ino_target))
2.212 + {
2.213 + /* Only a non-existent file in an existing directory is permitted. */
2.214 +
2.215 + if (!_image_isdir(fs, ino_target) || !path_is_leafname(target_remaining))
2.216 + {
2.217 + printf("Target %s not found.\n", target);
2.218 + return 1;
2.219 + }
2.220 +
2.221 + target_is_file = 1;
2.222 + target_is_new = 1;
2.223 + }
2.224 + else
2.225 + {
2.226 + target_is_file = _image_isfile(fs, ino_target);
2.227 + target_is_new = 0;
2.228 + }
2.229 +
2.230 + /* Only permit a target file when one source file is given. */
2.231 +
2.232 + if (target_is_file)
2.233 + {
2.234 + if (argc > 2)
2.235 + {
2.236 + printf("Target %s can only be a file when copying a single file.\n", target);
2.237 + return 1;
2.238 + }
2.239 + }
2.240 + else if (!_image_isdir(fs, ino_target))
2.241 + {
2.242 + printf("Target %s is not a directory.\n", target);
2.243 + return 1;
2.244 + }
2.245 +
2.246 + /* Copy each source object to the target directory. */
2.247 +
2.248 + for (i = 0; i < argc - 1; i++)
2.249 + {
2.250 + if (target_is_file)
2.251 + basename = target_remaining;
2.252 + else
2.253 + {
2.254 + basename = path_basename(argv[i]);
2.255 + target_is_new = image_find_file(fs, target, basename, &ino_file);
2.256 + }
2.257 +
2.258 + /* Directories are created with the same metadata. */
2.259 +
2.260 + if (isdir(argv[i]))
2.261 + {
2.262 + if (!target_is_new)
2.263 + {
2.264 + printf("Target %s cannot be created since it already exists.\n", target);
2.265 + return 1;
2.266 + }
2.267 +
2.268 + /* Obtain the metadata. */
2.269 +
2.270 + if (lstat(argv[i], &st))
2.271 + return 1;
2.272 +
2.273 + retval = image_make_dir(fs, ino_target, basename, st.st_mode,
2.274 + st.st_uid, st.st_gid, &ino_file);
2.275 +
2.276 + if (retval)
2.277 + {
2.278 + printf("Failed to create directory %s (%d).\n", argv[i], retval);
2.279 + return 1;
2.280 + }
2.281 + }
2.282 +
2.283 + /* Files are copied. */
2.284 +
2.285 + else if (isfile(argv[i]))
2.286 + {
2.287 + flags = EXT2_FILE_WRITE;
2.288 +
2.289 + /* Obtain the inode for the target file. */
2.290 +
2.291 + if (target_is_new)
2.292 + {
2.293 + /* Populate the inode details. */
2.294 +
2.295 + if (lstat(argv[i], &st))
2.296 + return 1;
2.297 +
2.298 + retval = image_create_file(fs, ino_target, basename, st.st_mode,
2.299 + st.st_uid, st.st_gid, &ino_file);
2.300 + if (retval)
2.301 + {
2.302 + printf("Failed to create file %s (%d).\n", argv[i], retval);
2.303 + return 1;
2.304 + }
2.305 +
2.306 + flags |= EXT2_FILE_CREATE;
2.307 + }
2.308 +
2.309 + /* NOTE: Overwrite/update metadata where appropriate. */
2.310 +
2.311 + if (copy_file_in(argv[i], fs, ino_file, flags))
2.312 + {
2.313 + printf("Failed to write to %s.\n", argv[i]);
2.314 + return 1;
2.315 + }
2.316 + }
2.317 + }
2.318 +
2.319 + return 0;
2.320 +}
2.321 +
2.322 +/* Copy source files out of the filesystem image into the external environment. */
2.323 +
2.324 +int copy_out(ext2_filsys fs, int argc, char *argv[])
2.325 +{
2.326 + /* Target filename details. */
2.327 +
2.328 + char *target = argv[argc - 1];
2.329 + int target_is_file;
2.330 +
2.331 + /* Target file and directory details. */
2.332 +
2.333 + ext2_file_t file;
2.334 + ext2_ino_t ino_file;
2.335 +
2.336 + /* Source file details. */
2.337 +
2.338 + const char *path;
2.339 + int i;
2.340 +
2.341 + /* Locate the target and test whether it is a directory. */
2.342 +
2.343 + if (!isdir(target))
2.344 + {
2.345 + /* Only a new or existing file in an existing directory is permitted. */
2.346 +
2.347 + if (isfile(target) || isdir_dirname(target))
2.348 + target_is_file = 1;
2.349 + else
2.350 + {
2.351 + printf("Target %s is not a directory.\n", target);
2.352 + return 1;
2.353 + }
2.354 +
2.355 + /* Only permit a target file when one source file is given. */
2.356 +
2.357 + if (argc > 2)
2.358 + {
2.359 + printf("Target %s can only be a file when copying a single file.\n", target);
2.360 + return 1;
2.361 + }
2.362 + }
2.363 + else
2.364 + target_is_file = 0;
2.365 +
2.366 + /* For each source filename, test whether it references a file. */
2.367 +
2.368 + for (i = 0; i < argc - 1; i++)
2.369 + {
2.370 + if (!image_isfile(fs, argv[i]))
2.371 + {
2.372 + printf("Source %s is not a file.\n", argv[i]);
2.373 + return 1;
2.374 + }
2.375 + }
2.376 +
2.377 + /* Copy each source file to the target directory. */
2.378 +
2.379 + for (i = 0; i < argc - 1; i++)
2.380 + {
2.381 + path = argv[i];
2.382 +
2.383 + if (image_find_path(fs, &path, &ino_file))
2.384 + return 1;
2.385 +
2.386 + if (copy_file_out(target, argv[i], target_is_file, fs, ino_file))
2.387 + {
2.388 + printf("Failed to read from %s.\n", argv[i]);
2.389 + return 1;
2.390 + }
2.391 +
2.392 + /* NOTE: Overwrite/update metadata where appropriate. */
2.393 + }
2.394 +
2.395 + return 0;
2.396 +}
2.397 +
2.398 +/* List directories in the filesystem image. */
2.399 +
2.400 +int list_dirs(ext2_filsys fs, int argc, char *argv[])
2.401 +{
2.402 + int i;
2.403 + const char *path;
2.404 +
2.405 + for (i = 0; i < argc; i++)
2.406 + {
2.407 + path = argv[i];
2.408 +
2.409 + /* List the directory contents. */
2.410 +
2.411 + puts(path);
2.412 +
2.413 + if (image_list_dir(fs, path, image_list_dir_proc, fs))
2.414 + return 1;
2.415 + }
2.416 +
2.417 + return 0;
2.418 +}
2.419 +
2.420 +/* Make directories in the filesystem image. */
2.421 +
2.422 +int make_dirs(ext2_filsys fs, int argc, char *argv[])
2.423 +{
2.424 + int i;
2.425 + char *path_end;
2.426 + const char *path;
2.427 + ext2_ino_t ino;
2.428 +
2.429 + /* Make each directory component in the given pathname. */
2.430 +
2.431 + for (i = 0; i < argc; i++)
2.432 + {
2.433 + path = argv[i];
2.434 + if (!*path)
2.435 + continue;
2.436 +
2.437 + /* Search for the remaining components. */
2.438 +
2.439 + if (!image_find_path(fs, &path, &ino))
2.440 + continue;
2.441 +
2.442 + /* From the first unrecognised component, make the remaining
2.443 + directories. */
2.444 +
2.445 + if (image_make_dirs(fs, &path, ino, 0777, 0, 0))
2.446 + return 1;
2.447 + }
2.448 +
2.449 + return 0;
2.450 +}
2.451 +
2.452 +int main(int argc, char *argv[])
2.453 +{
2.454 + int flags = EXT2_FLAG_RW; // | EXT2_FLAG_SOFTSUPP_FEATURES | EXT2_FLAG_64BITS;
2.455 + char *fsname, *operation, *filename;
2.456 + ext2_filsys fs = NULL;
2.457 + errcode_t retval;
2.458 + int exitcode = 0;
2.459 +
2.460 + if (argc < 4)
2.461 + {
2.462 + printf("Usage: %s <device or image file> <operation> <filename>...\n", argv[0]);
2.463 + return 1;
2.464 + }
2.465 +
2.466 + fsname = argv[1];
2.467 +
2.468 + /* Open the filesystem image using the POSIX file access mechanism. */
2.469 +
2.470 + retval = ext2fs_open(fsname, flags, 0, 0, unix_io_manager, &fs);
2.471 + if (retval)
2.472 + {
2.473 + printf("Could not open filesystem using %s\n", fsname);
2.474 + return 1;
2.475 + }
2.476 +
2.477 + //fs->default_bitmap_type = EXT2FS_BMAP64_RBTREE;
2.478 +
2.479 + retval = ext2fs_read_bitmaps(fs);
2.480 + if (retval)
2.481 + {
2.482 + printf("Could not read bitmaps from %s\n", fsname);
2.483 + return 1;
2.484 + }
2.485 +
2.486 + /* Perform the requested operation. */
2.487 +
2.488 + operation = argv[2];
2.489 +
2.490 + if (!strcmp(operation, "--copy-out"))
2.491 + {
2.492 + exitcode = copy_out(fs, argc - 3, &argv[3]);
2.493 + }
2.494 + else if (!strcmp(operation, "--copy-in"))
2.495 + {
2.496 + exitcode = copy_in(fs, argc - 3, &argv[3]);
2.497 + }
2.498 + else if (!strcmp(operation, "--list-dirs"))
2.499 + {
2.500 + exitcode = list_dirs(fs, argc - 3, &argv[3]);
2.501 + }
2.502 + else if (!strcmp(operation, "--make-dirs"))
2.503 + {
2.504 + exitcode = make_dirs(fs, argc - 3, &argv[3]);
2.505 + }
2.506 + else
2.507 + {
2.508 + printf("Operation %s is not recognised.\n", operation);
2.509 + exitcode = 1;
2.510 + }
2.511 +
2.512 + /* Close the filesystem image. */
2.513 +
2.514 + retval = ext2fs_flush(fs);
2.515 + if (retval)
2.516 + {
2.517 + printf("Error flushing filesystem in %s\n", fsname);
2.518 + exitcode = 1;
2.519 + }
2.520 +
2.521 + retval = ext2fs_close(fs);
2.522 + if (retval)
2.523 + {
2.524 + printf("Error closing filesystem in %s\n", fsname);
2.525 + exitcode = 1;
2.526 + }
2.527 +
2.528 + ext2fs_free(fs);
2.529 + return exitcode;
2.530 +}
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
3.2 +++ b/libe2access/host/file.c Tue Dec 28 01:37:59 2021 +0100
3.3 @@ -0,0 +1,77 @@
3.4 +/*
3.5 + * File access functions.
3.6 + *
3.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
3.8 + *
3.9 + * This program is free software; you can redistribute it and/or
3.10 + * modify it under the terms of the GNU General Public License as
3.11 + * published by the Free Software Foundation; either version 2 of
3.12 + * the License, or (at your option) any later version.
3.13 + *
3.14 + * This program is distributed in the hope that it will be useful,
3.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3.17 + * GNU General Public License for more details.
3.18 + *
3.19 + * You should have received a copy of the GNU General Public License
3.20 + * along with this program; if not, write to the Free Software
3.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
3.22 + * Boston, MA 02110-1301, USA
3.23 + */
3.24 +
3.25 +#include <stdio.h>
3.26 +#include <string.h>
3.27 +#include <sys/types.h>
3.28 +#include <sys/stat.h>
3.29 +
3.30 +
3.31 +
3.32 +/* Test object types in the external environment. */
3.33 +
3.34 +int isdir(const char *name)
3.35 +{
3.36 + struct stat st;
3.37 +
3.38 + if (!lstat(name, &st))
3.39 + return S_ISDIR(st.st_mode);
3.40 + else
3.41 + return 0;
3.42 +}
3.43 +
3.44 +int isdir_dirname(const char *name)
3.45 +{
3.46 + char dirname[strlen(name) + 1];
3.47 + char *s;
3.48 +
3.49 + strcpy(dirname, name);
3.50 + s = strrchr(dirname, (int) '/');
3.51 +
3.52 + if (s != NULL)
3.53 + *s = '\0';
3.54 +
3.55 + return isdir(dirname);
3.56 +}
3.57 +
3.58 +int isfile(const char *name)
3.59 +{
3.60 + struct stat st;
3.61 +
3.62 + if (!lstat(name, &st))
3.63 + return S_ISREG(st.st_mode);
3.64 + else
3.65 + return 0;
3.66 +}
3.67 +
3.68 +/* Open a file in the external environment. */
3.69 +
3.70 +FILE *open_file_in_dir(const char *dirname, const char *basename,
3.71 + const char *mode)
3.72 +{
3.73 + char pathname[strlen(dirname) + strlen(basename) + 1];
3.74 +
3.75 + strcpy(pathname, dirname);
3.76 + strcat(pathname, "/");
3.77 + strcat(pathname, basename);
3.78 +
3.79 + return fopen(pathname, mode);
3.80 +}
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
4.2 +++ b/libe2access/host/file.h Tue Dec 28 01:37:59 2021 +0100
4.3 @@ -0,0 +1,34 @@
4.4 +/*
4.5 + * File access functions.
4.6 + *
4.7 + * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
4.8 + *
4.9 + * This program is free software; you can redistribute it and/or
4.10 + * modify it under the terms of the GNU General Public License as
4.11 + * published by the Free Software Foundation; either version 2 of
4.12 + * the License, or (at your option) any later version.
4.13 + *
4.14 + * This program is distributed in the hope that it will be useful,
4.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
4.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4.17 + * GNU General Public License for more details.
4.18 + *
4.19 + * You should have received a copy of the GNU General Public License
4.20 + * along with this program; if not, write to the Free Software
4.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
4.22 + * Boston, MA 02110-1301, USA
4.23 + */
4.24 +
4.25 +#ifndef __FILE_H__
4.26 +#define __FILE_H__
4.27 +
4.28 +#include <stdio.h>
4.29 +
4.30 +int isdir(const char *name);
4.31 +int isdir_dirname(const char *name);
4.32 +int isfile(const char *name);
4.33 +
4.34 +FILE *open_file_in_dir(const char *dirname, const char *basename,
4.35 + const char *mode);
4.36 +
4.37 +#endif /* __FILE_H__ */
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
5.2 +++ b/libe2access/host/mkfs Tue Dec 28 01:37:59 2021 +0100
5.3 @@ -0,0 +1,47 @@
5.4 +#!/bin/sh
5.5 +
5.6 +# Make a filesystem image.
5.7 +#
5.8 +# Copyright (C) 2019, 2021 Paul Boddie <paul@boddie.org.uk>
5.9 +#
5.10 +# This program is free software; you can redistribute it and/or
5.11 +# modify it under the terms of the GNU General Public License as
5.12 +# published by the Free Software Foundation; either version 2 of
5.13 +# the License, or (at your option) any later version.
5.14 +#
5.15 +# This program is distributed in the hope that it will be useful,
5.16 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
5.17 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
5.18 +# GNU General Public License for more details.
5.19 +#
5.20 +# You should have received a copy of the GNU General Public License
5.21 +# along with this program; if not, write to the Free Software
5.22 +# Foundation, Inc., 51 Franklin Street, Fifth Floor,
5.23 +# Boston, MA 02110-1301, USA
5.24 +
5.25 +TARGET=$1
5.26 +
5.27 +if [ -e "$TARGET" ] ; then
5.28 + echo "File already exists: $TARGET" 1>&2
5.29 + exit 1
5.30 +fi
5.31 +
5.32 +if [ ! "$TARGET" ] ; then
5.33 + echo "Creating temporary file." 1>&2
5.34 + TARGET=`mktemp`
5.35 +fi
5.36 +
5.37 +SIZE=${2:-2000}
5.38 +
5.39 +# Make a filesystem.
5.40 +
5.41 + dd if=/dev/zero of="$TARGET" bs=1024 count=1 seek="$SIZE" \
5.42 +> /dev/null 2>&1
5.43 +
5.44 +if ! `/sbin/mkfs.ext2 -q "$TARGET"` ; then
5.45 + exit 1
5.46 +fi
5.47 +
5.48 +echo "$TARGET"
5.49 +
5.50 +# vim: tabstop=4 expandtab shiftwidth=4
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/libe2access/host/run_test Tue Dec 28 01:37:59 2021 +0100
6.3 @@ -0,0 +1,64 @@
6.4 +#!/bin/sh
6.5 +
6.6 +# Run a test program with its own image.
6.7 +#
6.8 +# Copyright (C) 2021 Paul Boddie <paul@boddie.org.uk>
6.9 +#
6.10 +# This program is free software; you can redistribute it and/or
6.11 +# modify it under the terms of the GNU General Public License as
6.12 +# published by the Free Software Foundation; either version 2 of
6.13 +# the License, or (at your option) any later version.
6.14 +#
6.15 +# This program is distributed in the hope that it will be useful,
6.16 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
6.17 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6.18 +# GNU General Public License for more details.
6.19 +#
6.20 +# You should have received a copy of the GNU General Public License
6.21 +# along with this program; if not, write to the Free Software
6.22 +# Foundation, Inc., 51 Franklin Street, Fifth Floor,
6.23 +# Boston, MA 02110-1301, USA
6.24 +
6.25 +THISDIR=`dirname "$0"`
6.26 +PROGNAME=`basename "$0"`
6.27 +
6.28 +# Obtain any option.
6.29 +
6.30 +if [ "$1" = '-k' ] ; then
6.31 + KEEP_IMAGE="$1"
6.32 + shift 1
6.33 +else
6.34 + KEEP_IMAGE=
6.35 +fi
6.36 +
6.37 +# Obtain the test name.
6.38 +
6.39 +TEST="$1"
6.40 +TESTPROG="$THISDIR/$TEST"
6.41 +
6.42 +if [ ! "$TEST" ] || [ ! -e "$TESTPROG" ] ; then
6.43 + echo "Usage: $PROGNAME [ -k ] <test>" 1>&2
6.44 + exit 1
6.45 +fi
6.46 +
6.47 +# Indicate the library location.
6.48 +
6.49 +export LD_LIBRARY_PATH="$THISDIR":"$LD_LIBRARY_PATH"
6.50 +
6.51 +# Make an image to use for testing.
6.52 +
6.53 +IMAGE=`"$THISDIR/mkfs"`
6.54 +
6.55 +# Run the test program.
6.56 +
6.57 +"$TESTPROG" "$IMAGE"
6.58 +
6.59 +# Show the image filename or remove the image.
6.60 +
6.61 +if [ "$KEEP_IMAGE" ] ; then
6.62 + echo "$IMAGE"
6.63 +else
6.64 + rm "$IMAGE"
6.65 +fi
6.66 +
6.67 +# vim: tabstop=4 expandtab shiftwidth=4
7.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
7.2 +++ b/libe2access/host/test_listing.c Tue Dec 28 01:37:59 2021 +0100
7.3 @@ -0,0 +1,169 @@
7.4 +/*
7.5 + * Test filesystem listing concurrency limitations.
7.6 + *
7.7 + * Copyright (C) 2019, 2021 Paul Boddie <paul@boddie.org.uk>
7.8 + *
7.9 + * This program is free software; you can redistribute it and/or
7.10 + * modify it under the terms of the GNU General Public License as
7.11 + * published by the Free Software Foundation; either version 2 of
7.12 + * the License, or (at your option) any later version.
7.13 + *
7.14 + * This program is distributed in the hope that it will be useful,
7.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
7.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
7.17 + * GNU General Public License for more details.
7.18 + *
7.19 + * You should have received a copy of the GNU General Public License
7.20 + * along with this program; if not, write to the Free Software
7.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
7.22 + * Boston, MA 02110-1301, USA
7.23 + */
7.24 +
7.25 +#include <stdio.h>
7.26 +#include <stdlib.h>
7.27 +#include <string.h>
7.28 +
7.29 +#include <sys/types.h>
7.30 +#include <sys/stat.h>
7.31 +
7.32 +#include <ext2fs/ext2fs.h>
7.33 +
7.34 +#include "file.h"
7.35 +#include "format.h"
7.36 +#include "image.h"
7.37 +#include "path.h"
7.38 +
7.39 +
7.40 +
7.41 +/* Show directory entries when iterating. */
7.42 +
7.43 +static int image_list_dir_proc(struct ext2_dir_entry *dirent, int offset,
7.44 + int blocksize, char *buf, void *priv_data)
7.45 +{
7.46 + ext2_filsys fs = (ext2_filsys) priv_data;
7.47 + struct ext2_inode inode;
7.48 + ext2_file_t file;
7.49 + __u64 size;
7.50 + char *to_remove[] = {"file0061", "file0062", "file0063", "file0125", "file0126", "file0127", 0};
7.51 + char **f;
7.52 +
7.53 + /* Obtain the inode details for metadata. */
7.54 +
7.55 + if (ext2fs_read_inode(fs, dirent->inode, &inode))
7.56 + return DIRENT_ABORT;
7.57 +
7.58 + /* Output details in the style of "ls -l" showing directory, permissions,
7.59 + owner, group and size information. */
7.60 +
7.61 + printf("%06d: %s%s %5d %5d %6d ",
7.62 + offset,
7.63 + _image_isdir(fs, dirent->inode) ? "d" : "-",
7.64 + get_permission_string(inode.i_mode),
7.65 + inode.i_uid,
7.66 + inode.i_gid,
7.67 + EXT2_I_SIZE(&inode));
7.68 +
7.69 + /* Output the name which is presumably not necessarily null-terminated. */
7.70 +
7.71 + fwrite(dirent->name, sizeof(char), ext2fs_dirent_name_len(dirent), stdout);
7.72 + fputc((int) '\n', stdout);
7.73 +
7.74 + /* Remove files at an awkward point in time. */
7.75 +
7.76 + if (!strncmp(dirent->name, "file0060", ext2fs_dirent_name_len(dirent)))
7.77 + {
7.78 + for (f = to_remove; *f; f++)
7.79 + if (ext2fs_unlink(fs, EXT2_ROOT_INO, *f, 0, 0))
7.80 + printf("%s not removed!\n", *f);
7.81 + }
7.82 +
7.83 + return 0;
7.84 +}
7.85 +
7.86 +
7.87 +
7.88 +int main(int argc, char *argv[])
7.89 +{
7.90 + int flags = EXT2_FLAG_RW;
7.91 + char *fsname;
7.92 + ext2_filsys fs = NULL;
7.93 + errcode_t retval;
7.94 + int exitcode = 0;
7.95 + char basename[32];
7.96 + ext2_ino_t ino;
7.97 + ext2_file_t file;
7.98 + int i;
7.99 +
7.100 + if (argc < 2)
7.101 + {
7.102 + printf("Usage: %s <device or image file>\n", argv[0]);
7.103 + return 1;
7.104 + }
7.105 +
7.106 + fsname = argv[1];
7.107 +
7.108 + /* Open the filesystem image using the POSIX file access mechanism. */
7.109 +
7.110 + retval = ext2fs_open(fsname, flags, 0, 0, unix_io_manager, &fs);
7.111 + if (retval)
7.112 + {
7.113 + printf("Could not open filesystem using %s\n", fsname);
7.114 + return 1;
7.115 + }
7.116 +
7.117 + retval = ext2fs_read_bitmaps(fs);
7.118 + if (retval)
7.119 + {
7.120 + printf("Could not read bitmaps from %s\n", fsname);
7.121 + return 1;
7.122 + }
7.123 +
7.124 + printf("Filesystem with blocksize %d\n", fs->blocksize);
7.125 +
7.126 + /* Create some files. */
7.127 +
7.128 + for (i = 1; i <= 200; i++)
7.129 + {
7.130 + sprintf(basename, "file%04d", i);
7.131 +
7.132 + retval = image_create_file(fs, EXT2_ROOT_INO, basename, 0644,
7.133 + 1000, 1000, &ino);
7.134 +
7.135 + if (retval)
7.136 + {
7.137 + printf("Could not create file %s\n", basename);
7.138 + return 1;
7.139 + }
7.140 +
7.141 + if (ext2fs_file_open(fs, ino, EXT2_FILE_WRITE | EXT2_FILE_CREATE, &file))
7.142 + {
7.143 + printf("Could not write file %s\n", basename);
7.144 + return 1;
7.145 + }
7.146 +
7.147 + ext2fs_file_flush(file);
7.148 + ext2fs_file_close(file);
7.149 + }
7.150 +
7.151 + image_list_dir(fs, "", image_list_dir_proc, fs);
7.152 + image_list_dir(fs, "", image_list_dir_proc, fs);
7.153 +
7.154 + /* Close the filesystem image. */
7.155 +
7.156 + retval = ext2fs_flush(fs);
7.157 + if (retval)
7.158 + {
7.159 + printf("Error flushing filesystem in %s\n", fsname);
7.160 + exitcode = 1;
7.161 + }
7.162 +
7.163 + retval = ext2fs_close(fs);
7.164 + if (retval)
7.165 + {
7.166 + printf("Error closing filesystem in %s\n", fsname);
7.167 + exitcode = 1;
7.168 + }
7.169 +
7.170 + ext2fs_free(fs);
7.171 + return exitcode;
7.172 +}
8.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
8.2 +++ b/libe2access/host/test_remove.c Tue Dec 28 01:37:59 2021 +0100
8.3 @@ -0,0 +1,264 @@
8.4 +/*
8.5 + * Test file removal semantics.
8.6 + *
8.7 + * Copyright (C) 2019, 2021 Paul Boddie <paul@boddie.org.uk>
8.8 + *
8.9 + * This program is free software; you can redistribute it and/or
8.10 + * modify it under the terms of the GNU General Public License as
8.11 + * published by the Free Software Foundation; either version 2 of
8.12 + * the License, or (at your option) any later version.
8.13 + *
8.14 + * This program is distributed in the hope that it will be useful,
8.15 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
8.16 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
8.17 + * GNU General Public License for more details.
8.18 + *
8.19 + * You should have received a copy of the GNU General Public License
8.20 + * along with this program; if not, write to the Free Software
8.21 + * Foundation, Inc., 51 Franklin Street, Fifth Floor,
8.22 + * Boston, MA 02110-1301, USA
8.23 + */
8.24 +
8.25 +#include <stdio.h>
8.26 +#include <stdlib.h>
8.27 +#include <string.h>
8.28 +
8.29 +#include <sys/types.h>
8.30 +#include <sys/stat.h>
8.31 +
8.32 +#include <ext2fs/ext2fs.h>
8.33 +
8.34 +#include "file.h"
8.35 +#include "format.h"
8.36 +#include "image.h"
8.37 +#include "path.h"
8.38 +
8.39 +
8.40 +
8.41 +/* Buffer size for file access. */
8.42 +
8.43 +const int BUFSIZE = 4096;
8.44 +
8.45 +/* Number of open files. */
8.46 +
8.47 +const int FILES = 20;
8.48 +
8.49 +
8.50 +
8.51 +/* Show directory entries when iterating. */
8.52 +
8.53 +static int image_list_dir_proc(struct ext2_dir_entry *dirent, int offset,
8.54 + int blocksize, char *buf, void *priv_data)
8.55 +{
8.56 + ext2_filsys fs = (ext2_filsys) priv_data;
8.57 + struct ext2_inode inode;
8.58 + ext2_file_t file;
8.59 + __u64 size;
8.60 +
8.61 + /* Obtain the inode details for metadata. */
8.62 +
8.63 + if (ext2fs_read_inode(fs, dirent->inode, &inode))
8.64 + return DIRENT_ABORT;
8.65 +
8.66 + /* Output details in the style of "ls -l" showing directory, permissions,
8.67 + owner, group and size information. */
8.68 +
8.69 + printf("%06d: %s%s %5d %5d %6d ",
8.70 + offset,
8.71 + _image_isdir(fs, dirent->inode) ? "d" : "-",
8.72 + get_permission_string(inode.i_mode),
8.73 + inode.i_uid,
8.74 + inode.i_gid,
8.75 + EXT2_I_SIZE(&inode));
8.76 +
8.77 + /* Output the name which is presumably not necessarily null-terminated. */
8.78 +
8.79 + fwrite(dirent->name, sizeof(char), ext2fs_dirent_name_len(dirent), stdout);
8.80 + fputc((int) '\n', stdout);
8.81 +
8.82 + return 0;
8.83 +}
8.84 +
8.85 +
8.86 +
8.87 +int main(int argc, char *argv[])
8.88 +{
8.89 + int flags = EXT2_FLAG_RW;
8.90 + char *fsname;
8.91 + ext2_filsys fs = NULL;
8.92 + errcode_t retval;
8.93 + int exitcode = 0;
8.94 + char basename[32];
8.95 + ext2_ino_t ino, inos[FILES];
8.96 + ext2_file_t file, files[FILES];
8.97 + char buf[BUFSIZE];
8.98 + unsigned int transferred;
8.99 + int i;
8.100 +
8.101 + if (argc < 2)
8.102 + {
8.103 + printf("Usage: %s <device or image file>\n", argv[0]);
8.104 + return 1;
8.105 + }
8.106 +
8.107 + fsname = argv[1];
8.108 +
8.109 + /* Open the filesystem image using the POSIX file access mechanism. */
8.110 +
8.111 + retval = ext2fs_open(fsname, flags, 0, 0, unix_io_manager, &fs);
8.112 + if (retval)
8.113 + {
8.114 + printf("Could not open filesystem using %s\n", fsname);
8.115 + return 1;
8.116 + }
8.117 +
8.118 + retval = ext2fs_read_bitmaps(fs);
8.119 + if (retval)
8.120 + {
8.121 + printf("Could not read bitmaps from %s\n", fsname);
8.122 + return 1;
8.123 + }
8.124 +
8.125 + printf("Filesystem with blocksize %d\n", fs->blocksize);
8.126 +
8.127 + /* Create some files. */
8.128 +
8.129 + for (i = 1; i <= FILES; i++)
8.130 + {
8.131 + sprintf(basename, "file%04d", i);
8.132 +
8.133 + retval = image_create_file(fs, EXT2_ROOT_INO, basename, 0644,
8.134 + 1000, 1000, &ino);
8.135 +
8.136 + if (retval)
8.137 + {
8.138 + printf("Could not create file %s\n", basename);
8.139 + return 1;
8.140 + }
8.141 +
8.142 + if (ext2fs_file_open(fs, ino, EXT2_FILE_WRITE | EXT2_FILE_CREATE, &file))
8.143 + {
8.144 + printf("Could not open file %s\n", basename);
8.145 + return 1;
8.146 + }
8.147 +
8.148 + ext2fs_file_flush(file);
8.149 +
8.150 + files[i - 1] = file;
8.151 + inos[i - 1] = ino;
8.152 + }
8.153 +
8.154 + image_list_dir(fs, "", image_list_dir_proc, fs);
8.155 + printf("----\n");
8.156 +
8.157 + /* Unlink the files. */
8.158 +
8.159 + for (i = 1; i <= FILES; i++)
8.160 + {
8.161 + sprintf(basename, "file%04d", i);
8.162 +
8.163 + if (ext2fs_unlink(fs, EXT2_ROOT_INO, basename, 0, 0))
8.164 + {
8.165 + printf("Could not unlink file %s\n", basename);
8.166 + return 1;
8.167 + }
8.168 + }
8.169 +
8.170 + image_list_dir(fs, "", image_list_dir_proc, fs);
8.171 + printf("----\n");
8.172 +
8.173 + /* Access and close unlinked files. */
8.174 +
8.175 + for (i = 1; i <= FILES; i++)
8.176 + {
8.177 + sprintf(basename, "file%04d", i);
8.178 + sprintf(buf, "writing to file%04d", i);
8.179 +
8.180 + file = files[i - 1];
8.181 +
8.182 + if (ext2fs_file_write(file, buf, strlen(buf), &transferred))
8.183 + {
8.184 + printf("Could not write to file %s\n", basename);
8.185 + return 1;
8.186 + }
8.187 +
8.188 + ext2fs_file_flush(file);
8.189 + ext2fs_file_close(file);
8.190 + }
8.191 +
8.192 + image_list_dir(fs, "", image_list_dir_proc, fs);
8.193 + printf("----\n");
8.194 +
8.195 + /* Create some more files. */
8.196 +
8.197 + for (i = 1; i <= FILES; i++)
8.198 + {
8.199 + sprintf(basename, "file%04d", i + FILES);
8.200 +
8.201 + retval = image_create_file(fs, EXT2_ROOT_INO, basename, 0644,
8.202 + 1000, 1000, &ino);
8.203 +
8.204 + if (retval)
8.205 + {
8.206 + printf("Could not create file %s\n", basename);
8.207 + return 1;
8.208 + }
8.209 +
8.210 + if (ext2fs_file_open(fs, ino, EXT2_FILE_WRITE | EXT2_FILE_CREATE, &file))
8.211 + {
8.212 + printf("Could not write file %s\n", basename);
8.213 + return 1;
8.214 + }
8.215 +
8.216 + ext2fs_file_flush(file);
8.217 + ext2fs_file_close(file);
8.218 + }
8.219 +
8.220 + image_list_dir(fs, "", image_list_dir_proc, fs);
8.221 + printf("----\n");
8.222 +
8.223 + /* Re-open the original files and read from them. */
8.224 +
8.225 + for (i = 1; i <= FILES; i++)
8.226 + {
8.227 + sprintf(basename, "file%04d", i);
8.228 +
8.229 + ino = inos[i - 1];
8.230 +
8.231 + if (ext2fs_file_open(fs, ino, 0, &file))
8.232 + {
8.233 + printf("Could not open file %s\n", basename);
8.234 + return 1;
8.235 + }
8.236 +
8.237 + if (ext2fs_file_read(file, buf, BUFSIZE, &transferred))
8.238 + {
8.239 + printf("Could not read from file %s\n", basename);
8.240 + return 1;
8.241 + }
8.242 +
8.243 + buf[transferred] = '\0';
8.244 + printf("Read from %s: %s\n", basename, buf);
8.245 +
8.246 + ext2fs_file_close(file);
8.247 + }
8.248 +
8.249 + /* Close the filesystem image. */
8.250 +
8.251 + retval = ext2fs_flush(fs);
8.252 + if (retval)
8.253 + {
8.254 + printf("Error flushing filesystem in %s\n", fsname);
8.255 + exitcode = 1;
8.256 + }
8.257 +
8.258 + retval = ext2fs_close(fs);
8.259 + if (retval)
8.260 + {
8.261 + printf("Error closing filesystem in %s\n", fsname);
8.262 + exitcode = 1;
8.263 + }
8.264 +
8.265 + ext2fs_free(fs);
8.266 + return exitcode;
8.267 +}
9.1 --- a/libe2access/include/e2access/image.h Sun Nov 28 22:18:33 2021 +0100
9.2 +++ b/libe2access/include/e2access/image.h Tue Dec 28 01:37:59 2021 +0100
9.3 @@ -1,7 +1,7 @@
9.4 /*
9.5 * Filesystem image access functions.
9.6 *
9.7 - * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
9.8 + * Copyright (C) 2019, 2021 Paul Boddie <paul@boddie.org.uk>
9.9 *
9.10 * This program is free software; you can redistribute it and/or
9.11 * modify it under the terms of the GNU General Public License as
9.12 @@ -23,8 +23,7 @@
9.13 #define __IMAGE_H__
9.14
9.15 #include <ext2fs/ext2fs.h>
9.16 -
9.17 -
9.18 +#include <sys/stat.h>
9.19
9.20 #ifdef __cplusplus
9.21 extern "C" {
9.22 @@ -46,6 +45,11 @@
9.23 errcode_t image_inode(ext2_filsys fs, const char *pathname,
9.24 struct ext2_inode *inode);
9.25
9.26 +errcode_t image_list_dir(ext2_filsys fs, const char *path,
9.27 + int (*proc)(struct ext2_dir_entry *, int, int, char *,
9.28 + void *),
9.29 + void *data);
9.30 +
9.31 errcode_t image_make_dir(ext2_filsys fs, ext2_ino_t ino_dir,
9.32 const char *basename, __u16 mode,
9.33 __u16 uid, __u16 gid, ext2_ino_t *ino);
10.1 --- a/libe2access/lib/src/format.c Sun Nov 28 22:18:33 2021 +0100
10.2 +++ b/libe2access/lib/src/format.c Tue Dec 28 01:37:59 2021 +0100
10.3 @@ -1,7 +1,7 @@
10.4 /*
10.5 * File metadata formatting.
10.6 *
10.7 - * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
10.8 + * Copyright (C) 2019, 2021 Paul Boddie <paul@boddie.org.uk>
10.9 *
10.10 * This program is free software; you can redistribute it and/or
10.11 * modify it under the terms of the GNU General Public License as
10.12 @@ -27,12 +27,12 @@
10.13
10.14 char *get_permission_string(uint16_t permissions)
10.15 {
10.16 - static char s[9] = "--------\0";
10.17 + static char s[11] = "---------\0";
10.18 static char letters[] = "rwx";
10.19 int i, letter;
10.20 uint16_t selector = 0400;
10.21
10.22 - for (i = 0, letter = 0; i < 9; i++, letter = (letter + 1) % 3, selector >>= 1)
10.23 + for (i = 0, letter = 0; i < 10; i++, letter = (letter + 1) % 3, selector >>= 1)
10.24 s[i] = permissions & selector ? letters[letter] : '-';
10.25
10.26 return s;
11.1 --- a/libe2access/lib/src/image.c Sun Nov 28 22:18:33 2021 +0100
11.2 +++ b/libe2access/lib/src/image.c Tue Dec 28 01:37:59 2021 +0100
11.3 @@ -1,7 +1,7 @@
11.4 /*
11.5 * Filesystem access functions.
11.6 *
11.7 - * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk>
11.8 + * Copyright (C) 2019, 2021 Paul Boddie <paul@boddie.org.uk>
11.9 *
11.10 * This program is free software; you can redistribute it and/or
11.11 * modify it under the terms of the GNU General Public License as
11.12 @@ -20,7 +20,6 @@
11.13 */
11.14
11.15 #include <string.h>
11.16 -#include <sys/stat.h>
11.17
11.18 #include <ext2fs/ext2fs.h>
11.19
11.20 @@ -186,6 +185,47 @@
11.21 return ext2fs_read_inode(fs, ino, inode);
11.22 }
11.23
11.24 +/* List a directory in the filesystem image. */
11.25 +
11.26 +errcode_t image_list_dir(ext2_filsys fs, const char *path,
11.27 + int (*proc)(struct ext2_dir_entry *, int, int, char *,
11.28 + void *),
11.29 + void *data)
11.30 +{
11.31 + const char *path_orig = path;
11.32 + char *buf;
11.33 + ext2_ino_t ino;
11.34 + errcode_t retval;
11.35 +
11.36 + retval = ext2fs_get_mem(fs->blocksize, &buf);
11.37 + if (retval)
11.38 + return retval;
11.39 +
11.40 + /* Locate the object and test whether it is a directory. */
11.41 +
11.42 + retval = image_find_path(fs, &path, &ino);
11.43 + if (retval)
11.44 + {
11.45 + ext2fs_free_mem(&buf);
11.46 + return retval;
11.47 + }
11.48 +
11.49 + if (!_image_isdir(fs, ino))
11.50 + return 1;
11.51 +
11.52 + /* List the directory contents. */
11.53 +
11.54 + retval = ext2fs_dir_iterate(fs, ino, 0, buf, proc, data);
11.55 + if (retval)
11.56 + {
11.57 + ext2fs_free_mem(&buf);
11.58 + return retval;
11.59 + }
11.60 +
11.61 + ext2fs_free_mem(&buf);
11.62 + return 0;
11.63 +}
11.64 +
11.65 /* Make a directory in the given directory in the filesystem image having the
11.66 given name and metadata. */
11.67