fi
}
+setup_56_special() {
+ LOCAL_NUMFILES=$1
+ LOCAL_NUMDIRS=$2
+ TDIR=$DIR/${tdir}g
+ setup_56 $1 $2
+ if [ ! -e "$TDIR/loop1b" ] ; then
+ for i in `seq 1 $LOCAL_NUMFILES` ; do
+ mknod $TDIR/loop${i}b b 7 $i
+ mknod $TDIR/null${i}c c 1 3
+ ln -s $TDIR/file0 $TDIR/link${i}l
+ done
+ for i in `seq 1 $LOCAL_NUMDIRS` ; do
+ mknod $TDIR/dir$i/loop${i}b b 7 $i
+ mknod $TDIR/dir$i/null${i}c c 1 3
+ ln -s $TDIR/dir$i/file0 $TDIR/dir$i/link${i}l
+ done
+ fi
+}
+
test_56g() {
$LSTRIPE -d $DIR
}
run_test 56i "check 'lfs find -ost UUID' skips directories ======="
+test_56j() {
+ setup_56_special $NUMFILES $NUMDIRS
+
+ EXPECTED=$((NUMDIRS+1))
+ NUMS=`$LFIND -type d $DIR/${tdir}g | wc -l`
+ [ $NUMS -eq $EXPECTED ] || \
+ error "lfs find -type d $DIR/${tdir}g wrong: found $NUMS, expected $EXPECTED"
+}
+run_test 56j "check lfs find -type d ============================="
+
+test_56k() {
+ setup_56_special $NUMFILES $NUMDIRS
+
+ EXPECTED=$(((NUMDIRS+1) * NUMFILES))
+ NUMS=`$LFIND -type f $DIR/${tdir}g | wc -l`
+ [ $NUMS -eq $EXPECTED ] || \
+ error "lfs find -type f $DIR/${tdir}g wrong: found $NUMS, expected $EXPECTED"
+}
+run_test 56k "check lfs find -type f ============================="
+
+test_56l() {
+ setup_56_special $NUMFILES $NUMDIRS
+
+ EXPECTED=$((NUMDIRS + NUMFILES))
+ NUMS=`$LFIND -type b $DIR/${tdir}g | wc -l`
+ [ $NUMS -eq $EXPECTED ] || \
+ error "lfs find -type b $DIR/${tdir}g wrong: found $NUMS, expected $EXPECTED"
+}
+run_test 56l "check lfs find -type b ============================="
+
+test_56m() {
+ setup_56_special $NUMFILES $NUMDIRS
+
+ EXPECTED=$((NUMDIRS + NUMFILES))
+ NUMS=`$LFIND -type c $DIR/${tdir}g | wc -l`
+ [ $NUMS -eq $EXPECTED ] || \
+ error "lfs find -type c $DIR/${tdir}g wrong: found $NUMS, expected $EXPECTED"
+}
+run_test 56m "check lfs find -type c ============================="
+
+test_56n() {
+ setup_56_special $NUMFILES $NUMDIRS
+
+ EXPECTED=$((NUMDIRS + NUMFILES))
+ NUMS=`$LFIND -type l $DIR/${tdir}g | wc -l`
+ [ $NUMS -eq $EXPECTED ] || \
+ error "lfs find -type l $DIR/${tdir}g wrong: found $NUMS, expected $EXPECTED"
+}
+run_test 56n "check lfs find -type l ============================="
+
test_57a() {
remote_mds && skip "remote MDS" && return
{"find", lfs_find, 0,
"To find files that match given parameters recursively in a directory tree.\n"
"usage: find <dir/file> ... \n"
- " [[!] --atime|-A N] [[!] --mtime|-M N] [[!] --ctime|-C N] [--maxdepth|-D N]\n"
- " [[!] --name|-n <pattern>] [--print0|-P] [--print|-p] [--obd|-O <uuid>]\n"
- "\t !: used before --atime, --mtime, --ctime specifies the negative value\n"
- "\t !: used before --name means find exclude the regular expression pattern\n"
- "If one of the options below is provided, find works the same as 'getstripe':\n"
- "To list the striping info for a given filename or files in a directory or\n"
- "recursively.\n"
- "OBSOLETE usage: find [--quiet | -q] [--verbose | -v]\n"
- " [--recursive | -r] <dir|file> ..."},
+ " [[!] --atime|-A [+-]N] [[!] --mtime|-M [+-]N] [[!] --ctime|-C [+-]N]\n"
+ " [--maxdepth|-D N] [[!] --name|-n <pattern>] [--print0|-P]\n"
+ " [--print|-p] [--obd|-O <uuid>] [[!] --type|-t <filetype>]\n"
+ "\t !: used before an option indicates 'NOT' the requested attribute\n"
+ "\t -: used before an value indicates 'AT MOST' the requested value\n"
+ "\t +: used before an option indicates 'AT LEAST' the requested value\n"},
{"check", lfs_check, 0,
"Display the status of MDS or OSTs (as specified in the command)\n"
"or all the servers (MDS and OSTs).\n"
/* Old find options. */
{"quiet", no_argument, 0, 'q'},
{"recursive", no_argument, 0, 'r'},
+ {"type", required_argument, 0, 't'},
{"verbose", no_argument, 0, 'v'},
{0, 0, 0, 0}
};
time(&t);
- while ((c = getopt_long_only(argc, argv, "-A:C:D:M:n:PpO:qrv",
+ while ((c = getopt_long_only(argc, argv, "-A:C:D:M:n:PpO:qrt:v",
long_opts, NULL)) >= 0) {
xtime = NULL;
xsign = NULL;
*xsign = ret;
break;
case 'D':
+ new_fashion = 1;
param.maxdepth = strtol(optarg, 0, 0);
break;
case 'n':
new_fashion = 1;
param.pattern = (char *)optarg;
- if (neg_opt)
- param.exclude_pattern = 1;
- else
- param.exclude_pattern = 0;
+ param.exclude_pattern = !!neg_opt;
break;
case 'O':
if (param.obduuid) {
param.obduuid = (struct obd_uuid *)optarg;
break;
case 'p':
+ new_fashion = 1;
param.zeroend = 1;
break;
case 'P':
new_fashion = 0;
param.recursive = 1;
break;
+ case 't':
+ param.exclude_type = !!neg_opt;
+ switch(optarg[0]) {
+ case 'b': param.type = S_IFBLK; break;
+ case 'c': param.type = S_IFCHR; break;
+ case 'd': param.type = S_IFDIR; break;
+ case 'f': param.type = S_IFREG; break;
+ case 'l': param.type = S_IFLNK; break;
+ case 'p': param.type = S_IFIFO; break;
+ case 's': param.type = S_IFSOCK; break;
+#ifdef S_IFDOOR /* Solaris only */
+ case 'D': param.type = S_IFDOOR; break;
+#endif
+ default: fprintf(stderr, "error: %s: bad type '%s'\n",
+ argv[0], optarg);
+ return CMD_HELP;
+ };
+ break;
case 'v':
new_fashion = 0;
param.verbose++;
if (new_fashion) {
param.quiet = 1;
} else {
+ static int deprecated_warning;
+ if (!deprecated_warning) {
+ fprintf(stderr, "lfs find: -q, -r, -v options "
+ "deprecated. Use 'lfs getstripe' instead.\n");
+ deprecated_warning = 1;
+ }
if (!param.recursive && param.maxdepth == -1)
param.maxdepth = 1;
}
return 0;
}
-typedef int (semantic_func_t)(char *path, DIR *parent, DIR *d, void *data);
+typedef int (semantic_func_t)(char *path, DIR *parent, DIR *d,
+ void *data, struct dirent64 *de);
#define MAX_LOV_UUID_COUNT max(LOV_MAX_STRIPE_COUNT, 1000)
#define OBD_NOT_FOUND (-1)
static int llapi_semantic_traverse(char *path, int size, DIR *parent,
semantic_func_t sem_init,
- semantic_func_t sem_fini, void *data)
+ semantic_func_t sem_fini, void *data,
+ struct dirent64 *de)
{
struct dirent64 *dent;
int len, ret;
GOTO(out, ret = -EINVAL);
}
- if (sem_init && (ret = sem_init(path, parent ?: p, d, data)))
+ if (sem_init && (ret = sem_init(path, parent ?: p, d, data, de)))
goto err;
if (!d)
break;
case DT_DIR:
ret = llapi_semantic_traverse(path, size, d, sem_init,
- sem_fini, data);
+ sem_fini, data, dent);
if (ret < 0)
goto out;
break;
default:
ret = 0;
if (sem_init) {
- ret = sem_init(path, d, NULL, data);
+ ret = sem_init(path, d, NULL, data, dent);
if (ret < 0)
goto out;
}
if (sem_fini && ret == 0)
- sem_fini(path, d, NULL, data);
+ sem_fini(path, d, NULL, data, dent);
}
}
path[len] = 0;
if (sem_fini)
- sem_fini(path, parent, d, data);
+ sem_fini(path, parent, d, data, de);
err:
if (d)
closedir(d);
return rc;
}
-static int cb_find_init(char *path, DIR *parent, DIR *dir, void *data)
+static unsigned llapi_dir_filetype_table[] = {
+ [DT_UNKNOWN]= 0,
+ [DT_FIFO]= S_IFIFO,
+ [DT_CHR] = S_IFCHR,
+ [DT_DIR] = S_IFDIR,
+ [DT_BLK] = S_IFBLK,
+ [DT_REG] = S_IFREG,
+ [DT_LNK] = S_IFLNK,
+ [DT_SOCK]= S_IFSOCK,
+#if defined(DT_DOOR) && defined(S_IFDOOR)
+ [DT_DOOR]= S_IFDOOR,
+#endif
+};
+#if defined(DT_DOOR) && defined(S_IFDOOR)
+static const int DT_MAX = DT_DOOR;
+#else
+static const int DT_MAX = DT_SOCK;
+#endif
+
+static int cb_find_init(char *path, DIR *parent, DIR *dir,
+ void *data, struct dirent64 *de)
{
struct find_param *param = (struct find_param *)data;
int decision = 1; /* 1 is accepted; -1 is rejected. */
lstat_t *st = ¶m->lmd->lmd_st;
int lustre_fs = 1;
- int ret = 0;
+ int checked_type = 0;
+ int ret;
LASSERT(parent != NULL || dir != NULL);
param->lmd->lmd_lmm.lmm_stripe_count = 0;
+ /* If a regular expression is presented, make the initial decision */
+ if (param->pattern != NULL) {
+ char *fname = strrchr(path, '/');
+ fname = (fname == NULL ? path : fname + 1);
+ ret = fnmatch(param->pattern, fname, 0);
+ if ((ret == FNM_NOMATCH && !param->exclude_pattern) ||
+ (ret == 0 && param->exclude_pattern))
+ goto decided;
+ }
+
+ /* See if we can check the file type from the dirent. */
+ if (param->type && de != NULL && de->d_type != DT_UNKNOWN &&
+ de->d_type <= DT_MAX) {
+ checked_type = 1;
+ if (llapi_dir_filetype_table[de->d_type] == param->type) {
+ if (param->exclude_type)
+ goto decided;
+ } else {
+ if (!param->exclude_type)
+ goto decided;
+ }
+ }
+
+
/* If a time or OST should be checked, the decision is not taken yet. */
if (param->atime || param->ctime || param->mtime || param->obduuid)
decision = 0;
/* Request MDS for the stat info. */
- if (!decision && dir) {
+ if (dir) {
/* retrieve needed file info */
ret = ioctl(dirfd(dir), LL_IOC_MDC_GETINFO,
(void *)param->lmd);
- } else if (!decision && parent) {
+ } else /* if (parent) LASSERT() above makes always true */ {
char *fname = strrchr(path, '/');
fname = (fname == NULL ? path : fname + 1);
}
}
+ if (param->type && !checked_type) {
+ if ((st->st_mode & S_IFMT) == param->type) {
+ if (param->exclude_type)
+ goto decided;
+ } else {
+ if (!param->exclude_type)
+ goto decided;
+ }
+ }
+
/* Prepare odb. */
if (param->obduuid) {
if (lustre_fs && param->got_uuids &&
}
}
- /* If a regular expression is presented, make the initial decision */
- if (param->pattern != NULL) {
- char *fname = strrchr(path, '/');
- fname = (fname == NULL ? path : fname + 1);
- ret = fnmatch(param->pattern, fname, 0);
- if ((ret == FNM_NOMATCH && !param->exclude_pattern) ||
- (ret == 0 && param->exclude_pattern))
- decision = -1;
- }
-
/* If an OBD UUID is specified but no one matches, skip this file. */
if (param->obduuid && param->obdindex == OBD_NOT_FOUND)
decision = -1;
return 0;
}
-static int cb_common_fini(char *path, DIR *parent, DIR *d, void *data)
+static int cb_common_fini(char *path, DIR *parent, DIR *d, void *data,
+ struct dirent64 *de)
{
struct find_param *param = (struct find_param *)data;
param->depth--;
strncpy(buf, path, PATH_MAX + 1);
ret = llapi_semantic_traverse(buf, PATH_MAX + 1, NULL, cb_find_init,
- cb_common_fini, param);
+ cb_common_fini, param, NULL);
find_param_fini(param);
free(buf);
return ret < 0 ? ret : 0;
}
-static int cb_getstripe(char *path, DIR *parent, DIR *d, void *data)
+static int cb_getstripe(char *path, DIR *parent, DIR *d, void *data,
+ struct dirent64 *de)
{
struct find_param *param = (struct find_param *)data;
int ret = 0;
strncpy(buf, path, PATH_MAX + 1);
ret = llapi_semantic_traverse(buf, PATH_MAX + 1, NULL, cb_getstripe,
- cb_common_fini, param);
+ cb_common_fini, param, NULL);
find_param_fini(param);
free(buf);
return ret < 0 ? ret : 0;
return rc;
}
-static int cb_quotachown(char *path, DIR *parent, DIR *d, void *data)
+static int cb_quotachown(char *path, DIR *parent, DIR *d, void *data,
+ struct dirent64 *de)
{
struct find_param *param = (struct find_param *)data;
lstat_t *st;
strncpy(buf, path, PATH_MAX + 1);
ret = llapi_semantic_traverse(buf, PATH_MAX + 1, NULL, cb_quotachown,
- NULL, ¶m);
+ NULL, ¶m, NULL);
out:
find_param_fini(¶m);
free(buf);