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>