source: bootcd/isolinux/syslinux-6.03/com32/modules/dir.c @ dd1be7c

Last change on this file since dd1be7c was e16e8f2, checked in by Edwin Eefting <edwin@datux.nl>, 3 years ago

bootstuff

  • Property mode set to 100644
File size: 3.2 KB
Line 
1/*
2 * Display directory contents
3 */
4#include <stdlib.h>
5#include <stdio.h>
6#include <console.h>
7#include <string.h>
8#include <com32.h>
9#include <dirent.h>
10#include <minmax.h>
11#include <unistd.h>
12#include <getkey.h>
13
14static int rows, cols;          /* Screen parameters */
15
16#define DIR_CHUNK       1024
17
18static const char *type_str(int type)
19{
20    switch (type) {
21    case DT_FIFO:
22        return "[fif]";
23    case DT_CHR:
24        return "[chr]";
25    case DT_DIR:
26        return "[dir]";
27    case DT_BLK:
28        return "[blk]";
29    case DT_UNKNOWN:
30    case DT_REG:
31        return "";
32    case DT_LNK:
33        return "[lnk]";
34    case DT_SOCK:
35        return "[sck]";
36    case DT_WHT:
37        return "[wht]";
38    default:
39        return "[???]";
40    }
41}
42
43static void free_dirents(struct dirent **dex, size_t n_de)
44{
45    size_t i;
46
47    for (i = 0; i < n_de; i++)
48        free(dex[i]);
49
50    free(dex);
51}
52
53static int compare_dirent(const void *p_de1, const void *p_de2)
54{
55    const struct dirent *de1 = *(const struct dirent **)p_de1;
56    const struct dirent *de2 = *(const struct dirent **)p_de2;
57    int ndir1, ndir2;
58
59    ndir1 = de1->d_type != DT_DIR;
60    ndir2 = de2->d_type != DT_DIR;
61
62    if (ndir1 != ndir2)
63        return ndir1 - ndir2;
64
65    return strcmp(de1->d_name, de2->d_name);
66}
67
68static int display_directory(const char *dirname)
69{
70    DIR *dir;
71    struct dirent *de;
72    struct dirent **dex = NULL;
73    size_t n_dex = 0, n_de = 0;
74    size_t i, j, k;
75    size_t nrows, ncols, perpage;
76    size_t endpage;
77    int maxlen = 0;
78    int pos, tpos, colwidth;
79
80    dir = opendir(dirname);
81    if (!dir) {
82        printf("Unable to read directory: %s\n", dirname);
83        return -1;
84    }
85
86    while ((de = readdir(dir)) != NULL) {
87        struct dirent *nde;
88
89        if (n_de >= n_dex) {
90            struct dirent **ndex;
91
92            ndex = realloc(dex, (n_dex + DIR_CHUNK) * sizeof *dex);
93            if (!ndex)
94                goto nomem;
95
96            dex = ndex;
97            n_dex += DIR_CHUNK;
98        }
99
100        nde = malloc(de->d_reclen);
101        if (!nde)
102            goto nomem;
103
104        memcpy(nde, de, de->d_reclen);
105        dex[n_de++] = nde;
106
107        maxlen = max(maxlen, de->d_reclen);
108    }
109
110    closedir(dir);
111
112    qsort(dex, n_de, sizeof *dex, compare_dirent);
113
114    maxlen -= offsetof(struct dirent, d_name) + 1;
115    ncols = (cols + 2)/(maxlen + 8);
116    ncols = min(ncols, n_de);
117    ncols = max(ncols, 1U);
118    colwidth = (cols + 2)/ncols;
119    perpage = ncols * (rows - 1);
120
121    for (i = 0; i < n_de; i += perpage) {
122        /* Rows on this page */
123        endpage = min(i+perpage, n_de);
124        nrows = ((endpage-i) + ncols - 1)/ncols;
125
126        for (j = 0; j < nrows; j++) {
127            pos = tpos = 0;
128            for (k = i+j; k < endpage; k += nrows) {
129                pos += printf("%*s%-5s %s",
130                              (tpos - pos), "",
131                              type_str(dex[k]->d_type),
132                              dex[k]->d_name);
133                tpos += colwidth;
134            }
135            printf("\n");
136        }
137
138        if (endpage >= n_de)
139            break;
140
141        get_key(stdin, 0);
142    }
143
144    free_dirents(dex, n_de);
145    return 0;
146
147nomem:
148    closedir(dir);
149    printf("Out of memory error!\n");
150    free_dirents(dex, n_de);
151    return -1;
152}
153
154int main(int argc, char *argv[])
155{
156    int rv;
157
158    if (getscreensize(1, &rows, &cols)) {
159        /* Unknown screen size? */
160        rows = 24;
161        cols = 80;
162    }
163
164    if (argc < 2)
165        rv = display_directory(".");
166    else if (argc == 2)
167        rv = display_directory(argv[1]);
168    else {
169        printf("Usage: dir directory\n");
170        rv = 1;
171    }
172
173    return rv ? 1 : 0;
174}
175 
Note: See TracBrowser for help on using the repository browser.