Changeset e3a3e3ad in mainline
- Timestamp:
- 2011-03-30T17:24:01Z (14 years ago)
- Branches:
- lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
- Children:
- beb6b3d
- Parents:
- 99b65d2
- Location:
- uspace/app/bdsh/cmds/modules/ls
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
uspace/app/bdsh/cmds/modules/ls/ls.c
r99b65d2 re3a3e3ad 38 38 #include <dirent.h> 39 39 #include <fcntl.h> 40 #include <getopt.h> 40 41 #include <sys/types.h> 41 42 #include <sys/stat.h> 42 43 #include <str.h> 44 #include <sort.h> 43 45 44 46 #include "errors.h" … … 51 53 static const char *cmdname = "ls"; 52 54 53 /** Sort array of files/directories 54 * 55 * Sort an array containing files and directories, 56 * in alphabetical order, with files first. 57 * 58 * @param d Current directory. 59 * @param tab Array of file/directories to sort. 60 * @param nbdirs Number of elements. 61 * 55 static struct option const long_options[] = { 56 { "help", no_argument, 0, 'h' }, 57 { "unsort", no_argument, 0, 'u' }, 58 { 0, 0, 0, 0 } 59 }; 60 61 /** Compare 2 directory elements. 62 * 63 * It compares 2 elements of a directory : a file is considered 64 * as lower than a directory, and if they have the same type, 65 * they are compared alphabetically. 66 * 67 * @param a Pointer to the structure of the first element. 68 * @param b Pointer to the structure of the second element. 69 * @param arg Pointer for an other and optionnal argument. 70 * 71 * @return -1 if a < b, 72 * 1 otherwise. 62 73 */ 63 static void ls_sort_dir(const char *d, char ** tab, int nbdirs) 64 { 65 int i = 0; 66 int j = 0; 67 int min = 0; 68 int rc; 69 char * buff1 = NULL; 70 char * buff2 = NULL; 71 char * tmp = NULL; 72 struct stat s1; 73 struct stat s2; 74 75 buff1 = (char *)malloc(PATH_MAX); 76 if (NULL == buff1) { 77 cli_error(CL_ENOMEM, "ls: failed to scan %s", d); 78 return; 79 } 80 81 buff2 = (char *)malloc(PATH_MAX); 82 if (NULL == buff2) { 83 cli_error(CL_ENOMEM, "ls: failed to scan %s", d); 84 return; 85 } 86 87 for(i=0;i<nbdirs;i++) { 88 min = i; 89 90 for(j=i;j<nbdirs;j++) { 91 memset(buff1, 0, sizeof(buff1)); 92 memset(buff2, 0, sizeof(buff2)); 93 snprintf(buff1, PATH_MAX - 1, "%s/%s", d, tab[min]); 94 snprintf(buff2, PATH_MAX - 1, "%s/%s", d, tab[j]); 95 96 rc = stat(buff1, &s1); 97 if (rc != 0) { 98 printf("ls: skipping bogus node %s\n", buff1); 99 printf("rc=%d\n", rc); 100 return; 101 } 102 103 rc = stat(buff2, &s2); 104 if (rc != 0) { 105 printf("ls: skipping bogus node %s\n", buff2); 106 printf("rc=%d\n", rc); 107 return; 108 } 109 110 if ((s2.is_file && s1.is_directory) 111 || (((s2.is_file && s1.is_file) 112 || (s2.is_directory && s1.is_directory)) 113 && str_cmp(tab[min], tab[j]) > 0)) 114 min = j; 115 } 116 117 tmp = tab[i]; 118 tab[i] = tab[min]; 119 tab[min] = tmp; 120 } 121 122 free(buff1); 123 free(buff2); 124 125 return; 74 static int ls_cmp(void *a, void *b, void *arg) 75 { 76 int a_isdir = (*((struct dir_elem_t *)a)).isdir; 77 char * a_name = (*((struct dir_elem_t *)a)).name; 78 79 int b_isdir = (*((struct dir_elem_t *)b)).isdir; 80 char * b_name = (*((struct dir_elem_t *)b)).name; 81 82 if ((!a_isdir && b_isdir) 83 || (((!b_isdir && !a_isdir) || (b_isdir && a_isdir)) 84 && str_cmp(a_name, b_name) < 0)) 85 return -1; 86 else 87 return 1; 126 88 } 127 89 … … 132 94 * @param d Name of the directory. 133 95 * @param dirp Directory stream. 134 *135 96 */ 136 static void ls_scan_dir(const char *d, DIR *dirp )97 static void ls_scan_dir(const char *d, DIR *dirp, int sort) 137 98 { 138 99 int alloc_blocks = 20; 139 100 int i = 0; 140 101 int nbdirs = 0; 102 int rc = 0; 141 103 char * buff = NULL; 142 char ** tmp = NULL;143 char ** tosort = NULL;104 struct dir_elem_t * tmp = NULL; 105 struct dir_elem_t * tosort = NULL; 144 106 struct dirent * dp = NULL; 145 107 struct stat s; 108 146 109 if (! dirp) 147 110 return; … … 152 115 return; 153 116 } 154 155 tosort = (char **)malloc(alloc_blocks*sizeof(char *)); 117 memset(buff, 0, sizeof(buff)); 118 119 if (!sort) { 120 while ((dp = readdir(dirp))) { 121 memset(buff, 0, sizeof(buff)); 122 /* Don't worry if inserting a double slash, this will be fixed by 123 * absolutize() later with subsequent calls to open() or readdir() */ 124 snprintf(buff, PATH_MAX - 1, "%s/%s", d, dp->d_name); 125 ls_print(dp->d_name, buff); 126 } 127 128 free(buff); 129 130 return; 131 } 132 133 tosort = (struct dir_elem_t *)malloc(alloc_blocks*sizeof(struct dir_elem_t)); 156 134 if (NULL == tosort) { 157 135 cli_error(CL_ENOMEM, "ls: failed to scan %s", d); 136 free(buff); 158 137 return; 159 138 } … … 166 145 alloc_blocks += alloc_blocks; 167 146 168 tmp = (char **)realloc(tosort, (alloc_blocks)*sizeof(char *)); 147 tmp = (struct dir_elem_t *)realloc(tosort, 148 alloc_blocks*sizeof(struct dir_elem_t)); 169 149 if (NULL == tmp) { 170 150 cli_error(CL_ENOMEM, "ls: failed to scan %s", d); 151 for(i=0;i<(nbdirs-1);i++) { 152 free(tosort[i].name); 153 } 154 free(tosort); 155 free(buff); 171 156 return; 172 157 } … … 175 160 } 176 161 177 tosort[nbdirs-1] = (char *)malloc(str_length(dp->d_name)+1); 178 if (NULL == tosort[nbdirs-1]) { 179 cli_error(CL_ENOMEM, "ls: failed to scan %s", d); 180 return; 181 } 182 memset(tosort[nbdirs-1], 0, str_length(dp->d_name)+1); 183 184 str_cpy(tosort[nbdirs-1], str_length(dp->d_name)+1, dp->d_name); 185 } 186 187 ls_sort_dir(d, tosort, nbdirs); 162 // fill the name field 163 tosort[nbdirs-1].name = (char *)malloc(str_length(dp->d_name)+1); 164 if (NULL == tosort[nbdirs-1].name) { 165 cli_error(CL_ENOMEM, "ls: failed to scan %s", d); 166 for(i=0;i<(nbdirs-1);i++) { 167 free(tosort[i].name); 168 } 169 free(tosort); 170 free(buff); 171 return; 172 } 173 174 memset(tosort[nbdirs-1].name, 0, str_length(dp->d_name)+1); 175 str_cpy(tosort[nbdirs-1].name, str_length(dp->d_name)+1, dp->d_name); 176 177 // fill the isdir field 178 memset(buff, 0, sizeof(buff)); 179 snprintf(buff, PATH_MAX - 1, "%s/%s", d, tosort[nbdirs-1].name); 180 181 rc = stat(buff, &s); 182 if (rc != 0) { 183 printf("ls: skipping bogus node %s\n", buff); 184 printf("rc=%d\n", rc); 185 for(i=0;i<nbdirs;i++) { 186 free(tosort[i].name); 187 } 188 free(tosort); 189 free(buff); 190 return; 191 } 192 193 tosort[nbdirs-1].isdir = s.is_directory ? 1 : 0; 194 } 195 196 if (!qsort(&tosort[0], nbdirs, sizeof(struct dir_elem_t), ls_cmp, NULL)) { 197 printf("Sorting error.\n"); 198 } 188 199 189 200 for(i=0;i<nbdirs;i++) { … … 191 202 /* Don't worry if inserting a double slash, this will be fixed by 192 203 * absolutize() later with subsequent calls to open() or readdir() */ 193 snprintf(buff, PATH_MAX - 1, "%s/%s", d, tosort[i] );194 ls_print(tosort[i] , buff);195 free(tosort[i] );204 snprintf(buff, PATH_MAX - 1, "%s/%s", d, tosort[i].name); 205 ls_print(tosort[i].name, buff); 206 free(tosort[i].name); 196 207 } 197 208 … … 202 213 } 203 214 204 /* ls_print currently does nothing more than print the entry. 205 * in the future, we will likely pass the absolute path, and 215 /** Print an entry. 216 * 217 * ls_print currently does nothing more than print the entry. 218 * In the future, we will likely pass the absolute path, and 206 219 * some sort of ls_options structure that controls how each 207 220 * entry is printed and what is printed about it. 208 221 * 209 * Now we just print basic DOS style lists */ 210 222 * Now we just print basic DOS style lists. 223 * 224 * @param name Name of the entry. 225 * @param pathname Path of the entry. 226 */ 211 227 static void ls_print(const char *name, const char *pathname) 212 228 { … … 238 254 } else { 239 255 help_cmd_ls(HELP_SHORT); 240 printf(" `%s' [path], if no path is given the current " 241 "working directory is used.\n", cmdname); 256 printf( 257 "Usage: %s [options] [path]\n" 258 "If not path is given, the current working directory is used.\n" 259 "Options:\n" 260 " -h, --help A short option summary\n" 261 " -u, --unsort Do not sort directory entries\n", 262 cmdname); 242 263 } 243 264 … … 251 272 char *buff; 252 273 DIR *dirp; 274 int c, opt_ind; 275 int sort = 1; 253 276 254 277 argc = cli_count_args(argv); 255 278 279 for (c = 0, optind = 0, opt_ind = 0; c != -1;) { 280 c = getopt_long(argc, argv, "hu", long_options, &opt_ind); 281 switch (c) { 282 case 'h': 283 help_cmd_ls(HELP_LONG); 284 return CMD_SUCCESS; 285 case 'u': 286 sort = 0; 287 break; 288 } 289 } 290 291 int dir = (int)argc > optind ? (int)argc-1 : optind-1; 292 argc -= (optind-1); 293 256 294 buff = (char *) malloc(PATH_MAX); 257 295 if (NULL == buff) { … … 260 298 } 261 299 memset(buff, 0, sizeof(buff)); 262 300 263 301 if (argc == 1) 264 302 getcwd(buff, PATH_MAX); 265 303 else 266 str_cpy(buff, PATH_MAX, argv[ 1]);267 304 str_cpy(buff, PATH_MAX, argv[dir]); 305 268 306 if (stat(buff, &s)) { 269 307 cli_error(CL_ENOENT, buff); … … 282 320 return CMD_FAILURE; 283 321 } 284 ls_scan_dir(buff, dirp );322 ls_scan_dir(buff, dirp, sort); 285 323 closedir(dirp); 286 324 } -
uspace/app/bdsh/cmds/modules/ls/ls.h
r99b65d2 re3a3e3ad 7 7 #define LS_DIR 2 8 8 9 static void ls_sort_dir(const char *, char **, int); 10 static void ls_scan_dir(const char *, DIR *); 9 static void ls_scan_dir(const char *, DIR *, int); 11 10 static void ls_print(const char *, const char *); 11 12 /** Structure to represent a directory entry. 13 * 14 * Useful to keep together important informations 15 * for sorting directory entries. 16 */ 17 struct dir_elem_t { 18 char * name; 19 int isdir; 20 }; 12 21 13 22 #endif /* LS_H */
Note:
See TracChangeset
for help on using the changeset viewer.