ncls: unify within lsContext #693

pull/1158/head
nick black 4 years ago committed by Nick Black
parent bc8905b30c
commit 5335e69b41

@ -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;
}

Loading…
Cancel
Save