1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-04-19 18:26:32 +02:00

(show_disk, show_point): If several filesystems are

mounted on the same mount point, prefer the last one, not the first.
Problem reported by Christian Jones in
<http://mail.gnu.org/archive/html/bug-coreutils/2004-04/msg00200.html>.
(show_disk): Remove unused statp arg.  Return bool, not int.
(show_point): Rewrite to avoid gotos.  Use the same algorithm
for lofs and dummies for each pass through the mount table,
rather than subtly different algorithms (which are probably
inadvertent).
This commit is contained in:
Jim Meyering
2004-05-04 07:26:33 +00:00
parent b9c20c62fb
commit 3145fdd1ed

197
src/df.c
View File

@@ -521,22 +521,26 @@ done:
}
/* If DISK corresponds to a mount point, show its usage
and return nonzero. Otherwise, return zero.
STATP must be the result of `stat (DISK, STATP)'. */
static int
show_disk (const char *disk, const struct stat *statp)
and return true. Otherwise, return false. */
static bool
show_disk (char const *disk)
{
struct mount_entry *me;
struct mount_entry const *me;
struct mount_entry const *best_match = NULL;
for (me = mount_list; me; me = me->me_next)
if (STREQ (disk, me->me_devname))
{
show_dev (me->me_devname, me->me_mountdir, me->me_type,
me->me_dummy, me->me_remote);
return 1;
}
best_match = me;
return 0;
if (best_match)
{
show_dev (best_match->me_devname, best_match->me_mountdir,
best_match->me_type, best_match->me_dummy,
best_match->me_remote);
return true;
}
return false;
}
/* Figure out which device file or directory POINT is mounted on
@@ -547,121 +551,104 @@ show_point (const char *point, const struct stat *statp)
{
struct stat disk_stats;
struct mount_entry *me;
struct mount_entry *matching_dummy = NULL;
struct mount_entry const *best_match = NULL;
/* If POINT is an absolute path name, see if we can find the
mount point without performing any extra stat calls at all. */
if (*point == '/')
{
for (me = mount_list; me; me = me->me_next)
{
if (STREQ (me->me_mountdir, point) && !STREQ (me->me_type, "lofs"))
{
/* Prefer non-dummy entries. */
if (! me->me_dummy)
goto show_me;
matching_dummy = me;
}
}
/* Find the best match: prefer non-dummies, and then prefer the
last match if there are ties. */
if (matching_dummy)
goto show_matching_dummy;
for (me = mount_list; me; me = me->me_next)
if (STREQ (me->me_mountdir, point) && !STREQ (me->me_type, "lofs")
&& (!best_match || best_match->me_dummy || !me->me_dummy))
best_match = me;
}
/* Calculate the real absolute path for POINT, and use that to find
the mount point. This avoids statting unavailable mount points,
which can hang df. */
{
char *resolved = canonicalize_file_name (point);
ssize_t resolved_len = resolved ? strlen (resolved) : -1;
struct mount_entry *best_match = NULL;
if (1 <= resolved_len && resolved[0] == '/')
{
size_t best_match_len = 0;
for (me = mount_list; me; me = me->me_next)
if (! me->me_dummy)
{
size_t len = strlen (me->me_mountdir);
if (best_match_len < len && len <= resolved_len
&& (len == 1 /* root file system */
|| ((len == resolved_len || resolved[len] == '/')
&& strncmp (me->me_mountdir, resolved, len) == 0)))
{
best_match = me;
best_match_len = len;
}
}
}
if (resolved)
free (resolved);
if (best_match && !STREQ (best_match->me_type, "lofs")
&& stat (best_match->me_mountdir, &disk_stats) == 0
&& disk_stats.st_dev == statp->st_dev)
{
me = best_match;
goto show_me;
}
}
for (me = mount_list; me; me = me->me_next)
if (! best_match)
{
if (me->me_dev == (dev_t) -1)
char *resolved = canonicalize_file_name (point);
ssize_t resolved_len = resolved ? strlen (resolved) : -1;
if (1 <= resolved_len && resolved[0] == '/')
{
if (stat (me->me_mountdir, &disk_stats) == 0)
me->me_dev = disk_stats.st_dev;
else
{
error (0, errno, "%s", quote (me->me_mountdir));
exit_status = 1;
/* So we won't try and fail repeatedly. */
me->me_dev = (dev_t) -2;
}
size_t best_match_len = 0;
for (me = mount_list; me; me = me->me_next)
if (!STREQ (me->me_type, "lofs")
&& (!best_match || best_match->me_dummy || !me->me_dummy))
{
size_t len = strlen (me->me_mountdir);
if (best_match_len <= len && len <= resolved_len
&& (len == 1 /* root file system */
|| ((len == resolved_len || resolved[len] == '/')
&& strncmp (me->me_mountdir, resolved, len) == 0)))
{
best_match = me;
best_match_len = len;
}
}
}
if (statp->st_dev == me->me_dev)
{
/* Skip bogus mtab entries. */
if (stat (me->me_mountdir, &disk_stats) != 0
|| disk_stats.st_dev != me->me_dev)
{
me->me_dev = (dev_t) -2;
continue;
}
if (resolved)
free (resolved);
/* Prefer non-dummy entries. */
if (! me->me_dummy)
goto show_me;
matching_dummy = me;
}
if (best_match
&& (stat (best_match->me_mountdir, &disk_stats) != 0
|| disk_stats.st_dev != statp->st_dev))
best_match = NULL;
}
if (matching_dummy)
goto show_matching_dummy;
/* 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)
if (! best_match)
for (me = mount_list; me; me = me->me_next)
{
show_dev (0, mp, 0, 0, 0);
free (mp);
if (me->me_dev == (dev_t) -1)
{
if (stat (me->me_mountdir, &disk_stats) == 0)
me->me_dev = disk_stats.st_dev;
else
{
error (0, errno, "%s", quote (me->me_mountdir));
exit_status = 1;
/* So we won't try and fail repeatedly. */
me->me_dev = (dev_t) -2;
}
}
if (statp->st_dev == me->me_dev
&& !STREQ (me->me_type, "lofs")
&& (!best_match || best_match->me_dummy || !me->me_dummy))
{
/* Skip bogus mtab entries. */
if (stat (me->me_mountdir, &disk_stats) != 0
|| disk_stats.st_dev != me->me_dev)
me->me_dev = (dev_t) -2;
else
best_match = me;
}
}
}
return;
if (best_match)
show_dev (best_match->me_devname, best_match->me_mountdir,
best_match->me_type, best_match->me_dummy, best_match->me_remote);
else
{
/* 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. */
show_matching_dummy:
me = matching_dummy;
show_me:
show_dev (me->me_devname, me->me_mountdir, me->me_type, me->me_dummy,
me->me_remote);
/* Find the actual mount point. */
char *mp = find_mount_point (point, statp);
if (mp)
{
show_dev (0, mp, 0, 0, 0);
free (mp);
}
}
}
/* Determine what kind of node PATH is and show the disk usage
@@ -671,7 +658,7 @@ static void
show_entry (const char *path, const struct stat *statp)
{
if ((S_ISBLK (statp->st_mode) || S_ISCHR (statp->st_mode))
&& show_disk (path, statp))
&& show_disk (path))
return;
show_point (path, statp);