Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • uspace/app/bdsh/cmds/modules/ls/ls.c

    r1e2629f r19f857a  
    3838#include <dirent.h>
    3939#include <fcntl.h>
    40 #include <getopt.h>
    4140#include <sys/types.h>
    4241#include <sys/stat.h>
    4342#include <str.h>
    44 #include <sort.h>
    4543
    4644#include "errors.h"
     
    5351static const char *cmdname = "ls";
    5452
    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 };
     53static void ls_scan_dir(const char *d, DIR *dirp)
     54{
     55        struct dirent *dp;
     56        char *buff;
    6057
    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.
    73  */
    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;
    88 }
    89 
    90 /** Scan a directory.
    91  *
    92  * Scan the content of a directory and print it.
    93  *
    94  * @param d             Name of the directory.
    95  * @param dirp  Directory stream.
    96  * @param sort  1 if the output must be sorted,
    97  *                              0 otherwise.
    98  */
    99 static void ls_scan_dir(const char *d, DIR *dirp, int sort)
    100 {
    101         int alloc_blocks = 20;
    102         int i = 0;
    103         int nbdirs = 0;
    104         int rc = 0;
    105         char * buff = NULL;
    106         struct dir_elem_t * tmp = NULL;
    107         struct dir_elem_t * tosort = NULL;
    108         struct dirent * dp = NULL;
    109         struct stat s;
    110        
    11158        if (! dirp)
    11259                return;
     
    11764                return;
    11865        }
    119         memset(buff, 0, sizeof(buff));
    120        
    121         if (!sort) {
    122                 while ((dp = readdir(dirp))) {
    123                         memset(buff, 0, sizeof(buff));
    124                         /* Don't worry if inserting a double slash, this will be fixed by
    125                          * absolutize() later with subsequent calls to open() or readdir() */
    126                         snprintf(buff, PATH_MAX - 1, "%s/%s", d, dp->d_name);
    127                         ls_print(dp->d_name, buff);
    128                 }
    12966
    130                 free(buff);
    131 
    132                 return;
    133         }
    134        
    135         tosort = (struct dir_elem_t *)malloc(alloc_blocks*sizeof(struct dir_elem_t));
    136         if (NULL == tosort) {
    137                 cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
    138                 free(buff);
    139                 return;
    140         }
    141         memset(tosort, 0, sizeof(tosort));
    142        
    14367        while ((dp = readdir(dirp))) {
    144                 nbdirs++;
    145                
    146                 if (nbdirs > alloc_blocks) {
    147                         alloc_blocks += alloc_blocks;
    148                        
    149                         tmp = (struct dir_elem_t *)realloc(tosort,
    150                                         alloc_blocks*sizeof(struct dir_elem_t));
    151                         if (NULL == tmp) {
    152                                 cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
    153                                 for(i=0;i<(nbdirs-1);i++) {
    154                                         free(tosort[i].name);
    155                                 }
    156                                 free(tosort);
    157                                 free(buff);
    158                                 return;
    159                         }
    160                        
    161                         tosort = tmp;
    162                 }
    163                
    164                 // fill the name field
    165                 tosort[nbdirs-1].name = (char *)malloc(str_length(dp->d_name)+1);
    166                 if (NULL == tosort[nbdirs-1].name) {
    167                         cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
    168                         for(i=0;i<(nbdirs-1);i++) {
    169                                 free(tosort[i].name);
    170                         }
    171                         free(tosort);
    172                         free(buff);
    173                         return;
    174                 }
    175                
    176                 memset(tosort[nbdirs-1].name, 0, str_length(dp->d_name)+1);
    177                 str_cpy(tosort[nbdirs-1].name, str_length(dp->d_name)+1, dp->d_name);
    178                
    179                 // fill the isdir field
    180                 memset(buff, 0, sizeof(buff));
    181                 snprintf(buff, PATH_MAX - 1, "%s/%s", d, tosort[nbdirs-1].name);
    182                
    183                 rc = stat(buff, &s);
    184                 if (rc != 0) {
    185                         printf("ls: skipping bogus node %s\n", buff);
    186                         printf("rc=%d\n", rc);
    187                         for(i=0;i<nbdirs;i++) {
    188                                 free(tosort[i].name);
    189                         }
    190                         free(tosort);
    191                         free(buff);
    192                         return;
    193                 }
    194                
    195                 tosort[nbdirs-1].isdir = s.is_directory ? 1 : 0;
    196         }
    197        
    198         if (!qsort(&tosort[0], nbdirs, sizeof(struct dir_elem_t), ls_cmp, NULL)) {
    199                 printf("Sorting error.\n");
    200         }
    201        
    202         for(i=0;i<nbdirs;i++) {
    20368                memset(buff, 0, sizeof(buff));
    20469                /* Don't worry if inserting a double slash, this will be fixed by
    20570                 * absolutize() later with subsequent calls to open() or readdir() */
    206                 snprintf(buff, PATH_MAX - 1, "%s/%s", d, tosort[i].name);
    207                 ls_print(tosort[i].name, buff);
    208                 free(tosort[i].name);
     71                snprintf(buff, PATH_MAX - 1, "%s/%s", d, dp->d_name);
     72                ls_print(dp->d_name, buff);
    20973        }
    210        
    211         free(tosort);
     74
    21275        free(buff);
    21376
     
    21578}
    21679
    217 /** Print an entry.
    218  *
    219  * ls_print currently does nothing more than print the entry.
    220  * In the future, we will likely pass the absolute path, and
     80/* ls_print currently does nothing more than print the entry.
     81 * in the future, we will likely pass the absolute path, and
    22182 * some sort of ls_options structure that controls how each
    22283 * entry is printed and what is printed about it.
    22384 *
    224  * Now we just print basic DOS style lists.
    225  *
    226  * @param name          Name of the entry.
    227  * @param pathname      Path of the entry.
    228  */
     85 * Now we just print basic DOS style lists */
     86
    22987static void ls_print(const char *name, const char *pathname)
    23088{
     
    256114        } else {
    257115                help_cmd_ls(HELP_SHORT);
    258                 printf(
    259                 "Usage:  %s [options] [path]\n"
    260                 "If not path is given, the current working directory is used.\n"
    261                 "Options:\n"
    262                 "  -h, --help       A short option summary\n"
    263                 "  -u, --unsort     Do not sort directory entries\n",
    264                 cmdname);
     116                printf("  `%s' [path], if no path is given the current "
     117                                "working directory is used.\n", cmdname);
    265118        }
    266119
     
    274127        char *buff;
    275128        DIR *dirp;
    276         int c, opt_ind;
    277         int sort = 1;
    278129
    279130        argc = cli_count_args(argv);
    280        
    281         for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
    282                 c = getopt_long(argc, argv, "hu", long_options, &opt_ind);
    283                 switch (c) {
    284                 case 'h':
    285                         help_cmd_ls(HELP_LONG);
    286                         return CMD_SUCCESS;
    287                 case 'u':
    288                         sort = 0;
    289                         break;
    290                 }
    291         }
    292        
    293         int dir = (int)argc > optind ? (int)argc-1 : optind-1;
    294         argc -= (optind-1);
    295        
     131
    296132        buff = (char *) malloc(PATH_MAX);
    297133        if (NULL == buff) {
     
    300136        }
    301137        memset(buff, 0, sizeof(buff));
    302        
     138
    303139        if (argc == 1)
    304140                getcwd(buff, PATH_MAX);
    305141        else
    306                 str_cpy(buff, PATH_MAX, argv[dir]);
    307        
     142                str_cpy(buff, PATH_MAX, argv[1]);
     143
    308144        if (stat(buff, &s)) {
    309145                cli_error(CL_ENOENT, buff);
     
    322158                        return CMD_FAILURE;
    323159                }
    324                 ls_scan_dir(buff, dirp, sort);
     160                ls_scan_dir(buff, dirp);
    325161                closedir(dirp);
    326162        }
Note: See TracChangeset for help on using the changeset viewer.