📄 fstab.c
字号:
/* 1999-02-22 Arkadiusz Mi秌iewicz <misiek@pld.ORG.PL> * - added Native Language Support * Sun Mar 21 1999 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> * - fixed strerr(errno) in gettext calls */#include <unistd.h>#include <errno.h>#include <stdio.h>#include <string.h>#include <sys/stat.h>#include "mntent.h"#include "fstab.h"#include "sundries.h" /* for xmalloc() etc */#include "mount_blkid.h"#include "paths.h"#include "nls.h"#define streq(s, t) (strcmp ((s), (t)) == 0)#define PROC_MOUNTS "/proc/mounts"/* Information about mtab. ------------------------------------*/static int have_mtab_info = 0;static int var_mtab_does_not_exist = 0;static int var_mtab_is_a_symlink = 0;static voidget_mtab_info(void) { struct stat mtab_stat; if (!have_mtab_info) { if (lstat(MOUNTED, &mtab_stat)) var_mtab_does_not_exist = 1; else if (S_ISLNK(mtab_stat.st_mode)) var_mtab_is_a_symlink = 1; have_mtab_info = 1; }}intmtab_does_not_exist(void) { get_mtab_info(); return var_mtab_does_not_exist;}intmtab_is_a_symlink(void) { get_mtab_info(); return var_mtab_is_a_symlink;}intmtab_is_writable() { static int ret = -1; /* Should we write to /etc/mtab upon an update? Probably not if it is a symlink to /proc/mounts, since that would create a file /proc/mounts in case the proc filesystem is not mounted. */ if (mtab_is_a_symlink()) return 0; if (ret == -1) { int fd = open(MOUNTED, O_RDWR | O_CREAT, 0644); if (fd >= 0) { close(fd); ret = 1; } else ret = 0; } return ret;}/* Contents of mtab and fstab ---------------------------------*/struct mntentchn mounttable, fstab;static int got_mtab = 0;static int got_fstab = 0;static void read_mounttable(void), read_fstab(void);struct mntentchn *mtab_head() { if (!got_mtab) read_mounttable(); return &mounttable;}struct mntentchn *fstab_head() { if (!got_fstab) read_fstab(); return &fstab;}static voidmy_free(const void *s) { if (s) free((void *) s);}static voiddiscard_mntentchn(struct mntentchn *mc0) { struct mntentchn *mc, *mc1; for (mc = mc0->nxt; mc && mc != mc0; mc = mc1) { mc1 = mc->nxt; my_free(mc->m.mnt_fsname); my_free(mc->m.mnt_dir); my_free(mc->m.mnt_type); my_free(mc->m.mnt_opts); free(mc); }}static voidread_mntentchn(mntFILE *mfp, const char *fnam, struct mntentchn *mc0) { struct mntentchn *mc = mc0; struct my_mntent *mnt; while ((mnt = my_getmntent(mfp)) != NULL) { if (!streq(mnt->mnt_type, MNTTYPE_IGNORE)) { mc->nxt = (struct mntentchn *) xmalloc(sizeof(*mc)); mc->nxt->prev = mc; mc = mc->nxt; mc->m = *mnt; mc->nxt = mc0; } } mc0->prev = mc; if (ferror(mfp->mntent_fp)) { int errsv = errno; error(_("warning: error reading %s: %s"), fnam, strerror (errsv)); mc0->nxt = mc0->prev = NULL; } my_endmntent(mfp);}/* * Read /etc/mtab. If that fails, try /proc/mounts. * This produces a linked list. The list head mounttable is a dummy. * Return 0 on success. */static voidread_mounttable() { mntFILE *mfp; const char *fnam; struct mntentchn *mc = &mounttable; got_mtab = 1; mc->nxt = mc->prev = NULL; fnam = MOUNTED; mfp = my_setmntent (fnam, "r"); if (mfp == NULL || mfp->mntent_fp == NULL) { int errsv = errno; fnam = PROC_MOUNTS; mfp = my_setmntent (fnam, "r"); if (mfp == NULL || mfp->mntent_fp == NULL) { error(_("warning: can't open %s: %s"), MOUNTED, strerror (errsv)); return; } if (verbose) printf (_("mount: could not open %s - " "using %s instead\n"), MOUNTED, PROC_MOUNTS); } read_mntentchn(mfp, fnam, mc);}static voidread_fstab() { mntFILE *mfp = NULL; const char *fnam; struct mntentchn *mc = &fstab; got_fstab = 1; mc->nxt = mc->prev = NULL; fnam = _PATH_FSTAB; mfp = my_setmntent (fnam, "r"); if (mfp == NULL || mfp->mntent_fp == NULL) { int errsv = errno; error(_("warning: can't open %s: %s"), _PATH_FSTAB, strerror (errsv)); return; } read_mntentchn(mfp, fnam, mc);} /* Given the name NAME, try to find it in mtab. */ struct mntentchn *getmntfile (const char *name) { struct mntentchn *mc, *mc0; mc0 = mtab_head(); for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) if (streq(mc->m.mnt_dir, name) || streq(mc->m.mnt_fsname, name)) return mc; return NULL;}/* * Given the directory name NAME, and the place MCPREV we found it last time, * try to find more occurrences. */ struct mntentchn *getmntdirbackward (const char *name, struct mntentchn *mcprev) { struct mntentchn *mc, *mc0; mc0 = mtab_head(); if (!mcprev) mcprev = mc0; for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev) if (streq(mc->m.mnt_dir, name)) return mc; return NULL;}/* * Given the device name NAME, and the place MCPREV we found it last time, * try to find more occurrences. */ struct mntentchn *getmntdevbackward (const char *name, struct mntentchn *mcprev) { struct mntentchn *mc, *mc0; mc0 = mtab_head(); if (!mcprev) mcprev = mc0; for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev) if (streq(mc->m.mnt_fsname, name)) return mc; return NULL;}/* * Given the name NAME, check that it occurs precisely once as dir or dev. */intis_mounted_once(const char *name) { struct mntentchn *mc, *mc0; int ct = 0; mc0 = mtab_head(); for (mc = mc0->prev; mc && mc != mc0; mc = mc->prev) if (streq(mc->m.mnt_dir, name) || streq(mc->m.mnt_fsname, name)) ct++; return (ct == 1);}/* Given the name FILE, try to find the option "loop=FILE" in mtab. */ struct mntentchn *getmntoptfile (const char *file) { struct mntentchn *mc, *mc0; const char *opts, *s; int l; if (!file) return NULL; l = strlen(file); mc0 = mtab_head(); for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) if ((opts = mc->m.mnt_opts) != NULL && (s = strstr(opts, "loop=")) && !strncmp(s+5, file, l) && (s == opts || s[-1] == ',') && (s[l+5] == 0 || s[l+5] == ',')) return mc; return NULL;}static inthas_label(const char *device, const char *label) { const char *devlabel; int ret; devlabel = mount_get_volume_label_by_spec(device); ret = !strcmp(label, devlabel); /* free(devlabel); */ return ret;}static inthas_uuid(const char *device, const char *uuid){ const char *devuuid; int ret; devuuid = mount_get_devname_by_uuid(device); ret = !strcmp(uuid, devuuid); /* free(devuuid); */ return ret;}/* Find the entry (SPEC,FILE) in fstab */struct mntentchn *getfsspecfile (const char *spec, const char *file) { struct mntentchn *mc, *mc0; mc0 = fstab_head(); /* first attempt: names occur precisely as given */ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) if (streq(mc->m.mnt_dir, file) && streq(mc->m.mnt_fsname, spec)) return mc; /* second attempt: names found after symlink resolution */ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) if ((streq(mc->m.mnt_dir, file) || streq(canonicalize(mc->m.mnt_dir), file)) && (streq(mc->m.mnt_fsname, spec) || streq(canonicalize(mc->m.mnt_fsname), spec))) return mc; /* third attempt: names found after LABEL= or UUID= resolution */ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) { if (!strncmp (mc->m.mnt_fsname, "LABEL=", 6) && (streq(mc->m.mnt_dir, file) || streq(canonicalize(mc->m.mnt_dir), file))) { if (has_label(spec, mc->m.mnt_fsname+6)) return mc; } if (!strncmp (mc->m.mnt_fsname, "UUID=", 5) &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -