diff options
| author | Aaron Burgemeister <dajoker@gmail.com> | 2010-07-15 19:54:49 -0600 |
|---|---|---|
| committer | Pádraig Brady <P@draigBrady.com> | 2010-08-27 22:16:10 +0100 |
| commit | ddf6fb8686b1ed6a26d5f1c76a642d0fb5fe7ba7 (patch) | |
| tree | 27c8712c7d87a57181506c24f2b2ebb58769646c /src/find-mount-point.c | |
| parent | maint: update to latest gnulib (diff) | |
| download | coreutils-ddf6fb8686b1ed6a26d5f1c76a642d0fb5fe7ba7.tar.gz coreutils-ddf6fb8686b1ed6a26d5f1c76a642d0fb5fe7ba7.zip | |
stat: add %m to output the mount point for a file
* src/find-mount-point.c: A new file refactoring
find_mount_point() out from df.c
* src/find-mount-point.h: Likewise.
* src/df.c: Use the new find-mount-point module.
* src/stat.c (print_stat): Handle the new %m format.
(find_bind_mount): A new function to
return the bind mount for a file if any.
(out_mount_mount): Print the bind mount for a file, or else
the standard mount point given by the find-mount-point module.
(usage): Document the %m format directive.
* src/Makefile.am: Reference the refactored find-mount-point.c
* po/POTFILES.in: Add find_mount_point.c to the translation list
* doc/coreutils.texi (stat invocation): Document %m,
and how it may differ from the mount point that df outputs.
* test/misc/stat-mount: A new test to correlate mount points
output from df and stat.
* tests/Makefile.am: Reference the new test.
* NEWS: Mention the new feature
* THANKS: Add the author
Signed-off-by: Pádraig Brady <P@draigBrady.com>
Diffstat (limited to 'src/find-mount-point.c')
| -rw-r--r-- | src/find-mount-point.c | 113 |
1 files changed, 113 insertions, 0 deletions
diff --git a/src/find-mount-point.c b/src/find-mount-point.c new file mode 100644 index 000000000..f3a20744d --- /dev/null +++ b/src/find-mount-point.c @@ -0,0 +1,113 @@ +/* find-mount-point.c -- find the root mount point for a file. + Copyright (C) 2010 Free Software Foundation, Inc. + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <config.h> +#include <sys/types.h> + +#include "system.h" +#include "error.h" +#include "quote.h" +#include "save-cwd.h" +#include "xgetcwd.h" +#include "find-mount-point.h" + +/* Return the root mountpoint of the file system on which FILE exists, in + malloced storage. FILE_STAT should be the result of stating FILE. + Give a diagnostic and return NULL if unable to determine the mount point. + Exit if unable to restore current working directory. */ +extern char * +find_mount_point (const char *file, const struct stat *file_stat) +{ + struct saved_cwd cwd; + struct stat last_stat; + char *mp = NULL; /* The malloced mount point. */ + + if (save_cwd (&cwd) != 0) + { + error (0, errno, _("cannot get current directory")); + return NULL; + } + + if (S_ISDIR (file_stat->st_mode)) + /* FILE is a directory, so just chdir there directly. */ + { + last_stat = *file_stat; + if (chdir (file) < 0) + { + error (0, errno, _("cannot change to directory %s"), quote (file)); + return NULL; + } + } + else + /* FILE is some other kind of file; use its directory. */ + { + char *xdir = dir_name (file); + char *dir; + ASSIGN_STRDUPA (dir, xdir); + free (xdir); + + if (chdir (dir) < 0) + { + error (0, errno, _("cannot change to directory %s"), quote (dir)); + return NULL; + } + + if (stat (".", &last_stat) < 0) + { + error (0, errno, _("cannot stat current directory (now %s)"), + quote (dir)); + goto done; + } + } + + /* Now walk up FILE's parents until we find another file system or /, + chdiring as we go. LAST_STAT holds stat information for the last place + we visited. */ + while (true) + { + struct stat st; + if (stat ("..", &st) < 0) + { + error (0, errno, _("cannot stat %s"), quote ("..")); + goto done; + } + if (st.st_dev != last_stat.st_dev || st.st_ino == last_stat.st_ino) + /* cwd is the mount point. */ + break; + if (chdir ("..") < 0) + { + error (0, errno, _("cannot change to directory %s"), quote ("..")); + goto done; + } + last_stat = st; + } + + /* Finally reached a mount point, see what it's called. */ + mp = xgetcwd (); + +done: + /* Restore the original cwd. */ + { + int save_errno = errno; + if (restore_cwd (&cwd) != 0) + error (EXIT_FAILURE, errno, + _("failed to return to initial working directory")); + free_cwd (&cwd); + errno = save_errno; + } + + return mp; +} |
