unzip/test/test_n.c \
unzip/test/test_o.c \
unzip/test/test_q.c \
+ unzip/test/test_symlink.c \
unzip/test/test_t.c \
unzip/test/test_t_bad.c \
unzip/test/test_u.c \
unzip/test/test_f_new.zip.uu \
unzip/test/test_f_old.zip.uu \
unzip/test/test_singlefile.zip.uu \
+ unzip/test/test_symlink_1.zip.uu \
+ unzip/test/test_symlink_2.zip.uu \
unzip/test/test_t_bad.zip.uu \
unzip/test/test_u_new.zip.uu \
unzip/test/test_u_old.zip.uu \
test_glob.c
test_not_exist.c
test_singlefile.c
+ test_symlink.c
test_C.c
test_p.c
test_d.c
--- /dev/null
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2026 Tobias Stoeckmann
+ * All rights reserved.
+ */
+#include "test.h"
+
+/* Test symlinks */
+DEFINE_TEST(test_symlink)
+{
+ const char *reffile1 = "test_symlink_1.zip";
+ const char *reffile2 = "test_symlink_2.zip";
+ int r;
+
+ if (!canSymlink()) {
+ skipping("System cannot create symlinks.");
+ return;
+ }
+
+ extract_reference_file(reffile1);
+ extract_reference_file(reffile2);
+
+ /* Extract first archive */
+ r = systemf("%s %s >test.out 2>test.err", testprog, reffile1);
+ assertEqualInt(0, r);
+ assertNonEmptyFile("test.out");
+ assertNonEmptyFile("test.err");
+ assertIsDir("dir", 0755);
+ assertIsSymlink("dlink", "dir", 1);
+ assertIsReg("file.txt", 0644);
+ assertIsSymlink("flink", "file.txt", 0);
+ assertFileNotExists("link.insecure");
+
+ /* Create dangling symlinks by deleting targets */
+ rmdir("dir");
+ unlink("file.txt");
+ assertFileNotExists("dir");
+ assertFileNotExists("file.txt");
+ assertIsSymlink("dlink", "dir", 1);
+ assertIsSymlink("flink", "file.txt", 0);
+
+ /* Extract second archive, overwriting dangling symlinks */
+ r = systemf("%s -o %s >test.out 2>test.err", testprog, reffile2);
+ assertEqualInt(0, r);
+ assertEmptyFile("test.out");
+ assertEmptyFile("test.err");
+ assertFileNotExists("dir");
+ assertIsDir("dlink", 0755);
+ assertTextFileContents("hello world\n", "dlink/file.txt");
+ assertIsReg("flink", 0644);
+}
--- /dev/null
+begin 644 test_symlink_1.zip
+M4$L#!!0``````)&NUEP````````````````$`"``9&ER+W5X"P`!!.@#```$
+MZ`,``%54#0`'@I(Y:H*2.6J"DCEJ4$L#!!0``````)"NUEP0>JNZ`P````,`
+M```%`"``9&QI;FMU>`L``03H`P``!.@#``!55`T`!X"2.6J`DCEJ@)(Y:F1I
+M<E!+`P0*``@```"5KM9<````````````````"``@`&9I;&4N='AT=7@+``$$
+MZ`,```3H`P``550-``>+DCEJBY(Y:HN2.6I02P<(````````````````4$L#
+M!!0``````)>NUEPE%O?@"`````@````%`"``9FQI;FMU>`L``03H`P``!.@#
+M``!55`T`!X^2.6J/DCEJCY(Y:F9I;&4N='AT4$L#!!0``````(RNUEP&4/WP
+M"@````H````-`"``:6YS96-U<F4N;&EN:W5X"P`!!.@#```$Z`,``%54#0`'
+M>9(Y:GF2.6IYDCEJ+BXO;W5T<VED95!+`0(4`Q0``````)&NUEP`````````
+M```````$`!@```````````#M00````!D:7(O=7@+``$$Z`,```3H`P``550%
+M``&"DCEJ4$L!`A0#%```````D*[67!!ZJ[H#`````P````4`&```````````
+M`/^A0@```&1L:6YK=7@+``$$Z`,```3H`P``550%``&`DCEJ4$L!`@H#"@`(
+M````E:[67`````````````````@`&````````````*2!B````&9I;&4N='AT
+M=7@+``$$Z`,```3H`P``550%``&+DCEJ4$L!`A0#%```````EZ[67"46]^`(
+M````"`````4`&````````````/^AW@```&9L:6YK=7@+``$$Z`,```3H`P``
+M550%``&/DCEJ4$L!`A0#%```````C*[67`90_?`*````"@````T`&```````
+M`````/^A*0$``&EN<V5C=7)E+FQI;FMU>`L``03H`P``!.@#``!55`4``7F2
+8.6I02P4&``````4`!0"!`0``?@$`````
+`
+end
--- /dev/null
+begin 644 test_symlink_2.zip
+M4$L#!`H`"````,NNUEP````````````````.`"``9&QI;FLO9FEL92YT>'1U
+M>`L``03H`P``!.@#``!55`T`!^^2.6KODCEJ[Y(Y:FAE;&QO('=O<FQD"E!+
+M!P@M.PBO#`````P```!02P,$"@`(````V*[67`````````````````4`(`!F
+M;&EN:W5X"P`!!.@#```$Z`,``%54#0`'"9,Y:A>3.6H)DSEJ8V]N=&5N="!F
+M;&EN:PI02P<(%P(`(PX````.````4$L!`@H#"@`(````RZ[67"T["*\,````
+M#`````X`&````````````*2!`````&1L:6YK+V9I;&4N='AT=7@+``$$Z`,`
+M``3H`P``550%``'ODCEJ4$L!`@H#"@`(````V*[67!<"`",.````#@````4`
+M&````````````*2!:````&9L:6YK=7@+``$$Z`,```3H`P``550%``$)DSEJ
+64$L%!@`````"``(`GP```,D`````````
+`
+end