Skip to content

Commit

Permalink
Replace dirent implementation with one capable of detecting symlinks
Browse files Browse the repository at this point in the history
Now symlinks are skipped on Windows too
  • Loading branch information
rapperskull committed Feb 29, 2024
1 parent 1d92f4f commit 59bfde6
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 214 deletions.
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
[submodule "deps/asprintf"]
path = deps/asprintf
url = https://github.com/eiszapfen2000/asprintf.git
[submodule "deps/dirent"]
path = deps/dirent
url = https://github.com/tronkko/dirent.git
6 changes: 6 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ set(SOURCE_FILES
)

set(DEPS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps)
set(DIRENT_DIR ${DEPS_DIR}/dirent)
set(GETOPT_DIR ${DEPS_DIR}/getopt_port)
set(ASPRINTF_DIR ${DEPS_DIR}/asprintf)

Expand Down Expand Up @@ -36,6 +37,11 @@ set_property(TARGET extract-xiso PROPERTY C_STANDARD 99)
set_property(TARGET extract-xiso PROPERTY C_EXTENSIONS OFF)

if(WIN32)
add_library(dirent INTERFACE)
target_include_directories(dirent INTERFACE ${DIRENT_DIR}/include)

target_link_libraries(extract-xiso dirent)

add_library(getopt STATIC ${GETOPT_DIR}/getopt.c)
target_sources(getopt PUBLIC ${GETOPT_DIR}/getopt.h)
target_include_directories(getopt PUBLIC ${GETOPT_DIR})
Expand Down
1 change: 1 addition & 0 deletions deps/dirent
Submodule dirent added at 57ff23
79 changes: 60 additions & 19 deletions extract-xiso.c
Original file line number Diff line number Diff line change
Expand Up @@ -242,24 +242,14 @@

#if defined(__GNUC__)
#define _GNU_SOURCE
#define unused __attribute__((__unused__))
#elif defined(_MSC_VER)
#pragma warning(disable: 4706) // C4706: assignment within conditional expression
#define unused __pragma(warning(suppress:4100)) /* This unfortunately disables the warning for the whole line and the next one */
#else
#define unused
#endif

#ifndef DEBUG
#define DEBUG 0
#endif

#if DEBUG
#define unused_release
#else
#define unused_release unused
#endif

#include <time.h>
#include <errno.h>
#include <fcntl.h>
Expand All @@ -272,6 +262,7 @@
#include <string.h>
#include <inttypes.h>
#include <locale.h>
#include <dirent.h> /* Provided by CMake on Windows */
#include <sys/stat.h>
#include <sys/types.h>
#include "cp1252/cp1252.c"
Expand All @@ -283,10 +274,8 @@
#if defined(_WIN32)
#include <io.h>
#include <direct.h>
#include "win32/dirent.c"
#include <getopt.h> /* Provided by CMake */
#else
#include <dirent.h>
#include <limits.h>
#include <unistd.h>
#endif
Expand Down Expand Up @@ -337,9 +326,6 @@
#define exiso_target "Windows"

#if defined(_MSC_VER)
#define S_ISDIR(x) ((x) & _S_IFDIR)
#define S_ISREG(x) ((x) & _S_IFREG)

typedef SSIZE_T ssize_t;
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
Expand All @@ -353,7 +339,6 @@
#define lseek _lseeki64
#define mkdir(a, b) _mkdir(a)
#define stat _stat64
#define lstat _stat64
#define realpath(a, b) _fullpath(b, a, _MAX_PATH)

#define bswap_16(x) _byteswap_ushort(x)
Expand Down Expand Up @@ -425,6 +410,21 @@ typedef int64_t file_time_t;
#define max(a, b) ( (a) > (b) ? (a) : (b) )
#endif

/* These definitions need to be after all the includes */
#if defined(__GNUC__)
#define unused __attribute__((__unused__))
#elif defined(_MSC_VER)
#define unused __pragma(warning(suppress:4100)) /* This unfortunately disables the warning for the whole line and the next one */
#else
#define unused
#endif

#if DEBUG
#define unused_release
#else
#define unused_release unused
#endif

#define exiso_version "2.7.1 (01.11.14)"
#define VERSION_LENGTH 16

Expand Down Expand Up @@ -619,6 +619,9 @@ int calculate_directory_offsets( dir_node_avl *in_avl, uint32_t *io_context, int
int write_dir_start_and_file_positions( dir_node_avl *in_avl, wdsafp_context *io_context, int in_depth );
int write_volume_descriptors( int in_xiso, uint32_t in_total_sectors );

static int is_lnk_lstat(struct dirent* p, bool* lnk);
static int is_lnk(struct dirent* p, bool* lnk);

#if DEBUG
void write_sector( int in_xiso, xoff_t in_start, const char *in_name, const char *in_extension );
#endif
Expand Down Expand Up @@ -2014,14 +2017,49 @@ int calculate_directory_size( dir_node_avl *in_avl, uint32_t *out_size, int in_d
return 0;
}

static int is_lnk_lstat(struct dirent* p, bool* lnk) {
if (p == NULL || lnk == NULL) {
errno = EFAULT;
return -1;
}
#if !defined(_WIN32)
struct stat sb = { 0 };
if (lstat(p->d_name, &sb) == -1) {
return -1;
}
*lnk = S_ISLNK(sb.st_mode);
#else
*lnk = false;
#endif // _WIN32
return 0;
}

static int is_lnk(struct dirent* p, bool* lnk) {
if (p == NULL || lnk == NULL) {
errno = EFAULT;
return -1;
}
#if defined(_DIRENT_HAVE_D_TYPE)
if (p->d_type == DT_UNKNOWN) {
return is_lnk_lstat(p, lnk);
}
else {
*lnk = (p->d_type == DT_LNK);
return 0;
}
#else
return is_lnk_lstat(p, lnk);
#endif // _DIRENT_HAVE_D_TYPE
}


int generate_avl_tree_local( dir_node_avl **out_root, int *io_n ) {
struct dirent *p = NULL;
struct stat sb = { 0 };
dir_node_avl *avl = NULL;
DIR *dir = NULL;
int err = 0, i = 0, j = 0;
bool empty_dir = true;
bool empty_dir = true, lnk;

if ( ( dir = opendir( "." ) ) == NULL ) mem_err();

Expand All @@ -2034,16 +2072,19 @@ int generate_avl_tree_local( dir_node_avl **out_root, int *io_n ) {
for ( j = i; j < *io_n; ++j ) exiso_log( "\b" );
*io_n = i;
flush();

if (is_lnk(p, &lnk) == -1) read_err();
else if (lnk) continue;

if ( ( avl = (dir_node_avl *) calloc( 1, sizeof(dir_node_avl) ) ) == NULL ) mem_err();
if (!err && ( avl = (dir_node_avl *) calloc( 1, sizeof(dir_node_avl) ) ) == NULL ) mem_err();
if (!err && (avl->filename = strdup(p->d_name)) == NULL) mem_err();
if (!err) {
if (s_cp1252) {
avl->filename_cp1252 = avl->filename;
avl->filename = NULL;
} else if ((avl->filename_cp1252 = getCP1252String(p->d_name)) == NULL) mem_err();
}
if ( ! err && lstat( p->d_name, &sb ) == -1 ) read_err();
if ( ! err && stat( p->d_name, &sb ) == -1 ) read_err();
if ( ! err ) {
if ( S_ISDIR( sb.st_mode ) ) {
empty_dir = false;
Expand Down
195 changes: 0 additions & 195 deletions win32/dirent.c

This file was deleted.

0 comments on commit 59bfde6

Please sign in to comment.