Как распечатать имя файла внутри архивного файла?

Я новичок в C и системном программировании. Я хочу открыть файл архива и распечатать имя файла внутри архивного файла (например, мой файл архива weds.a; внутри weds.a у меня есть файл thurs.txt и fri.txt “. Я хочу создать вывод, который показывает файл thurs.txt fri.txt

EDITED: он должен работать как команда ar -t.

Может ли кто-нибудь дать мне несколько советов о том, как это сделать? Я читал справочную страницу и искал примеры в Интернете, но меня нет. Кажется, я что-то упустил. В приведенном ниже коде отображается только количество ссылок. Может кто-нибудь помочь? Заранее спасибо за помощь!!

#include  #include  #include  #include  #include  #include  #include  #include  #include  #include  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 (eg, 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 для enums имен:

     ar -tv weds.a 

    - необязательно; v означает, что вы получите информацию о размере и времени.

    Если вы хотите ознакомиться с самим архивом, вы должны знать различия в форматах в разных системах. Соответствующий заголовок (обычно) . У меня есть информация для ряда систем, многие из которых устарели, и существует множество различных трюков, используемых для обработки длинных имен файлов (и других даже более простых проблем с файловым форматом), но вы можете иметь более ограниченную область действия. Любая такая работа, основанная на будет нетривиальной; вам лучше всего использовать то, что уже существует (программа 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 !.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 вы найдете:

     /* 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 "!\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 !.// 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 !.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-символьное имя в таблицу строк.