Annotation of embedaddon/pimd/libite/tree.c, revision 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>