diff --git a/cabextract/ChangeLog b/cabextract/ChangeLog index 5358652..d8fd73c 100644 --- a/cabextract/ChangeLog +++ b/cabextract/ChangeLog @@ -1,3 +1,11 @@ +2023-02-19 Stuart Caie + + * ensure_filepath(): had wrong logic, for the archive-controlled + part of a pathname, it was using the result of lstat() whether + it succeeded or not, and thus not creating directories when it + ought to. Fixed and added a testcase for cabextract's --directory + option. Thanks to iq2luc for raising the issue and offering a fix. + 2023-02-04 Stuart Caie * src/cabextract.c: By default, cabextract will now overwrite diff --git a/cabextract/Makefile.am b/cabextract/Makefile.am index 42dce77..7335650 100644 --- a/cabextract/Makefile.am +++ b/cabextract/Makefile.am @@ -9,7 +9,7 @@ bundled_mspack = mspack/mspack.h \ mspack/macros.h mspack/readbits.h mspack/readhuff.h TESTS = test/bugs.test test/case-ascii.test test/case-utf8.test \ - test/dirwalk-vulns.test test/encoding.test \ + test/dir.test test/dirwalk-vulns.test test/encoding.test \ test/mixed.test test/search.test test/simple.test \ test/split.test test/utf8-stresstest.test \ test/symlinks.test diff --git a/cabextract/src/cabextract.c b/cabextract/src/cabextract.c index 0a19a9b..25c03af 100644 --- a/cabextract/src/cabextract.c +++ b/cabextract/src/cabextract.c @@ -1227,8 +1227,10 @@ static int ensure_filepath(char *path, int n) { /* in the archive-determined part of the path and not keeping symlinks: * use lstat() and delete symlinks if found */ ok = (lstat(path, &st_buf) == 0); - if (ok && (st_buf.st_mode & S_IFMT) == S_IFLNK) unlink(path); - ok = S_ISDIR(st_buf.st_mode); + if (ok) { + if ((st_buf.st_mode & S_IFMT) == S_IFLNK) unlink(path); + ok = S_ISDIR(st_buf.st_mode); + } } if (!ok) ok = (mkdir(path, 0777 & ~user_umask) == 0); *p = '/'; diff --git a/cabextract/test/dir.test b/cabextract/test/dir.test new file mode 100755 index 0000000..6906b67 --- /dev/null +++ b/cabextract/test/dir.test @@ -0,0 +1,59 @@ +#!/bin/sh +# test that cabextract creates directories as expected +. test/testcase + +# extract to user-chosen absolute path +"$cabextract" -d $tmpdir/test cabs/dir.cab >$actual +compare_with <$actual +compare_with <$actual +compare_with <$actual +compare_with <$actual +compare_with <