Skip to content

Commit 59bfde6

Browse files
committed
Replace dirent implementation with one capable of detecting symlinks
Now symlinks are skipped on Windows too
1 parent 1d92f4f commit 59bfde6

File tree

5 files changed

+70
-214
lines changed

5 files changed

+70
-214
lines changed

.gitmodules

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,6 @@
44
[submodule "deps/asprintf"]
55
path = deps/asprintf
66
url = https://github.com/eiszapfen2000/asprintf.git
7+
[submodule "deps/dirent"]
8+
path = deps/dirent
9+
url = https://github.com/tronkko/dirent.git

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ set(SOURCE_FILES
88
)
99

1010
set(DEPS_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps)
11+
set(DIRENT_DIR ${DEPS_DIR}/dirent)
1112
set(GETOPT_DIR ${DEPS_DIR}/getopt_port)
1213
set(ASPRINTF_DIR ${DEPS_DIR}/asprintf)
1314

@@ -36,6 +37,11 @@ set_property(TARGET extract-xiso PROPERTY C_STANDARD 99)
3637
set_property(TARGET extract-xiso PROPERTY C_EXTENSIONS OFF)
3738

3839
if(WIN32)
40+
add_library(dirent INTERFACE)
41+
target_include_directories(dirent INTERFACE ${DIRENT_DIR}/include)
42+
43+
target_link_libraries(extract-xiso dirent)
44+
3945
add_library(getopt STATIC ${GETOPT_DIR}/getopt.c)
4046
target_sources(getopt PUBLIC ${GETOPT_DIR}/getopt.h)
4147
target_include_directories(getopt PUBLIC ${GETOPT_DIR})

deps/dirent

Submodule dirent added at 57ff230

extract-xiso.c

Lines changed: 60 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -242,24 +242,14 @@
242242

243243
#if defined(__GNUC__)
244244
#define _GNU_SOURCE
245-
#define unused __attribute__((__unused__))
246245
#elif defined(_MSC_VER)
247246
#pragma warning(disable: 4706) // C4706: assignment within conditional expression
248-
#define unused __pragma(warning(suppress:4100)) /* This unfortunately disables the warning for the whole line and the next one */
249-
#else
250-
#define unused
251247
#endif
252248

253249
#ifndef DEBUG
254250
#define DEBUG 0
255251
#endif
256252

257-
#if DEBUG
258-
#define unused_release
259-
#else
260-
#define unused_release unused
261-
#endif
262-
263253
#include <time.h>
264254
#include <errno.h>
265255
#include <fcntl.h>
@@ -272,6 +262,7 @@
272262
#include <string.h>
273263
#include <inttypes.h>
274264
#include <locale.h>
265+
#include <dirent.h> /* Provided by CMake on Windows */
275266
#include <sys/stat.h>
276267
#include <sys/types.h>
277268
#include "cp1252/cp1252.c"
@@ -283,10 +274,8 @@
283274
#if defined(_WIN32)
284275
#include <io.h>
285276
#include <direct.h>
286-
#include "win32/dirent.c"
287277
#include <getopt.h> /* Provided by CMake */
288278
#else
289-
#include <dirent.h>
290279
#include <limits.h>
291280
#include <unistd.h>
292281
#endif
@@ -337,9 +326,6 @@
337326
#define exiso_target "Windows"
338327

339328
#if defined(_MSC_VER)
340-
#define S_ISDIR(x) ((x) & _S_IFDIR)
341-
#define S_ISREG(x) ((x) & _S_IFREG)
342-
343329
typedef SSIZE_T ssize_t;
344330
#define strcasecmp _stricmp
345331
#define strncasecmp _strnicmp
@@ -353,7 +339,6 @@
353339
#define lseek _lseeki64
354340
#define mkdir(a, b) _mkdir(a)
355341
#define stat _stat64
356-
#define lstat _stat64
357342
#define realpath(a, b) _fullpath(b, a, _MAX_PATH)
358343

359344
#define bswap_16(x) _byteswap_ushort(x)
@@ -425,6 +410,21 @@ typedef int64_t file_time_t;
425410
#define max(a, b) ( (a) > (b) ? (a) : (b) )
426411
#endif
427412

