mirror of
https://github.com/coreutils/coreutils.git
synced 2024-12-04 07:24:22 +08:00
(find_mount_point): Use save_cwd/restore_cwd.
"save-cwd.h": New include. (show_dev): Deal with null values for DISK and FSTYPE, including interpreting special 0 errno return from get_fs_usage. (show_point): Don't fail if we can't find a mount entry for POINT, just call show_dev with 0 values and let it fail if necessary. (main): Require a non-zero MOUNT_LIST only if showing all filesystems. (find_mount_point): New function. (xgetcwd): New declaration. All from Miles.
This commit is contained in:
parent
3fa102417e
commit
ac66871c65
123
src/df.c
123
src/df.c
@ -27,10 +27,12 @@
|
||||
#include "mountlist.h"
|
||||
#include "fsusage.h"
|
||||
#include "system.h"
|
||||
#include "save-cwd.h"
|
||||
#include "error.h"
|
||||
|
||||
char *xmalloc ();
|
||||
char *xstrdup ();
|
||||
char *xgetcwd ();
|
||||
|
||||
/* The maximum length of a human-readable string. Be pessimistic
|
||||
and assume `int' is 64-bits wide. Converting 2^63 - 1 gives the
|
||||
@ -237,7 +239,9 @@ excluded_fstype (const char *fstype)
|
||||
/* Display a space listing for the disk device with absolute path DISK.
|
||||
If MOUNT_POINT is non-NULL, it is the path of the root of the
|
||||
filesystem on DISK.
|
||||
If FSTYPE is non-NULL, it is the type of the filesystem on DISK. */
|
||||
If FSTYPE is non-NULL, it is the type of the filesystem on DISK.
|
||||
If MOUNT_POINT is non-NULL, then DISK may be NULL -- certain systems may
|
||||
not be able to produce statistics in this case. */
|
||||
|
||||
static void
|
||||
show_dev (const char *disk, const char *mount_point, const char *fstype)
|
||||
@ -302,10 +306,15 @@ show_dev (const char *disk, const char *mount_point, const char *fstype)
|
||||
(inodes_used * 100.0 / fsu.fsu_files + 0.5);
|
||||
}
|
||||
|
||||
if (! disk)
|
||||
disk = "-"; /* unknown */
|
||||
|
||||
printf ((print_type ? "%-13s" : "%-20s"), disk);
|
||||
if (strlen (disk) > (print_type ? 13 : 20) && !posix_format)
|
||||
printf ((print_type ? "\n%13s" : "\n%20s"), "");
|
||||
|
||||
if (! fstype)
|
||||
fstype = "-"; /* unknown */
|
||||
if (print_type)
|
||||
printf (" %-5s ", fstype);
|
||||
|
||||
@ -362,10 +371,91 @@ show_disk (const char *disk)
|
||||
show_dev (disk, (char *) NULL, (char *) NULL);
|
||||
}
|
||||
|
||||
/* Return the root mountpoint of the filesystem on which FILE exists, in
|
||||
malloced storage. FILE_STAT should be the result of stating FILE. */
|
||||
static char *
|
||||
find_mount_point (file, file_stat)
|
||||
char *file;
|
||||
struct stat *file_stat;
|
||||
{
|
||||
struct saved_cwd cwd;
|
||||
struct stat last_stat;
|
||||
char *mp = 0; /* The malloced mount point path. */
|
||||
|
||||
if (save_cwd (&cwd))
|
||||
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)
|
||||
return NULL;
|
||||
}
|
||||
else
|
||||
/* FILE is some other kind of file, we need to use its directory. */
|
||||
{
|
||||
int rv;
|
||||
char *dir = xstrdup (file);
|
||||
char *end = dir + strlen (dir);
|
||||
|
||||
/* Strip off the last pathname element of FILE to get the directory. */
|
||||
while (end > dir + 1 && end[-1] == '/')
|
||||
*--end = '\0';
|
||||
while (end > dir && end[-1] != '/')
|
||||
end--;
|
||||
if (end == dir)
|
||||
/* FILE only has a single element, use the cwd's parent. */
|
||||
rv = chdir ("..");
|
||||
else
|
||||
{
|
||||
*end = '\0';
|
||||
rv = chdir (dir);
|
||||
}
|
||||
free (dir);
|
||||
|
||||
if (rv < 0)
|
||||
return NULL;
|
||||
|
||||
if (stat (".", &last_stat) < 0)
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Now walk up FILE's parents until we find another filesystem or /,
|
||||
chdiring as we go. LAST_STAT holds stat information for the last place
|
||||
we visited. */
|
||||
for (;;)
|
||||
{
|
||||
struct stat st;
|
||||
if (stat ("..", &st) < 0)
|
||||
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)
|
||||
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, mp))
|
||||
exit (1); /* We're scrod. */
|
||||
free_cwd (&cwd);
|
||||
errno = save_errno;
|
||||
}
|
||||
|
||||
return mp;
|
||||
}
|
||||
|
||||
/* Figure out which device file or directory POINT is mounted on
|
||||
and show its disk usage.
|
||||
STATP is the results of `stat' on POINT. */
|
||||
|
||||
static void
|
||||
show_point (const char *point, const struct stat *statp)
|
||||
{
|
||||
@ -397,8 +487,21 @@ show_point (const char *point, const struct stat *statp)
|
||||
return;
|
||||
}
|
||||
}
|
||||
error (0, 0, _("cannot find mount point for %s"), point);
|
||||
exit_status = 1;
|
||||
|
||||
/* We couldn't find the mount entry corresponding to POINT. Go ahead and
|
||||
print as much info as we can; methods that require the device to be
|
||||
present will fail at a later point. */
|
||||
{
|
||||
/* Find the actual mount point. */
|
||||
char *mp = find_mount_point (point, statp);
|
||||
if (mp)
|
||||
{
|
||||
show_dev (0, mp, 0);
|
||||
free (mp);
|
||||
}
|
||||
else
|
||||
error (0, errno, "%s", point);
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine what kind of node PATH is and show the disk usage
|
||||
@ -639,20 +742,22 @@ with the portable output format"));
|
||||
|| print_type),
|
||||
show_all_fs);
|
||||
|
||||
if (mount_list == NULL)
|
||||
error (1, errno, _("cannot read table of mounted filesystems"));
|
||||
|
||||
print_header ();
|
||||
if (require_sync)
|
||||
sync ();
|
||||
|
||||
if (optind == argc)
|
||||
show_all_entries ();
|
||||
{
|
||||
if (mount_list == NULL)
|
||||
error (1, errno, _("cannot read table of mounted filesystems"));
|
||||
print_header ();
|
||||
show_all_entries ();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Display explicitly requested empty filesystems. */
|
||||
show_listed_fs = 1;
|
||||
|
||||
print_header ();
|
||||
for (i = optind; i < argc; ++i)
|
||||
if (argv[i])
|
||||
show_entry (argv[i], &stats[i - optind]);
|
||||
|
Loading…
Reference in New Issue
Block a user