From bc2f6842d1cda18be0e0a8fadd103cb3a717ab1c Mon Sep 17 00:00:00 2001 From: Jonas 'Sortie' Termansen Date: Sun, 27 Mar 2016 14:51:44 +0200 Subject: [PATCH] Add -type option to find(1). --- utils/find.c | 98 +++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 16 deletions(-) diff --git a/utils/find.c b/utils/find.c index 4fc9e38f..0a2c5ff9 100644 --- a/utils/find.c +++ b/utils/find.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2015 Jonas 'Sortie' Termansen. + * Copyright (c) 2013, 2015, 2016 Jonas 'Sortie' Termansen. * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -30,6 +30,17 @@ #include #include +#define TYPE_BLK (1 << 0) +#define TYPE_CHR (1 << 1) +#define TYPE_DIR (1 << 2) +#define TYPE_FIFO (1 << 3) +#define TYPE_LNK (1 << 4) +#define TYPE_REG (1 << 5) +#define TYPE_SOCK (1 << 6) +#define TYPE_OTHER (1 << 7) +#define ALL_TYPES (TYPE_BLK | TYPE_CHR | TYPE_DIR | TYPE_FIFO | \ + TYPE_LNK | TYPE_REG | TYPE_SOCK | TYPE_OTHER) + char* AddElemToPath(const char* path, const char* elem) { size_t pathlen = strlen(path); @@ -45,22 +56,42 @@ char* AddElemToPath(const char* path, const char* elem) return ret; } -static const int TYPE_FILE = 1 << 0; -static const int TYPE_DIR = 1 << 1; - -bool Find(int dirfd, const char* relpath, const char* path, int types) +bool find(int dirfd, const char* relpath, const char* path, int types) { bool ret = true; int fd = openat(dirfd, relpath, O_RDONLY | O_SYMLINK_NOFOLLOW); - if ( fd < 0 ) { error(0, errno, "%s", path); return false; } + if ( fd < 0 ) + { + error(0, errno, "%s", path); + return false; + } struct stat st; - if ( fstat(fd, &st) ) { error(0, errno, "stat: %s", path); return false; } - if ( S_ISDIR(st.st_mode) ) + if ( fstat(fd, &st) ) + { + error(0, errno, "stat: %s", path); + return false; + } + if ( S_ISBLK(st.st_mode) ) + { + if ( types & TYPE_BLK ) + printf("%s\n", path); + } + else if ( S_ISCHR(st.st_mode) ) + { + if ( types & TYPE_CHR ) + printf("%s\n", path); + } + else if ( S_ISDIR(st.st_mode) ) { if ( types & TYPE_DIR ) printf("%s\n", path); DIR* dir = fdopendir(fd); - if ( !dir ) { error(0, errno, "fdopendir"); close(fd); return false; } + if ( !dir ) + { + error(0, errno, "fdopendir"); + close(fd); + return false; + } struct dirent* entry; while ( (entry = readdir(dir)) ) { @@ -68,19 +99,42 @@ bool Find(int dirfd, const char* relpath, const char* path, int types) if ( !strcmp(name, ".") || !strcmp(name, "..") ) continue; char* newpath = AddElemToPath(path, name); - if ( !Find(fd, name, newpath, types) ) + if ( !find(fd, name, newpath, types) ) { ret = false; break; } } closedir(dir); + + } + else if ( S_ISFIFO(st.st_mode) ) + { + if ( types & TYPE_FIFO ) + printf("%s\n", path); + } + else if ( S_ISLNK(st.st_mode) ) + { + if ( types & TYPE_LNK ) + printf("%s\n", path); } else if ( S_ISREG(st.st_mode) ) { - if ( types & TYPE_FILE ) + if ( types & TYPE_REG ) printf("%s\n", path); } + else if ( S_ISSOCK(st.st_mode) ) + { + if ( types & TYPE_SOCK ) + printf("%s\n", path); + } + else + { + if ( types & TYPE_OTHER ) + printf("%s\n", path); + } + if ( !S_ISDIR(st.st_mode) ) + close(fd); return ret; } @@ -99,16 +153,28 @@ int main(int argc, char* argv[]) if ( path ) error(1, 0, "multiple paths are not supported"); path = arg; + continue; } - else if ( !strcmp(arg, "-type") ) + found_options = true; + if ( !strcmp(arg, "-type") ) { if ( i + 1 == argc ) error(1, 0, "-type expects an argument"); arg = argv[++i]; - if ( !strcmp(arg, "f") ) - types |= TYPE_FILE; + if ( !strcmp(arg, "b") ) + types |= TYPE_BLK; + else if ( !strcmp(arg, "c") ) + types |= TYPE_CHR; else if ( !strcmp(arg, "d") ) types |= TYPE_DIR; + else if ( !strcmp(arg, "f") ) + types |= TYPE_REG; + else if ( !strcmp(arg, "l") ) + types |= TYPE_LNK; + else if ( !strcmp(arg, "p") ) + types |= TYPE_FIFO; + else if ( !strcmp(arg, "S") ) + types |= TYPE_SOCK; else error(1, 0, "unknown `-type %s'", arg); } @@ -118,6 +184,6 @@ int main(int argc, char* argv[]) if ( !path ) path = "."; if ( !types ) - types = TYPE_FILE | TYPE_DIR; - return Find(AT_FDCWD, path, path, types) ? 0 : 1; + types = ALL_TYPES; + return find(AT_FDCWD, path, path, types) ? 0 : 1; }