diff --git a/doc/man/man1/ncls.1.md b/doc/man/man1/ncls.1.md index a40cfc7fd..f0803d5bf 100644 --- a/doc/man/man1/ncls.1.md +++ b/doc/man/man1/ncls.1.md @@ -8,7 +8,7 @@ ncls - List paths with rendering of multimedia # SYNOPSIS -**ncls** [**-h**] [**-d**] [**-l**] [**-R**] [ paths ] +**ncls** [**-h**] [**-d**] [**-l**] [**-L**] [**-R**] [ paths ] # DESCRIPTION @@ -21,6 +21,8 @@ ncls - List paths with rendering of multimedia **-l**: use a long listing format. +**-L**: when showing file information for a symbolic link, show information for the file the link references rather than for the link itself. + **-R**: list subdirectories recursively. **-h**: Print help information, and exit with success. diff --git a/src/ls/main.cpp b/src/ls/main.cpp index 751d164d3..2d921d0ff 100644 --- a/src/ls/main.cpp +++ b/src/ls/main.cpp @@ -1,5 +1,7 @@ #include #include +#include +#include #include #include @@ -8,18 +10,77 @@ usage(std::ostream& os, const char* name, int code){ os << "usage: " << name << " -h | [ -lR ] paths...\n"; os << " -d: list directories themselves, not their contents\n"; os << " -l: use a long listing format\n"; + os << " -L: dereference symlink arguments\n"; os << " -R: list subdirectories recursively\n"; os << " -h: print usage information\n"; os << std::flush; exit(code); } -int main(int argc, char** argv){ +// handle a single inode of arbitrary type +static int +handle_inode(const char* p, const struct stat* st, bool longlisting){ + return 0; +} + +// if |directories| is true, only print details of |p|, and return. otherwise, +// if |recursedirs| or |toplevel| is set, we will recurse, passing false as +// toplevel (but preserving |recursedirs|). +static int +handle_dir(const char* p, const struct stat* st, bool longlisting, + bool recursedirs, bool directories, bool toplevel){ + if(directories){ + return handle_inode(p, st, longlisting); + } + std::cout << "DIRECTORY: " << p << std::endl; // FIXME handle directory (recursedirs, directories) + return 0; +} + +// handle a directory path *listed on the command line*. +static inline int +handle_cmdline_dir(const char* p, const struct stat* st, bool longlisting, + bool recursedirs, bool directories){ + return handle_dir(p, st, longlisting, recursedirs, directories, true); +} + +static int +handle_path(const char* p, bool longlisting, bool recursedirs, + bool directories, bool dereflinks){ + struct stat st; + if(stat(p, &st)){ + std::cerr << "Error running stat(" << p << "): " << strerror(errno) << std::endl; + return -1; + } + if((st.st_mode & S_IFMT) == S_IFDIR){ + return handle_cmdline_dir(p, &st, longlisting, recursedirs, directories); + }else if((st.st_mode & S_IFMT) == S_IFLNK){ + std::cout << p << std::endl; // FIXME handle symlink (dereflinks) + }else if((st.st_mode & S_IFMT) == S_IFREG){ + std::cout << p << std::endl; // FIXME handle normal file + }else{ + // FIXME handle weirdo + } + return 0; +} + +static int +list_paths(const char* const * argv, bool longlisting, bool recursedirs, + bool directories, bool dereflinks){ + int ret = 0; + while(*argv){ + ret |= handle_path(*argv, longlisting, recursedirs, directories, dereflinks); + ++argv; + } + return ret; +} + +int main(int argc, char* const * argv){ bool longlisting = false; bool recursedirs = false; bool directories = false; + bool dereflinks = false; int c; - while((c = getopt(argc, argv, "dhlR")) != -1){ + while((c = getopt(argc, argv, "dhlLR")) != -1){ switch(c){ case 'd': directories = true; @@ -27,6 +88,9 @@ int main(int argc, char** argv){ case 'l': longlisting = true; break; + case 'L': + dereflinks = true; + break; case 'R': recursedirs = true; break; @@ -38,10 +102,8 @@ int main(int argc, char** argv){ break; } } - // FIXME if argv[optind] == nullptr, pass "." - while(argv[optind]){ - std::cout << "arg: " << argv[optind] << std::endl; - ++optind; - } + static const char* const default_args[] = { ".", nullptr }; + list_paths(argv[optind] ? argv + optind : default_args, longlisting, + recursedirs, directories, dereflinks); return EXIT_SUCCESS; }