linux 写个小软件,教你写一个 linux 下的打包软件 tar.md

教你写一个linux 下的打包软件 tar.md

相信你对 linux 的 .tar.gz 有点熟悉,这就是先 tar 打包(.tar 后缀),再对此 tar 文件用 gzip压缩(.tar.gz)的后缀名。

值得注意的是, tar不是压缩软件,它只做把一堆文件/文件夹打包到一个文件(tar 文件)里的事情,而文件联系,文件权限,相对的路径等都会给你保存好。

一开始设计是 tar 跟 gzip只做一件事情,各司其事,后来发现太麻烦了,于是就把压缩功能整合到 tar 里了。

- Create a gzipped archive:

tar czf target.tar.gz file1 file2 file3

最近学习 OS 时写了一个类似tar的项目,那么今天就趁热打铁简单说一下如何写一个打包软件,这个软件会将重复的文件内容通过 md5 比较,复用旧的内容。

b13a859e1422dc8f68545f964be01a04.png

基本单位 block

block 可以理解为文件系统的最小单位,分别有以下类型:

directory block,文件夹 block,存储文件夹 meta 信息;

file block,文件 block,存储文件 meta 信息;

data block,只用来存文件内容;

Directory block,注意的是 entry 里要有 fileindex 来存储重复文件的 name 的下标。

同时,给 项目一个 root dir。

typedef struct {

char name[SIFS_MAX_NAME_LENGTH]; // name of the directory

time_t modtime; // time last modified

uint32_t nentries;// 文件夹内的文件/文件夹数量

struct {

SIFS_BLOCKID blockID; // subdirectory 或者 file 的 blockID

uint32_t fileindex; // 重复文件的不同名字

} entries[SIFS_MAX_ENTRIES];

} SIFS_DIRBLOCK;

文件 Block,length 就是有多少 bytes 的文件内容,之后用来算有多少个 data block,firstblockID记录第一个数据 block 的 id,nfiles 记录有多少重复内容的文件数量了,filenames 就是重复此文件 block 的文件内容的文件名字。

typedef struct {

time_t modtime; // time first file added

size_t length; // length of files' contents in bytes

unsigned char md5[MD5_BYTELEN];//the MD5 cryptographic digest (a summary) of the files' contents

SIFS_BLOCKID firstblockID;// the block number (blockID) of the files' first data-block

uint32_t nfiles; // n files with identical contents

char filenames[SIFS_MAX_ENTRIES][SIFS_MAX_NAME_LENGTH];// an array of each same file's name and its modification time.

} SIFS_FILEBLOCK;

bitmaps数组,记录了每个 block 的类型,有:文件、文件夹以及data block 三种类型。

通用函数

就让大家看看关键函数好了:

读 tar 后的文件的 meta 头,记录了 block 的大小( blocksize) 以及多少个 blocks。

void read_vol_header(FILE *vol, SIFS_VOLUME_HEADER *header) {

fread(header, sizeof(SIFS_VOLUME_HEADER), 1, vol);

printf("header->blocksize %zu, header->nblocks %u\n", header->blocksize , header->nblocks);

}

bitmap,每次操作 tar 文件都要读的。

void read_bitmap(FILE *vol, SIFS_BIT *bitmap, int nblocks) {

int size = nblocks * sizeof(SIFS_BIT);

fread(bitmap, size, 1, vol);

}

root_block同理,读和写啥东西都要从 root block、root dir 出发。

void read_root_block(FILE *vol, SIFS_DIRBLOCK *dirblock){

fread(dirblock, sizeof(SIFS_DIRBLOCK), 1, vol);

printf("read_root_block finish, dirblock.name: %s, dirblock.entrieds: %d, dirblock.modtime %ld\n", dirblock->name, dirblock->nentries,dirblock->modtime);

}

路径嘛,你懂的,./sifs_put volumn ~/res.txt /dirB/subdirB/subsubdir/newfileB,要读的内容可以靠 read 函数解决,但是写到 tar 文件里的就要手动解析递归查路径了。

```

void read_route_names(char* pathname, char** route_names, int *route_cnt) {

char *dir;

char pathname_to_split = copyStr(pathname);

strcpy(pathname_to_split, pathname);

while ((dir = strsep(&pathname_to_split, "/")) != NULL) {

route_names[route_cnt] = copyStr(dir);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值