Changes in / [917a8c8:beb6b3d] in mainline


Ignore:
Location:
uspace/app/bdsh/cmds/modules/ls
Files:
2 edited

Legend:

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

    r917a8c8 rbeb6b3d  
    3838#include <dirent.h>
    3939#include <fcntl.h>
     40#include <getopt.h>
    4041#include <sys/types.h>
    4142#include <sys/stat.h>
    4243#include <str.h>
     44#include <sort.h>
    4345
    4446#include "errors.h"
     
    5153static const char *cmdname = "ls";
    5254
    53 static void ls_scan_dir(const char *d, DIR *dirp)
    54 {
    55         struct dirent *dp;
    56         char *buff;
    57 
     55static 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.
     73 */
     74static 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 */
     97static void ls_scan_dir(const char *d, DIR *dirp, int sort)
     98{
     99        int alloc_blocks = 20;
     100        int i = 0;
     101        int nbdirs = 0;
     102        int rc = 0;
     103        char * buff = NULL;
     104        struct dir_elem_t * tmp = NULL;
     105        struct dir_elem_t * tosort = NULL;
     106        struct dirent * dp = NULL;
     107        struct stat s;
     108       
    58109        if (! dirp)
    59110                return;
     
    64115                return;
    65116        }
    66 
     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));
     134        if (NULL == tosort) {
     135                cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
     136                free(buff);
     137                return;
     138        }
     139        memset(tosort, 0, sizeof(tosort));
     140       
    67141        while ((dp = readdir(dirp))) {
     142                nbdirs++;
     143               
     144                if (nbdirs > alloc_blocks) {
     145                        alloc_blocks += alloc_blocks;
     146                       
     147                        tmp = (struct dir_elem_t *)realloc(tosort,
     148                                        alloc_blocks*sizeof(struct dir_elem_t));
     149                        if (NULL == tmp) {
     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);
     156                                return;
     157                        }
     158                       
     159                        tosort = tmp;
     160                }
     161               
     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        }
     199       
     200        for(i=0;i<nbdirs;i++) {
    68201                memset(buff, 0, sizeof(buff));
    69202                /* Don't worry if inserting a double slash, this will be fixed by
    70203                 * 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 
     204                snprintf(buff, PATH_MAX - 1, "%s/%s", d, tosort[i].name);
     205                ls_print(tosort[i].name, buff);
     206                free(tosort[i].name);
     207        }
     208       
     209        free(tosort);
    75210        free(buff);
    76211
     
    78213}
    79214
    80 /* ls_print currently does nothing more than print the entry.
    81  * 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
    82219 * some sort of ls_options structure that controls how each
    83220 * entry is printed and what is printed about it.
    84221 *
    85  * Now we just print basic DOS style lists */
    86 
     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 */
    87227static void ls_print(const char *name, const char *pathname)
    88228{
     
    114254        } else {
    115255                help_cmd_ls(HELP_SHORT);
    116                 printf("  `%s' [path], if no path is given the current "
    117                                 "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);
    118263        }
    119264
     
    127272        char *buff;
    128273        DIR *dirp;
     274        int c, opt_ind;
     275        int sort = 1;
    129276
    130277        argc = cli_count_args(argv);
    131 
     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       
    132294        buff = (char *) malloc(PATH_MAX);
    133295        if (NULL == buff) {
     
    136298        }
    137299        memset(buff, 0, sizeof(buff));
    138 
     300       
    139301        if (argc == 1)
    140302                getcwd(buff, PATH_MAX);
    141303        else
    142                 str_cpy(buff, PATH_MAX, argv[1]);
    143 
     304                str_cpy(buff, PATH_MAX, argv[dir]);
     305       
    144306        if (stat(buff, &s)) {
    145307                cli_error(CL_ENOENT, buff);
     
    158320                        return CMD_FAILURE;
    159321                }
    160                 ls_scan_dir(buff, dirp);
     322                ls_scan_dir(buff, dirp, sort);
    161323                closedir(dirp);
    162324        }
  • uspace/app/bdsh/cmds/modules/ls/ls.h

    r917a8c8 rbeb6b3d  
    77#define LS_DIR   2
    88
    9 static void ls_scan_dir(const char *, DIR *);
     9static void ls_scan_dir(const char *, DIR *, int);
    1010static 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 */
     17struct dir_elem_t {
     18        char * name;
     19        int isdir;
     20};
    1121
    1222#endif /* LS_H */
Note: See TracChangeset for help on using the changeset viewer.