Changes in uspace/app/bdsh/cmds/modules/ls/ls.c [cfc3027:19f857a] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bdsh/cmds/modules/ls/ls.c
rcfc3027 r19f857a 38 38 #include <dirent.h> 39 39 #include <fcntl.h> 40 #include <getopt.h>41 40 #include <sys/types.h> 42 41 #include <sys/stat.h> 43 42 #include <str.h> 44 #include <sort.h>45 43 46 44 #include "errors.h" … … 48 46 #include "util.h" 49 47 #include "entry.h" 48 #include "ls.h" 50 49 #include "cmds.h" 51 52 /* Various values that can be returned by ls_scope() */53 #define LS_BOGUS 054 #define LS_FILE 155 #define LS_DIR 256 57 /** Structure to represent a directory entry.58 *59 * Useful to keep together important information60 * for sorting directory entries.61 */62 struct dir_elem_t {63 char *name;64 struct stat s;65 };66 50 67 51 static const char *cmdname = "ls"; 68 52 69 static struct option const long_options[] = { 70 { "help", no_argument, 0, 'h' }, 71 { "unsort", no_argument, 0, 'u' }, 72 { 0, 0, 0, 0 } 73 }; 53 static void ls_scan_dir(const char *d, DIR *dirp) 54 { 55 struct dirent *dp; 56 char *buff; 74 57 75 /** Print an entry. 76 * 77 * ls_print currently does nothing more than print the entry. 78 * In the future, we will likely pass the absolute path, and 58 if (! dirp) 59 return; 60 61 buff = (char *)malloc(PATH_MAX); 62 if (NULL == buff) { 63 cli_error(CL_ENOMEM, "ls: failed to scan %s", d); 64 return; 65 } 66 67 while ((dp = readdir(dirp))) { 68 memset(buff, 0, sizeof(buff)); 69 /* Don't worry if inserting a double slash, this will be fixed by 70 * absolutize() later with subsequent calls to open() or readdir() */ 71 snprintf(buff, PATH_MAX - 1, "%s/%s", d, dp->d_name); 72 ls_print(dp->d_name, buff); 73 } 74 75 free(buff); 76 77 return; 78 } 79 80 /* ls_print currently does nothing more than print the entry. 81 * in the future, we will likely pass the absolute path, and 79 82 * some sort of ls_options structure that controls how each 80 83 * entry is printed and what is printed about it. 81 84 * 82 * Now we just print basic DOS style lists. 83 * 84 * @param de Directory element. 85 */ 86 static void ls_print(struct dir_elem_t *de) 85 * Now we just print basic DOS style lists */ 86 87 static void ls_print(const char *name, const char *pathname) 87 88 { 88 if (de->s.is_file) 89 printf("%-40s\t%llu\n", de->name, (long long) de->s.size); 90 else if (de->s.is_directory) 91 printf("%-40s\t<dir>\n", de->name); 92 else 93 printf("%-40s\n", de->name); 94 } 89 struct stat s; 90 int rc; 95 91 96 97 /** Compare 2 directory elements. 98 * 99 * It compares 2 elements of a directory : a file is considered 100 * as bigger than a directory, and if they have the same type, 101 * they are compared alphabetically. 102 * 103 * @param a Pointer to the structure of the first element. 104 * @param b Pointer to the structure of the second element. 105 * @param arg Pointer for an other and optionnal argument. 106 * 107 * @return -1 if a < b, 1 otherwise. 108 */ 109 static int ls_cmp(void *a, void *b, void *arg) 110 { 111 struct dir_elem_t *da = a; 112 struct dir_elem_t *db = b; 113 114 if ((da->s.is_directory && db->s.is_file) || 115 ((da->s.is_directory == db->s.is_directory) && 116 str_cmp(da->name, db->name) < 0)) 117 return -1; 118 else 119 return 1; 120 } 121 122 /** Scan a directory. 123 * 124 * Scan the content of a directory and print it. 125 * 126 * @param d Name of the directory. 127 * @param dirp Directory stream. 128 * @param sort 1 if the output must be sorted, 129 * 0 otherwise. 130 */ 131 static void ls_scan_dir(const char *d, DIR *dirp, int sort) 132 { 133 int alloc_blocks = 20; 134 int i; 135 int nbdirs = 0; 136 int rc; 137 int len; 138 char *buff; 139 struct dir_elem_t *tmp; 140 struct dir_elem_t *tosort; 141 struct dirent *dp; 142 143 if (!dirp) 144 return; 145 146 buff = (char *) malloc(PATH_MAX); 147 if (!buff) { 148 cli_error(CL_ENOMEM, "ls: failed to scan %s", d); 92 rc = stat(pathname, &s); 93 if (rc != 0) { 94 /* Odd chance it was deleted from the time readdir() found it */ 95 printf("ls: skipping bogus node %s\n", pathname); 96 printf("rc=%d\n", rc); 149 97 return; 150 98 } 151 99 152 tosort = (struct dir_elem_t *) malloc(alloc_blocks * sizeof(*tosort)); 153 if (!tosort) { 154 cli_error(CL_ENOMEM, "ls: failed to scan %s", d); 155 free(buff); 156 return; 157 } 158 159 while ((dp = readdir(dirp))) { 160 if (nbdirs + 1 > alloc_blocks) { 161 alloc_blocks += alloc_blocks; 162 163 tmp = (struct dir_elem_t *) realloc(tosort, 164 alloc_blocks * sizeof(struct dir_elem_t)); 165 if (!tmp) { 166 cli_error(CL_ENOMEM, "ls: failed to scan %s", d); 167 goto out; 168 } 169 tosort = tmp; 170 } 171 172 /* fill the name field */ 173 tosort[nbdirs].name = (char *) malloc(str_length(dp->d_name) + 1); 174 if (!tosort[nbdirs].name) { 175 cli_error(CL_ENOMEM, "ls: failed to scan %s", d); 176 goto out; 177 } 178 179 str_cpy(tosort[nbdirs].name, str_length(dp->d_name) + 1, dp->d_name); 180 len = snprintf(buff, PATH_MAX - 1, "%s/%s", d, tosort[nbdirs].name); 181 buff[len] = '\0'; 100 if (s.is_file) 101 printf("%-40s\t%llu\n", name, (long long) s.size); 102 else if (s.is_directory) 103 printf("%-40s\t<dir>\n", name); 104 else 105 printf("%-40s\n", name); 182 106 183 rc = stat(buff, &tosort[nbdirs++].s); 184 if (rc != 0) { 185 printf("ls: skipping bogus node %s\n", buff); 186 printf("rc=%d\n", rc); 187 goto out; 188 } 189 } 190 191 if (sort) { 192 if (!qsort(&tosort[0], nbdirs, sizeof(struct dir_elem_t), 193 ls_cmp, NULL)) { 194 printf("Sorting error.\n"); 195 } 196 } 197 198 for (i = 0; i < nbdirs; i++) 199 ls_print(&tosort[i]); 200 201 out: 202 for(i = 0; i < nbdirs; i++) 203 free(tosort[i].name); 204 free(tosort); 205 free(buff); 107 return; 206 108 } 207 109 … … 212 114 } else { 213 115 help_cmd_ls(HELP_SHORT); 214 printf( 215 "Usage: %s [options] [path]\n" 216 "If not path is given, the current working directory is used.\n" 217 "Options:\n" 218 " -h, --help A short option summary\n" 219 " -u, --unsort Do not sort directory entries\n", 220 cmdname); 116 printf(" `%s' [path], if no path is given the current " 117 "working directory is used.\n", cmdname); 221 118 } 222 119 … … 227 124 { 228 125 unsigned int argc; 229 struct dir_elem_t de; 126 struct stat s; 127 char *buff; 230 128 DIR *dirp; 231 int c, opt_ind;232 int sort = 1;233 129 234 130 argc = cli_count_args(argv); 235 236 for (c = 0, optind = 0, opt_ind = 0; c != -1;) { 237 c = getopt_long(argc, argv, "hu", long_options, &opt_ind); 238 switch (c) { 239 case 'h': 240 help_cmd_ls(HELP_LONG); 241 return CMD_SUCCESS; 242 case 'u': 243 sort = 0; 244 break; 245 } 246 } 247 248 argc -= optind; 249 250 de.name = (char *) malloc(PATH_MAX); 251 if (!de.name) { 131 132 buff = (char *) malloc(PATH_MAX); 133 if (NULL == buff) { 252 134 cli_error(CL_ENOMEM, "%s: ", cmdname); 253 135 return CMD_FAILURE; 254 136 } 255 memset( de.name, 0, sizeof(PATH_MAX));256 257 if (argc == 0)258 getcwd( de.name, PATH_MAX);137 memset(buff, 0, sizeof(buff)); 138 139 if (argc == 1) 140 getcwd(buff, PATH_MAX); 259 141 else 260 str_cpy( de.name, PATH_MAX, argv[optind]);261 262 if (stat( de.name, &de.s)) {263 cli_error(CL_ENOENT, de.name);264 free( de.name);142 str_cpy(buff, PATH_MAX, argv[1]); 143 144 if (stat(buff, &s)) { 145 cli_error(CL_ENOENT, buff); 146 free(buff); 265 147 return CMD_FAILURE; 266 148 } 267 149 268 if ( de.s.is_file) {269 ls_print( &de);150 if (s.is_file) { 151 ls_print(buff, buff); 270 152 } else { 271 dirp = opendir( de.name);153 dirp = opendir(buff); 272 154 if (!dirp) { 273 155 /* May have been deleted between scoping it and opening it */ 274 cli_error(CL_EFAIL, "Could not stat %s", de.name);275 free( de.name);156 cli_error(CL_EFAIL, "Could not stat %s", buff); 157 free(buff); 276 158 return CMD_FAILURE; 277 159 } 278 ls_scan_dir( de.name, dirp, sort);160 ls_scan_dir(buff, dirp); 279 161 closedir(dirp); 280 162 } 281 163 282 free( de.name);164 free(buff); 283 165 284 166 return CMD_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.