gpt4 book ai didi

c - 如何在 dev_t 和主要/次要设备号之间进行转换?

转载 作者:太空狗 更新时间:2023-10-29 14:55:55 25 4
gpt4 key购买 nike

我正在尝试编写一个处理 ustar 文件的可移植程序。对于设备文件,这些存档存储主要次要设备编号。但是,POSIX 中规定的struct stat 仅包含单个 st_rdev 类型 dev_t 的成员,用“设备 ID(如果文件是字符或 block 特殊文件)”描述。

如何以可移植的方式在一对主要和次要设备编号与 stat() 返回的单个 st_rdev 成员之间进行转换?

最佳答案

虽然所有 POSIX 编程接口(interface)都按原样使用设备号(类型为 dev_t ),但 FUZxxl 在对该答案的评论中指出,常见的 UStar 文件格式——最常见的 tar 存档格式——确实将设备号拆分为主要和次要。 (它们通常每个编码为七个八进制数字,因此出于兼容性原因,应该限制为 21 位无符号主要和 21 位无符号次要。这也意味着将设备号映射到主要或次要不是可靠的方法。)

以下包括在 Jonathon Reinhart's answer 上扩展的文件,在网上挖掘各种系统手册页和文档(makedev()major()minor())后,加上对此问题的评论。

#if defined(custom_makedev) && defined(custom_major) && defined(custom_minor)
/* Already defined */
#else

#undef custom_makedev
#undef custom_major
#undef custom_minor

#if defined(__linux__) || defined(__GLIBC__)
/* Linux, Android, and other systems using GNU C library */
#ifndef _BSD_SOURCE
#define _BSD_SOURCE 1
#endif
#include <sys/types.h>
#define custom_makedev(dmajor, dminor) makedev(dmajor, dminor)
#define custom_major(devnum) major(devnum)
#define custom_minor(devnum) minor(devnum)

#elif defined(_WIN32)
/* 32- and 64-bit Windows. VERIFY: These are just a guess! */
#define custom_makedev(dmajor, dminor) ((((unsigned int)dmajor << 8) & 0xFF00U) | ((unsigned int)dminor & 0xFFFF00FFU))
#define custom_major(devnum) (((unsigned int)devnum & 0xFF00U) >> 8)
#define custom_minor(devnum) ((unsigned int)devnum & 0xFFFF00FFU)

#elif defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
/* FreeBSD, OpenBSD, NetBSD, and DragonFlyBSD */
#include <sys/types.h>
#define custom_makedev(dmajor, dminor) makedev(dmajor, dminor)
#define custom_major(devnum) major(devnum)
#define custom_minor(devnum) minor(devnum)

#elif defined(__APPLE__) && defined(__MACH__)
/* Mac OS X */
#include <sys/types.h>
#define custom_makedev(dmajor, dminor) makedev(dmajor, dminor)
#define custom_major(devnum) major(devnum)
#define custom_minor(devnum) minor(devnum)

#elif defined(_AIX) || defined (__osf__)
/* AIX, OSF/1, Tru64 Unix */
#include <sys/types.h>
#define custom_makedev(dmajor, dminor) makedev(dmajor, dminor)
#define custom_major(devnum) major(devnum)
#define custom_minor(devnum) minor(devnum)

#elif defined(hpux)
/* HP-UX */
#include <sys/sysmacros.h>
#define custom_makedev(dmajor, dminor) makedev(dmajor, dminor)
#define custom_major(devnum) major(devnum)
#define custom_minor(devnum) minor(devnum)

#elif defined(sun)
/* Solaris */
#include <sys/types.h>
#include <sys/mkdev.h>
#define custom_makedev(dmajor, dminor) makedev(dmajor, dminor)
#define custom_major(devnum) major(devnum)
#define custom_minor(devnum) minor(devnum)

#else
/* Unknown OS. Try a the BSD approach. */
#ifndef _BSD_SOURCE
#define _BSD_SOURCE 1
#endif
#include <sys/types.h>
#if defined(makedev) && defined(major) && defined(minor)
#define custom_makedev(dmajor, dminor) makedev(dmajor, dminor)
#define custom_major(devnum) major(devnum)
#define custom_minor(devnum) minor(devnum)
#endif
#endif

#if !defined(custom_makedev) || !defined(custom_major) || !defined(custom_minor)
#error Unknown OS: please add definitions for custom_makedev(), custom_major(), and custom_minor(), for device number major/minor handling.
#endif

#endif

人们可以从现有的支持 UStar 格式的存档器中收集更多的定义。在我看来,与每个操作系统/架构上的现有实现的兼容性是这里最重要的事情。

以上内容应涵盖所有使用 GNU C 库、Linux(包括 Android)、FreeBSD、OpenBSD、NetBSD、DragonFlyBSD、Mac OS X、AIX、Tru64、HP-UX 和 Solaris 的系统,以及任何定义宏的系统包括 <sys/types.h>。对于 Windows 部分,我不确定。

据我了解,Windows 对所有普通文件使用设备 0,对设备使用 HANDLE(空指针类型)。我完全不确定上述逻辑在 Windows 上是否合理,但许多旧系统将设备号的 8 位最低有效位放入次要位,然后将接下来的 8 位放入主要位,惯例似乎是任何剩余位也会被(不转移)变成小调。检查现有的 UStar 格式的 tar 存档并引用设备会很有用,但我个人根本不使用 Windows。

如果未检测到系统,并且系统不使用 BSD 样式的包含来定义宏,则上述将出错并停止编译。 (我个人会添加编译时机制,以帮助找到正确的 header 定义,使用例如 findxargsgrep ,以防万一,并建议将添加也发送到上游。touch empty.h ; cpp -dM empty.h ; rm -f empty.h 应该显示所有预定义的宏,帮助识别操作系统和/或 C 库。)

最初,POSIX 声明 dev_t 必须是算术类型(因此,理论上,在某些系统上它可能是 floatdouble 的某种变体),但 IEEE Std 1003.1, 2013 Edition 声明它必须是整数类型。我敢打赌,这意味着没有任何已知的 POSIX-y 系统使用过浮点 dev_t 类型。看起来 Windows 使用空指针或 HANDLE 类型,但 Windows 无论如何都不符合 POSIX。

关于c - 如何在 dev_t 和主要/次要设备号之间进行转换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35392291/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com