@@ -17,6 +17,9 @@ static char *mntpt;
struct pptr_args {
char *pathbuf;
+ char *filter_name;
+ uint64_t filter_ino;
+ bool shortformat;
};
static int
@@ -25,12 +28,27 @@ pptr_print(
void *arg)
{
const struct xfs_fid *fid = &rec->p_handle.ha_fid;
+ struct pptr_args *args = arg;
if (rec->p_flags & PARENTREC_FILE_IS_ROOT) {
printf(_("Root directory.\n"));
return 0;
}
+ if (args->filter_ino && fid->fid_ino != args->filter_ino)
+ return 0;
+ if (args->filter_name && strcmp(args->filter_name, rec->p_name))
+ return 0;
+
+ if (args->shortformat) {
+ printf("%llu:%u:%zu:%s\n",
+ (unsigned long long)fid->fid_ino,
+ (unsigned int)fid->fid_gen,
+ strlen(rec->p_name),
+ rec->p_name);
+ return 0;
+ }
+
printf(_("p_ino = %llu\n"), (unsigned long long)fid->fid_ino);
printf(_("p_gen = %u\n"), (unsigned int)fid->fid_gen);
printf(_("p_namelen = %zu\n"), strlen(rec->p_name));
@@ -39,6 +57,21 @@ pptr_print(
return 0;
}
+static int
+filter_path_components(
+ const char *name,
+ uint64_t ino,
+ void *arg)
+{
+ struct pptr_args *args = arg;
+
+ if (args->filter_ino && ino == args->filter_ino)
+ return ECANCELED;
+ if (args->filter_name && !strcmp(args->filter_name, name))
+ return ECANCELED;
+ return 0;
+}
+
static int
paths_print(
const char *mntpt,
@@ -51,6 +84,12 @@ paths_print(
int mntpt_len = strlen(mntpt);
int ret;
+ if (args->filter_ino || args->filter_name) {
+ ret = path_walk_components(path, filter_path_components, args);
+ if (ret != ECANCELED)
+ return 0;
+ }
+
/* Trim trailing slashes from the mountpoint */
while (mntpt_len > 0 && mntpt[mntpt_len - 1] == '/')
mntpt_len--;
@@ -103,7 +142,7 @@ parent_f(
}
mntpt = fs->fs_dir;
- while ((c = getopt(argc, argv, "b:pz")) != EOF) {
+ while ((c = getopt(argc, argv, "b:i:n:psz")) != EOF) {
switch (c) {
case 'b':
errno = 0;
@@ -114,9 +153,24 @@ parent_f(
return 1;
}
break;
+ case 'i':
+ args.filter_ino = strtoull(optarg, &p, 0);
+ if (*p != '\0' || args.filter_ino == 0) {
+ fprintf(stderr, _("Bad inode number '%s'.\n"),
+ optarg);
+ exitcode = 1;
+ return 1;
+ }
+ break;
+ case 'n':
+ args.filter_name = optarg;
+ break;
case 'p':
listpath_flag = 1;
break;
+ case 's':
+ args.shortformat = true;
+ break;
case 'z':
single_path = true;
break;
@@ -203,7 +257,10 @@ printf(_(
" list the current file's parents and their filenames\n"
"\n"
" -b -- use this many bytes to hold parent pointer records\n"
+" -i -- Only show parent pointer records containing the given inode\n"
+" -n -- Only show parent pointer records containing the given filename\n"
" -p -- list the current file's paths up to the root\n"
+" -s -- Print records in short format: ino/gen/namelen/filename\n"
" -z -- print only the first path from the root\n"
"\n"
"If ino and gen are supplied, use them instead.\n"
@@ -217,7 +274,7 @@ parent_init(void)
parent_cmd.cfunc = parent_f;
parent_cmd.argmin = 0;
parent_cmd.argmax = -1;
- parent_cmd.args = _("[-pz] [-b bufsize] [ino gen]");
+ parent_cmd.args = _("[-psz] [-b bufsize] [-i ino] [-n name] [ino gen]");
parent_cmd.flags = CMD_NOMAP_OK;
parent_cmd.oneline = _("print parent inodes");
parent_cmd.help = parent_help;
@@ -1004,7 +1004,7 @@ and
options behave as described above, in
.B chproj.
.TP
-.BR parent " [ " \-pz " ] [ " \-b " bufsize ] [" " ino gen " "]"
+.BR parent " [ " \-fpz " ] [ " \-b " bufsize ] [ " \-i " ino ] [ " \-n " name ] [" " ino gen " "]"
By default this command prints out the parent inode numbers,
inode generation numbers and basenames of all the hardlinks which
point to the inode of the current file.
@@ -1023,11 +1023,20 @@ the open file.
.TP 0.4i
.B \-b
Use a buffer of this size to receive parent pointer records from the kernel.
-.TP
+.TP 0.4i
+.B \-i
+Only show parent pointer records containing this inode number.
+.TP 0.4i
+.B \-n
+Only show parent pointer records containing this directory entry name.
+.TP 0.4i
.B \-p
the output is similar to the default output except pathnames up to
the mount-point are printed out instead of the component name.
.TP
+.B \-s
+Print records in short format: ino/gen/namelen/name
+.TP
.B \-z
Print only the first path from the root.
.RE