Annotation of embedaddon/pimd/libite/tree.c, revision 1.1.1.1

1.1       misho       1: /* Simple /bin/tree replacement
                      2:  *
                      3:  * Copyright (c) 2015  Joachim Nilsson <troglobit@gmail.com>
                      4:  *
                      5:  * Permission to use, copy, modify, and/or distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17: 
                     18: #include <errno.h>
                     19: #include <dirent.h>
                     20: #include <stdio.h>
                     21: #include <stdlib.h>
                     22: #include <string.h>
                     23: #include <sys/types.h>
                     24: #include <sys/stat.h>
                     25: #include <unistd.h>
                     26: 
                     27: static int all = 0;
                     28: 
                     29: static int filter(const struct dirent *entry)
                     30: {
                     31:        /* Skip current dir ".", and prev dir "..", from list of files */
                     32:        if ((1 == strlen(entry->d_name) && entry->d_name[0] == '.') ||
                     33:            (2 == strlen(entry->d_name) && !strcmp(entry->d_name, "..")))
                     34:                return 0;
                     35: 
                     36:        if (!all && entry->d_name[0] == '.')
                     37:                return 0;
                     38:        
                     39:        return 1;
                     40: }
                     41: 
                     42: static void get_perms(struct stat *st, char *buf, size_t len)
                     43: {
                     44:        mode_t m = st->st_mode;
                     45: 
                     46:        snprintf(buf, len, "[%c%c%c%c%c%c%c%c%c%c] ",
                     47:                 S_ISCHR(m) ? 'c' : S_ISBLK(m) ? 'b' : S_ISFIFO(m) ? 'p' : S_ISLNK(m) ? 'l' : S_ISSOCK(m) ? 's' : '-',
                     48:                 (m & S_IRUSR) ? 'r' : '-',
                     49:                 (m & S_IWUSR) ? 'w' : '-',
                     50:                 (m & S_ISUID ) ? 's' : (m & S_IXUSR) ? 'x' : '-',
                     51:                 (m & S_IRGRP) ? 'r' : '-',
                     52:                 (m & S_IWGRP) ? 'w' : '-',
                     53:                 (m & S_ISGID) ? 's' : (m & S_IXGRP) ? 'x' : '-',
                     54:                 (m & S_IROTH) ? 'r' : '-',
                     55:                 (m & S_IWOTH) ? 'w' : '-',
                     56:                 (m & S_IXOTH) ? 'x' : '-'
                     57:                );
                     58: }
                     59: 
                     60: static int descend(char *path, int show_perms, char *pfx)
                     61: {
                     62:        int result = 0;
                     63:        struct stat st;
                     64: 
                     65:        if (-1 == lstat(path, &st))
                     66:                return 1;
                     67: 
                     68:        if ((st.st_mode & S_IFMT) == S_IFDIR) {
                     69:                int i, n;
                     70:                struct dirent **namelist = NULL;
                     71: 
                     72:                n = scandir(path, &namelist, filter, alphasort);
                     73:                if (n) {
                     74:                        for (i = 0; i < n; i++) {
                     75:                                char t = ' ', p[14] = "", s[256] = "";
                     76:                                char buf[256];
                     77:                                char dir[80];
                     78: 
                     79:                                if (i + 1 == n) {
                     80:                                        printf("%s `- ", pfx);
                     81:                                        snprintf(dir, sizeof(dir), "%s     ", pfx);
                     82:                                } else {
                     83:                                        printf("%s|-- ", pfx);
                     84:                                        snprintf(dir, sizeof(dir), "%s|    ", pfx);
                     85:                                }
                     86: 
                     87:                                snprintf(buf, sizeof(buf), "%s/%s", path, namelist[i]->d_name);
                     88:                                if (!lstat(buf, &st)) {
                     89:                                        if (show_perms)
                     90:                                                get_perms(&st, p, sizeof(p));
                     91:                                        if ((st.st_mode & S_IFMT) == S_IFDIR)
                     92:                                                t = '/';
                     93:                                        if (S_ISLNK(st.st_mode)) {
                     94:                                                snprintf(s, sizeof(s), "-> ");
                     95:                                                if (-1 == readlink(buf, &s[3], sizeof(s) - 3))
                     96:                                                        s[0] = 0;
                     97:                                        }
                     98:                                }
                     99: 
                    100:                                printf("%s%s%c%s\n", p, namelist[i]->d_name, t, s);
                    101:                                if (t == '/')
                    102:                                        result += descend(buf, show_perms, dir);
                    103: 
                    104:                                free(namelist[i]);
                    105:                        }
                    106: 
                    107:                        free(namelist);
                    108:                }
                    109:        } else {
                    110:                errno = ENOTDIR;
                    111:                result = -1;
                    112:        }
                    113: 
                    114:        return result;
                    115: }
                    116: 
                    117: int tree(char *path, int show_perms)
                    118: {
                    119:        printf("[%s]\n", path);
                    120:        return descend(path, show_perms, "");
                    121: }
                    122: 
                    123: #ifdef UNITTEST
                    124: #include "lite.h"
                    125: 
                    126: int main(void)
                    127: {
                    128:        int i, result = 0;
                    129:        struct { char *path; int fail; } arr[] = {
                    130:                { "/etc/passwd", -1 },
                    131:                { "/dev",         0 },
                    132:                { "/sbin",        0 },
                    133:        };
                    134: 
                    135:        for (i = 0; i < NELEMS(arr); i++) {
                    136:                if (tree(arr[i].path, 1) != arr[i].fail)
                    137:                        result++;
                    138:        }
                    139: 
                    140:        return result;
                    141: }
                    142: #endif
                    143: 
                    144: /**
                    145:  * Local Variables:
                    146:  *  compile-command: "make V=1 -f tree.mk"
                    147:  *  version-control: t
                    148:  *  indent-tabs-mode: t
                    149:  *  c-file-style: "linux"
                    150:  * End:
                    151:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>