diff --git a/src/ls/main.cpp b/src/ls/main.cpp index f83f6b0d1..d320ea001 100644 --- a/src/ls/main.cpp +++ b/src/ls/main.cpp @@ -18,13 +18,20 @@ usage(std::ostream& os, const char* name, int code){ exit(code); } +// context as configured on the command line +struct lsContext { + bool longlisting; + bool recursedirs; + bool directories; + bool dereflinks; +}; + static int -handle_path(const char* p, bool longlisting, bool recursedirs, - bool directories, bool dereflinks, bool toplevel); +handle_path(const char* p, const lsContext& ctx, bool toplevel); // handle a single inode of arbitrary type static int -handle_inode(const char* p, const struct stat* st, bool longlisting){ +handle_inode(const char* p, const struct stat* st, const lsContext& ctx){ std::cout << p << std::endl; // FIXME handle symlink (dereflinks) return 0; } @@ -33,12 +40,11 @@ handle_inode(const char* p, const struct stat* st, bool longlisting){ // 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); +handle_dir(const char* p, const struct stat* st, const lsContext& ctx, bool toplevel){ + if(ctx.directories){ + return handle_inode(p, st, ctx); } - if(!recursedirs && !toplevel){ + if(!ctx.recursedirs && !toplevel){ return 0; } DIR* dir = opendir(p); @@ -49,7 +55,7 @@ handle_dir(const char* p, const struct stat* st, bool longlisting, struct dirent* dent; int r = 0; while(errno = 0, (dent = readdir(dir))){ - r |= handle_path(dent->d_name, longlisting, recursedirs, directories, false, false); + r |= handle_path(dent->d_name, ctx, false); } if(errno){ std::cerr << "Error reading from " << p << ": " << strerror(errno) << std::endl; @@ -61,60 +67,65 @@ handle_dir(const char* p, const struct stat* st, bool longlisting, } static int -handle_deref(const char* p, const struct stat* st, bool longlisting, - bool recursedirs, bool directories){ +handle_deref(const char* p, const struct stat* st, const lsContext& ctx){ // FIXME dereference and rerun on target return 0; } +// handle some path, either absolute or relative to the current directory. +// toplevel is true iff the path was directly listed on the command line. +// recursedirs, directories, longlisting, and dereflinks are all based off +// command-line parameters. static int -handle_path(const char* p, bool longlisting, bool recursedirs, - bool directories, bool dereflinks, bool toplevel){ +handle_path(const char* p, const lsContext& ctx, bool toplevel){ 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_dir(p, &st, longlisting, recursedirs, directories, toplevel); + return handle_dir(p, &st, ctx, toplevel); }else if((st.st_mode & S_IFMT) == S_IFLNK){ - if(toplevel && dereflinks){ - return handle_deref(p, &st, longlisting, recursedirs, directories); + if(toplevel && ctx.dereflinks){ + return handle_deref(p, &st, ctx); } } - return handle_inode(p, &st, longlisting); + return handle_inode(p, &st, ctx); } +// these are our command line arguments. they're the only paths for which +// handle_path() gets toplevel == true. static int -list_paths(const char* const * argv, bool longlisting, bool recursedirs, - bool directories, bool dereflinks){ +list_paths(const char* const * argv, const lsContext& ctx){ int ret = 0; while(*argv){ - ret |= handle_path(*argv, longlisting, recursedirs, directories, dereflinks, true); + ret |= handle_path(*argv, ctx, true); ++argv; } return ret; } int main(int argc, char* const * argv){ - bool longlisting = false; - bool recursedirs = false; - bool directories = false; - bool dereflinks = false; + lsContext ctx = { + .longlisting = false, + .recursedirs = false, + .directories = false, + .dereflinks = false, + }; int c; while((c = getopt(argc, argv, "dhlLR")) != -1){ switch(c){ case 'd': - directories = true; + ctx.directories = true; break; case 'l': - longlisting = true; + ctx.longlisting = true; break; case 'L': - dereflinks = true; + ctx.dereflinks = true; break; case 'R': - recursedirs = true; + ctx.recursedirs = true; break; case 'h': usage(std::cout, argv[0], EXIT_SUCCESS); @@ -125,7 +136,6 @@ int main(int argc, char* const * argv){ } } static const char* const default_args[] = { ".", nullptr }; - list_paths(argv[optind] ? argv + optind : default_args, longlisting, - recursedirs, directories, dereflinks); + list_paths(argv[optind] ? argv + optind : default_args, ctx); return EXIT_SUCCESS; }