Changes in uspace/app/bdsh/cmds/modules/ls/ls.c [19f857a:a701812] in mainline
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bdsh/cmds/modules/ls/ls.c
r19f857a ra701812 1 /* Copyright (c) 2008, Tim Post <tinkertim@gmail.com> 1 /* 2 * Copyright (c) 2008 Tim Post 2 3 * All rights reserved. 3 4 * 4 5 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * Redistributions of source code must retain the above copyright notice, this 8 * list of conditions and the following disclaimer. 9 * 10 * Redistributions in binary form must reproduce the above copyright notice, 11 * this list of conditions and the following disclaimer in the documentation 12 * and/or other materials provided with the distribution. 13 * 14 * Neither the name of the original program's authors nor the names of its 15 * contributors may be used to endorse or promote products derived from this 16 * software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * - Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * - The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 27 */ 30 28 … … 38 36 #include <dirent.h> 39 37 #include <fcntl.h> 38 #include <getopt.h> 40 39 #include <sys/types.h> 41 40 #include <sys/stat.h> 42 41 #include <str.h> 42 #include <sort.h> 43 43 44 44 #include "errors.h" … … 46 46 #include "util.h" 47 47 #include "entry.h" 48 #include "ls.h"49 48 #include "cmds.h" 50 49 50 /* Various values that can be returned by ls_scope() */ 51 #define LS_BOGUS 0 52 #define LS_FILE 1 53 #define LS_DIR 2 54 55 /** Structure to represent a directory entry. 56 * 57 * Useful to keep together important information 58 * for sorting directory entries. 59 */ 60 struct dir_elem_t { 61 char *name; 62 struct stat s; 63 }; 64 51 65 static const char *cmdname = "ls"; 52 66 53 static void ls_scan_dir(const char *d, DIR *dirp) 54 { 67 static struct option const long_options[] = { 68 { "help", no_argument, 0, 'h' }, 69 { "unsort", no_argument, 0, 'u' }, 70 { 0, 0, 0, 0 } 71 }; 72 73 /** Print an entry. 74 * 75 * ls_print currently does nothing more than print the entry. 76 * In the future, we will likely pass the absolute path, and 77 * some sort of ls_options structure that controls how each 78 * entry is printed and what is printed about it. 79 * 80 * Now we just print basic DOS style lists. 81 * 82 * @param de Directory element. 83 */ 84 static void ls_print(struct dir_elem_t *de) 85 { 86 if (de->s.is_file) 87 printf("%-40s\t%llu\n", de->name, (long long) de->s.size); 88 else if (de->s.is_directory) 89 printf("%-40s\t<dir>\n", de->name); 90 else 91 printf("%-40s\n", de->name); 92 } 93 94 95 /** Compare 2 directory elements. 96 * 97 * It compares 2 elements of a directory : a file is considered 98 * as bigger than a directory, and if they have the same type, 99 * they are compared alphabetically. 100 * 101 * @param a Pointer to the structure of the first element. 102 * @param b Pointer to the structure of the second element. 103 * @param arg Pointer for an other and optionnal argument. 104 * 105 * @return -1 if a < b, 1 otherwise. 106 */ 107 static int ls_cmp(void *a, void *b, void *arg) 108 { 109 struct dir_elem_t *da = a; 110 struct dir_elem_t *db = b; 111 112 if ((da->s.is_directory && db->s.is_file) || 113 ((da->s.is_directory == db->s.is_directory) && 114 str_cmp(da->name, db->name) < 0)) 115 return -1; 116 else 117 return 1; 118 } 119 120 /** Scan a directory. 121 * 122 * Scan the content of a directory and print it. 123 * 124 * @param d Name of the directory. 125 * @param dirp Directory stream. 126 * @param sort 1 if the output must be sorted, 127 * 0 otherwise. 128 */ 129 static void ls_scan_dir(const char *d, DIR *dirp, int sort) 130 { 131 int alloc_blocks = 20; 132 int i; 133 int nbdirs = 0; 134 int rc; 135 int len; 136 char *buff; 137 struct dir_elem_t *tmp; 138 struct dir_elem_t *tosort; 55 139 struct dirent *dp; 56 char *buff; 57 58 if (! dirp) 140 141 if (!dirp) 59 142 return; 60 143 61 buff = (char *) malloc(PATH_MAX);62 if ( NULL ==buff) {144 buff = (char *) malloc(PATH_MAX); 145 if (!buff) { 63 146 cli_error(CL_ENOMEM, "ls: failed to scan %s", d); 64 147 return; 65 148 } 66 149 150 tosort = (struct dir_elem_t *) malloc(alloc_blocks * sizeof(*tosort)); 151 if (!tosort) { 152 cli_error(CL_ENOMEM, "ls: failed to scan %s", d); 153 free(buff); 154 return; 155 } 156 67 157 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 158 if (nbdirs + 1 > alloc_blocks) { 159 alloc_blocks += alloc_blocks; 160 161 tmp = (struct dir_elem_t *) realloc(tosort, 162 alloc_blocks * sizeof(struct dir_elem_t)); 163 if (!tmp) { 164 cli_error(CL_ENOMEM, "ls: failed to scan %s", d); 165 goto out; 166 } 167 tosort = tmp; 168 } 169 170 /* fill the name field */ 171 tosort[nbdirs].name = (char *) malloc(str_size(dp->d_name) + 1); 172 if (!tosort[nbdirs].name) { 173 cli_error(CL_ENOMEM, "ls: failed to scan %s", d); 174 goto out; 175 } 176 177 str_cpy(tosort[nbdirs].name, str_size(dp->d_name) + 1, dp->d_name); 178 len = snprintf(buff, PATH_MAX - 1, "%s/%s", d, tosort[nbdirs].name); 179 buff[len] = '\0'; 180 181 rc = stat(buff, &tosort[nbdirs++].s); 182 if (rc != 0) { 183 printf("ls: skipping bogus node %s\n", buff); 184 printf("rc=%d\n", rc); 185 goto out; 186 } 187 } 188 189 if (sort) { 190 if (!qsort(&tosort[0], nbdirs, sizeof(struct dir_elem_t), 191 ls_cmp, NULL)) { 192 printf("Sorting error.\n"); 193 } 194 } 195 196 for (i = 0; i < nbdirs; i++) 197 ls_print(&tosort[i]); 198 199 out: 200 for(i = 0; i < nbdirs; i++) 201 free(tosort[i].name); 202 free(tosort); 75 203 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, and82 * some sort of ls_options structure that controls how each83 * entry is printed and what is printed about it.84 *85 * Now we just print basic DOS style lists */86 87 static void ls_print(const char *name, const char *pathname)88 {89 struct stat s;90 int rc;91 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);97 return;98 }99 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 else105 printf("%-40s\n", name);106 107 return;108 204 } 109 205 … … 114 210 } else { 115 211 help_cmd_ls(HELP_SHORT); 116 printf(" `%s' [path], if no path is given the current " 117 "working directory is used.\n", cmdname); 212 printf( 213 "Usage: %s [options] [path]\n" 214 "If not path is given, the current working directory is used.\n" 215 "Options:\n" 216 " -h, --help A short option summary\n" 217 " -u, --unsort Do not sort directory entries\n", 218 cmdname); 118 219 } 119 220 … … 124 225 { 125 226 unsigned int argc; 126 struct stat s; 127 char *buff; 227 struct dir_elem_t de; 128 228 DIR *dirp; 229 int c, opt_ind; 230 int sort = 1; 129 231 130 232 argc = cli_count_args(argv); 131 132 buff = (char *) malloc(PATH_MAX); 133 if (NULL == buff) { 233 234 for (c = 0, optind = 0, opt_ind = 0; c != -1;) { 235 c = getopt_long(argc, argv, "hu", long_options, &opt_ind); 236 switch (c) { 237 case 'h': 238 help_cmd_ls(HELP_LONG); 239 return CMD_SUCCESS; 240 case 'u': 241 sort = 0; 242 break; 243 } 244 } 245 246 argc -= optind; 247 248 de.name = (char *) malloc(PATH_MAX); 249 if (!de.name) { 134 250 cli_error(CL_ENOMEM, "%s: ", cmdname); 135 251 return CMD_FAILURE; 136 252 } 137 memset( buff, 0, sizeof(buff));138 139 if (argc == 1)140 getcwd( buff, PATH_MAX);253 memset(de.name, 0, sizeof(PATH_MAX)); 254 255 if (argc == 0) 256 getcwd(de.name, PATH_MAX); 141 257 else 142 str_cpy( buff, PATH_MAX, argv[1]);143 144 if (stat( buff, &s)) {145 cli_error(CL_ENOENT, buff);146 free( buff);258 str_cpy(de.name, PATH_MAX, argv[optind]); 259 260 if (stat(de.name, &de.s)) { 261 cli_error(CL_ENOENT, de.name); 262 free(de.name); 147 263 return CMD_FAILURE; 148 264 } 149 265 150 if ( s.is_file) {151 ls_print( buff, buff);266 if (de.s.is_file) { 267 ls_print(&de); 152 268 } else { 153 dirp = opendir( buff);269 dirp = opendir(de.name); 154 270 if (!dirp) { 155 271 /* May have been deleted between scoping it and opening it */ 156 cli_error(CL_EFAIL, "Could not stat %s", buff);157 free( buff);272 cli_error(CL_EFAIL, "Could not stat %s", de.name); 273 free(de.name); 158 274 return CMD_FAILURE; 159 275 } 160 ls_scan_dir( buff, dirp);276 ls_scan_dir(de.name, dirp, sort); 161 277 closedir(dirp); 162 278 } 163 279 164 free( buff);280 free(de.name); 165 281 166 282 return CMD_SUCCESS;
Note:
See TracChangeset
for help on using the changeset viewer.