tar文件格式解析

源文地址:http://www.fileformat.info/format/tar/corion.htm

TAR是磁带存档程序 (tape archiver) 的首字母缩写。
Unix Tar是将多个文件存储为未压缩的单个文档文件的程序。

1.标准格式
    单个tar文件包含多个记录,单个记录包含512个字节。虽然这种格式用于磁带上,但是也常用于其他媒体。
    一个头记录代表单个归档的文件,记录后紧接着为0或者文件内容。在tar文件结尾可能包含一个以0填充的记录,
一个合理的系统应该在tar文件结尾写入这样的记录,但是在读取tar文件时,不能假设一定存在这样的记录。
    这些记录也许为了物理I/O操作,每个块由N个记录组成(N由tar命令可选参数-b指定),每个块由系统接口write一次性写入。
在磁带媒介上,一次写入即为一个磁带记录。在写tar文件时,最后一个记录块应该是一个完整块大小,不足时以0填充的记录。
在读取tar文件时,合理的系统应该正确处理其最后一个块的归档是短于其他记录,还是在以0填充的记录后包含多余的记录块。

头记录以C形式定义如下:
/*
* Standard Archive Format - Standard TAR - USTAR
*/
#define  RECORDSIZE  512
#define  NAMSIZ      100
#define  TUNMLEN      32
#define  TGNMLEN      32

union record {
    char        charptr[RECORDSIZE];
    struct header {
        char    name[NAMSIZ];
        char    mode[8];
        char    uid[8];
        char    gid[8];
        char    size[12];
        char    mtime[12];
        char    chksum[8];
        char    linkflag;
        char    linkname[NAMSIZ];
        char    magic[8];
        char    uname[TUNMLEN];
        char    gname[TGNMLEN];
        char    devmajor[8];
        char    devminor[8];
    } header;
};

/* 当计算校验和时,checksum字段用CHKBLANKS进行计算 */
#define    CHKBLANKS    "        "        /* 8个空格, 无结尾符 */

/* 如果uname和gname有效,magic字段使用TMAGIC填充*/
#define    TMAGIC    "ustar  "        /* 7个字符和1个结尾符 */

/* 如果是GNU格式转储条目,magic字段使用GNUMAGIC填充 */
#define    GNUMAGIC  "GNUtar "        /* 7个字符和1个结尾符 */

/* linkflag字段定义文件类型 */
#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'        /* 连续文件 */

/* Further link types may be defined later. */

/* 位定义用于mode字段 - 8进制值 */
#define  TSUID    04000        /* 设置UID可执行权限 */
#define  TSGID    02000        /* 设置GID可执行权限 */
#define  TSVTX    01000        /* 设置粘滞位 */

/* 文件权限 */
#define  TUREAD   00400        /* 拥有者可读 */
#define  TUWRITE  00200        /* 拥有者可写 */
#define  TUEXEC   00100        /* 拥有者可执行/搜索 */
#define  TGREAD   00040        /* 同组用户可读 */
#define  TGWRITE  00020        /* 同组用户可写 */
#define  TGEXEC   00010        /* 同组用户可执行/搜索 */
#define  TOREAD   00004        /* 其他用户可读 */
#define  TOWRITE  00002        /* 其他用户可写 */
#define  TOEXEC   00001        /* 其他用户可执行/搜索 */

    在头记录中的所有字符均使用8位本地ASCII编码。结构体中每个字段都是连续的,即结构中没有冗余数据。
媒介上的每个字符都连续存放。
    在每个文件的头记录后,存放的文件内容没有经过任何方式的转换和任何字符集的限制。tar格式不区分文本文件
和二进制文件,不会进行文件内容的转译。
    结构体header中的name、linkname、magic、uname和gname都是以'\0'为结尾的字符串,其他所有字段均以八进制的0填充。
size和mtime字段包含额外一个空格,其他的数字字段宽度包含两个额外数字位:空格和结尾符。
    字段name代表文件路径,可能包含目录前缀(以/分隔)。字段mode的9个bit位用于记录文件权限,3个bit位用于记录文件UID、GID和粘滞位。
