From: Tim Kientzle Date: Sat, 25 Jul 2009 06:18:47 +0000 (-0400) Subject: Fix ISO9660 hardlink handling and fix the parsing of X-Git-Tag: v2.8.0~508 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b9d9fba5d8b7a0f4bdc83cc4e5cbcddeb804d2a5;p=thirdparty%2Flibarchive.git Fix ISO9660 hardlink handling and fix the parsing of Rockridge symlinks. Update tests to verify the correct behavior here. SVN-Revision: 1275 --- diff --git a/libarchive/archive_read_support_format_iso9660.c b/libarchive/archive_read_support_format_iso9660.c index 1921c5809..6ec46ad11 100644 --- a/libarchive/archive_read_support_format_iso9660.c +++ b/libarchive/archive_read_support_format_iso9660.c @@ -579,6 +579,7 @@ archive_read_format_iso9660_read_header(struct archive_read *a, && file->size > 0) { archive_entry_set_hardlink(entry, iso9660->previous_pathname.s); + archive_entry_unset_size(entry); iso9660->entry_bytes_remaining = 0; iso9660->entry_sparse_offset = 0; release_file(iso9660, file); @@ -1174,12 +1175,12 @@ static void parse_rockridge_SL1(struct file_info *file, const unsigned char *data, int data_length) { - int component_continues = 1; + const char *separator = ""; - if (!file->symlink_continues) + if (!file->symlink_continues || file->symlink.length < 1) archive_string_empty(&file->symlink); - else - archive_strcat(&file->symlink, "/"); + else if (file->symlink.s[file->symlink.length - 1] != '/') + separator = "/"; file->symlink_continues = 0; /* @@ -1216,9 +1217,8 @@ parse_rockridge_SL1(struct file_info *file, const unsigned char *data, unsigned char nlen = *data++; data_length -= 2; - if (!component_continues) - archive_strcat(&file->symlink, "/"); - component_continues = 0; + archive_strcat(&file->symlink, separator); + separator = "/"; switch(flag) { case 0: /* Usual case, this is text. */ @@ -1232,7 +1232,7 @@ parse_rockridge_SL1(struct file_info *file, const unsigned char *data, return; archive_strncat(&file->symlink, (const char *)data, nlen); - component_continues = 1; + separator = ""; break; case 0x02: /* Current dir. */ archive_strcat(&file->symlink, "."); @@ -1243,6 +1243,7 @@ parse_rockridge_SL1(struct file_info *file, const unsigned char *data, case 0x08: /* Root of filesystem. */ archive_string_empty(&file->symlink); archive_strcat(&file->symlink, "/"); + separator = ""; break; case 0x10: /* Undefined (historically "volume root" */ archive_string_empty(&file->symlink); diff --git a/libarchive/test/test_read_format_isojoliet_bz2.c b/libarchive/test/test_read_format_isojoliet_bz2.c index d84d9d8df..2d5ea3145 100644 --- a/libarchive/test/test_read_format_isojoliet_bz2.c +++ b/libarchive/test/test_read_format_isojoliet_bz2.c @@ -108,14 +108,10 @@ joliettest(int withrr) assertEqualInt(2, archive_entry_gid(ae)); } - /* A hardlink to the regular file. */ + /* A regular file with a hardlink. */ assertEqualInt(0, archive_read_next_header(a, &ae)); assertEqualString("hardlink", archive_entry_pathname(ae)); assert(S_ISREG(archive_entry_stat(ae)->st_mode)); - if (withrr) { - assertEqualString("long-joliet-file-name.textfile", - archive_entry_hardlink(ae)); - } assertEqualInt(6, archive_entry_size(ae)); assertEqualInt(0, archive_read_data_block(a, &p, &size, &offset)); assertEqualInt(6, (int)size); @@ -129,11 +125,11 @@ joliettest(int withrr) assertEqualInt(2, archive_entry_gid(ae)); } - /* A regular file. */ + /* Another link to the regular file. */ assertEqualInt(0, archive_read_next_header(a, &ae)); assertEqualString("long-joliet-file-name.textfile", archive_entry_pathname(ae)); assert(S_ISREG(archive_entry_stat(ae)->st_mode)); - assertEqualInt(6, archive_entry_size(ae)); + assertEqualInt(0, archive_entry_size(ae)); if (withrr) { assertEqualInt(86401, archive_entry_mtime(ae)); assertEqualInt(86401, archive_entry_atime(ae)); diff --git a/libarchive/test/test_read_format_isorr_bz2.c b/libarchive/test/test_read_format_isorr_bz2.c index 2dfc2ae73..d01057419 100644 --- a/libarchive/test/test_read_format_isorr_bz2.c +++ b/libarchive/test/test_read_format_isorr_bz2.c @@ -33,9 +33,12 @@ rm -rf /tmp/iso mkdir /tmp/iso mkdir /tmp/iso/dir echo "hello" >/tmp/iso/file -dd if=/dev/zero bs=1 count=12345678 >>/tmp/iso/file +dd if=/dev/zero count=1 bs=12345678 >>/tmp/iso/file ln /tmp/iso/file /tmp/iso/hardlink (cd /tmp/iso; ln -s file symlink) +(cd /tmp/iso; ln -s /tmp/ symlink2) +(cd /tmp/iso; ln -s /tmp/../ symlink3) +(cd /tmp/iso; ln -s .././../tmp/ symlink4) TZ=utc touch -afhm -t 197001020000.01 /tmp/iso /tmp/iso/file /tmp/iso/dir TZ=utc touch -afhm -t 197001030000.02 /tmp/iso/symlink mkhybrid -R -uid 1 -gid 2 /tmp/iso | bzip2 > test_read_format_isorr_bz2.iso.bz2 @@ -52,6 +55,7 @@ DEFINE_TEST(test_read_format_isorr_bz2) const void *p; size_t size; off_t offset; + int i; int r; extract_reference_file(refname); @@ -67,68 +71,104 @@ DEFINE_TEST(test_read_format_isorr_bz2) assertEqualInt(ARCHIVE_OK, archive_read_open_filename(a, refname, 10240)); - /* First entry is '.' root directory. */ - assertEqualInt(0, archive_read_next_header(a, &ae)); - assertEqualString(".", archive_entry_pathname(ae)); - assert(S_ISDIR(archive_entry_stat(ae)->st_mode)); - assertEqualInt(2048, archive_entry_size(ae)); - assertEqualInt(86401, archive_entry_mtime(ae)); - assertEqualInt(0, archive_entry_mtime_nsec(ae)); - assertEqualInt(86401, archive_entry_ctime(ae)); - assertEqualInt(0, archive_entry_stat(ae)->st_nlink); - assertEqualInt(0, archive_entry_uid(ae)); - assertEqualIntA(a, ARCHIVE_EOF, - archive_read_data_block(a, &p, &size, &offset)); - assertEqualInt((int)size, 0); + /* Retrieve each of the 8 files on the ISO image and + * verify that each one is what we expect. */ + for (i = 0; i < 8; ++i) { + assertEqualInt(0, archive_read_next_header(a, &ae)); - /* A directory. */ - assertEqualInt(0, archive_read_next_header(a, &ae)); - assertEqualString("dir", archive_entry_pathname(ae)); - assert(S_ISDIR(archive_entry_stat(ae)->st_mode)); - assertEqualInt(2048, archive_entry_size(ae)); - assertEqualInt(86401, archive_entry_mtime(ae)); - assertEqualInt(86401, archive_entry_atime(ae)); - assertEqualInt(2, archive_entry_stat(ae)->st_nlink); - assertEqualInt(1, archive_entry_uid(ae)); - assertEqualInt(2, archive_entry_gid(ae)); - - /* A regular file. */ - assertEqualInt(0, archive_read_next_header(a, &ae)); - assertEqualString("file", archive_entry_pathname(ae)); - assert(S_ISREG(archive_entry_stat(ae)->st_mode)); - assertEqualInt(12345684, archive_entry_size(ae)); - assertEqualInt(0, archive_read_data_block(a, &p, &size, &offset)); - assertEqualInt(0, offset); - assertEqualMem(p, "hello\n", 6); - assertEqualInt(86401, archive_entry_mtime(ae)); - assertEqualInt(86401, archive_entry_atime(ae)); - assertEqualInt(2, archive_entry_stat(ae)->st_nlink); - assertEqualInt(1, archive_entry_uid(ae)); - assertEqualInt(2, archive_entry_gid(ae)); - - /* A hardlink to the regular file. */ - assertEqualInt(0, archive_read_next_header(a, &ae)); - assertEqualString("hardlink", archive_entry_pathname(ae)); - assert(S_ISREG(archive_entry_stat(ae)->st_mode)); - assertEqualString("file", archive_entry_hardlink(ae)); - assertEqualInt(12345684, archive_entry_size(ae)); - assertEqualInt(86401, archive_entry_mtime(ae)); - assertEqualInt(86401, archive_entry_atime(ae)); - assertEqualInt(2, archive_entry_stat(ae)->st_nlink); - assertEqualInt(1, archive_entry_uid(ae)); - assertEqualInt(2, archive_entry_gid(ae)); - - /* A symlink to the regular file. */ - assertEqualInt(0, archive_read_next_header(a, &ae)); - assertEqualString("symlink", archive_entry_pathname(ae)); - assert(S_ISLNK(archive_entry_stat(ae)->st_mode)); - assertEqualString("file", archive_entry_symlink(ae)); - assertEqualInt(0, archive_entry_size(ae)); - assertEqualInt(172802, archive_entry_mtime(ae)); - assertEqualInt(172802, archive_entry_atime(ae)); - assertEqualInt(1, archive_entry_stat(ae)->st_nlink); - assertEqualInt(1, archive_entry_uid(ae)); - assertEqualInt(2, archive_entry_gid(ae)); + if (strcmp(".", archive_entry_pathname(ae)) == 0) { + /* '.' root directory. */ + assert(S_ISDIR(archive_entry_stat(ae)->st_mode)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(0, archive_entry_mtime_nsec(ae)); + assertEqualInt(86401, archive_entry_ctime(ae)); + assertEqualInt(0, archive_entry_stat(ae)->st_nlink); + assertEqualInt(0, archive_entry_uid(ae)); + assertEqualIntA(a, ARCHIVE_EOF, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt((int)size, 0); + } else if (strcmp("dir", archive_entry_pathname(ae)) == 0) { + /* A directory. */ + assertEqualString("dir", archive_entry_pathname(ae)); + assert(S_ISDIR(archive_entry_stat(ae)->st_mode)); + assertEqualInt(2048, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("file", archive_entry_pathname(ae)) == 0) { + /* A regular file. */ + assertEqualString("file", archive_entry_pathname(ae)); + assert(S_ISREG(archive_entry_stat(ae)->st_mode)); + assertEqualInt(12345684, archive_entry_size(ae)); + assertEqualInt(0, + archive_read_data_block(a, &p, &size, &offset)); + assertEqualInt(0, offset); + assertEqualMem(p, "hello\n", 6); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("hardlink", archive_entry_pathname(ae)) == 0) { + /* A hardlink to the regular file. */ + /* Note: If "hardlink" gets returned before "file", + * then "hardlink" will get returned as a regular file + * and "file" will get returned as the hardlink. + * This test should tolerate that, since it's a + * perfectly permissible thing for libarchive to do. */ + assertEqualString("hardlink", archive_entry_pathname(ae)); + assert(S_ISREG(archive_entry_stat(ae)->st_mode)); + assertEqualString("file", archive_entry_hardlink(ae)); + assertEqualInt(0, archive_entry_size_is_set(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(86401, archive_entry_mtime(ae)); + assertEqualInt(86401, archive_entry_atime(ae)); + assertEqualInt(2, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink", archive_entry_pathname(ae)) == 0) { + /* A symlink to the regular file. */ + assert(S_ISLNK(archive_entry_stat(ae)->st_mode)); + assertEqualString("file", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(172802, archive_entry_mtime(ae)); + assertEqualInt(172802, archive_entry_atime(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink2", archive_entry_pathname(ae)) == 0) { + /* A symlink to /tmp (an absolute path) */ + assert(S_ISLNK(archive_entry_stat(ae)->st_mode)); + assertEqualString("/tmp", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink3", archive_entry_pathname(ae)) == 0) { + /* A symlink to /tmp/.. (with a ".." component) */ + assert(S_ISLNK(archive_entry_stat(ae)->st_mode)); + assertEqualString("/tmp/..", archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else if (strcmp("symlink4", archive_entry_pathname(ae)) == 0) { + /* A symlink to a path with ".." and "." components */ + assert(S_ISLNK(archive_entry_stat(ae)->st_mode)); + assertEqualString(".././../tmp", + archive_entry_symlink(ae)); + assertEqualInt(0, archive_entry_size(ae)); + assertEqualInt(1, archive_entry_stat(ae)->st_nlink); + assertEqualInt(1, archive_entry_uid(ae)); + assertEqualInt(2, archive_entry_gid(ae)); + } else { + failure("Saw a file that shouldn't have been there"); + assertEqualString(archive_entry_pathname(ae), ""); + } + } /* End of archive. */ assertEqualInt(ARCHIVE_EOF, archive_read_next_header(a, &ae)); @@ -139,11 +179,7 @@ DEFINE_TEST(test_read_format_isorr_bz2) /* Close the archive. */ assertEqualInt(0, archive_read_close(a)); -#if ARCHIVE_VERSION_NUMBER < 2000000 - archive_read_finish(a); -#else assertEqualInt(0, archive_read_finish(a)); -#endif } diff --git a/libarchive/test/test_read_format_isorr_bz2.iso.bz2.uu b/libarchive/test/test_read_format_isorr_bz2.iso.bz2.uu index d4e3fc898..fe2cad906 100644 --- a/libarchive/test/test_read_format_isorr_bz2.iso.bz2.uu +++ b/libarchive/test/test_read_format_isorr_bz2.iso.bz2.uu @@ -1,23 +1,25 @@ begin 644 test_read_format_isorr_bz2.iso.bz2 -M0EIH.3%!629363S[0-4``,?_W?__R_158__Z/__?8*?OWB8AZB2```4@`,0" -M@0C0`SX`6UH$P:F@32FCU-D1Z@#U'J!HT>H#0`!H`T9`#U-#33(-`-3TFA#1 -MJ933TFR%#(&@`#0-````'J`T``,.-#1HT&C0-``````R````-`9``8<:&C1H -M-&@:`````!D````:`R``P1*(1$]3U,C(--``T!H:9``````:``&F)?&F1;DY -M&:FB?6\AB@WG9X@8AM,HTK/Q9EXPZD#E2A$D)(@;F(G^B.92GLB`=H@`+I1! -M1$`';Y%%P_YU^!0+8BJ(@#DC&D@D4"1D4?Z1!$1`&Z`V[]0H($(!6L90;:>A0V<))XH7BH%"KAF8!:H8\].K:4`Y`,4,!RN:#SL[!;-"!6%0F?`H -M2_2AM@*%/%<\*!XL/C2%A1AI$8/AF(#SZ;]:>$5^/NKNO<+EH@_CS4XUI(Q* -M123&G=9T]QQR?"=WMV(,&60`1D0:U043)E&22GWA);Z:"9R.A@,4,IL+O=L7 -MACF:V5C!L"HB&,82/[./'>PAEG-"PA,D6T1+ -M2<\S]-*$,]X-XF%:_)1,W,=`,^+.N0""6@"85=H@<2FZ=HI-GDHK&)>/T74Y -M+5>[4:S`Z`M87AHD`H6BE*8R%X=9AS$7&+Z?F%A.`AX!"XZRR@C5_?4^P".90`*]#[D(PA*&MPV7U2 -M;.]7.&/5!?P@C:J)S&T%=%,KJ@X0[""E8G!I!/I%`KSMA<#^!%C+Y*")'1]( -MJ06:CXD^5K*:`$E`B`0$P5;&R;BF<5/Y7&(5A`?:!J@`` +M0EIH.3%!629364.3#=@``-+_W?__2_358_WZ/__?8*?OWB8A_B2```4@`,0" +M@0C0`YX`)E`6H-")J&IDV2,C)H&F330``-`:&@:8@#(PAD``--1HF1HF0T3$ +MTAIH#U-'J``T``````>H#(!P``#0-#0T-,@`T``&@&AH``&0``<```T#0T-# +M3(`-``!H!H:``!D``")1$R0GJ>ILI/1D!,)D&&)J8:`(&$&:F(9&F3TC#"EX +MTR!;ER)EHN+:;W/S@4P0$!1`'?C!I(C`4DT=*4*P$/@01$1`'#%;N4 +MH7542A!ONH!@P1E2HR^G,V=@ML2GHX=3^O73`3FP:9@S)-O6IGS+"0)6J653D1?G4V:>6BI; +M4#0@[$G.L/OV.O4.[7`DJ*XBG4[&MFVSJA`K"H:BI0+^G0+#@JE+*T.,1!`E +M*.^+/,"DY36'@:(33(1@^F!.&Q/!^U"AZ5''>2`_4G?2K^#%G4,(Q?3;:K-2 +MJJ5CBN,>-M66$(\$B"$V#=,3B(">#:B=F0CHU"0"HH=)/ +M9PD5$]I2SY$*J!@NFVGOWT4::?:,*TDA*L:4IJ18UE(""4D!!<'BD]#H+,HS +M2$@1+.&<=#;P%*@D/$6G,2N):O[12QA20]EP`\,+8_`,?HL3C/US`W:M^L8# +MYF%%M`JPN>8]-D[#'&#C$!6OT40;E-T)XT["%`6H@@*=@@9Y8HJHD;.]/6," +MZ_/='):KW:K4N.F%H0O#14`H6>3)&BI!C#@++V4C$:'R*:`LT40Y$;PYB%PUE)R-[P]K[@,X^?BP2 +ME$%ZW\$,0AE+6X+^I78V+U_?UZF?M)YK\A1P3)?C[)"'6AKL*,('(VP[[FI3?'#?DO +M)SA=J#1"3.*-1;`<8RJ-(!07(M(LC6:`)(`@:Y4_@*AOB%80'5C(&)M@>%A] +>`03A;8?5JI>F&!NYJB@B`.1W?_%W)%.%"00Y,-V` ` end