可有效存储在 tar 存档标头的大小字段中的最大无符号整数是多少

Posted

技术标签:

【中文标题】可有效存储在 tar 存档标头的大小字段中的最大无符号整数是多少【英文标题】:what is the largest unsigned integer that is valid to store in the size field of a tar archive header 【发布时间】:2018-10-25 16:36:36 【问题描述】:

在 POSIX tar 归档格式here 的 GNU 规范中,标头结构定义为:

struct posix_header
                              /* byte offset */
  char name[100];               /*   0 */
  char mode[8];                 /* 100 */
  char uid[8];                  /* 108 */
  char gid[8];                  /* 116 */
  char size[12];                /* 124 */
  char mtime[12];               /* 136 */
  char chksum[8];               /* 148 */
  char typeflag;                /* 156 */
  char linkname[100];           /* 157 */
  char magic[6];                /* 257 */
  char version[2];              /* 263 */
  char uname[32];               /* 265 */
  char gname[32];               /* 297 */
  char devmajor[8];             /* 329 */
  char devminor[8];             /* 337 */
  char prefix[155];             /* 345 */
                                /* 500 */
;

标头的size 字段定义为长度为12 的char 数组,该字段的字节长度似乎为12 个字节(由字节偏移注释推断)。这在理论上提供了 12 个字节(=96 位)的空间来存储无符号整数。但是,我怀疑情况并非如此。

最大大小值是否仅等于 12 位 (999,999,999,999)?或者 由于这个大小值表示文件中的字节数,这是否意味着由于数据大小可能等于不能被 8 整除的位数,所以该大小值可能不完全准确?还是文件总是以 8 位的增量保存(将未使用的位填充以填充整个字节),因此位的数据长度总是可以被 8 整除?

【问题讨论】:

This reference 应该会有所帮助。 【参考方案1】:

根据standard documentation

namelinknamemagicunamegname 是以 null 结尾的字符串。所有其他字段都是 ASCII 中的零填充八进制数。 由于历史原因,还应使用最终的 NUL 或空格字符。

因此,11 个字节为您提供 11 个八进制数字(0..777777777778,或 0..0x1FFFFFFFF 范围),您的程序需要以您认为合适的方式将其转换为二进制表示- 例如,像这样:

uint64_t size;
sscanf(header->size, "%" SCNo64 "", &size);

Demo.

【讨论】:

这是否意味着每个字节都包含一个 ascii 字符,其字符值是 0 到 7 之间的数字?并且这 11 个字符代表一个八进制数(以 8 为基数的数字)?因此,您将采用以 8 为底的数字并将其转换为以 10 为底的数字以获得文件的“正常”字节数?因此 77777777777 (base-8) = 8589934591(base-10) 将是最大值? 那么大小会不到 8 GB? @Rafe 是的,每个字节都包含一个 ascii 字符,代表一个数字 '0''7'(含),前导零用于填充长度,第 12 个字节中有一个空终止符。 8589934591(十进制)是最大值,最大大小为 8GB。 酷。对他们为什么选择八进制数字有任何见解吗?一个字节中没有足够的空间来存储较大数字基数的一位数吗? @Rafe 我知道 PDP-11 人喜欢八进制,因为您可以相对轻松地读取 base-8 中的机器代码 (how?)。我怀疑这就是八进制表示首先成为 C 标准的原因。标题是由同一个人在 70 年代后期开发的,所以我唯一的猜测是他们选择八进制是出于个人喜好,而不是出于任何技术原因。【参考方案2】:

标头中的每个字段都存储为以空字符结尾的字符串。在文件大小的情况下,它被存储为一个八进制字符串。

因此,您总共有 11 个八进制字符(为空字节留出空间),这意味着文件大小为 33 位,或最多 8GB。

【讨论】:

以上是关于可有效存储在 tar 存档标头的大小字段中的最大无符号整数是多少的主要内容,如果未能解决你的问题,请参考以下文章

提取存储在 tar 存档中的文件的先前版本

为啥将用户标识符存储在 HTTP 请求标头字段中被认为是无状态的,但将其存储在 URI 中却不是?

mysql 字段类型详解

关于数据库中的字段的大小定义

如何使用 Java(apache 压缩)在 Windows 中创建“有效”的 unix TAR 存档?

如何使用 bash 从 tar.gz 存档中列出目录大小