c - 如何打印存档文件中的文件名?

标签 c operating-system stat

我是 C 语言和系统编程的新手。我想打开一个存档文件并打印出存档文件中的文件名(例如,我的存档文件是 weds.a;在 weds.a 中,我有 thurs.txt 和 fri.txt”。我想创建显示的输出 周四.txt 星期五.txt

已编辑:它应该像 ar -t 命令一样工作。

有人可以给我一些提示吗?我一直在阅读手册页并在网上寻找示例,但我一无所获。我相信我错过了一些东西。我下面的代码只打印链接数。有人可以帮忙吗?预先感谢您的帮助!!

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/utsname.h>
#include <ctype.h>
#include <string.h>

int main (int argc, char **argv)
{
    int in_fd;
    struct stat sb;

    if (argc != 2) {
        printf("Error", argv[0]);
        exit(EXIT_FAILURE);
    }

    if (stat(argv[1], &sb) == -1) {
        perror("stat");
        exit(EXIT_FAILURE);     //change from EXIT_SUCCESS to EXIT_FAILURE
    }

    //open the archive file (e.g., hw.a)
    in_fd = open(argv[1], O_RDONLY);
    if (in_fd == -1)
    {
        perror("Can't open input file\n");
        exit(-1);
    }


    printf("Link Count: %ld\n", (long)sb.st_nlink);

    return 0;
}

最佳答案

最简单的方法是使用 ar 程序列出名称:

ar -tv weds.a

- 是可选的; v 意味着您将获得大小和时间信息。

如果您想阅读存档文件本身,您必须了解不同系统上格式的差异。相关 header (通常)是 <ar.h> 。我有许多系统的信息,其中许多已经过时,并且有各种不同的技巧用于处理长文件名(以及其他更基本的文件格式问题),但您可能考虑的范围更有限。任何基于 <ar.h> 的此类工作都将是非常重要的;如果可能的话,你最好重用已经存在的东西(ar 程序)。


这是来自 Mac OS X 10.8.4 机器的存档。

$ cat thurs.txt
0123456789:;<=>?@ABCDEFGHIJKLMNO
$ cat fri.txt
PQRSTUVWXYZ[\]^_`abcdefghijklmno
$ odx weds.a
0x0000: 21 3C 61 72 63 68 3E 0A 74 68 75 72 73 2E 74 78   !<arch>.thurs.tx
0x0010: 74 20 20 20 20 20 20 20 31 33 37 34 30 39 36 30   t       13740960
0x0020: 31 32 20 20 32 38 37 36 20 20 35 30 30 30 20 20   12  2876  5000  
0x0030: 31 30 30 36 34 34 20 20 33 33 20 20 20 20 20 20   100644  33      
0x0040: 20 20 60 0A 30 31 32 33 34 35 36 37 38 39 3A 3B     `.0123456789:;
0x0050: 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B   <=>?@ABCDEFGHIJK
0x0060: 4C 4D 4E 4F 0A 0A 66 72 69 2E 74 78 74 20 20 20   LMNO..fri.txt   
0x0070: 20 20 20 20 20 20 31 33 37 34 30 39 36 30 30 35         1374096005
0x0080: 20 20 32 38 37 36 20 20 35 30 30 30 20 20 31 30     2876  5000  10
0x0090: 30 36 34 34 20 20 33 33 20 20 20 20 20 20 20 20   0644  33        
0x00A0: 60 0A 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D   `.PQRSTUVWXYZ[\]
0x00B0: 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D   ^_`abcdefghijklm
0x00C0: 6E 6F 0A 0A                                       no..
0x00C4:
$

幸运的是,相同的文件在 Linux 上也产生基本相同的存档。在 Linux header <ar.h> 中,您会发现:

/* Archive files start with the ARMAG identifying string.  Then follows a
   `struct ar_hdr', and as many bytes of member file data as its `ar_size'
   member indicates, for each member file.  */

#define ARMAG   "!<arch>\n" /* String that begins an archive file.  */
#define SARMAG  8       /* Size of that string.  */

#define ARFMAG  "`\n"       /* String in ar_fmag at end of each header.  */

struct ar_hdr
  {
    char ar_name[16];       /* Member file name, sometimes / terminated. */
    char ar_date[12];       /* File date, decimal seconds since Epoch.  */
    char ar_uid[6], ar_gid[6];  /* User and group IDs, in ASCII decimal.  */
    char ar_mode[8];        /* File mode, in ASCII octal.  */
    char ar_size[10];       /* File size, in ASCII decimal.  */
    char ar_fmag[2];        /* Always contains ARFMAG.  */
  };

Mac OS X header 具有相同的结构以及 ARMAG 和 ARFMAG 值,但多了一个宏:

#define AR_EFMT1        "#1/"           /* extended format #1 */

您可以在文件开头看到 ARMAG 字符串。然后每个文件前面都有一个 struct ar_hdr 。请注意,此处的示例名称以空白结尾,而不是以斜线结尾。 之后,您会找到该文件的数据。您可以完整阅读标题。请注意,如果任何名称超过 15 个字符,或者如果名称包含空格,那么您会在包含文件名字符串的存档文件的开头获得一个额外的条目,并且您还会在 per - 标识字符串表中相关字符串的文件头。

具有长名称等的 Linux 存档

0x0000: 21 3C 61 72 63 68 3E 0A 2F 2F 20 20 20 20 20 20   !<arch>.//      
0x0010: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20                   
* (1)
0x0030: 20 20 20 20 20 20 20 20 34 36 20 20 20 20 20 20           46      
0x0040: 20 20 60 0A 66 69 6C 74 65 72 2E 73 74 64 65 72     `.filter.stder
0x0050: 72 2E 73 68 2F 0A 6C 6F 6E 67 20 6E 61 6D 65 20   r.sh/.long name 
0x0060: 77 69 74 68 20 73 70 61 63 65 73 2E 74 78 74 2F   with spaces.txt/
0x0070: 0A 0A 74 68 75 72 73 2E 74 78 74 2F 20 20 20 20   ..thurs.txt/    
0x0080: 20 20 31 33 37 34 30 39 36 32 31 31 20 20 31 39     1374096211  19
0x0090: 39 34 38 34 35 30 30 30 20 20 31 30 30 36 34 30   94845000  100640
0x00A0: 20 20 33 33 20 20 20 20 20 20 20 20 60 0A 30 31     33        `.01
0x00B0: 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41   23456789:;<=>?@A
0x00C0: 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 0A 0A   BCDEFGHIJKLMNO..
0x00D0: 66 72 69 2E 74 78 74 2F 20 20 20 20 20 20 20 20   fri.txt/        
0x00E0: 31 33 37 34 30 39 36 31 39 37 20 20 31 39 39 34   1374096197  1994
0x00F0: 38 34 35 30 30 30 20 20 31 30 30 36 34 30 20 20   845000  100640  
0x0100: 33 33 20 20 20 20 20 20 20 20 60 0A 50 51 52 53   33        `.PQRS
0x0110: 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63   TUVWXYZ[\]^_`abc
0x0120: 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 0A 0A 2F 30   defghijklmno../0
0x0130: 20 20 20 20 20 20 20 20 20 20 20 20 20 20 31 33                 13
0x0140: 37 31 31 34 35 35 38 34 20 20 31 39 39 34 38 34   71145584  199484
0x0150: 35 30 30 30 20 20 31 30 30 36 34 30 20 20 32 33   5000  100640  23
0x0160: 30 20 20 20 20 20 20 20 60 0A 23 21 2F 62 69 6E   0       `.#!/bin
0x0170: 2F 62 61 73 68 0A 73 65 74 20 2D 78 0A 72 6D 20   /bash.set -x.rm 
0x0180: 2D 66 20 6F 75 74 2E 5B 31 32 33 5D 0A 2E 2F 67   -f out.[123]../g
0x0190: 65 6E 6F 75 74 65 72 72 2E 73 68 20 31 3E 2F 64   enouterr.sh 1>/d
0x01A0: 65 76 2F 6E 75 6C 6C 0A 2E 2F 67 65 6E 6F 75 74   ev/null../genout
0x01B0: 65 72 72 2E 73 68 20 32 3E 2F 64 65 76 2F 6E 75   err.sh 2>/dev/nu
0x01C0: 6C 6C 0A 28 20 2E 2F 67 65 6E 6F 75 74 65 72 72   ll.( ./genouterr
0x01D0: 2E 73 68 20 32 3E 26 31 20 31 3E 26 33 20 7C 20   .sh 2>&1 1>&3 | 
0x01E0: 67 72 65 70 20 27 5B 30 2D 39 5D 30 27 20 3E 26   grep '[0-9]0' >&
0x01F0: 32 29 20 33 3E 6F 75 74 2E 33 20 32 3E 6F 75 74   2) 3>out.3 2>out
0x0200: 2E 32 20 31 3E 6F 75 74 2E 31 0A 6C 73 20 2D 6C   .2 1>out.1.ls -l
0x0210: 20 6F 75 74 2E 5B 31 32 33 5D 0A 28 20 2E 2F 67    out.[123].( ./g
0x0220: 65 6E 6F 75 74 65 72 72 2E 73 68 20 32 3E 26 31   enouterr.sh 2>&1
0x0230: 20 31 3E 26 33 20 7C 20 67 72 65 70 20 27 5B 30    1>&3 | grep '[0
0x0240: 2D 39 5D 30 27 20 3E 26 32 29 20 33 3E 26 31 0A   -9]0' >&2) 3>&1.
0x0250: 2F 31 38 20 20 20 20 20 20 20 20 20 20 20 20 20   /18             
0x0260: 31 33 37 34 30 39 36 35 37 37 20 20 31 39 39 34   1374096577  1994
0x0270: 38 34 35 30 30 30 20 20 31 30 30 36 34 30 20 20   845000  100640  
0x0280: 33 33 20 20 20 20 20 20 20 20 60 0A 30 31 32 33   33        `.0123
0x0290: 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41 42 43   456789:;<=>?@ABC
0x02A0: 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 0A 0A         DEFGHIJKLMNO..
0x02AE:

具有长名称等的 Mac OS X 存档

0x0000: 21 3C 61 72 63 68 3E 0A 74 68 75 72 73 2E 74 78   !<arch>.thurs.tx
0x0010: 74 20 20 20 20 20 20 20 31 33 37 34 30 39 36 30   t       13740960
0x0020: 31 32 20 20 32 38 37 36 20 20 35 30 30 30 20 20   12  2876  5000  
0x0030: 31 30 30 36 34 34 20 20 33 33 20 20 20 20 20 20   100644  33      
0x0040: 20 20 60 0A 30 31 32 33 34 35 36 37 38 39 3A 3B     `.0123456789:;
0x0050: 3C 3D 3E 3F 40 41 42 43 44 45 46 47 48 49 4A 4B   <=>?@ABCDEFGHIJK
0x0060: 4C 4D 4E 4F 0A 0A 66 72 69 2E 74 78 74 20 20 20   LMNO..fri.txt   
0x0070: 20 20 20 20 20 20 31 33 37 34 30 39 36 30 30 35         1374096005
0x0080: 20 20 32 38 37 36 20 20 35 30 30 30 20 20 31 30     2876  5000  10
0x0090: 30 36 34 34 20 20 33 33 20 20 20 20 20 20 20 20   0644  33        
0x00A0: 60 0A 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D   `.PQRSTUVWXYZ[\]
0x00B0: 5E 5F 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D   ^_`abcdefghijklm
0x00C0: 6E 6F 0A 0A 66 69 6C 74 65 72 2E 73 74 64 65 72   no..filter.stder
0x00D0: 72 2E 73 68 31 33 37 34 30 39 37 37 39 34 20 20   r.sh1374097794  
0x00E0: 32 38 37 36 20 20 35 30 30 30 20 20 31 30 30 36   2876  5000  1006
0x00F0: 34 34 20 20 32 33 30 20 20 20 20 20 20 20 60 0A   44  230       `.
0x0100: 23 21 2F 62 69 6E 2F 62 61 73 68 0A 73 65 74 20   #!/bin/bash.set 
0x0110: 2D 78 0A 72 6D 20 2D 66 20 6F 75 74 2E 5B 31 32   -x.rm -f out.[12
0x0120: 33 5D 0A 2E 2F 67 65 6E 6F 75 74 65 72 72 2E 73   3]../genouterr.s
0x0130: 68 20 31 3E 2F 64 65 76 2F 6E 75 6C 6C 0A 2E 2F   h 1>/dev/null../
0x0140: 67 65 6E 6F 75 74 65 72 72 2E 73 68 20 32 3E 2F   genouterr.sh 2>/
0x0150: 64 65 76 2F 6E 75 6C 6C 0A 28 20 2E 2F 67 65 6E   dev/null.( ./gen
0x0160: 6F 75 74 65 72 72 2E 73 68 20 32 3E 26 31 20 31   outerr.sh 2>&1 1
0x0170: 3E 26 33 20 7C 20 67 72 65 70 20 27 5B 30 2D 39   >&3 | grep '[0-9
0x0180: 5D 30 27 20 3E 26 32 29 20 33 3E 6F 75 74 2E 33   ]0' >&2) 3>out.3
0x0190: 20 32 3E 6F 75 74 2E 32 20 31 3E 6F 75 74 2E 31    2>out.2 1>out.1
0x01A0: 0A 6C 73 20 2D 6C 20 6F 75 74 2E 5B 31 32 33 5D   .ls -l out.[123]
0x01B0: 0A 28 20 2E 2F 67 65 6E 6F 75 74 65 72 72 2E 73   .( ./genouterr.s
0x01C0: 68 20 32 3E 26 31 20 31 3E 26 33 20 7C 20 67 72   h 2>&1 1>&3 | gr
0x01D0: 65 70 20 27 5B 30 2D 39 5D 30 27 20 3E 26 32 29   ep '[0-9]0' >&2)
0x01E0: 20 33 3E 26 31 0A 23 31 2F 32 38 20 20 20 20 20    3>&1.#1/28     
0x01F0: 20 20 20 20 20 20 31 33 37 34 30 39 37 38 32 32         1374097822
0x0200: 20 20 32 38 37 36 20 20 35 30 30 30 20 20 31 30     2876  5000  10
0x0210: 30 36 34 34 20 20 36 31 20 20 20 20 20 20 20 20   0644  61        
0x0220: 60 0A 6C 6F 6E 67 20 6E 61 6D 65 20 77 69 74 68   `.long name with
0x0230: 20 73 70 61 63 65 73 2E 74 78 74 00 00 00 30 31    spaces.txt...01
0x0240: 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F 40 41   23456789:;<=>?@A
0x0250: 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 0A 0A   BCDEFGHIJKLMNO..
0x0260:

差异

Linux 存档在文件顶部有一个必须记住的字符串列表。 Mac OS X 存档有一个特殊的条目 #1/28,它将 header 标识为后面跟着一个包含文件名的 28 字节条目(空值填充为 4 字节的倍数;给定的长度包括空值填充)。 Mac 存档在长度恰好为 16 个字符时名称后没有空格; Linux 存档将 16 个字符的名称放入字符串表中。

关于c - 如何打印存档文件中的文件名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17709993/

相关文章:

c - 如何使用特定的定界符进行自动换行,而不进行动态分配

c - C库函数中的系统调用

r - 如何按组获取汇总统计数据

c - stat 系统调用的 st_mode 标志

linux - Perl:从 star 命令获取用户名和组名

c - mifare desfire 中的 ISO14443-4(RATS)

c - 在c文件的当前目录中打开并写入一个文件

c - gcc: 警告: 'used' 属性被忽略

c# - 在 C# 中确定操作系统和处理器类型

assembly - 我们看到一个进程的虚拟地址(在分页系统中),这些虚拟地址存在哪里?