Changeset 81f70b4 in mainline for uspace/app/bdsh/cmds/modules/ls/ls.c


Ignore:
Timestamp:
2012-03-31T18:14:08Z (12 years ago)
Author:
Jan Vesely <jano.vesely@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
d5f99e6
Parents:
95c9158 (diff), 2f4fa79 (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Mainline changes and some usb fixes.

File:
1 edited

Legend:

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

    r95c9158 r81f70b4  
    4242#include <sort.h>
    4343
     44#include "ls.h"
    4445#include "errors.h"
    4546#include "config.h"
     
    4849#include "cmds.h"
    4950
    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 
    6551static const char *cmdname = "ls";
     52
     53static ls_job_t ls;
    6654
    6755static struct option const long_options[] = {
    6856        { "help", no_argument, 0, 'h' },
    6957        { "unsort", no_argument, 0, 'u' },
     58        { "recursive", no_argument, 0, 'r' },
    7059        { 0, 0, 0, 0 }
    7160};
     61
     62/* Prototypes for the ls command, excluding entry points. */
     63static unsigned int ls_start(ls_job_t *);
     64static void ls_print(struct dir_elem_t *);
     65static int ls_cmp(void *, void *, void *);
     66static signed int ls_scan_dir(const char *, DIR *, struct dir_elem_t **);
     67static unsigned int ls_recursive(const char *, DIR *);
     68static unsigned int ls_scope(const char *, struct dir_elem_t *);
     69
     70static unsigned int ls_start(ls_job_t *ls)
     71{
     72        ls->recursive = 0;
     73        ls->sort = 1;
     74
     75        return 1;
     76}
    7277
    7378/** Print an entry.
     
    9297}
    9398
    94 
    9599/** Compare 2 directory elements.
    96100 *
     
    127131 *                              0 otherwise.
    128132 */
    129 static void ls_scan_dir(const char *d, DIR *dirp, int sort)
     133static signed int ls_scan_dir(const char *d, DIR *dirp,
     134    struct dir_elem_t **dir_list_ptr)
    130135{
    131136        int alloc_blocks = 20;
     
    140145       
    141146        if (!dirp)
    142                 return;
     147                return -1;
    143148
    144149        buff = (char *) malloc(PATH_MAX);
    145150        if (!buff) {
    146151                cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
    147                 return;
     152                return -1;
    148153        }
    149154       
     
    152157                cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
    153158                free(buff);
    154                 return;
     159                return -1;
    155160        }
    156161       
     
    187192        }
    188193       
    189         if (sort) {
     194        if (ls.sort) {
    190195                if (!qsort(&tosort[0], nbdirs, sizeof(struct dir_elem_t),
    191196                    ls_cmp, NULL)) {
     
    196201        for (i = 0; i < nbdirs; i++)
    197202                ls_print(&tosort[i]);
     203
     204        /* Populate the directory list. */
     205        if (ls.recursive) {
     206                tmp = (struct dir_elem_t *) realloc(*dir_list_ptr,
     207                    nbdirs * sizeof(struct dir_elem_t));
     208                if (!tmp) {
     209                        cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
     210                        goto out;
     211                }
     212                *dir_list_ptr = tmp;
     213
     214                for (i = 0; i < nbdirs; i++) {
     215                        (*dir_list_ptr)[i].name = str_dup(tosort[i].name);
     216                        if (!(*dir_list_ptr)[i].name) {
     217                                cli_error(CL_ENOMEM, "ls: failed to scan %s", d);
     218                                goto out;
     219                        }
     220                }
     221        }
    198222       
    199223out:
     
    202226        free(tosort);
    203227        free(buff);
     228
     229        return nbdirs;
     230}
     231
     232/** Visit a directory recursively.
     233 *
     234 * ls_recursive visits all the subdirectories recursively and
     235 * prints the files and directories in them.
     236 *
     237 * @param path  Path the current directory being visited.
     238 * @param dirp  Directory stream.
     239 */
     240static unsigned int ls_recursive(const char *path, DIR *dirp)
     241{
     242        int i, nbdirs, ret;
     243        unsigned int scope;
     244        char *subdir_path;
     245        DIR *subdirp;
     246        struct dir_elem_t *dir_list;
     247       
     248        const char * const trailing_slash = "/";
     249
     250        nbdirs = 0;
     251        dir_list = (struct dir_elem_t *) malloc(sizeof(struct dir_elem_t));
     252
     253        printf("\n%s:\n", path);
     254
     255        subdir_path = (char *) malloc(PATH_MAX);
     256        if (!subdir_path) {
     257                ret = CMD_FAILURE;
     258                goto out;
     259        }
     260
     261        nbdirs = ls_scan_dir(path, dirp, &dir_list);
     262        if (nbdirs == -1) {
     263                ret = CMD_FAILURE;
     264                goto out;
     265        }
     266
     267        for (i = 0; i < nbdirs; ++i) {
     268                memset(subdir_path, 0, PATH_MAX);
     269
     270                if (str_size(subdir_path) + str_size(path) + 1 <= PATH_MAX)
     271                        str_append(subdir_path, PATH_MAX, path);
     272                if (path[str_size(path)-1] != '/' &&
     273                    str_size(subdir_path) + str_size(trailing_slash) + 1 <= PATH_MAX)
     274                        str_append(subdir_path, PATH_MAX, trailing_slash);
     275                if (str_size(subdir_path) +
     276                    str_size(dir_list[i].name) + 1 <= PATH_MAX)
     277                        str_append(subdir_path, PATH_MAX, dir_list[i].name);
     278
     279                scope = ls_scope(subdir_path, &dir_list[i]);
     280                switch (scope) {
     281                case LS_FILE:
     282                        break;
     283                case LS_DIR:
     284                        subdirp = opendir(subdir_path);
     285                        if (!subdirp) {
     286                                /* May have been deleted between scoping it and opening it */
     287                                cli_error(CL_EFAIL, "Could not stat %s", dir_list[i].name);
     288                                ret = CMD_FAILURE;
     289                                goto out;
     290                        }
     291
     292                        ret = ls_recursive(subdir_path, subdirp);
     293                        closedir(subdirp);
     294                        if (ret == CMD_FAILURE)
     295                                goto out;
     296                        break;
     297                case LS_BOGUS:
     298                        ret = CMD_FAILURE;
     299                        goto out;
     300                }       
     301        }
     302   
     303        ret = CMD_SUCCESS;
     304
     305out:
     306        for (i = 0; i < nbdirs; i++)
     307                free(dir_list[i].name);
     308        free(dir_list);
     309        free(subdir_path);
     310
     311        return ret;
     312}
     313
     314static unsigned int ls_scope(const char *path, struct dir_elem_t *de)
     315{
     316        if (stat(path, &de->s)) {
     317                cli_error(CL_ENOENT, path);
     318                return LS_BOGUS;
     319        }
     320
     321        if (de->s.is_file)
     322                return LS_FILE;
     323        else if (de->s.is_directory)
     324                return LS_DIR;
     325
     326        return LS_BOGUS;
    204327}
    205328
     
    215338                "Options:\n"
    216339                "  -h, --help       A short option summary\n"
    217                 "  -u, --unsort     Do not sort directory entries\n",
     340                "  -u, --unsort     Do not sort directory entries\n"
     341                "  -r, --recursive  List subdirectories recursively\n",
    218342                cmdname);
    219343        }
     
    228352        DIR *dirp;
    229353        int c, opt_ind;
    230         int sort = 1;
     354        int ret = 0;
     355        unsigned int scope;
     356
     357        if (!ls_start(&ls)) {
     358                cli_error(CL_EFAIL, "%s: Could not initialize", cmdname);
     359                return CMD_FAILURE;
     360        }
    231361
    232362        argc = cli_count_args(argv);
    233363       
    234364        for (c = 0, optind = 0, opt_ind = 0; c != -1;) {
    235                 c = getopt_long(argc, argv, "hu", long_options, &opt_ind);
     365                c = getopt_long(argc, argv, "hur", long_options, &opt_ind);
    236366                switch (c) {
    237367                case 'h':
     
    239369                        return CMD_SUCCESS;
    240370                case 'u':
    241                         sort = 0;
     371                        ls.sort = 0;
     372                        break;
     373                case 'r':
     374                        ls.recursive = 1;
    242375                        break;
    243376                }
     
    251384                return CMD_FAILURE;
    252385        }
    253         memset(de.name, 0, sizeof(PATH_MAX));
     386        memset(de.name, 0, PATH_MAX);
    254387       
    255388        if (argc == 0)
     
    257390        else
    258391                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);
    263                 return CMD_FAILURE;
    264         }
    265 
    266         if (de.s.is_file) {
     392
     393        scope = ls_scope(de.name, &de);
     394        switch (scope) {
     395        case LS_FILE:
    267396                ls_print(&de);
    268         } else {
     397                break;
     398        case LS_DIR:
    269399                dirp = opendir(de.name);
    270400                if (!dirp) {
     
    274404                        return CMD_FAILURE;
    275405                }
    276                 ls_scan_dir(de.name, dirp, sort);
     406                if (ls.recursive)
     407                        ret = ls_recursive(de.name, dirp);
     408                else 
     409                        ret = ls_scan_dir(de.name, dirp, NULL);
     410
    277411                closedir(dirp);
     412                break;
     413        case LS_BOGUS:
     414                return CMD_FAILURE;
    278415        }
    279416
    280417        free(de.name);
    281418
    282         return CMD_SUCCESS;
    283 }
    284 
     419        if (ret == -1 || ret == CMD_FAILURE)
     420                return CMD_FAILURE;
     421        else
     422                return CMD_SUCCESS;
     423}
     424
Note: See TracChangeset for help on using the changeset viewer.