Allow loading files from archive subdirectory (#13443)

* Allow loading files from archive subdirectory

Common example is "games.7z#game1/version1.ext" current code assumes that
everything that is before last slash is part of filesystem directory which
is false in this case.

* Fix listing of archive subdirectories

Currently file_archive_get_file_list_cb returns 0 on skipped entries.
It's wrong as calling convention for it is "0 means to stop iterating".
So on first extensionless file or an explicitly listed directory
further listing has stopped
This commit is contained in:
Vladimir Serbinenko 2022-01-11 13:59:38 +01:00 committed by GitHub
parent 4dda10b86d
commit 2f130a23e4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 5 additions and 15 deletions

View File

@ -62,7 +62,7 @@ static int file_archive_get_file_list_cb(
/* Skip if directory. */
if (last_char == '/' || last_char == '\\' )
return 0;
return 1;
string_list_initialize(&ext_list);
if (string_split_noalloc(&ext_list, valid_exts, "|"))
@ -72,7 +72,7 @@ static int file_archive_get_file_list_cb(
if (!file_ext)
{
string_list_deinitialize(&ext_list);
return 0;
return 1;
}
if (!string_list_find_elem_prefix(&ext_list, ".", file_ext))

View File

@ -82,33 +82,23 @@
*/
const char *path_get_archive_delim(const char *path)
{
const char *last_slash = find_last_slash(path);
const char *delim = NULL;
char buf[5];
buf[0] = '\0';
/* We search for delimiters after the last slash
* in the file path to avoid capturing delimiter
* characters in any parent directory names.
* If there are no slashes in the file name, then
* the path is just the file basename - in this
* case we search the path in its entirety */
if (!last_slash)
last_slash = path;
/* Find delimiter position
* > Since filenames may contain '#' characters,
* must loop until we find the first '#' that
* is directly *after* a compression extension */
delim = strchr(last_slash, '#');
delim = strchr(path, '#');
while (delim)
{
/* Check whether this is a known archive type
* > Note: The code duplication here is
* deliberate, to maximise performance */
if (delim - last_slash > 4)
if (delim - path > 4)
{
strlcpy(buf, delim - 4, sizeof(buf));
buf[4] = '\0';
@ -121,7 +111,7 @@ const char *path_get_archive_delim(const char *path)
string_is_equal(buf + 1, ".7z"))
return delim;
}
else if (delim - last_slash > 3)
else if (delim - path > 3)
{
strlcpy(buf, delim - 3, sizeof(buf));
buf[3] = '\0';