Ignore:
File:
1 edited

Legend:

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

    r59cce22 rc878693  
    4242#include <vfs/vfs.h>
    4343#include <str.h>
     44#include <cap.h>
    4445
    4546#include "ls.h"
     
    5859        { "unsort", no_argument, 0, 'u' },
    5960        { "recursive", no_argument, 0, 'r' },
     61        { "exact-size", no_argument, 0, 'e' },
     62        { "single-column", no_argument, 0, '1' },
    6063        { 0, 0, 0, 0 }
    6164};
     
    6366/* Prototypes for the ls command, excluding entry points. */
    6467static unsigned int ls_start(ls_job_t *);
    65 static void ls_print(struct dir_elem_t *);
    66 static int ls_cmp(const void *, const void *);
     68static errno_t ls_print(struct dir_elem_t *);
     69static errno_t ls_print_single_column(struct dir_elem_t *);
     70static int ls_cmp_type_name(const void *, const void *);
     71static int ls_cmp_name(const void *, const void *);
    6772static signed int ls_scan_dir(const char *, DIR *, struct dir_elem_t **);
    6873static unsigned int ls_recursive(const char *, DIR *);
     
    7479        ls->sort = 1;
    7580
     81        ls->exact_size = false;
     82        ls->single_column = false;
     83        ls->printer = ls_print;
    7684        return 1;
    7785}
     
    8896 * @param de            Directory element.
    8997 */
    90 static void ls_print(struct dir_elem_t *de)
    91 {
    92         if (de->s.is_file)
    93                 printf("%-40s\t%llu\n", de->name, (long long) de->s.size);
    94         else if (de->s.is_directory)
    95                 printf("%-40s\t<dir>\n", de->name);
     98static errno_t ls_print(struct dir_elem_t *de)
     99{
     100        int width = 13;
     101
     102        if (de->s.is_file) {
     103                if (ls.exact_size) {
     104                        printf("%-40s\t%*llu\n", de->name, width, (long long) de->s.size);
     105                        return EOK;
     106                }
     107
     108                cap_spec_t cap;
     109                cap_from_blocks(de->s.size, 1, &cap);
     110                cap_simplify(&cap);
     111
     112                char *rptr;
     113                errno_t rc = cap_format(&cap, &rptr);
     114                if (rc != EOK) {
     115                        return rc;
     116                }
     117
     118                char *sep = str_rchr(rptr, ' ');
     119                if (sep == NULL) {
     120                        free(rptr);
     121                        return ENOENT;
     122                }
     123
     124                *sep = '\0';
     125
     126                printf("%-40s\t%*s %2s\n", de->name, width - 3, rptr, sep + 1);
     127                free(rptr);
     128        } else if (de->s.is_directory)
     129                printf("%-40s\t%*s\n", de->name, width, "<dir>");
    96130        else
    97131                printf("%-40s\n", de->name);
     132
     133        return EOK;
     134}
     135
     136static errno_t ls_print_single_column(struct dir_elem_t *de)
     137{
     138        if (de->s.is_file) {
     139                printf("%s\n", de->name);
     140        } else {
     141                printf("%s/\n", de->name);
     142        }
     143
     144        return EOK;
    98145}
    99146
     
    109156 * @return              -1 if a < b, 1 otherwise.
    110157 */
    111 static int ls_cmp(const void *a, const void *b)
     158static int ls_cmp_type_name(const void *a, const void *b)
    112159{
    113160        struct dir_elem_t const *da = a;
     
    120167        else
    121168                return 1;
     169}
     170
     171/** Compare directories/files per name
     172 *
     173 * This comparision ignores the type of
     174 * the node. Sorted will strictly by name.
     175 *
     176 */
     177static int ls_cmp_name(const void *a, const void *b)
     178{
     179        struct dir_elem_t const *da = a;
     180        struct dir_elem_t const *db = b;
     181
     182        return str_cmp(da->name, db->name);
    122183}
    123184
     
    192253        }
    193254
    194         if (ls.sort)
    195                 qsort(&tosort[0], nbdirs, sizeof(struct dir_elem_t), ls_cmp);
    196 
    197         for (i = 0; i < nbdirs; i++)
    198                 ls_print(&tosort[i]);
     255        if (ls.sort) {
     256                int (*compar)(const void *, const void *);
     257                compar = ls.single_column ? ls_cmp_name : ls_cmp_type_name;
     258                qsort(&tosort[0], nbdirs, sizeof(struct dir_elem_t), compar);
     259        }
     260
     261        for (i = 0; i < nbdirs; i++) {
     262                if (ls.printer(&tosort[i]) != EOK) {
     263                        cli_error(CL_ENOMEM, "%s: Out of memory", cmdname);
     264                        goto out;
     265                }
     266        }
    199267
    200268        /* Populate the directory list. */
    201         if (ls.recursive && nbdirs > 0) {
     269        if (ls.recursive) {
    202270                tmp = (struct dir_elem_t *) realloc(*dir_list_ptr,
    203271                    nbdirs * sizeof(struct dir_elem_t));
     
    333401                    "If not path is given, the current working directory is used.\n"
    334402                    "Options:\n"
    335                     "  -h, --help       A short option summary\n"
    336                     "  -u, --unsort     Do not sort directory entries\n"
    337                     "  -r, --recursive  List subdirectories recursively\n",
     403                    "  -h, --help            A short option summary\n"
     404                    "  -u, --unsort          Do not sort directory entries\n"
     405                    "  -r, --recursive       List subdirectories recursively\n"
     406                    "  -e, --exact-size      File sizes will be unformatted (raw bytes count)\n"
     407                    "  -1, --single-column   Only the names will be returned\n",
    338408                    cmdname);
    339409        }
     
    364434
    365435        while (c != -1) {
    366                 c = getopt_long(argc, argv, "hur", long_options, &opt_ind);
     436                c = getopt_long(argc, argv, "hure1", long_options, &opt_ind);
    367437                switch (c) {
    368438                case 'h':
     
    375445                        ls.recursive = 1;
    376446                        break;
     447                case 'e':
     448                        ls.exact_size = true;
     449                        break;
     450                case '1':
     451                        ls.single_column = true;
     452                        ls.printer = ls_print_single_column;
     453                        break;
    377454                }
    378455        }
     
    400477        switch (scope) {
    401478        case LS_FILE:
    402                 ls_print(&de);
     479                if (ls.printer(&de) != EOK) {
     480                        cli_error(CL_ENOMEM, "%s: Out of memory", cmdname);
     481                        return CMD_FAILURE;
     482                }
    403483                break;
    404484        case LS_DIR:
Note: See TracChangeset for help on using the changeset viewer.