# HG changeset patch # User Paul Boddie # Date 1705358696 -3600 # Node ID fb7127ee218e20ac17972ffa3cf35bfd0bf04d1e # Parent abb6e29facd69f4fb64808083fafb6863e9e0d69 Added a program for listing directories based on the fsaccess operation. diff -r abb6e29facd6 -r fb7127ee218e test_files/Control --- a/test_files/Control Mon Jan 15 01:18:41 2024 +0100 +++ b/test_files/Control Mon Jan 15 23:44:56 2024 +0100 @@ -1,3 +1,3 @@ provides: fstest_files -requires: libc libstdc++ libexec libfsclient libsystypes l4re_c-util +requires: libc libstdc++ libexec libfsclient libsystypes l4re_c-util libe2access maintainer: paul@boddie.org.uk diff -r abb6e29facd6 -r fb7127ee218e test_files/programs/Makefile --- a/test_files/programs/Makefile Mon Jan 15 01:18:41 2024 +0100 +++ b/test_files/programs/Makefile Mon Jan 15 23:44:56 2024 +0100 @@ -1,7 +1,7 @@ PKGDIR ?= .. L4DIR ?= $(PKGDIR)/../../.. -TARGET = clip dstest_exec_payload +TARGET = clip dstest_exec_payload ls MODE = static @@ -9,6 +9,8 @@ SRC_C_dstest_exec_payload = dstest_exec_payload.c -REQUIRES_LIBS = libc libfsclient l4re_c-util libsystypes +SRC_C_ls = ls.c + +REQUIRES_LIBS = libc libfsclient l4re_c-util libsystypes libe2access include $(L4DIR)/mk/prog.mk diff -r abb6e29facd6 -r fb7127ee218e test_files/programs/ls.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/test_files/programs/ls.c Mon Jan 15 23:44:56 2024 +0100 @@ -0,0 +1,183 @@ +/* + * List filesystem objects using the client library. + * + * Originally developed as fsaccess/op_list_objects.c, this should eventually + * use C library functions instead of client library functions. + * + * Copyright (C) 2019, 2022, 2024 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 + */ + +#include +#include +#include + +#include +#include + +#include /* get_permission_string */ +#include +#include + +#define FMTnlinkd "%" pFMTnlink "d" + + + +/* NOTE: For inclusion in the C library: stream acquisition and access. */ + +#include +#include +#include + +file_t *output; + + + +/* Show object details. */ + +static void _show_object(const char *basename, struct stat *st) +{ + char buffer[strlen(basename) + 64]; + + sprintf(buffer, "%s%s %5d %5d %6ld " FMTnlinkd " %s\n", + S_ISDIR(st->st_mode) ? "d" : "-", + get_permission_string(st->st_mode), + st->st_uid, + st->st_gid, + st->st_size, + st->st_nlink, + basename); + + client_write(output, buffer, strlen(buffer)); +} + +/* Show an object in a directory. */ + +static int _show_dirent(const char *dirname, struct dirent *dirent) +{ + struct stat st; + char path[strlen(dirname) + 1 + strlen(dirent->d_name) + 1]; + + sprintf(path, "%s/%s", dirname, dirent->d_name); + + if (client_stat(path, &st)) + return 1; + + _show_object(dirent->d_name, &st); + + return 0; +} + +/* List a directory or file. */ + +static int _list_object(const char *path) +{ + struct stat st; + file_t *reader; + struct dirent *dirent; + + if (client_stat(path, &st)) + return 1; + + if (S_ISDIR(st.st_mode)) + { + reader = client_opendir(path); + + if (reader == NULL) + return 1; + + /* Show the directory entries. */ + + while ((dirent = client_readdir(reader)) != NULL) + { + if (_show_dirent(path, dirent)) + { + free(dirent); + return 1; + } + + free(dirent); + } + + client_close(reader); + } + else + _show_object(path_basename(path), &st); + + return 0; +} + +/* List an object in the filesystem image. */ + +static int list_object(const char *path) +{ + /* Emit each object's name. */ + + client_write(output, path, strlen(path)); + client_write(output, "\n", 1); + + /* List individual files or directories. */ + + if (_list_object(path)) + { + /* NOTE: Should write via a standard error stream provided in the same + way as the output stream. */ + + fprintf(stderr, "Failed to list object: %s\n", path); + return 1; + } + + return 0; +} + +/* List objects in the filesystem image. */ + +int main(int argc, char *argv[]) +{ + int i; + + /* NOTE: For inclusion in the C library: stream acquisition and access. */ + + output = client_get_stream(ENV_OUTPUT_STREAM_NAME, O_WRONLY); + + /* List the top level without any argument. */ + + if (argc < 2) + { + if (list_object("")) + return 1; + } + else + { + /* Otherwise, list all specified objects. */ + + for (i = 1; i < argc; i++) + { + if (list_object(argv[i])) + return 1; + } + } + + /* NOTE: For inclusion in the C library: stream acquisition and access. */ + + client_flush(output); + + return 0; +} + +/* vim: tabstop=4 expandtab shiftwidth=4 +*/