Hi, this patch adds the --dereference option to df, so if a symlink is specified
as an argument to df (possibly /dev/disk/by-uuid/*), df outputs info about the
filesystem the symlinked file is on instead. Now, I realize the option's name is
a bit misleading, since the arguments are stat-ed anyway, but IMHO that's
exactly
what it looks like from a user's perspective.
Thanks,
Ondrej
From 94125f4646c61f75ec2c872cd945d0a31a4cc80a Mon Sep 17 00:00:00 2001
From: Ondrej Oprala <[email protected]>
Date: Wed, 15 May 2013 14:34:27 +0200
Subject: [PATCH] df: add the --dereference option
With --dereference specified, df should print info about the
filesystem the pointed-to file is on if a symlink is passed
as an argument to df.
* NEWS: Mention the new feature.
* doc/coreutils.texi: Likewise.
* src/df.c: Add new static global variable dereference.
(get_point): Use me_devname while looking for best match instead
of me_mountdir if --dereference was specified.
---
NEWS | 4 ++++
doc/coreutils.texi | 8 ++++++++
src/df.c | 23 +++++++++++++++++++----
3 files changed, 31 insertions(+), 4 deletions(-)
diff --git a/NEWS b/NEWS
index eec93df..6d7def3 100644
--- a/NEWS
+++ b/NEWS
@@ -25,6 +25,10 @@ GNU coreutils NEWS -*- outline -*-
** New features
+ df accepts a new option: --dereference (-L). If a symlink is passed as an
+ argument, df prints information about the filesystem the pointed-to file
+ is on instead.
+
id -Z reports the SMACK security context where available.
join accepts a new option: --zero-terminated (-z). As with the sort,uniq
diff --git a/doc/coreutils.texi b/doc/coreutils.texi
index d607eaf..52db41b 100644
--- a/doc/coreutils.texi
+++ b/doc/coreutils.texi
@@ -11097,6 +11097,14 @@ This option is equivalent to @option{--block-size=1K}.
Limit the listing to local file systems. By default, remote file systems
are also listed.
+@item -L
+@itemx --dereference
+@opindex -L
+@opindex --dereference
+@cindex symlink dereferencing
+Print the actual mount point if a symlink is passed as an argument
+to @command{df}.
+
@item --no-sync
@opindex --no-sync
@cindex file system space, retrieving old data more quickly
diff --git a/src/df.c b/src/df.c
index 0515131..21b07e9 100644
--- a/src/df.c
+++ b/src/df.c
@@ -66,6 +66,9 @@ static bool show_listed_fs;
/* Human-readable options for output. */
static int human_output_opts;
+/* Show the actual mount point if a symlink is passed as an argument. */
+static bool dereference;
+
/* The units to use when printing sizes. */
static uintmax_t output_block_size;
@@ -249,6 +252,7 @@ static struct option const long_options[] =
{"human-readable", no_argument, NULL, 'h'},
{"si", no_argument, NULL, 'H'},
{"local", no_argument, NULL, 'l'},
+ {"dereference", no_argument, NULL, 'L'},
{"megabytes", no_argument, NULL, MEGABYTES_OPTION}, /* obsolescent, */
{"output", optional_argument, NULL, OUTPUT_OPTION},
{"portability", no_argument, NULL, 'P'},
@@ -1071,11 +1075,17 @@ get_point (const char *point, const struct stat *statp)
if (!STREQ (me->me_type, "lofs")
&& (!best_match || best_match->me_dummy || !me->me_dummy))
{
- size_t len = strlen (me->me_mountdir);
+ size_t len;
+ if (dereference)
+ len = strlen (me->me_devname);
+ else
+ len = strlen (me->me_mountdir);
+
if (best_match_len <= len && len <= resolved_len
&& (len == 1 /* root file system */
|| ((len == resolved_len || resolved[len] == '/')
- && STREQ_LEN (me->me_mountdir, resolved, len))))
+ && ((dereference && STREQ_LEN (me->me_devname, resolved, len))
+ || STREQ_LEN (me->me_mountdir, resolved, len)))))
{
best_match = me;
best_match_len = len;
@@ -1085,7 +1095,7 @@ get_point (const char *point, const struct stat *statp)
free (resolved);
if (best_match
&& (stat (best_match->me_mountdir, &disk_stats) != 0
- || disk_stats.st_dev != statp->st_dev))
+ || (!dereference && disk_stats.st_dev != statp->st_dev)))
best_match = NULL;
if (! best_match)
@@ -1230,6 +1240,7 @@ or all file systems by default.\n\
-l, --local limit listing to local file systems\n\
--no-sync do not invoke sync before getting usage info (default)\
\n\
+ -L --dereference show the actual mount point if a symlink is given\n\
"), stdout);
fputs (_("\
--output[=FIELD_LIST] use the output format defined by FIELD_LIST,\n\
@@ -1272,6 +1283,7 @@ main (int argc, char **argv)
fs_exclude_list = NULL;
show_all_fs = false;
show_listed_fs = false;
+ dereference = false;
human_output_opts = -1;
print_type = false;
file_systems_processed = false;
@@ -1287,7 +1299,7 @@ main (int argc, char **argv)
while (true)
{
int oi = -1;
- int c = getopt_long (argc, argv, "aB:iF:hHklmPTt:vx:", long_options,
+ int c = getopt_long (argc, argv, "aB:iF:hHklLmPTt:vx:", long_options,
&oi);
if (c == -1)
break;
@@ -1328,6 +1340,9 @@ main (int argc, char **argv)
case 'l':
show_local_fs = true;
break;
+ case 'L':
+ dereference = true;
+ break;
case MEGABYTES_OPTION:
/* Distinguish between the long and the short option.
As we want to remove the long option soon,
--
1.8.1.4