Changeset a30e435 in mainline


Ignore:
Timestamp:
2011-04-01T12:00:23Z (14 years ago)
Author:
Jakub Jermar <jakub@…>
Branches:
lfn, master, serial, ticket/834-toolchain-update, topic/msim-upgrade, topic/simplify-dev-export
Children:
ba63912
Parents:
73aec008 (diff), 1e2629f (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:

Merge 'ls' improvements from Jerome Portal.

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

Legend:

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

    r73aec008 ra30e435  
    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 * @param sort  1 if the output must be sorted,
     97 *                              0 otherwise.
     98 */
     99static 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       
    58111        if (! dirp)
    59112                return;
     
    64117                return;
    65118        }
    66 
     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                }
     129
     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       
    67143        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++) {
    68203                memset(buff, 0, sizeof(buff));
    69204                /* Don't worry if inserting a double slash, this will be fixed by
    70205                 * 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 
     206                snprintf(buff, PATH_MAX - 1, "%s/%s", d, tosort[i].name);
     207                ls_print(tosort[i].name, buff);
     208                free(tosort[i].name);
     209        }
     210       
     211        free(tosort);
    75212        free(buff);
    76213
     
    78215}
    79216
    80 /* ls_print currently does nothing more than print the entry.
    81  * in the future, we will likely pass the absolute path, and
     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
    82221 * some sort of ls_options structure that controls how each
    83222 * entry is printed and what is printed about it.
    84223 *
    85  * Now we just print basic DOS style lists */
    86 
     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 */
    87229static void ls_print(const char *name, const char *pathname)
    88230{
     
    114256        } else {
    115257                help_cmd_ls(HELP_SHORT);
    116                 printf("  `%s' [path], if no path is given the current "
    117                                 "working directory is used.\n", cmdname);
     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);
    118265        }
    119266
     
    127274        char *buff;
    128275        DIR *dirp;
     276        int c, opt_ind;
     277        int sort = 1;
    129278
    130279        argc = cli_count_args(argv);
    131 
     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       
    132296        buff = (char *) malloc(PATH_MAX);
    133297        if (NULL == buff) {
     
    136300        }
    137301        memset(buff, 0, sizeof(buff));
    138 
     302       
    139303        if (argc == 1)
    140304                getcwd(buff, PATH_MAX);
    141305        else
    142                 str_cpy(buff, PATH_MAX, argv[1]);
    143 
     306                str_cpy(buff, PATH_MAX, argv[dir]);
     307       
    144308        if (stat(buff, &s)) {
    145309                cli_error(CL_ENOENT, buff);
     
    158322                        return CMD_FAILURE;
    159323                }
    160                 ls_scan_dir(buff, dirp);
     324                ls_scan_dir(buff, dirp, sort);
    161325                closedir(dirp);
    162326        }
  • uspace/app/bdsh/cmds/modules/ls/ls.h

    r73aec008 ra30e435  
    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.