其实tar的原理很简单: comment by bob 2006-8-3 11:48
tar文件的构成:
tar文件最顶端是512字节的header ,里面记录了对应的file的stat信息,比如uid,gid,mode等等
然后是文件正文内容
如果tar里面包含了其他的文件的话, 又是一个header ,剩下的又是文件正文
..........................
最后tar文件的末尾是 最少 1024个字节的 '\0' 表示tar结尾。当然一般情况下是 10240个bytes 0
--------------------------------------------------------------------------------------------
tar 源码分析:
因为基础上面的结构,所以tar的source code 就比较容易理解了:
tar 采用了block和record的概念
record = 20 个 block (default)
源码里面用20个block的连续的buffer来存储tar fd中的内容,当然一旦这20个block没用,就会flush,又从
tar fd中读10240 个字节到这20个blocks中来。
其中最重要就是 current_header , 是最开始 20个blocks中的第一个,对应了 tar_stat_info->header
如果想了解tar文件包含的文件信息, 就可以读取这个header (调用print_header可以打印出来)
如果要从tar文件中extract某个file ,也很简单, 只需要从第二个block开始读即可了,一直读current_stat_info->stat->st_size
个字节就可以了(因为我们的tar文件中只含有一个file,所以不必考虑后面的 10240个 '\0' 了
标准的tar生成的tar包的size总是 10240的倍数,所以一个tar包,的最小大小总是 10240 ,即使一个file很小。
--
去年的时候,根据备份的需要的,我把tar精简了一下,适合嵌入式应用
做成了库德形式,
类似这样:
OpenArchive();//Open or Create one Archive File
GetElementInfo();//Get information of one element in the archive including timestamp, type, size.
DeleteElement();//Delete one element from one archive.
AddFileToArchive();//Add one element to one archive.
CloseArchive();//Close one archive.
FindFirstElement();//Get information of first element from the archive.
ExtractElement(); //Extract one element from the archive.
---
简单的测试程序:
|
#include "app.h"
#include "archive.h"
//example.c
int main(int argc, char **argv)
{
struct stat stat_file;
int fd = -1;
int rc = 0;
S_archive_stat_info *ft = NULL;
//fd = OpenArchive("/tmp/1/kk.tar.gz","w");
fd = OpenArchive(argv[2],"w");
printf("has called OpenArchive () \n");
printf("in main fd=%d\n",fd);
if(fd < 0) {
//fatal_error("can't open /var/bob.tar.gz\n");
return -1;
}
printf("sizeof S_archive_stat_info =%d\n",sizeof(S_archive_stat_info));
printf("size of tar_stat_info = %d\n",sizeof(struct tar_stat_info));
stat(argv[1] , &stat_file);
printf("stat.st_mtime = %ld\n",stat_file.st_mtime );
printf("open OK \n");
rc = AddFileToArchive(fd,argv[1]);
printf("rc = %d\n",rc);
if(rc < 0) {
//有可能是磁盘满了,要判断这个错误
//直接返回即可,不必CloseArchive()了, 因为处理处理代码,我已经加上了。
return -1;
}
CloseArchive(fd);
return 0;
}
|