1 /* 2 * List filesystem objects using the client library. 3 * 4 * Copyright (C) 2019, 2022 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 26 #include <sys/stat.h> 27 #include <sys/types.h> 28 29 #include <e2access/format.h> /* get_permission_string */ 30 #include <e2access/path.h> 31 #include <fsclient/client.h> 32 #include <systypes/format.h> 33 34 #include "ops.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 (client_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 file_t *reader; 77 struct dirent *dirent; 78 79 if (client_stat(path, &st)) 80 return 1; 81 82 if (S_ISDIR(st.st_mode)) 83 { 84 reader = client_opendir(path); 85 86 if (reader == NULL) 87 return 1; 88 89 /* Show the directory entries. */ 90 91 while ((dirent = client_readdir(reader)) != NULL) 92 { 93 if (_show_dirent(path, dirent)) 94 { 95 free(dirent); 96 return 1; 97 } 98 99 free(dirent); 100 } 101 102 client_close(reader); 103 } 104 else 105 _show_object(path_basename(path), &st); 106 107 return 0; 108 } 109 110 /* List an object in the filesystem image. */ 111 112 static int list_object(const char *path) 113 { 114 /* Emit each object's name. */ 115 116 puts(path); 117 118 /* List individual files or directories. */ 119 120 if (_list_object(path)) 121 { 122 fprintf(stderr, "Failed to list object: %s\n", path); 123 return 1; 124 } 125 126 return 0; 127 } 128 129 /* List objects in the filesystem image. */ 130 131 int list_objects(int argc, char *argv[]) 132 { 133 int i; 134 135 /* List the top level without any argument. */ 136 137 if (!argc) 138 return list_object(""); 139 140 /* Otherwise, list all specified objects. */ 141 142 for (i = 0; i < argc; i++) 143 { 144 if (list_object(argv[i])) 145 return 1; 146 } 147 148 return 0; 149 } 150 151 /* vim: tabstop=4 expandtab shiftwidth=4 152 */