当在给定模式下创建需要特别权限的文件,而从存档中还原文件的用户没有相应的权限时,指定特殊权限的模式位将被忽略。从存档文件中还原文件时,
系统不支持的模式将被忽略。当创建或更新存档文件时,不支持的模式应该自行构造数据。比如组权限可以从其他权限复制。
    uid和gid字段是分别对应文件所有者的ID和组ID。如果操作系统不支持文件所有者的ID和组ID,这些字段应忽略。
    size字段是以字节为单位的文件大小;存档中的软链接文件的size字段为0。
    mtime字段是存档时文件的修改时间,以八进制的ASCII编码,表示为自1970年1月1日00:00起的协调世界时,所经过的秒数。
    chksum字段是以八进制的ASCII编码一个头记录中所有字节的累加值。头记录中的每个字节以无符号整数进行累加,累加值初始为零,其精度不小于
17个比特位。在计算校验和时,chksum字段每个字节被视为空格符。
    字段typeflag指定文件的类型。在提取文件时,如果系统不支持指定的文件类型,则该文件将被视为普通文件,并打印警告信息到标准错误输出。
LF_NORMAL、LF_OLDNORMAL:
    普通文件,为了兼容老版本的tar命令,当字段typeflag值为LF_OLDNORMAL时,应认定为普通文件。新的归档文件应该设置此字段为LF_NORMAL。
同时为了向后兼容,tar将名字以'/'结尾的目录视为普通文件。
LF_LINK:
    硬链接,源文件和链接文件具有相同的设备和inode值。链接名由字段linkname指定,以'\0'为结尾符。
LF_SYMLINK:
    软链接,链接名由字段linkname指定,以'\0'为结尾符。
LF_CHR、LF_BLK:
    分别代表字符设备和块设备文件类型,字段devmajor和devminor分别代表主设备号和副设备号。
LF_DIR:
    目录或子目录,目录名由字段name指定,以'/'结尾。在系统上,目录相应磁盘分配是基于字段size,分配到最近的大小合适磁盘块。
若字段size为0表示没有这样的限制;若系统不支持此种策略,字段size将被忽略。
LF_FIFO:
    FIFO管道文件,FIFO管道文件的归档只保存文件记录,而不会保存文件内容。
LF_CONTIG:
    连续文件,在不支持连续文件的系统上,此类文件与普通文件一样;否则它占用的物理磁盘空间都是连续的。不支持空间连续分配的系统应将此类型文件视为普通文件。

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以使用 Apache Commons Compress 库来解析tar文件并读取其中的内容。以下是一个示例代码: ```java import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import org.apache.commons.compress.archivers.tar.TarArchiveEntry; import org.apache.commons.compress.archivers.tar.TarArchiveInputStream; public class TarReader { public static void main(String[] args) { Path tarFilePath = Paths.get("path/to/tar/file.tar"); try (InputStream is = new FileInputStream(tarFilePath.toFile()); TarArchiveInputStream tais = new TarArchiveInputStream(is)) { TarArchiveEntry entry; while ((entry = tais.getNextTarEntry()) != null) { if (entry.isFile()) { // 只读取文件类型的条目 byte[] content = new byte[(int) entry.getSize()]; tais.read(content, 0, content.length); String fileName = entry.getName(); System.out.println("File name: " + fileName); System.out.println("File content: " + new String(content)); } } } catch (IOException e) { e.printStackTrace(); } } } ``` 在以上示例代码中,我们首先创建一个 `TarArchiveInputStream` 对象,它需要一个 `InputStream` 对象作为参数。然后我们通过 `getNextTarEntry()` 方法读取tar文件中的下一个条目,如果该条目是一个文件类型,则读取该文件内容并输出。需要注意的是,tar文件中的文件名和内容都是通过 `TarArchiveEntry` 对象来获取的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值