Refactor, replace deprecated setfsent() & C:o with setmntent()

The setfsent() family of APIs was never standardized and on Linux only
GLIBC implement them.  We've tried to overcome this limitation, and to
support uClibc/uClibc-ng and musl libc, by providing replacements APIs
in helpers.c.

However, and since we want to support alternative /etc/fstab files, the
setmntent() family of APIs is more widespread and supports reading from
any fstab or mtab file.

Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
Joachim Wiberg
2022-04-20 07:20:33 +02:00
parent 05be281301
commit 5593372ffb
5 changed files with 31 additions and 105 deletions
+2 -2
View File
@@ -33,8 +33,8 @@ AC_PROG_MKDIR_P
# Configuration.
AC_HEADER_STDC
AC_CHECK_HEADERS([fstab.h termios.h sys/ioctl.h])
AC_CHECK_FUNCS([strstr getopt getfsenty])
AC_CHECK_HEADERS([termios.h sys/ioctl.h mntent.h])
AC_CHECK_FUNCS([strstr getopt getmntent])
# Check for uint[8,16,32]_t
AC_TYPE_UINT8_T
+27 -42
View File
@@ -26,11 +26,10 @@
#include <ctype.h>
#include <dirent.h>
#ifdef HAVE_FSTAB_H
#include <fstab.h>
#endif
#include <getopt.h>
#ifdef HAVE_MNTENT_H
#include <mntent.h>
#endif
#include <time.h> /* tzet() */
#include <sys/klog.h>
#include <sys/mount.h>
@@ -111,41 +110,43 @@ static void banner(void)
*/
static int fsck(int pass)
{
struct fstab *fs;
struct mntent *mnt;
int rc = 0;
FILE *fp;
if (!setfsent()) {
fp = setmntent("/etc/fstab", "r");
if (!fp) {
_pe("Failed opening fstab");
return 1;
}
while ((fs = getfsent())) {
while ((mnt = getmntent(fp))) {
char cmd[80];
struct stat st;
int fsck_rc = 0;
if (fs->fs_passno != pass)
if (mnt->mnt_passno != pass)
continue;
errno = 0;
if (stat(fs->fs_spec, &st) || !S_ISBLK(st.st_mode)) {
if (!string_match(fs->fs_spec, "UUID=") && !string_match(fs->fs_spec, "LABEL=")) {
_d("Cannot fsck %s, not a block device: %s", fs->fs_spec, strerror(errno));
if (stat(mnt->mnt_fsname, &st) || !S_ISBLK(st.st_mode)) {
if (!string_match(mnt->mnt_fsname, "UUID=") && !string_match(mnt->mnt_fsname, "LABEL=")) {
_d("Cannot fsck %s, not a block device: %s", mnt->mnt_fsname, strerror(errno));
continue;
}
}
if (ismnt("/proc/mounts", fs->fs_file, "rw")) {
_d("Skipping fsck of %s, already mounted rw on %s.", fs->fs_spec, fs->fs_file);
if (ismnt("/proc/mounts", mnt->mnt_dir, "rw")) {
_d("Skipping fsck of %s, already mounted rw on %s.", mnt->mnt_fsname, mnt->mnt_dir);
continue;
}
#ifdef FSCK_FIX
snprintf(cmd, sizeof(cmd), "fsck -yf %s", fs->fs_spec);
snprintf(cmd, sizeof(cmd), "fsck -yf %s", mnt->mnt_fsname);
#else
snprintf(cmd, sizeof(cmd), "fsck -a %s", fs->fs_spec);
snprintf(cmd, sizeof(cmd), "fsck -a %s", mnt->mnt_fsname);
#endif
fsck_rc = run_interactive(cmd, "Checking filesystem %.13s", fs->fs_spec);
fsck_rc = run_interactive(cmd, "Checking filesystem %.13s", mnt->mnt_fsname);
/*
* "failure" is defined as exiting with a return code of
* 2 or larger. A return code of 1 indicates that filesystem
@@ -169,7 +170,7 @@ static int fsck(int pass)
rc += fsck_rc;
}
endfsent();
endmntent(fp);
return rc;
}
@@ -202,38 +203,22 @@ static void fs_mount(const char *src, const char *tgt, const char *fstype,
}
#ifndef SYSROOT
/* If / is not listed in fstab, or listed as 'ro', leave it alone */
static int fs_readonly_root(struct fstab *fs)
{
char *tok, *str;
if (!fs)
return 1;
str = fs->fs_mntops;
while ((tok = strtok(str, ","))) {
if (!strcmp(tok, "ro"))
return 1;
str = NULL;
}
return 0;
}
static void fs_remount_root(int fsckerr)
{
struct fstab *fs;
struct mntent *mnt;
FILE *fp;
if (!setfsent())
fp = setmntent("/etc/fstab", "r");
if (!fp)
return;
while ((fs = getfsent())) {
if (!strcmp(fs->fs_file, "/"))
break;
while ((mnt = getmntent(fp))) {
if (strcmp(mnt->mnt_dir, "/"))
continue;
}
if (fs_readonly_root(fs))
/* If / is not listed in fstab, or listed as 'ro', leave it alone */
if (!mnt || hasmntopt(mnt, "ro"))
goto out;
if (fsckerr)
@@ -243,7 +228,7 @@ static void fs_remount_root(int fsckerr)
"Remounting / as read-write");
out:
endfsent();
endmntent(fp);
}
#else
static void fs_remount_root(int fsckerr)
-42
View File
@@ -587,48 +587,6 @@ int in_container(void)
return 0;
}
#ifndef HAVE_GETFSENT
static lfile_t *fstab = NULL;
int setfsent(void)
{
if (fstab)
lfclose(fstab);
fstab = lfopen("/etc/fstab", " \t\n");
if (!fstab)
return 0;
return 1;
}
struct fstab *getfsent(void)
{
static struct fstab fs;
fs.fs_spec = lftok(fstab);
if (fs.fs_spec == NULL)
return NULL;
fs.fs_file = lftok(fstab);
fs.fs_vfstype = lftok(fstab);
fs.fs_mntops = lftok(fstab);
fs.fs_type = "rw";
fs.fs_freq = atoi(lftok(fstab) ?: "0");
fs.fs_passno = atoi(lftok(fstab) ?: "0");
return &fs;
}
void endfsent(void)
{
if (fstab)
lfclose(fstab);
fstab = NULL;
}
#endif /* HAVE_GETFSENT */
/**
* Local Variables:
* indent-tabs-mode: t
-19
View File
@@ -27,9 +27,6 @@
#include "config.h"
#ifdef HAVE_FSTAB_H
#include <fstab.h>
#endif
#include <mntent.h>
#include <sched.h> /* sched_yield() */
#include <stdarg.h>
@@ -52,22 +49,6 @@ typedef enum {
PROGRESS_MODERN,
} pstyle_t;
#ifndef HAVE_FSTAB_H
struct fstab {
char *fs_spec; /* block device name */
char *fs_file; /* mount point */
char *fs_vfstype; /* file-system type */
char *fs_mntops; /* mount options */
const char *fs_type; /* rw/rq/ro/sw/xx option */
int fs_freq; /* dump frequency, in days */
int fs_passno; /* pass number on parallel dump */
};
int setfsent (void);
void endfsent (void);
struct fstab *getfsent (void);
#endif /* HAVE_FSTAB_H */
char *console (void);
void console_init (void);
ssize_t cprintf (const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+2
View File
@@ -23,7 +23,9 @@
#include <errno.h>
#include <string.h>
#ifdef HAVE_MNTENT_H
#include <mntent.h>
#endif
#include <sys/mount.h>
#include "helpers.h"