tar 包的解析

Tar是Unix平台下非常流行的打包格式,该格式不负责压缩,只负责打包,简单的将多个文件或文件夹组合。
在这里插入图片描述

除了文件本身的数据,Tar还会使用“标头”来记录文件名、文件属性、大小等信息。拥有了这些信息,再加上文件本身的数据,便可以将打包前的文件及其目录结构还原出来。

/* typeflag:字段定义文件类型 */
#define  LF_OLDNORMAL '\0'       /* 普通磁盘文件,Unix兼容 */
#define  LF_NORMAL    '0'        /* 普通磁盘文件 */
#define  LF_LINK      '1'        /* 硬链接 */
#define  LF_SYMLINK   '2'        /* 符号链接(软链接) */
#define  LF_CHR       '3'        /* 字符设备文件 */
#define  LF_BLK       '4'        /* 块设备文件 */
#define  LF_DIR       '5'        /* 目录 */
#define  LF_FIFO      '6'        /* FIFO管道文件 */
#define  LF_CONTIG    '7'        /* 连续文件 */

不必了解其中的每一项代表什么含义,只需要关注以下几项:

name:文件名(路径)。
size:文件大小(文件数据部分的尺寸)。
typeflag:类型标志,标志该节点是一个普通文件,还是软连接抑或是目录等。
下面是我一个解析样例,可提取多级文件夹里的指定文件:

#include <stdio.h>
#include <io.h>
#include <string.h>
// #include <.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <fcntl.h>

#define min(a,b) (((a) < (b)) ? a : b)

struct posix_tar_header
{
	char name[100];
	char mode[8];
	char uid[8];
	char gid[8];
	char size[12];
	char mtime[12];
	char chksum[8];
	char typeflag;
	char linkname[100];
	char magic[6];
	char version[2];
	char uname[32];
	char gname[32];
	char devmajor[8];
	char devminor[8];
	char prefix[155];
};

int main(int argc,char *argv[])
{
	if (argc != 3)
	{

		printf("请输入文件: argc[%d] \n",argc);
		exit(1);
	}
	printf("[解压文件: %s\n",argv[1]);
	int fd = open(argv[1],O_RDWR);
	
	char buf[1024*4];
	int chunk = sizeof(buf);

	while(1)
	{
		read(fd,buf,512);//读取tar header
		if (buf[0] == 0)
			break;
		
		struct posix_tar_header *phdr = (struct posix_tar_header*)buf;
		
		//从tar header头得到size
		char *p = phdr->size;
		int f_len = 0;
		int ret;
		while(*p)//8进制->10进制
			f_len = (f_len * 8) + (*p++ - '0');

		//printf("typeflag=%d,f_len=%d\n",phdr->typeflag,f_len);

		int bytes_left = f_len;//此文件大小
		if(phdr->typeflag =='5')   //文件夹
		{
			printf("	%s (%d bytes)\n",phdr->name,f_len); 
			#if 0
			ret= mkdir(phdr->name);
			if(ret!=0)
		    {
			   printf("	mkdir %s failed\n",phdr->name);
			   return 0;
			}
			#endif
		}
		else 
		{
			//比较文件名和指定文件名是否相同
			char *filename= strrchr(phdr->name, '/')+1;
			//printf("filename[%s],argv[%s]\n",filename,argv[2]);
			if((strcmp(filename,argv[2]))!=0)
			{
				while(bytes_left)
				{
					int iobytes = min(chunk,bytes_left);
					read(fd,buf,((iobytes - 1) / 512 + 1) * 512);
					bytes_left -= iobytes;
				}
			}
			else
			{
				int fdout = open(filename,O_CREAT|O_TRUNC|O_RDWR,0777);
				if (fdout == -1)
				{
					printf("	failed to extract file: %s\n",phdr->name);
					printf("	fdout open failed\n");
					return 0;
				}		
				while(bytes_left)
				{
					int iobytes = min(chunk,bytes_left);
					//read(fd,buf,iobytes);
					read(fd,buf,((iobytes - 1) / 512 + 1) * 512);
					write(fdout,buf,iobytes);
					bytes_left -= iobytes;
				}
				close(fdout);
			}
		}
		
	}
	close(fd);
	printf("done]\n");
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值