目录
拥有者、所属组、其他人的八进制权限(char ar_mode[8])
1.知识回顾
之前在OS39.【Linux】动态库和静态库 自制静态库文章提到过使用ar -rc命令生成静态库,即将所有o文件的集合(不含main函数的源文件生成的o文件)打包(ar命令)为静态库
其实ar命令不仅仅能打包o文件,准确来说,ar命令的作用是"create, modify, and extract from archives",即创建、修改、解压归档文件
博主比较好奇,就研究了一下ar归档文件的格式
2.archives是什么
百度翻译对archive的解释:

man手册对archives的描述:
The GNU ar program creates, modifies, and extracts from archives. An archive is a single file holding a collection of other files in a structure that makes it possible to retrieve the original individual files (called members of the archive).
archives定义:
1.归档是一个单一文件,以一种结构包含一组其他文件
2.这种结构可以检索出(retrieve)原始各个文件(称为归档成员文件)
man手册对文件内容的描述:
The original files' contents, mode (permissions), timestamp, owner, and group are preserved in the archive, and can be restored on extraction.
可以看出"归档是一个单一文件,以一种结构包含一组其他文件"中的结构还含有其他内容,例如模式(权限),时间戳,所有者,所属组,还有文件的原始内容,说明: 归档文件中含有的其他文件没有经过压缩
3.ar命令打包非链接文件
从以上分析可以看出ar命令不仅仅可以打包链接文件,还可以打包非链接文件
ar命令特别说明
ar命令不是从Linux才有的,其实早在Unix就已经出现了ar命令\,可以参考Unix早期版本的源代码:
Unix版本树:
https://www.tuhs.org/cgi-bin/utree.pl
Unix V10源代码:
准备工作
现将3个文件打包为一个归档文件
文件1: test.txt
teststring
文件2: test.bin
四字节的十六进制数据
0xAA 0xBB 0xCC 0xDD
printf '\xAA\xBB\xCC\xDD' > test.bin
文件3: test.c
int main()
{
return 0;
}

修改test.bin的拥有者为root:
sudo chown root test.bin

test.bin添加可执行权限:
sudo chmod a+x test.bin

修改test.txt的所属组为root:
sudo chgrp root test.txt

打包为test.a:
ar -rc test.a test.txt test.c test.bin

使用file命令分析test.a:
test.a是一个ar命令生成的归档文件
![]()
十六进制分析test.a
十六进制编辑器打开test.a,这里使用Windows下的HxD:

归档文件头(魔数)
文件开头的字节就是归档文件的魔数,用来表明这是一个归档文件
是!<arch>还是!<arch>加上后面的0x0A呢? 换句话说,是下图的哪种情况?

由于ar命令是Unix引入的,那么这要查Unix源码了,在Unix V10的/cmd/asd/ar.h中:
#define ARMAG "!\n"
#define SARMAG 8
#define ARFMAG "`\n"
struct ar_hdr {
char ar_name[16];
char ar_date[12];
char ar_uid[6];
char ar_gid[6];
char ar_mode[8];
char ar_size[10];
char ar_fmag[2];
};
这个ARMAG是ARchive MAGic number(归档文件魔数)的缩写,其为"!<arch>\n",需要带上\n,而且\n的ASCII码为0x0A
那么这个图是对的:

文件内容
原来没有归档时的文件内容:



对应到下图红框部分:

注意:所有数据按偶字节边界对齐,即每个成员(归档文件头 + 归档文件内容)的起始偏移必须是2的倍数,因此某些情况下,文件内容的末尾会添加0x0A用于对齐,就像上图的那样
元数据
上方代码的struct ar_hdr结构体ar_hdr是archive_header的缩写,即归档文件头,存储这每个文件的元数据(meta data),有心的读者可能会去算这个结构体的大小:
#include
struct ar_hdr {
char ar_name[16];
char ar_date[12];
char ar_uid[6];
char ar_gid[6];
char ar_mode[8];
char ar_size[10];
char ar_fmag[2];
};
int main()
{
std::cout<
运行结果:

占60字节,对应到test.a,从文件名开始,到文件内容前,统计字节数:
0x43-0x08+1==0x3C==十进制的60

0x8B-0x50+1==0x3C==十进制的60

0xE5-0xAA+1==0x3C==十进制的60

发现从文件名开始,到文件内容前这部分占的字节数都是60,恰为struct ar_hdr结构体的大小
结论: 显然这部分内容就是每个文件的struct ar_hdr结构体实例化后的内容
有了这个结构体就能解析struct ar_hdr结构体的各个字段了
文件名(char ar_name[16])
下图黄框部分:

Unix源代码的/cmd/ar.c是这样打印归档文件中的各个文件名的:
char *
trim(s)
char *s;
{
register char *p1, *p2;
for(p1 = s; *p1; p1++)
;
while(p1 > s) {
if(*--p1 != '/')
break;
*p1 = 0;
}
p2 = s;
for(p1 = s; *p1; p1++)
if(*p1 == '/')
p2 = p1+1;
return(p2);
}
结论: 文件名的结尾是/
时间戳(char ar_date[12])
下图紫框部分:

UID(char ar_uid[6])
下图橙框部分:

GID(char ar_gid[6])
下图灰框部分:

拥有者、所属组、其他人的八进制权限(char ar_mode[8])
下图蓝框部分:

文件大小(char ar_size[10])
文件大小是以ASCII码的形式呈现的,下图棕框部分:

ar_fmag
这个ar_fmag是每个归档文件头末尾必须要有的,在https://unix.org/whitepapers/ar-format.html网站中有说明:

例如在Unix V10源码的/cmd/ar.c的getdir()函数中(截取部分代码):
if (strncmp(arbuf.ar_fmag, ARFMAG, sizeof(arbuf.ar_fmag))) {
fprintf(stderr, "ar: malformed archive (at %ld)\n", lseek(af, 0L, 1));
done(1);
}
会发现strncmp将arbuf.ar_fmag和宏ARFMAG比较,而ARFMAG会被替换为0x60 0x0A,也就是/cmd/asd/ar.h中定义的:
#define ARFMAG "`\n"
所有元数据一览
下图的每一格中的数据代表一个字节,用十六进制表示
21 3C 61 72 63 68 3E 0A 74 65 73 74 2E 74 78 74 2F 20 20 20 20 20 20 20 30 20 20 20 20 20 20 20 20 20 20 20 30 20 20 20 20 20 30 20 20 20 20 20 36 34 34 20 20 20 20 20 31 31 20 20 20 20 20 20 20 20 60 0A 74 65 73 74 73 74 72 69 6E 67 0A 0A 74 65 73 74 2E 63 2F 20 20 20 20 20 20 20 20 20 30 20 20 20 20 20 20 20 20 20 20 20 30 20 20 20 20 20 30 20 20 20 20 20 36 34 34 20 20 20 20 20 32 39 20 20 20 20 20 20 20 20 60 0A 69 6E 74 20 6D 61 69 6E 28 29 0A 7B 0A 20 20 20 20 72 65 74 75 72 6E 20 30 3B 0A 7D 0A 0A 74 65 73 74 2E 62 69 6E 2F 20 20 20 20 20 20 20 30 20 20 20 20 20 20 20 20 20 20 20 30 20 20 20 20 20 30 20 20 20 20 20 36 34 34 20 20 20 20 20 34 20 20 20 20 20 20 20 20 20 60 0A AA BB CC DD
浙公网安备 33010602011771号