413+
/* These definitions need to be after all the includes */
414+
#if defined(__GNUC__)
415+
#define unused __attribute__((__unused__))
416+
#elif defined(_MSC_VER)
417+
#define unused __pragma(warning(suppress:4100)) /* This unfortunately disables the warning for the whole line and the next one */
418+
#else
419+
#define unused
420+
#endif
421+
422+
#if DEBUG
423+
#define unused_release
424+
#else
425+
#define unused_release unused
426+
#endif
427+
428428
#define exiso_version "2.7.1 (01.11.14)"
429429
#define VERSION_LENGTH 16
430430

@@ -619,6 +619,9 @@ int calculate_directory_offsets( dir_node_avl *in_avl, uint32_t *io_context, int
619619
int write_dir_start_and_file_positions( dir_node_avl *in_avl, wdsafp_context *io_context, int in_depth );
620620
int write_volume_descriptors( int in_xiso, uint32_t in_total_sectors );
621621

622+
static int is_lnk_lstat(struct dirent* p, bool* lnk);
623+
static int is_lnk(struct dirent* p, bool* lnk);
624+
622625
#if DEBUG
623626
void write_sector( int in_xiso, xoff_t in_start, const char *in_name, const char *in_extension );
624627
#endif
@@ -2014,14 +2017,49 @@ int calculate_directory_size( dir_node_avl *in_avl, uint32_t *out_size, int in_d
20142017
return 0;
20152018
}
20162019

2020+
static int is_lnk_lstat(struct dirent* p, bool* lnk) {
2021+
if (p == NULL || lnk == NULL) {
2022+
errno = EFAULT;
2023+
return -1;
2024+
}
2025+
#if !defined(_WIN32)
2026+
struct stat sb = { 0 };
2027+
if (lstat(p->d_name, &sb) == -1) {
2028+
return -1;
2029+
}
2030+
*lnk = S_ISLNK(sb.st_mode);
2031+
#else
2032+
*lnk = false;
2033+
#endif // _WIN32
2034+
return 0;
2035+
}
2036+
2037+
static int is_lnk(struct dirent* p, bool* lnk) {
2038+
if (p == NULL || lnk == NULL) {
2039+
errno = EFAULT;
2040+
return -1;
2041+
}
2042+
#if defined(_DIRENT_HAVE_D_TYPE)
2043+
if (p->d_type == DT_UNKNOWN) {
2044+
return is_lnk_lstat(p, lnk);
2045+
}
2046+
else {
2047+
*lnk = (p->d_type == DT_LNK);
2048+
return 0;
2049+
}
2050+
#else
2051+
return is_lnk_lstat(p, lnk);
2052+
#endif // _DIRENT_HAVE_D_TYPE
2053+
}
2054+
20172055

20182056
int generate_avl_tree_local( dir_node_avl **out_root, int *io_n ) {
20192057
struct dirent *p = NULL;
20202058
struct stat sb = { 0 };
20212059
dir_node_avl *avl = NULL;
20222060
DIR *dir = NULL;
20232061
int err = 0, i = 0, j = 0;
2024-
bool empty_dir = true;
2062+
bool empty_dir = true, lnk;
20252063

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

@@ -2034,16 +2072,19 @@ int generate_avl_tree_local( dir_node_avl **out_root, int *io_n ) {
20342072
for ( j = i; j < *io_n; ++j ) exiso_log( "\b" );
20352073
*io_n = i;
20362074
flush();
2075+
2076+
if (is_lnk(p, &lnk) == -1) read_err();
2077+
else if (lnk) continue;
20372078

2038-
if ( ( avl = (dir_node_avl *) calloc( 1, sizeof(dir_node_avl) ) ) == NULL ) mem_err();
2079+
if (!err && ( avl = (dir_node_avl *) calloc( 1, sizeof(dir_node_avl) ) ) == NULL ) mem_err();
20392080
if (!err && (avl->filename = strdup(p->d_name)) == NULL) mem_err();
20402081
if (!err) {
20412082
if (s_cp1252) {
20422083
avl->filename_cp1252 = avl->filename;
20432084
avl->filename = NULL;
20442085
} else if ((avl->filename_cp1252 = getCP1252String(p->d_name)) == NULL) mem_err();
20452086
}
2046-
if ( ! err && lstat( p->d_name, &sb ) == -1 ) read_err();
2087+
if ( ! err && stat( p->d_name, &sb ) == -1 ) read_err();
20472088
if ( ! err ) {
20482089
if ( S_ISDIR( sb.st_mode ) ) {
20492090
empty_dir = false;

win32/dirent.c

Lines changed: 0 additions & 195 deletions
This file was deleted.

0 commit comments

Comments
 (0)