mirror of
https://github.com/troglobit/libite.git
synced 2026-10-02 05:42:49 +07:00
New function: tree(), simple /bin/tree replacement.
Signed-off-by: Joachim Nilsson <troglobit@gmail.com>
This commit is contained in:
@@ -35,7 +35,7 @@ DISTFILES = README LICENSE
|
||||
HEADERS = lite.h
|
||||
OBJS := chomp.o copyfile.o dir.o fexist.o fisdir.o fmode.o fsendfile.o
|
||||
OBJS += ifconfig.o makepath.o pidfile.o pidfilefn.o rsync.o
|
||||
OBJS += strlcpy.o strlcat.o strtonum.o tempfile.o
|
||||
OBJS += strlcpy.o strlcat.o strtonum.o tempfile.o tree.o
|
||||
DEPS := $(OBJS:.o=.d)
|
||||
JUNK = *~ *.bak *.map .*.d *.d DEADJOE semantic.cache *.gdb *.elf core core.*
|
||||
|
||||
@@ -61,6 +61,7 @@ test: clean
|
||||
$(MAKE) -f pidfilefn.mk
|
||||
$(MAKE) -f rsync.mk
|
||||
$(MAKE) -f tempfile.mk
|
||||
$(MAKE) -f tree.mk
|
||||
|
||||
$(OBJS): Makefile
|
||||
|
||||
|
||||
@@ -182,7 +182,14 @@ Generic Functions
|
||||
|
||||
Secure replacement for `tmpfile()`. Creates an invisible temporary
|
||||
file in `/tmp` that is removed when the returned `FILE` pointer is
|
||||
closed. **Note:** Requires Linux v3.11, or later.
|
||||
closed.
|
||||
|
||||
**Note:** Requires Linux v3.11, or later, will fall back to the old
|
||||
and unsafe `tmpfile()` on older systems.
|
||||
|
||||
- `tree()`
|
||||
|
||||
Very simple `/bin/tree` replacement.
|
||||
|
||||
|
||||
OpenBSD Functions
|
||||
|
||||
@@ -69,6 +69,8 @@ size_t strlcat (char *dst, const char *src, size_t siz);
|
||||
long long strtonum (const char *numstr, long long minval, long long maxval, const char **errstrp);
|
||||
#endif
|
||||
|
||||
int tree(char *path, int show_perms);
|
||||
|
||||
#ifndef touch
|
||||
# define touch(x) do { if (mknod((x), S_IFREG|0644, 0) && errno != EEXIST) warn("Failed creating %s", x); } while (0)
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,154 @@
|
||||
/* Simple /bin/tree replacement
|
||||
*
|
||||
* Copyright (c) 2015 Joachim Nilsson <troglobit@gmail.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static int all = 0;
|
||||
|
||||
static int filter(const struct dirent *entry)
|
||||
{
|
||||
/* Skip current dir ".", and prev dir "..", from list of files */
|
||||
if ((1 == strlen(entry->d_name) && entry->d_name[0] == '.') ||
|
||||
(2 == strlen(entry->d_name) && !strcmp(entry->d_name, "..")))
|
||||
return 0;
|
||||
|
||||
if (!all && entry->d_name[0] == '.')
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void get_perms(struct stat *st, char *buf, size_t len)
|
||||
{
|
||||
mode_t m = st->st_mode;
|
||||
|
||||
// printf("%#o\n", m);
|
||||
snprintf(buf, len, "[%c%c%c%c%c%c%c%c%c%c] ",
|
||||
S_ISCHR(m) ? 'c' : S_ISBLK(m) ? 'b' : S_ISFIFO(m) ? 'p' : S_ISLNK(m) ? 'l' : S_ISSOCK(m) ? 's' : '-',
|
||||
(m & S_IRUSR) ? 'r' : '-',
|
||||
(m & S_IWUSR) ? 'w' : '-',
|
||||
(m & S_ISUID ) ? 's' : (m & S_IXUSR) ? 'x' : '-',
|
||||
(m & S_IRGRP) ? 'r' : '-',
|
||||
(m & S_IWGRP) ? 'w' : '-',
|
||||
(m & S_ISGID) ? 's' : (m & S_IXGRP) ? 'x' : '-',
|
||||
(m & S_IROTH) ? 'r' : '-',
|
||||
(m & S_IWOTH) ? 'w' : '-',
|
||||
(m & S_IXOTH) ? 'x' : '-'
|
||||
);
|
||||
}
|
||||
|
||||
static int descend(char *path, int perms, char *pfx)
|
||||
{
|
||||
int result = 0;
|
||||
struct stat st;
|
||||
|
||||
if (-1 == lstat(path, &st))
|
||||
return 1;
|
||||
|
||||
if ((st.st_mode & S_IFMT) == S_IFDIR) {
|
||||
int i, n;
|
||||
struct dirent **namelist = NULL;
|
||||
|
||||
n = scandir(path, &namelist, filter, alphasort);
|
||||
if (n) {
|
||||
for (i = 0; i < n; i++) {
|
||||
char t = ' ', p[14] = "", s[256] = "";
|
||||
char buf[256];
|
||||
char dir[80];
|
||||
|
||||
if (i + 1 == n) {
|
||||
printf("%s `- ", pfx);
|
||||
snprintf(dir, sizeof(dir), "%s ", pfx);
|
||||
} else {
|
||||
printf("%s|-- ", pfx);
|
||||
snprintf(dir, sizeof(dir), "%s| ", pfx);
|
||||
}
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s/%s", path, namelist[i]->d_name);
|
||||
if (!lstat(buf, &st)) {
|
||||
if (perms) {
|
||||
// printf("buf: %s --> ", buf);
|
||||
get_perms(&st, p, sizeof(p));
|
||||
}
|
||||
if ((st.st_mode & S_IFMT) == S_IFDIR)
|
||||
t = '/';
|
||||
if (S_ISLNK(st.st_mode)) {
|
||||
snprintf(s, sizeof(s), "-> ");
|
||||
if (-1 == readlink(buf, &s[3], sizeof(s) - 3))
|
||||
s[0] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s%s%c%s\n", p, namelist[i]->d_name, t, s);
|
||||
if (t == '/')
|
||||
result += descend(buf, perms, dir);
|
||||
|
||||
free(namelist[i]);
|
||||
}
|
||||
|
||||
free(namelist);
|
||||
}
|
||||
} else {
|
||||
errno = ENOTDIR;
|
||||
result = -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int tree(char *path, int show_perms)
|
||||
{
|
||||
printf("[%s]\n", path);
|
||||
return descend(path, show_perms, "");
|
||||
}
|
||||
|
||||
#ifdef UNITTEST
|
||||
#include "lite.h"
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i, result = 0;
|
||||
struct { char *path; int fail; } arr[] = {
|
||||
{ "/etc/passwd", -1 },
|
||||
{ "/dev", 0 },
|
||||
{ "/sbin", 0 },
|
||||
};
|
||||
|
||||
for (i = 0; i < NELEMS(arr); i++) {
|
||||
if (tree(arr[i].path, 1) != arr[i].fail)
|
||||
result++;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Local Variables:
|
||||
* compile-command: "make V=1 -f tree.mk"
|
||||
* version-control: t
|
||||
* indent-tabs-mode: t
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
Reference in New Issue
Block a user