1
0
mirror of git://git.sv.gnu.org/coreutils.git synced 2026-02-20 14:22:26 +02:00
Files
coreutils/src/find-mount-point.c
Paul Eggert 6d61667d0d maint: go back to using ‘error’
Now that Gnulib’s ‘error’ module does proper static checking
for not returning, we need no longer use the ‘die’ macro.
This makes code easier to read for people that are used to ‘error’.
* cfg.mk (error_fns, exclude_file_name_regexp): Remove ‘die’.
(sc_die_EXIT_FAILURE): Remove.
* src/die.h: Remove.  All includes removed.  All calls to ‘die’
changed back to calls to ‘error’.
* src/install.c (get_ids): Use quoteaf (problem found with
make syntax-check).
* src/system.h: Include error.h, since some of our macros call ‘error’.
Stop including error.h elsewhere.
2023-07-01 11:51:16 -07:00

112 lines
3.3 KiB
C

/* find-mount-point.c -- find the root mount point for a file.
Copyright (C) 2010-2023 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 <https://www.gnu.org/licenses/>. */
#include <config.h>
#include <sys/types.h>
#include "system.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 nullptr if unable to determine the mount point.
Exit if unable to restore current working directory. */
extern char *
find_mount_point (char const *file, struct stat const *file_stat)
{
struct saved_cwd cwd;
struct stat last_stat;
char *mp = nullptr; /* The malloc'd mount point. */
if (save_cwd (&cwd) != 0)
{
error (0, errno, _("cannot get current directory"));
return nullptr;
}
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"), quoteaf (file));
return nullptr;
}
}
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"), quoteaf (dir));
return nullptr;
}
if (stat (".", &last_stat) < 0)
{
error (0, errno, _("cannot stat current directory (now %s)"),
quoteaf (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"), quoteaf (".."));
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"), quoteaf (".."));
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;
}