0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

如何写Linux下的tar打包软件?

Linux爱好者 来源:YongHao写东西的cache 作者:YongHao写东西的ca 2021-03-10 10:44 次阅读
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

相信你对 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 比较,复用旧的内容。

基本单位 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 《- time()

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 《- time()

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

”, 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

”, 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);

(*route_cnt)++;

}

}

以上几乎是 mkdir,rmdir,writefile,readfile,putfile 等等操作都要做的。

实现

然后,应该举一个 readfile 的例子就可以做代表了。

int recursive_dirinfo(SIFS_DIRBLOCK *cur_dir_block, char **route_names, int route_name_p, int route_cnt);

实现:

int recursive_dirinfo(SIFS_DIRBLOCK *cur_dir_block, char **route_names, int route_name_p, int route_cnt) {

for(int i=0; i《cur_dir_block-》nentries ; i++) {

int blockid = cur_dir_block-》entries[i].blockID;

if(bitmap[blockid]==SIFS_DIR) {

SIFS_DIRBLOCK dirblock;

int start = sizeof(SIFS_VOLUME_HEADER) + header.nblocks*sizeof(SIFS_BIT);

read_dir_block(vol, &dirblock, blockid * blocksize, start);

if(strcmp(dirblock.name, route_names[route_name_p]) == 0) {

if(route_name_p+2 == route_cnt) {

return do_read_file(cur_dir_block, route_names[route_name_p+1], blockid);

}

return recursive_dirinfo(&dirblock, route_names, route_name_p+1, route_cnt);

}

}

}

return 1;

}

