#include "fstool.h"
#include "util.h"
-#include "wrappers.h"
-#include "wrappers-dirent.h"
#include <lib/vserver.h>
#include <getopt.h>
#include <stdio.h>
#include <stdlib.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#define ENSC_WRAPPERS_DIRENT 1
+#define ENSC_WRAPPERS_FCNTL 1
+#define ENSC_WRAPPERS_UNISTD 1
+#include <wrappers.h>
struct Arguments const * global_args = 0;
inline static bool
isSpecialDir(char const *d)
{
- return (d[0]=='.' && (d[1]=='\0' || (d[1]=='.' && d[2]=='\0')));
+ return ( (d[0]=='.' && !global_args->do_display_dot) ||
+ (d[0]=='.' && (d[1]=='\0' || (d[1]=='.' && d[2]=='\0'))) );
}
#define CONCAT_PATHS(LHS, LHS_LEN, RHS) \
{
bool do_again = false;
size_t path_len = strlen(path);
- DIR * dir = Eopendir(".");
uint64_t err = 0;
+ struct stat cur_st;
+ DIR * dir = opendir(".");
- {
- struct stat st;
- if (lstat(".", &st)==-1) perror("lstat()");
- else err += handleFile(".", path, &st) ? 0 : 1;
+ if (dir==0) {
+ perror("opendir()");
+ return 1;
}
+ // show current directory entry first
+ if (lstat(".", &cur_st)==-1) perror("lstat()");
+ else err += handleFile(".", path, &cur_st) ? 0 : 1;
+
+ // strip trailing '/'
+ while (path_len>0 && path[path_len-1]=='/') --path_len;
+
+ // process regular files before directories
for (;;) {
struct dirent *ent = Ereaddir(dir);
struct stat st;
continue;
}
- if (!S_ISDIR(st.st_mode)) continue;
- safeChdir(ent->d_name, &st);
+ if (!S_ISDIR(st.st_mode) ||
+ (global_args->local_fs && st.st_dev!=cur_st.st_dev))
+ continue;
+
+ if (safeChdir(ent->d_name, &st)==-1) {
+ perror("chdir()");
+ ++err;
+ continue;
+ }
+
{
CONCAT_PATHS(path, path_len, ent->d_name);
err += iterateFilesystem(new_path);
return 1;
}
- if (S_ISDIR(st.st_mode) && !global_args->do_display_dir)
+ if (S_ISDIR(st.st_mode) && !global_args->do_display_dir) {
+ Echdir(path);
return iterateFilesystem(path);
+ }
else
return handleFile(path, path, &st);
}
.is_legacy = false,
.do_set = false,
.do_unset = false,
+ .local_fs = false,
+ .set_mask = 0,
+ .del_mask = 0
};
global_args = &args;
switch (c) {
case CMD_HELP : showHelp(1, argv[0], 0);
case CMD_VERSION : showVersion();
- case CMD_IMMUTABLE : args.immutable = true; break;
- case CMD_IMMULINK : args.immulink = true; break;
- case CMD_LEGACY : args.is_legacy = true; break;
+ case CMD_IMMU : args.set_mask |= VC_IATTR_IUNLINK; break;
+ case CMD_ADMIN : args.set_mask |= VC_IATTR_ADMIN; break;
+ case CMD_WATCH : args.set_mask |= VC_IATTR_WATCH; break;
+ case CMD_HIDE : args.set_mask |= VC_IATTR_HIDE; break;
+ case CMD_BARRIER : args.set_mask |= VC_IATTR_BARRIER; break;
+ case CMD_UNSET_IMMU : args.del_mask |= VC_IATTR_IUNLINK; break;
+ case CMD_UNSET_ADMIN : args.del_mask |= VC_IATTR_ADMIN; break;
+ case CMD_UNSET_WATCH : args.del_mask |= VC_IATTR_WATCH; break;
+ case CMD_UNSET_HIDE : args.del_mask |= VC_IATTR_HIDE; break;
+ case CMD_UNSET_BARRIER : args.del_mask |= VC_IATTR_BARRIER; break;
case 'R' : args.do_recurse = true; break;
case 'a' : args.do_display_dot = true; break;
case 'd' : args.do_display_dir = true; break;
case 's' : args.do_set = true; break;
case 'u' : args.do_unset = true; break;
case 'c' : args.ctx_str = optarg; break;
+ case 'x' : args.local_fs = true; break;
default :
WRITE_MSG(2, "Try '");
WRITE_STR(2, argv[0]);