From 94125f4646c61f75ec2c872cd945d0a31a4cc80a Mon Sep 17 00:00:00 2001 From: Ondrej Oprala 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