【问题标题】:Is there a Linux C API call to query a mounted filesystem to see if it is read-only?是否有 Linux C API 调用来查询已挂载的文件系统以查看它是否为只读?
【发布时间】:2017-02-07 22:02:56
【问题描述】:

首先,一些背景信息为这个问题提供一些动机:我有一个程序在无头 Linux 服务器上运行,并在几个可移动外部硬盘驱动器上读取/写入文件,每个驱动器都使用 ext4 文件系统格式化.偶尔,这些驱动器之一上的文件系统元数据会因任何原因而损坏(尽管有 ext4 日志),这可能会导致 ext4 文件系统驱动器检测到问题并将分区重新挂载为只读,大概是为了防止级联错误损坏开车更远。

好的,很公平;但我现在想做的是在我的程序中添加一个功能,该功能可以检测驱动器何时处于这种重新安装的只读状态,以便它可以主动通知用户他的驱动器有问题。

我的问题是,查询文件系统以确定它是否以只读方式安装的优雅/受支持的方法是什么?

尝试将文件写入文件系统还不够好,因为这可能会由于其他原因而失败,而且如果我不需要,我也不想写入文件系统。

我的程序可以fopen("/proc/mounts", "r") 并解析它生成的文本行(在与我的分区对应的行上查找“rw”标记),如果必须的话,我会这样做,但这个解决方案似乎有点hacky(太像屏幕抓取,如果文本格式发生变化可能会破坏)。

那么,我可以使用一些轻量级/专用的 Linux 系统调用来告诉我给定的文件系统挂载点(例如“/dev/sda1”)当前是否以只读方式挂载? stat() 似乎可以做到这一点,但我不知道怎么做。

【问题讨论】:

  • 甚至还有一个 POSIX.1 函数可以做到这一点:statvfs() or fstatvfs() 在所需挂载上的任何文件上。如果.f_flag & ST_RDONLY,则以只读方式挂载。
  • 一个愚蠢的解决方案是使用access()
  • 旁注:如果您查看 statvfs 的手册页 [按照 Nominal Animal 的建议],它会注意到 older 版本的statvfs 通过解析/proc/mounts 收集了标志——所以你离得不远了。手册页还指出,statvfs 现在调用 linux 系统调用 statfs 来获取此信息。
  • @NominalAnimal 我认为您的评论包含我正在寻找的答案;如果您想将其重新发布为答案,我会标记它。

标签: c linux filesystems stat


【解决方案1】:

getmntent() family 应该可以满足您的需求。

姓名

getmntent, setmntent, addmntent, endmntent, hasmntopt, getmntent_r - 获取文件系统描述符文件条目

概要

   #include <stdio.h>
   #include <mntent.h>

   FILE *setmntent(const char *filename, const char *type);

   struct mntent *getmntent(FILE *stream);

   int addmntent(FILE *stream, const struct mntent *mnt);

   int endmntent(FILE *streamp);

   char *hasmntopt(const struct mntent *mnt, const char *opt);

   /* GNU extension */
   #include <mntent.h>

   struct mntent *getmntent_r(FILE *streamp, struct mntent *mntbuf,
                              char *buf, int buflen);

描述

这些例程用于访问文件系统描述文件 /etc/fstab 和挂载的文件系统描述文件 /etc/mtab。

setmntent() 函数打开文件系统描述文件 文件名并返回一个可以被 getmntent() 使用的文件指针。 参数类型是所需的访问类型,可以采用相同的 值作为 fopen(3) 的模式参数。

getmntent() 函数读取文件系统的下一行 来自流的描述文件并返回指向结构的指针 包含文件中某一行的细分字段。指针 指向内存的静态区域,该区域被后续的覆盖 调用 getmntent()。

addmntent()函数将mntent结构mnt添加到末尾 开放的流。

endmntent() 函数关闭与 文件系统描述文件。

hasmntopt() 函数扫描 mnt_opts 字段(见下文) mntent 结构 mnt 用于匹配 opt 的子字符串。看 和 mount(8) 获取有效的挂载选项。

可重入的getmntent_r()函数与getmntent()类似,但是 将 struct mount 存储在提供的 *mntbuf 中并存储字符串 由提供的数组 buf 中该结构中的条目指向 大小布伦。

mntent结构定义如下:

       struct mntent {
           char *mnt_fsname;   /* name of mounted filesystem */
           char *mnt_dir;      /* filesystem path prefix */
           char *mnt_type;     /* mount type (see mntent.h) */
           char *mnt_opts;     /* mount options (see mntent.h) */
           int   mnt_freq;     /* dump frequency in days */
           int   mnt_passno;   /* pass number on parallel fsck */
       };

...

【讨论】:

  • 听起来这会给我有关 /etc/fstab 内容的信息,如果文件系统已重新挂载为已读,则可能不一定与挂载文件系统的当前状态相同- 仅由于磁盘错误(?)
  • @JeremyFriesner 我不知道任何简单的方法来以编程方式确定文件系统是否由于磁盘错误而以只读方式重新安装,而不是尝试写入它。如果这是您必须满足的要求,您可能应该以某种方式对其进行测试。如果幸运的话,可见的安装选项将会改变。或者你可以问另一个后续问题 - 那里的人可能已经知道了。
  • getmntent 家族只是读取和解析/etc/fstab/etc/mtab(实际上是调用setmntent 时输入的任何文件),并且配对也非常简单 - 它读取文件行按行然后将行拆分为字段。不用说,程序员需要将拆分字段mnt_fsname 与要验证的文件系统进行比较,并且需要解析字符串以获取来自mnt_opts 的“ro”挂载选项。这不是一个好的解决方案,而 @Nominal Animal 的评论 statvfs() 或类似的评论更干净更好。
  • 要遵循getmntent() 的解决方案并解决问题(即检查文件系统是否以只读方式重新挂载),需要输入/etc/mtab,因为它是“挂载的文件系统描述文件”根据getmntent()的手册页。
【解决方案2】:

检查要写入的打开文件的文件系统是否已以只读方式挂载的最简单方法是检查errno 变量中的EROFS 错误。

如果您无法在该文件系统中拥有可写目录或文件,则您无法获得一种可移植的方式来检查文件系统是否已变为只读(如果由于设备错误而变为只读,则更多)

另一种方法是请管理员检查,或尝试自己阅读/proc/mounts文件。但这只是 linux 特有的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-18
    • 1970-01-01
    • 2011-03-09
    • 1970-01-01
    • 2022-06-20
    • 2020-02-19
    • 2016-03-16
    相关资源
    最近更新 更多