1 /* 2 * List filesystem objects using the client library. 3 * 4 * Originally developed as fsaccess/op_list_objects.c, this should eventually 5 * use C library functions instead of client library functions. 6 * 7 * Copyright (C) 2019, 2022, 2024 Paul Boddie <paul@boddie.org.uk> 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License as 11 * published by the Free Software Foundation; either version 2 of 12 * the License, or (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 22 * Boston, MA 02110-1301, USA 23 */ 24 25 #include <dirent.h> 26 #include <stdio.h> 27 #include <stdlib.h> 28 #include <string.h> 29 30 #include <sys/stat.h> 31 #include <sys/types.h> 32 33 #include <e2access/format.h> /* get_permission_string */ 34 #include <e2access/path.h> 35 #include <fsclient/client.h> 36 #include <systypes/format.h> 37 38 #define FMTnlinkd "%" pFMTnlink "d" 39 40 41 42 /* Show object details. */ 43 44 static void _show_object(const char *basename, struct stat *st) 45 { 46 printf("%s%s %5d %5d %6ld " FMTnlinkd " %s\n", 47 S_ISDIR(st->st_mode) ? "d" : "-", 48 get_permission_string(st->st_mode), 49 st->st_uid, 50 st->st_gid, 51 st->st_size, 52 st->st_nlink, 53 basename); 54 } 55 56 /* Show an object in a directory. */ 57 58 static int _show_dirent(const char *dirname, struct dirent *dirent) 59 { 60 struct stat st; 61 char path[strlen(dirname) + 1 + strlen(dirent->d_name) + 1]; 62 63 sprintf(path, "%s/%s", dirname, dirent->d_name); 64 65 if (client_stat(path, &st)) 66 return 1; 67 68 _show_object(dirent->d_name, &st); 69 70 return 0; 71 } 72 73 /* List a directory or file. */ 74 75 static int _list_object(const char *path) 76 { 77 struct stat st; 78 file_t *reader; 79 struct dirent *dirent; 80 81 if (client_stat(path, &st)) 82 return 1; 83 84 if (S_ISDIR(st.st_mode)) 85 { 86 reader = client_opendir(path); 87 88 if (!client_opened(reader)) 89 { 90 client_close(reader); 91 return 1; 92 } 93 94 /* Show the directory entries. */ 95 96 while ((dirent = client_readdir(reader)) != NULL) 97 { 98 if (_show_dirent(path, dirent)) 99 { 100 free(dirent); 101 return 1; 102 } 103 104 free(dirent); 105 } 106 107 client_close(reader); 108 } 109 else 110 _show_object(path_basename(path), &st); 111 112 return 0; 113 } 114 115 /* List an object in the filesystem. */ 116 117 static int list_object(const char *path) 118 { 119 /* Emit each object's name. */ 120 121 printf("%s\n", path); 122 123 /* List individual files or directories. */ 124 125 if (_list_object(path)) 126 { 127 /* NOTE: Should write via a standard error stream provided in the same 128 way as the output stream. */ 129 130 fprintf(stderr, "Failed to list object: %s\n", path); 131 return 1; 132 } 133 134 return 0; 135 } 136 137 /* List objects in the filesystem. */ 138 139 int main(int argc, char *argv[]) 140 { 141 int i; 142 143 /* List the top level without any argument. */ 144 145 if (argc < 2) 146 { 147 if (list_object("")) 148 return 1; 149 } 150 else 151 { 152 /* Otherwise, list all specified objects. */ 153 154 for (i = 1; i < argc; i++) 155 { 156 if (list_object(argv[i])) 157 return 1; 158 } 159 } 160 161 return 0; 162 } 163 164 /* vim: tabstop=4 expandtab shiftwidth=4 165 */