以``。/sifs_put volumn ~/res.txt /dirB/subdirB/subsubdir/newfileB 为例子,如果递归找到 subsubdir`这个文件夹 block,进行相应操作:

•写文件就往 bitmap 一直找没有用过的 block,够写文件就写进去,文件夹更新一下信息。

•读文件就是根据此文件夹 block,找里面的 newfileB

int do_read_file(SIFS_DIRBLOCK *parent_dir, char *filename, int parent_dir_block) {

printf(“do_find_file_info, filename %s

”, filename);

for(int i=1; i《header.nblocks ; i++) {

SIFS_FILEBLOCK fileblock;

if(bitmap[i]==SIFS_FILE) {

int start = sizeof(SIFS_VOLUME_HEADER) + header.nblocks*sizeof(SIFS_BIT);

read_file_block(vol, &fileblock, i * blocksize, start);

*nbytes = fileblock.length;

int need_data_blocks = *nbytes / header.blocksize;

if(strcmp(fileblock.filenames[0], filename) == 0) {

for(int d_block_id = fileblock.firstblockID; d_block_id - i -1 《 need_data_blocks; d_block_id++) {

read_data_block(vol, (char*)(*data)+(d_block_id - i -1), blocksize, d_block_id * header.blocksize, start);

}

return 0;

}

}

}

return 1;

}

而真实的 tar 自然更复杂,还要记录用户权限、用户、group文件等等:

struct posix_header

{ /* byte offset */

char name[100]; /* 0 */ 文件名

char mode[8]; /* 100 */ 用户权限

char uid[8]; /* 108 */ user id

char gid[8]; /* 116 */ group id

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 */ user name

char gname[32]; /* 297 */ group name

char devmajor[8]; /* 329 */ 设备文件 major

char devminor[8]; /* 337 */ 设备文件 minor

char prefix[155]; /* 345 */

/* 500 */

};

文件类型标志定义,包含了所有 Unix 系统中的文件类型

#define REGTYPE ‘0’ /* regular file */

#define LNKTYPE ‘1’ /* link */

#define SYMTYPE ‘2’ /* reserved */

#define CHRTYPE ‘3’ /* character special */

#define BLKTYPE ‘4’ /* block special */

#define DIRTYPE ‘5’ /* directory */

#define FIFOTYPE ‘6’ /* FIFO special */

#define CONTTYPE ‘7’ /* reserved */

概览如此,写起来其实有点烦 - = -,有兴趣的读者可以写写。

原文标题:带你写一个 linux 下的打包软件 tar

文章出处:【微信公众号:Linux爱好者】欢迎添加关注!文章转载请注明出处。

责任编辑:haq

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • Linux
    +关注

    关注

    88

    文章

    11817

    浏览量

    219558
  • 软件
    +关注

    关注

    69

    文章

    5362

    浏览量

    91894

原文标题:带你写一个 linux 下的打包软件 tar

文章出处:【微信号:LinuxHub,微信公众号:Linux爱好者】欢迎添加关注!文章转载请注明出处。

收藏 人收藏
加入交流群
微信小助手二维码

扫码添加小助手

加入工程师交流群

    评论

    相关推荐
    热点推荐

    i.mx93 在 Linux 环境的 H.264 软件解码和编码能力怎么样?

    我知道 i.MX93 没有硬件编码器或解码器。 我想知道 i.mx93 在 Linux 环境的 H.264 软件解码和编码能力。 我的目标是 720P60。 有可能吗?
    发表于 04-23 09:30

    Linux系统配置FCB-EV9520L与LVDS转USB3.0编码采集模块教程

    Linux系统上运行LVDS转USB3.0编码采集模块涉及几个关键步骤,包括Linux环境配置、硬件连接、软件安装与配置以及测试。以下是一个基本的指南
    的头像 发表于 03-04 16:05 217次阅读
    <b class='flag-5'>Linux</b>系统<b class='flag-5'>下</b>配置FCB-EV9520L与LVDS转USB3.0编码采集模块教程

    linux的压缩和解压操作

    什么不同呢? 不同之处在于: 1) 一般情况,小文件使用gzip来压缩,大文件使用bzip2来压缩;2) bzip2 比 gzip 的压缩率更高。 3、 目录和多级目录的解压和压缩用 tar
    发表于 12-23 06:56

    【飞凌OK-T153 开发板试用】SDK初试

    SDK初试 编绎环境 硬件: x86_64虚拟机 软件: ubuntu 18.04 x64 SDK解压 tar jxvf OKT153-linux-sdk.tar.bz2.0* >
    发表于 11-14 05:17

    你觉得哪个软件verilog体验最好?有什么优势?

    你觉得哪个软件verilog体验最好?有什么优势?请在评论区留言跟大家分享一吧。
    发表于 11-10 07:47

    Linux搭建平台

    起因:本人用IDE感觉好不方便,所以配置了相关的Linux环境,Linx配置环境文档看得有点乱,索性整理了一。 环境是zsh,用bash的可以稍微改一。主要下载了nuclei-sdk
    发表于 11-05 09:00

    linux中使用env时如何下载软件包?

    在windows的env中可以直接使用pkgs —update去下载软件包,Linux环境这个指令好像不生效,那么Linux环境
    发表于 10-11 09:23

    dist打包好的工程,还能用env工具进行配置吗?

    就是我在BSP里面用scons —dist打包好一个工程后,把工程放到其它路径进行项目开发,中间需要用menuconfig进行配置,发现打不开了,想是不是打包出来的工程就无法配置了,请教一各位这种情况一般是怎么处理的?是重新
    发表于 09-24 08:18

    聊聊 Webpack 那些安全事儿:打包风险与防护小技巧

    Webpack 作为前端工程化的核心工具,几乎成为现代 Web 应用打包的标配。它通过模块合并、代码压缩、依赖管理等功能提升开发效率,但也因配置复杂、代码混淆等特性,潜藏着诸多安全风险。本文结合实战
    的头像 发表于 09-02 10:22 895次阅读
    聊聊 Webpack 那些安全事儿:<b class='flag-5'>打包</b>风险与防护小技巧

    FLASH烧/编程白皮书

    白皮书:如何烧Flash——不同场景不同需求的选择认识Flash NAND vs. NOR如何烧/编程不同方案比较
    发表于 07-28 16:05 0次下载

    【HZ-RK3568开发板免费体验】系统烧

    开发过程中也是常用的该方式。 笔者本文将讲解单个统一固件烧的方式,关于多个分区镜像烧将在系统移植讲解。 值得注意的是,通过统一固件解包/打包工具,可以把统一固件解包为多个分区镜像,也可以将多个分区
    发表于 07-25 09:40

    linux环境 软件启动失败怎么解决?

    anyway. /usr/lib/x86_64-linux-gnu/libproxy/libpxbackend-1.0.so: undefined symbol
    发表于 06-23 07:37

    dist打包好的工程,还能用env工具进行配置吗?

    就是我在BSP里面用scons —dist打包好一个工程后,把工程放到其它路径进行项目开发,中间需要用menuconfig进行配置,发现打不开了,想是不是打包出来的工程就无法配置了,请教一各位这种情况一般是怎么处理的?是重新
    发表于 06-13 07:59

    打包机数据采集远程监控系统方案

    在现代工业生产中,打包机作为产品包装环节的关键设备,其稳定运行和高效管理对于企业的生产效率和产品质量至关重要。然而,传统的打包机管理模式往往依赖人工巡检和现场操作,存在数据采集不及时、设备状态监控
    的头像 发表于 05-28 13:52 712次阅读
    <b class='flag-5'>打包</b>机数据采集远程监控系统方案

    Linux文件系统打包及镜像制作,触觉智能RK3562开发板演示

    本文介绍Linux开发板文件系统打包及镜像制作的方法,演示Linux文件系统打包及镜像制作,适用于想将配置好的系统环境打包成镜像批量烧录。触
    的头像 发表于 04-28 16:45 1165次阅读
    <b class='flag-5'>Linux</b>文件系统<b class='flag-5'>打包</b>及镜像制作,触觉智能RK3562开发板演示