如何在档案文件中打印文件名?

时间:2013-07-17 20:52:43

标签: c operating-system stat

我是C和系统编程的新手。我想打开一个存档文件并打印出存档文件中文件的名称(例如,我的存档文件是weds.a;在weds.a中,我有thurs.txt和fri.txt。)我想创建显示的输出 thurs.txt fri.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;
}

1 个答案:

答案 0 :(得分:2)

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

ar -tv weds.a

-是可选的; v表示您将获得尺寸和时间信息。

如果您想要阅读存档文件本身,您必须了解不同系统上格式的差异。相关标题是(通常)<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标题<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标头具有相同的结构和ARMAG和ARFMAG值,但是有一个额外的宏:

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

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

具有长名称等的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,该条目标识标头后面跟着一个包含文件名的28字节条目(空填充为4个字节的倍数;给定的长度包括空填充)。 Mac档案名称后面没有空格,正好是16个字符长; Linux归档文件将16个字符的名称放入字符串表中。