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>