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