Merge branch 'develop' into master
This commit is contained in:
commit
03a29a618f
|
@ -66,3 +66,14 @@ CMakeError.log
|
|||
/test/cfg
|
||||
/src/.vs
|
||||
*.o
|
||||
src/connector/jdbc/.settings/
|
||||
tests/comparisonTest/cassandra/cassandratest/.classpath
|
||||
tests/comparisonTest/cassandra/cassandratest/.project
|
||||
tests/comparisonTest/cassandra/cassandratest/.settings/
|
||||
tests/comparisonTest/opentsdb/opentsdbtest/.classpath
|
||||
tests/comparisonTest/opentsdb/opentsdbtest/.factorypath
|
||||
tests/comparisonTest/opentsdb/opentsdbtest/.project
|
||||
tests/comparisonTest/opentsdb/opentsdbtest/.settings/
|
||||
tests/examples/JDBC/JDBCDemo/.classpath
|
||||
tests/examples/JDBC/JDBCDemo/.project
|
||||
tests/examples/JDBC/JDBCDemo/.settings/
|
||||
|
|
|
@ -29,41 +29,10 @@ IF (TD_RANDOM_NETWORK_FAIL)
|
|||
ADD_DEFINITIONS(-DTAOS_RANDOM_NETWORK_FAIL)
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_ARM)
|
||||
ADD_DEFINITIONS(-D_TD_ARM_)
|
||||
IF (TD_ARM_64)
|
||||
ADD_DEFINITIONS(-D_TD_ARM_64_)
|
||||
ENDIF ()
|
||||
IF (TD_ARM_32)
|
||||
ADD_DEFINITIONS(-D_TD_ARM_32_)
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_MIPS)
|
||||
ADD_DEFINITIONS(-D_TD_MIPS_)
|
||||
IF (TD_MIPS_64)
|
||||
ADD_DEFINITIONS(-D_TD_MIPS_64_)
|
||||
ENDIF ()
|
||||
IF (TD_MIPS_32)
|
||||
ADD_DEFINITIONS(-D_TD_MIPS_32_)
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_LINUX_64)
|
||||
ADD_DEFINITIONS(-D_M_X64)
|
||||
ADD_DEFINITIONS(-D_TD_LINUX_64)
|
||||
IF (NOT TD_ARM)
|
||||
#IF ((${CMAKE_CXX_COMPILER_ID} MATCHES "Clang") OR (${CMAKE_CXX_COMPILER_ID} MATCHES "clang"))
|
||||
# SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -Wno-missing-braces -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
#ELSE ()
|
||||
# SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -malign-double -g3 -gdwarf-2 -malign-stringops -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
#ENDIF ()
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
ELSE ()
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
ENDIF ()
|
||||
MESSAGE(STATUS "CMAKE_CXX_COMPILER_ID: " ${CMAKE_CXX_COMPILER_ID})
|
||||
MESSAGE(STATUS "COMMON_FLAGS: " ${COMMON_FLAGS})
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
|
||||
FIND_PATH(ICONV_INCLUDE_EXIST iconv.h /usr/include/ /usr/local/include/)
|
||||
IF (ICONV_INCLUDE_EXIST)
|
||||
|
@ -75,13 +44,39 @@ IF (TD_LINUX_32)
|
|||
ADD_DEFINITIONS(-D_TD_LINUX_32)
|
||||
ADD_DEFINITIONS(-DUSE_LIBICONV)
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g -fsigned-char -munaligned-access -fpack-struct=8 -latomic -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
IF (NOT TD_ARM)
|
||||
EXIT ()
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_ARM_64)
|
||||
ADD_DEFINITIONS(-D_TD_ARM_64_)
|
||||
ADD_DEFINITIONS(-D_TD_ARM_)
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_ARM_32)
|
||||
ADD_DEFINITIONS(-D_TD_ARM_32_)
|
||||
ADD_DEFINITIONS(-D_TD_ARM_)
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g -fsigned-char -fpack-struct=8 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_MIPS_64)
|
||||
ADD_DEFINITIONS(-D_TD_MIPS_64_)
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_MIPS_32)
|
||||
ADD_DEFINITIONS(-D_TD_MIPS_32_)
|
||||
SET(COMMON_FLAGS "-std=gnu99 -Wall -Werror -fPIC -g3 -gdwarf-2 -msse4.2 -D_FILE_OFFSET_BITS=64 -D_LARGE_FILE")
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_APLHINE)
|
||||
SET(COMMON_FLAGS "${COMMON_FLAGS} -largp")
|
||||
link_libraries(/usr/lib/libargp.a)
|
||||
ADD_DEFINITIONS(-D_ALPINE)
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_LINUX)
|
||||
ADD_DEFINITIONS(-DLINUX)
|
||||
ADD_DEFINITIONS(-D_LINUX)
|
||||
ADD_DEFINITIONS(-D_TD_LINUX)
|
||||
ADD_DEFINITIONS(-D_REENTRANT -D__USE_POSIX -D_LIBC_REENTRANT)
|
||||
|
||||
|
@ -94,12 +89,9 @@ IF (TD_LINUX)
|
|||
SET(GCC_COVERAGE_LINK_FLAGS "-lgcov --coverage")
|
||||
SET(COMMON_FLAGS "${COMMON_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS} ${GCC_COVERAGE_LINK_FLAGS}")
|
||||
ENDIF ()
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_APLHINE)
|
||||
SET(COMMON_FLAGS "${COMMON_FLAGS} -largp")
|
||||
link_libraries(/usr/lib/libargp.a)
|
||||
ADD_DEFINITIONS(-D_ALPINE)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc)
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_DARWIN_64)
|
||||
|
@ -124,6 +116,12 @@ IF (TD_WINDOWS)
|
|||
SET(DEBUG_FLAGS "/Zi /W3 /GL")
|
||||
SET(RELEASE_FLAGS "/W0 /GL")
|
||||
ENDIF ()
|
||||
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/iconv)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/regex)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/wepoll/inc)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/MsvcLibX/include)
|
||||
ENDIF ()
|
||||
|
||||
IF (TD_WINDOWS_64)
|
||||
|
@ -136,3 +134,9 @@ IF (TD_WINDOWS_32)
|
|||
ADD_DEFINITIONS(-D_TD_WINDOWS_32)
|
||||
ENDIF ()
|
||||
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc)
|
||||
INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc)
|
||||
|
||||
MESSAGE(STATUS "CMAKE_CXX_COMPILER_ID: " ${CMAKE_CXX_COMPILER_ID})
|
||||
|
|
|
@ -27,7 +27,7 @@ ELSEIF (TD_WINDOWS_64)
|
|||
#INSTALL(TARGETS taos RUNTIME DESTINATION driver)
|
||||
#INSTALL(TARGETS shell RUNTIME DESTINATION .)
|
||||
IF (TD_MVN_INSTALLED)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-1.0.2-dist.jar DESTINATION connector/jdbc)
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/taos-jdbcdriver-2.0.0-dist.jar DESTINATION connector/jdbc)
|
||||
ENDIF ()
|
||||
ELSE ()
|
||||
INSTALL(FILES ${LIBRARY_OUTPUT_PATH}/libtaos.dll DESTINATION driver)
|
||||
|
|
|
@ -15,44 +15,18 @@ PROJECT(TDengine)
|
|||
|
||||
# Set macro definitions according to os platform
|
||||
SET(TD_LINUX FALSE)
|
||||
SET(TD_LINUX_64 FALSE)
|
||||
SET(TD_LINUX_32 FALSE)
|
||||
SET(TD_ARM FALSE)
|
||||
SET(TD_ARM_64 FALSE)
|
||||
SET(TD_ARM_32 FALSE)
|
||||
SET(TD_MIPS FALSE)
|
||||
SET(TD_MIPS_64 FALSE)
|
||||
SET(TD_MIPS_32 FALSE)
|
||||
SET(TD_LINUX_64 FALSE)
|
||||
SET(TD_LINUX_32 FALSE)
|
||||
SET(TD_ARM_64 FALSE)
|
||||
SET(TD_ARM_32 FALSE)
|
||||
SET(TD_MIPS_64 FALSE)
|
||||
SET(TD_MIPS_32 FALSE)
|
||||
SET(TD_APLHINE FALSE)
|
||||
SET(TD_WINDOWS FALSE)
|
||||
SET(TD_WINDOWS_64 FALSE)
|
||||
SET(TD_WINDOWS_32 FALSE)
|
||||
SET(TD_DARWIN_64 FALSE)
|
||||
SET(TD_APLHINE FALSE)
|
||||
|
||||
# if generate ARM version:
|
||||
# cmake -DCPUTYPE=aarch32 .. or cmake -DCPUTYPE=aarch64
|
||||
IF (${CPUTYPE} MATCHES "aarch32")
|
||||
SET(TD_ARM TRUE)
|
||||
SET(TD_ARM_32 TRUE)
|
||||
SET(TD_PAGMODE_LITE TRUE)
|
||||
MESSAGE(STATUS "input cpuType: aarch32")
|
||||
ELSEIF (${CPUTYPE} MATCHES "aarch64")
|
||||
SET(TD_ARM TRUE)
|
||||
SET(TD_ARM_64 TRUE)
|
||||
MESSAGE(STATUS "input cpuType: aarch64")
|
||||
ELSEIF (${CPUTYPE} MATCHES "mips64")
|
||||
SET(TD_MIPS TRUE)
|
||||
SET(TD_MIPS_64 TRUE)
|
||||
MESSAGE(STATUS "input cpuType: mips64")
|
||||
ELSEIF (${CPUTYPE} MATCHES "x64")
|
||||
MESSAGE(STATUS "input cpuType: x64")
|
||||
ELSEIF (${CPUTYPE} MATCHES "x86")
|
||||
MESSAGE(STATUS "input cpuType: x86")
|
||||
ELSE ()
|
||||
MESSAGE(STATUS "input cpuType unknown " ${CPUTYPE})
|
||||
ENDIF ()
|
||||
|
||||
|
||||
SET(TD_WINDOWS_64 FALSE)
|
||||
SET(TD_WINDOWS_32 FALSE)
|
||||
SET(TD_DARWIN FALSE)
|
||||
SET(TD_DARWIN_64 FALSE)
|
||||
|
||||
IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
||||
#
|
||||
|
@ -68,12 +42,8 @@ IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
|||
MESSAGE(STATUS "The current platform is Linux 64-bit")
|
||||
ELSEIF (${CMAKE_SIZEOF_VOID_P} MATCHES 4)
|
||||
SET(TD_LINUX_32 TRUE)
|
||||
IF (TD_ARM)
|
||||
MESSAGE(STATUS "The current platform is Linux 32-bit")
|
||||
ELSE ()
|
||||
MESSAGE(FATAL_ERROR "The current platform is Linux 32-bit, but no ARM not supported yet")
|
||||
EXIT ()
|
||||
ENDIF ()
|
||||
MESSAGE(STATUS "The current platform is Linux 32-bit")
|
||||
|
||||
ELSE ()
|
||||
MESSAGE(FATAL_ERROR "The current platform is Linux neither 32-bit nor 64-bit, not supported yet")
|
||||
EXIT ()
|
||||
|
@ -84,6 +54,7 @@ IF (${CMAKE_SYSTEM_NAME} MATCHES "Linux")
|
|||
MESSAGE(STATUS "The current OS is Alpine, append extra flags")
|
||||
ENDIF()
|
||||
ELSEIF (${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
SET(TD_DARWIN TRUE)
|
||||
IF (${CMAKE_SIZEOF_VOID_P} MATCHES 8)
|
||||
SET(TD_DARWIN_64 TRUE)
|
||||
MESSAGE(STATUS "The current platform is Darwin 64-bit")
|
||||
|
@ -105,3 +76,25 @@ ELSE()
|
|||
MESSAGE(FATAL_ERROR "The current platform is not Linux/Darwin/Windows, stop compile")
|
||||
EXIT ()
|
||||
ENDIF ()
|
||||
|
||||
# if generate ARM version:
|
||||
# cmake -DCPUTYPE=aarch32 .. or cmake -DCPUTYPE=aarch64
|
||||
IF (${CPUTYPE} MATCHES "aarch32")
|
||||
SET(TD_LINUX TRUE)
|
||||
SET(TD_ARM_32 TRUE)
|
||||
MESSAGE(STATUS "input cpuType: aarch32")
|
||||
ELSEIF (${CPUTYPE} MATCHES "aarch64")
|
||||
SET(TD_LINUX TRUE)
|
||||
SET(TD_ARM_64 TRUE)
|
||||
MESSAGE(STATUS "input cpuType: aarch64")
|
||||
ELSEIF (${CPUTYPE} MATCHES "mips64")
|
||||
SET(TD_LINUX TRUE)
|
||||
SET(TD_MIPS_64 TRUE)
|
||||
MESSAGE(STATUS "input cpuType: mips64")
|
||||
ELSEIF (${CPUTYPE} MATCHES "x64")
|
||||
MESSAGE(STATUS "input cpuType: x64")
|
||||
ELSEIF (${CPUTYPE} MATCHES "x86")
|
||||
MESSAGE(STATUS "input cpuType: x86")
|
||||
ELSE ()
|
||||
MESSAGE(STATUS "input cpuType unknown " ${CPUTYPE})
|
||||
ENDIF ()
|
||||
|
|
|
@ -7,4 +7,9 @@ ADD_SUBDIRECTORY(regex)
|
|||
ADD_SUBDIRECTORY(iconv)
|
||||
ADD_SUBDIRECTORY(lz4)
|
||||
ADD_SUBDIRECTORY(cJson)
|
||||
ADD_SUBDIRECTORY(MQTT-C)
|
||||
ADD_SUBDIRECTORY(wepoll)
|
||||
ADD_SUBDIRECTORY(MsvcLibX)
|
||||
|
||||
IF (TD_LINUX)
|
||||
ADD_SUBDIRECTORY(MQTT-C)
|
||||
ENDIF ()
|
|
@ -10,11 +10,11 @@ option(MQTT_C_TESTS "Build MQTT-C tests?" OFF)
|
|||
list (APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
|
||||
# MQTT-C library
|
||||
add_library(mqttc STATIC
|
||||
ADD_LIBRARY(mqttc STATIC
|
||||
src/mqtt_pal.c
|
||||
src/mqtt.c
|
||||
)
|
||||
target_include_directories(mqttc PUBLIC include)
|
||||
TARGET_INCLUDE_DIRECTORIES(mqttc PUBLIC include)
|
||||
target_link_libraries(mqttc PUBLIC
|
||||
$<$<C_COMPILER_ID:MSVS>:ws2_32>
|
||||
)
|
||||
|
@ -30,7 +30,7 @@ endif()
|
|||
# Configure with mbed TLS support
|
||||
if(MQTT_C_MbedTLS_SUPPORT)
|
||||
find_package(MbedTLS REQUIRED)
|
||||
target_include_directories(mqttc PUBLIC ${MBEDTLS_INCLUDE_DIRS})
|
||||
TARGET_INCLUDE_DIRECTORIES(mqttc PUBLIC ${MBEDTLS_INCLUDE_DIRS})
|
||||
target_link_libraries(mqttc INTERFACE ${MBEDTLS_LIBRARY})
|
||||
target_compile_definitions(mqttc PUBLIC MQTT_USE_MBEDTLS)
|
||||
endif()
|
||||
|
@ -70,7 +70,7 @@ if(MQTT_C_TESTS)
|
|||
|
||||
add_executable(tests tests.c)
|
||||
target_link_libraries(tests ${CMOCKA_LIBRARY} mqttc)
|
||||
target_include_directories(tests PRIVATE ${CMOCKA_INCLUDE_DIR})
|
||||
TARGET_INCLUDE_DIRECTORIES(tests PRIVATE ${CMOCKA_INCLUDE_DIR})
|
||||
endif()
|
||||
|
||||
# Install includes and library
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
PROJECT(TDengine)
|
||||
|
||||
IF (TD_WINDOWS)
|
||||
INCLUDE_DIRECTORIES(include)
|
||||
AUX_SOURCE_DIRECTORY(src SRC)
|
||||
ADD_LIBRARY(MsvcLibXw64 ${SRC})
|
||||
ENDIF ()
|
|
@ -0,0 +1,206 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: debugm.h *
|
||||
* *
|
||||
* Description: Debug macros *
|
||||
* *
|
||||
* Notes: Macros inspired by my Tcl/Bash/Batch debugging libraries. *
|
||||
* The idea is to output the function call stack, indenting *
|
||||
* subroutines proportionally to the call depth. *
|
||||
* To ease reading the output, it must look like real C code.*
|
||||
* *
|
||||
* DEBUG_GLOBALS Define global variables used by macros below: *
|
||||
* int iDebug = FALSE; Global variable enabling debug output if TRUE.*
|
||||
* int iIndent = 0; Global variable controlling debug indentation.*
|
||||
* *
|
||||
* DEBUG_PRINTF((format, ...)) Print a debug string if debug is on. *
|
||||
* The double parenthesis are necessary *
|
||||
* because C90 does not support macros *
|
||||
* with variable list of arguments. *
|
||||
* DEBUG_ENTER((format, ...)) Print a function name and arguments. *
|
||||
* Increase indentation of further calls.*
|
||||
* It's the caller's responsibility to *
|
||||
* format the routine name and arguments.*
|
||||
* DEBUG_LEAVE((format, ...)) Print a function return value. *
|
||||
* Decrease indentation of further calls.*
|
||||
* It's the caller's responsibility to *
|
||||
* format the return instruction & value.*
|
||||
* *
|
||||
* Any call to DEBUG_ENTER MUST be matched by one call to *
|
||||
* DEBUG_LEAVE or RETURN_... when the function returns. * *
|
||||
* *
|
||||
* History: *
|
||||
* 2012-01-16 JFL jf.larvoire@hp.com created this file. *
|
||||
* 2012-02-03 JFL Renamed DEBUG_IF_IS_ON DEBUG_CODE_IF_ON. *
|
||||
* Renamed file from debug.h to debugm.h because of a file *
|
||||
* name collision with another library on my PC. *
|
||||
* 2014-02-10 JFL Added macros for an extra debug mode. *
|
||||
* 2014-07-02 JFL renamed macro RETURN() as RETURN_CONST(), and defined *
|
||||
* new macro RETURN() to return nothing. *
|
||||
* Idem for RETURN_COMMENT() as RETURN_CONST_COMMENT(). *
|
||||
* 2016-09-09 JFL Flush every DEBUG_PRINTF output, to make sure to see *
|
||||
* every debug string printed before a program crash. *
|
||||
* 2016-09-13 JFL Added macros DEBUG_WSTR2NEWUTF8() and DEBUG_FREEUTF8(). *
|
||||
* 2016-10-04 JFL Added macros DEBUG_OFF(), DEBUG_MORE(), DEBUG_LESS(). *
|
||||
* Allow using DEBUG_ON()/MORE()/LESS()/OFF() in release mode.
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _DEBUGM_H
|
||||
#define _DEBUGM_H 1
|
||||
|
||||
#include <stdio.h> /* Macros use printf */
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4127) /* Avoid warnings on while(0) below */
|
||||
#endif
|
||||
|
||||
#define DEBUG_DO(code) do {code} while (0)
|
||||
#define DEBUG_DO_NOTHING() do {} while (0)
|
||||
|
||||
/* Conditional compilation based on Microsoft's standard _DEBUG definition */
|
||||
#if defined(_DEBUG)
|
||||
|
||||
#define DEBUG_VERSION " Debug"
|
||||
|
||||
#define DEBUG_GLOBALS \
|
||||
int iDebug = 0; /* Global variable enabling debug output if TRUE. */ \
|
||||
int iIndent = 0; /* Global variable controlling debug indentation. */
|
||||
|
||||
extern int iDebug; /* Global variable enabling of disabling debug messages */
|
||||
#define DEBUG_ON() iDebug = 1 /* Turn debug mode on */
|
||||
#define DEBUG_MORE() iDebug += 1 /* Increase the debug level */
|
||||
#define DEBUG_LESS() iDebug -= 1 /* Decrease the debug level */
|
||||
#define DEBUG_OFF() iDebug = 0 /* Turn debug mode off */
|
||||
#define DEBUG_IS_ON() (iDebug > 0) /* Check if the debug mode is enabled */
|
||||
#define XDEBUG_ON() iDebug = 2 /* Turn extra debug mode on. Same as calling DEBUG_MORE() twice. */
|
||||
#define XDEBUG_IS_ON() (iDebug > 1) /* Check if the extra debug mode is enabled */
|
||||
|
||||
#define DEBUG_CODE(code) code /* Code included in the _DEBUG version only */
|
||||
#define DEBUG_CODE_IF_ON(code) DEBUG_CODE(if (DEBUG_IS_ON()) {code}) /*
|
||||
Debug code executed if debug mode is on */
|
||||
#define XDEBUG_CODE_IF_ON(code) DEBUG_CODE(if (XDEBUG_IS_ON()) {code}) /*
|
||||
Debug code executed if extra debug mode is on */
|
||||
|
||||
extern int iIndent; /* Debug messages indentation */
|
||||
#define DEBUG_INDENT_STEP 2 /* How many spaces to add for each indentation level */
|
||||
#define DEBUG_PRINT_INDENT() printf("%*s", iIndent, "")
|
||||
|
||||
/* Debug code, conditionally printing a string based on global variable 'debug' */
|
||||
/* The enter and leave variants print, then respectively increase or decrease indentation,
|
||||
to make recursive calls easier to review. */
|
||||
#define DEBUG_FPRINTF(args) DEBUG_DO(if (DEBUG_IS_ON()) {DEBUG_PRINT_INDENT(); fprintf args;})
|
||||
#define DEBUG_PRINTF(args) DEBUG_DO(if (DEBUG_IS_ON()) {DEBUG_PRINT_INDENT(); printf args; fflush(stdout);})
|
||||
#define XDEBUG_PRINTF(args) DEBUG_DO(if (XDEBUG_IS_ON()) {DEBUG_PRINT_INDENT(); printf args; fflush(stdout);})
|
||||
#define DEBUG_ENTER(args) DEBUG_DO(DEBUG_PRINTF(args); iIndent += DEBUG_INDENT_STEP;)
|
||||
#define DEBUG_LEAVE(args) DEBUG_DO(DEBUG_PRINTF(args); iIndent -= DEBUG_INDENT_STEP;)
|
||||
|
||||
#define DEBUG_RETURN_INT(i, comment) DEBUG_DO(int DEBUG_i = (i); \
|
||||
DEBUG_LEAVE(("return %d; // " comment "\n", DEBUG_i)); return DEBUG_i;)
|
||||
|
||||
/* print return instruction and decrease indent */
|
||||
#define RETURN() DEBUG_DO(DEBUG_LEAVE(("return;\n")); return;)
|
||||
#define RETURN_CONST(value) DEBUG_DO(DEBUG_LEAVE(("return %s;\n", #value)); return value;)
|
||||
#define RETURN_INT(i) DEBUG_DO(int DEBUG_i = (i); \
|
||||
DEBUG_LEAVE(("return %d;\n", DEBUG_i)); return DEBUG_i;)
|
||||
#define RETURN_STRING(s) DEBUG_DO(char *DEBUG_s = (s); \
|
||||
DEBUG_LEAVE(("return \"%s\";\n", DEBUG_s)); return DEBUG_s;)
|
||||
#define RETURN_CHAR(c) DEBUG_DO(char DEBUG_c = (c); \
|
||||
DEBUG_LEAVE(("return '%c';\n", DEBUG_c)); return DEBUG_c;)
|
||||
#define RETURN_BOOL(b) DEBUG_DO(int DEBUG_b = (b); \
|
||||
DEBUG_LEAVE(("return %s;\n", DEBUG_b ? "TRUE" : "FALSE")); return DEBUG_b;)
|
||||
|
||||
#define RETURN_COMMENT(args) DEBUG_DO(DEBUG_LEAVE(("return; // ")); \
|
||||
if (DEBUG_IS_ON()) printf args; return;)
|
||||
#define RETURN_CONST_COMMENT(value, args) DEBUG_DO(DEBUG_LEAVE(("return %s; // ", #value)); \
|
||||
if (DEBUG_IS_ON()) printf args; return value;)
|
||||
#define RETURN_INT_COMMENT(i, args) DEBUG_DO(int DEBUG_i = (i); \
|
||||
DEBUG_LEAVE(("return %d; // ", DEBUG_i)); if (DEBUG_IS_ON()) printf args; return DEBUG_i;)
|
||||
#define RETURN_BOOL_COMMENT(b, args) DEBUG_DO(int DEBUG_b = (b); \
|
||||
DEBUG_LEAVE(("return %s; // ", DEBUG_b ? "TRUE" : "FALSE")); if (DEBUG_IS_ON()) printf args; return DEBUG_b;)
|
||||
|
||||
#else /* !defined(_DEBUG) */
|
||||
|
||||
#define DEBUG_VERSION "" /* Non debug version: Simply don't say it */
|
||||
|
||||
#define DEBUG_GLOBALS
|
||||
|
||||
#define DEBUG_ON() (void)0
|
||||
#define DEBUG_MORE() (void)0
|
||||
#define DEBUG_LESS() (void)0
|
||||
#define DEBUG_OFF() (void)0
|
||||
#define DEBUG_IS_ON() 0
|
||||
#define XDEBUG_IS_ON() 0
|
||||
#define DEBUG_CODE(code) /* Code included in _DEBUG version only */
|
||||
#define DEBUG_CODE_IF_ON(code) /* Code included in _DEBUG version only */
|
||||
#define XDEBUG_CODE_IF_ON(code) /* Code included in _DEBUG version only */
|
||||
|
||||
#define DEBUG_PRINT_INDENT() DEBUG_DO_NOTHING() /* Print call-depth spaces */
|
||||
|
||||
#define DEBUG_FPRINTF(args) DEBUG_DO_NOTHING() /* Print a debug string to a stream */
|
||||
#define DEBUG_PRINTF(args) DEBUG_DO_NOTHING() /* Print a debug string to stdout */
|
||||
#define XDEBUG_PRINTF(args) DEBUG_DO_NOTHING() /* Print an extra debug string to stdout */
|
||||
#define DEBUG_ENTER(args) DEBUG_DO_NOTHING() /* Print and increase indent */
|
||||
#define DEBUG_LEAVE(args) DEBUG_DO_NOTHING() /* Print and decrease indent */
|
||||
|
||||
#define DEBUG_RETURN_INT(i, comment) return(i)
|
||||
|
||||
/* print return instruction and decrease indent */
|
||||
#define RETURN() return
|
||||
#define RETURN_CONST(value) return(value)
|
||||
#define RETURN_INT(i) return(i)
|
||||
#define RETURN_STRING(s) return(s)
|
||||
#define RETURN_CHAR(c) return(c)
|
||||
#define RETURN_BOOL(b) return(b)
|
||||
|
||||
#define RETURN_COMMENT(args) return
|
||||
#define RETURN_CONST_COMMENT(value, args) return(value)
|
||||
#define RETURN_INT_COMMENT(i, args) return(i)
|
||||
#define RETURN_BOOL_COMMENT(b, args) return(b)
|
||||
|
||||
#endif /* defined(_DEBUG) */
|
||||
|
||||
#define STRINGIZE(s) #s /* Convert a macro name to a string */
|
||||
#define VALUEIZE(s) STRINGIZE(s) /* Convert a macro value to a string */
|
||||
#define MACRODEF(s) "#define " #s " " STRINGIZE(s)
|
||||
|
||||
/* Display a macro name and value. */
|
||||
#define DEBUG_PRINT_MACRO(name) DEBUG_DO( \
|
||||
const char *pszName = #name; /* Don't use STRINGIZE because we're already inside a macro */ \
|
||||
const char *pszValue = STRINGIZE(name); /* Don't use VALUEIZE because we're already inside a macro */ \
|
||||
DEBUG_PRINT_INDENT(); \
|
||||
if (strcmp(pszName, pszValue)) { \
|
||||
printf("#define %s %s\n", pszName, pszValue); \
|
||||
} else { /* Not 100% certain, but most likely. */ \
|
||||
printf("#undef %s\n", pszName); \
|
||||
} \
|
||||
)
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/* Helper macros for displaying Unicode strings */
|
||||
#define DEBUG_WSTR2UTF8(from, to, toSize) DEBUG_CODE( \
|
||||
WideCharToMultiByte(CP_UTF8, 0, from, lstrlenW(from)+1, to, toSize, NULL, NULL); \
|
||||
)
|
||||
|
||||
/* Dynamically allocate a new buffer, then convert a Unicode string to UTF-8 */
|
||||
/* The dynamic allocation is useful in modules using lots of UTF-16 pathnames.
|
||||
This avoids having many local buffers of length UTF8_PATH_MAX, which may
|
||||
make the stack grow too large and overflow. */
|
||||
#define DEBUG_WSTR2NEWUTF8(pwStr, pUtf8) \
|
||||
DEBUG_CODE( \
|
||||
do { \
|
||||
int nUtf8 = (int)lstrlenW(pwStr) * 2 + 1; \
|
||||
pUtf8 = malloc(nUtf8); \
|
||||
DEBUG_WSTR2UTF8(pwStr, pUtf8, nUtf8); \
|
||||
} while (0); \
|
||||
) /* DEBUG_FREE(pUtf8) MUST be used to free the UTF-8 string after use, else there will be a memory leak */
|
||||
|
||||
#define DEBUG_FREEUTF8(pUtf8) DEBUG_CODE(free(pUtf8))
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
#endif /* !defined(_DEBUGM_H) */
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: direct.h *
|
||||
* *
|
||||
* Description: MsvcLibX extensions to direct.h. *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-03-24 JFL Created this file, with content moved from unistd.h. *
|
||||
* 2015-11-15 JFL Visual Studio 2015 moved this file to the Windows Kit UCRT.
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _MSVCLIBX_DIRECT_H
|
||||
#define _MSVCLIBX_DIRECT_H 1
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#include <direct.h> /* Include MSVC's own <direct.h> file */
|
||||
|
||||
#undef mkdir /* This MSVC macro is incompatible with mkdir() function in unistd.h */
|
||||
|
||||
#endif /* defined(_MSVCLIBX_DIRECT_H) */
|
||||
|
|
@ -0,0 +1,282 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: dirent.h *
|
||||
* *
|
||||
* Description: DOS/WIN32 port of standard C library's dirent.h. *
|
||||
* *
|
||||
* Notes: There are also remains of an OS/2 implementation here. *
|
||||
* This code did work c. 1990, in an OS/2 1.3 port of dirc.c.*
|
||||
* It's not maintained anymore, and unlikely to still work. *
|
||||
* Left in as a historic reference, in the very unlikely *
|
||||
* case somebody wants to revive it. *
|
||||
* *
|
||||
* History: *
|
||||
* 2012-01-09 JFL Created this file, based on dirc and other programs. *
|
||||
* 2013-03-09 JFL Rewrote the stat/fstat/lstat and fseeko/ftello definitions*
|
||||
* based on _FILE_OFFSET_BITS, _LARGEFILE_SOURCE, and *
|
||||
* _LARGEFILE_SOURCE64 definitions. *
|
||||
* 2014-02-06 JFL Moved stat extensions to statx.h. *
|
||||
* 2014-02-27 JFL Use a WIN32_FIND_DATAW in Windows, to support UTF-8 names.*
|
||||
* 2014-03-20 JFL Restructured Windows opendir and readdir functions into *
|
||||
* Wide and MultiByte versions, and changed the Unicode and *
|
||||
* Ansi versions to macros. *
|
||||
* 2014-06-06 JFL Fixed macro _D_EXACT_NAMLEN(). *
|
||||
* 2015-12-07 JFL Added the conditional definition of symlink constants, so *
|
||||
* that our code builds even in XP and older Windows SDKs. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _DIRENT_H
|
||||
#define _DIRENT_H 1
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#define _DIRENT_FOR_DOS_WINDOWS /* Uniquely identify this module */
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <time.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#ifndef ENAMETOOLONG /* Not defined in DOS' errno.h */
|
||||
#define ENAMETOOLONG 38
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Macros to extract size information from a struct dirent */
|
||||
#define _D_EXACT_NAMLEN(d) (strlen((d)->d_name)) /* Name length, not including NUL */
|
||||
|
||||
#define _DIRENT_HAVE_D_TYPE /* We commit to providing this field */
|
||||
|
||||
/************************ MS-DOS-specific definitions ************************/
|
||||
|
||||
#ifdef _MSDOS /* Automatically defined when targeting an MS-DOS application */
|
||||
|
||||
#include <dos.h>
|
||||
|
||||
#define NAME_MAX 12
|
||||
|
||||
#pragma pack(1)
|
||||
struct _fileinfo { /* MS-DOS structure returning file search results */
|
||||
uint8_t fiReserved[21];
|
||||
uint8_t fiAttribute; /* Attributes of file found */
|
||||
uint16_t fiFileTime; /* Time of last write */
|
||||
uint16_t fiFileDate; /* Time of last write */
|
||||
uint32_t fiSize; /* File Size */
|
||||
char fiFileName[13]; /* File name and extension */
|
||||
};
|
||||
#pragma pack()
|
||||
typedef struct _fileinfo fileinfo;
|
||||
|
||||
#pragma pack(1)
|
||||
struct dirent { /* Standard C library structure returning directory entries. */
|
||||
/* Standard fields */
|
||||
_ino_t d_ino; /* We don't need it, but it's required by the spec */
|
||||
unsigned char d_type; /* File type. Values defined in macros DT_xxxx */
|
||||
/* unsigned char d_namlen; /* File name length, not including NUL */
|
||||
/* OS-specific extensions (allowed by the Posix specification) */
|
||||
/* Matches exactly the struc _fileinfo above, to avoid doing any copying */
|
||||
uint8_t d_reserved[21];
|
||||
uint8_t d_attribs; /* Attribute of file found */
|
||||
uint16_t d_time; /* Time of last write */
|
||||
uint16_t d_date; /* Time of last write */
|
||||
uint32_t d_filesize; /* File Size */
|
||||
/* Standard field: The file name, which must be last in the dirent structure */
|
||||
char d_name[NAME_MAX+1]; /* Null-terminated file name. Must be last */
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
#pragma pack(1)
|
||||
struct _dirhandle { /* Private structure, not for use by users */
|
||||
struct dirent sDirent;
|
||||
/* char dta_buf[128]; /* Protection area, in case MS-DOS uses the whole DTA, and not just the struct _fileinfo ahead of it. */
|
||||
char wildcards[4]; /* Leave room for the "\*.*" that we append initially. This field MUST follow sDirent. */
|
||||
char first; /* Tracks if this is the first search call */
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
/* Macros to extract size information from a struct dirent */
|
||||
#define _D_ALLOC_NAMLEN(d) 13 /* Upper bound of the block size to alloc for a name */
|
||||
|
||||
/* MS-DOS compatible functions for searching with a specific attribute */
|
||||
int srch1st(char *pszFile, uint16_t wAttr, fileinfo *pFI); /* Search first matching file */
|
||||
int srchnext(fileinfo *pFI); /* Search next matching file */
|
||||
#define DOS_SEARCH_FUNCTIONS_DEFINED 1
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
/************************ Win32-specific definitions *************************/
|
||||
|
||||
#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */
|
||||
|
||||
#ifndef WINVER
|
||||
#define WINVER 0x0400
|
||||
#endif
|
||||
|
||||
#include <dos.h>
|
||||
#include <windows.h>
|
||||
|
||||
/* Add symlink definitions, that may be missing in XP and older Windows SDKs */
|
||||
#ifndef IO_REPARSE_TAG_SYMLINK
|
||||
#define IO_REPARSE_TAG_SYMLINK 0xA000000CL
|
||||
#endif
|
||||
#ifndef SYMBOLIC_LINK_FLAG_DIRECTORY
|
||||
#define SYMBOLIC_LINK_FLAG_DIRECTORY 1
|
||||
#endif
|
||||
#ifndef FSCTL_SET_REPARSE_POINT
|
||||
#define FSCTL_SET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
|
||||
#endif
|
||||
#ifndef FSCTL_GET_REPARSE_POINT
|
||||
#define FSCTL_GET_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 42, METHOD_BUFFERED, FILE_ANY_ACCESS)
|
||||
#endif
|
||||
#ifndef FSCTL_DELETE_REPARSE_POINT
|
||||
#define FSCTL_DELETE_REPARSE_POINT CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 43, METHOD_BUFFERED, FILE_SPECIAL_ACCESS)
|
||||
#endif
|
||||
|
||||
#define NAME_MAX (4 * FILENAME_MAX) /* Worst case using UTF-8 encoding: 4 bytes/WCHAR */
|
||||
|
||||
struct dirent { /* Structure used to return information about directory entries. */
|
||||
/* OS-specific extensions */
|
||||
uint32_t d_attribs;
|
||||
uint32_t d_ReparseTag;
|
||||
FILETIME d_CreationTime;
|
||||
FILETIME d_LastAccessTime;
|
||||
FILETIME d_LastWriteTime;
|
||||
uint64_t d_filesize;
|
||||
char d_shortname[14*sizeof(WCHAR)];
|
||||
/* Standard fields */
|
||||
_ino_t d_ino; /* We don't need it, but it's required by the spec */
|
||||
unsigned char d_type; /* File type. Values defined in macros DT_xxxx */
|
||||
/* unsigned char d_namlen; /* File name length, not including NUL */
|
||||
char d_name[(NAME_MAX+1)*sizeof(WCHAR)]; /* Null-terminated file name */
|
||||
};
|
||||
|
||||
struct _dirhandle { /* Private structure, not for use by users */
|
||||
struct dirent sDirent;
|
||||
WCHAR wszDirName[MAX_PATH+1]; /* Null-terminated directory name */
|
||||
HANDLE hFindFile; /* Search handle */
|
||||
WIN32_FIND_DATAW wfd; /* Where Win32 will store the file information */
|
||||
};
|
||||
|
||||
/* Macros to extract size information from a struct dirent */
|
||||
#define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN(d)+1) /* Upper bound of the block size to alloc for a name */
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
/************************* OS/2-specific definitions *************************/
|
||||
|
||||
#ifdef _OS2 /* Automatically defined when targeting an OS/2 application? */
|
||||
|
||||
#include <dos.h>
|
||||
|
||||
#define INCL_DOSFILEMGR
|
||||
#define INCL_DOSMISC
|
||||
#define INCL_VIO
|
||||
#include "os2.h"
|
||||
|
||||
#define NAME_MAX CCHMAXPATHCOMP
|
||||
|
||||
struct dirent { /* Structure used to return information about directory entries. */
|
||||
_ino_t d_ino; /* We don't need it, but it's required by the spec */
|
||||
/* Non standard extensions, to ease adapting old DOS/WIN32 apps */
|
||||
uintmax_t d_filesize; /* File size */
|
||||
uint16_t time; /* MS-DOS time */
|
||||
uint16_t date; /* MS-DOS date */
|
||||
uint8_t attribs; /* Attributes, the MS-DOS way */
|
||||
/* Standard fields */
|
||||
unsigned char d_type; /* File type. Values defined in macros DT_xxxx */
|
||||
/* unsigned char d_namlen; /* File name length, not including NUL */
|
||||
char d_name[NAME_MAX+1]; /* Null-terminated file name. Must be last */
|
||||
};
|
||||
|
||||
struct _dirhandle { /* Private structure, not for use by users */
|
||||
struct dirent sDirent;
|
||||
short hDir; /* Directory handle */
|
||||
FILEFINDBUF buf; /* Where OS/2 will store the file information */
|
||||
};
|
||||
|
||||
/* Macros to extract size information from a struct dirent */
|
||||
#define _D_ALLOC_NAMLEN(d) (_D_EXACT_NAMLEN(d)+1) /* Upper bound of the block size to alloc for a name */
|
||||
|
||||
#endif /* defined(_OS2) */
|
||||
|
||||
/********************** End of OS-specific definitions ***********************/
|
||||
|
||||
typedef struct _dirhandle DIR; /* Directory enumerator handle */
|
||||
typedef struct dirent _dirent; /* Directory entry */
|
||||
|
||||
#define MAXNAMELEN NAME_MAX /* Alias used by some Unix versions */
|
||||
|
||||
/* File types for struct dirent d_type. Must match the S_IFMT field in sys/stat.h. */
|
||||
#define DT_UNKNOWN 0
|
||||
#define DT_FIFO 1 /* Fifo (not used in DOS/Windows dirs) */
|
||||
#define DT_CHR 2 /* Character device (not used in DOS/Windows) */
|
||||
#define DT_DIR 4 /* Directory */
|
||||
#define DT_BLK 6 /* Block device (not used in DOS/Windows) */
|
||||
#define DT_REG 8 /* Normal file */
|
||||
#define DT_LNK 10 /* Symbolic link */
|
||||
#define DT_SOCK 12 /* Socket (not used in DOS/Windows dirs) */
|
||||
#define DT_VOLID 15 /* Volume ID (non-standard extension for MS-DOS FAT) */
|
||||
|
||||
/* Functions operating on directories */
|
||||
#if defined(_MSDOS)
|
||||
|
||||
extern DIR *opendir(const char *name); /* Open a directory */
|
||||
extern int closedir(DIR *pDir); /* Close the directory. Return 0 if successful, -1 if not. */
|
||||
extern _dirent *readdir(DIR *pDir); /* Read a directory entry. Return pDirEnt, or NULL for EOF or error. */
|
||||
|
||||
#elif defined(_WIN32)
|
||||
|
||||
#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
|
||||
#define opendir opendirU
|
||||
#define readdir readdirU
|
||||
#define scandir scandirU
|
||||
#else /* _ANSI_SOURCE */
|
||||
#define opendir opendirA
|
||||
#define readdir readdirA
|
||||
#define scandir scandirA
|
||||
#endif
|
||||
extern DIR *opendirW(const WCHAR *name); /* Open a directory - Wide char version */
|
||||
extern DIR *opendirM(const char *name, UINT cp); /* Open a directory - MultiByte char version */
|
||||
#define opendirA(name) opendirM(name, CP_ACP) /* Open a directory - ANSI version */
|
||||
#define opendirU(name) opendirM(name, CP_UTF8) /* Open a directory - UTF-8 version */
|
||||
extern int closedir(DIR *pDir); /* Close the directory. Return 0 if successful, -1 if not. */
|
||||
extern _dirent *readdirW(DIR *pDir); /* Read a directory entry. Return pDirEnt, or NULL for EOF or error. */
|
||||
extern _dirent *readdirM(DIR *pDir, UINT cp); /* Read a directory entry. Return pDirEnt, or NULL for EOF or error. */
|
||||
#define readdirA(pDir) readdirM(pDir, CP_ACP) /* Read a directory entry. Return pDirEnt, or NULL for EOF or error. */
|
||||
#define readdirU(pDir) readdirM(pDir, CP_UTF8) /* Read a directory entry. Return pDirEnt, or NULL for EOF or error. */
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
/* extern int readdir_r(DIR *pDir, _dirent *__entry, _dirent **__result); /* Reentrant readdir */
|
||||
/* extern void rewinddir(DIR *pDir); /* Rewind DIRP to the beginning of the directory. */
|
||||
/* extern void seekdir(DIR *pDir, long lPos); /* Seek to position POS on DIRP. */
|
||||
/* extern long telldir(DIR *pDir); /* Return the current position of DIRP. */
|
||||
/* extern int dirfd(DIR *pDir); /* Return the file descriptor used by DIRP. */
|
||||
|
||||
/* Scan the directory dir, calling cbSelect() on each directory entry.
|
||||
Entries for which cbSelect() returns nonzero are individually malloc'd,
|
||||
sorted using qsort with cbCompare(), and collected in a malloc'd array in
|
||||
*namelist. Returns the number of entries selected, or -1 on error. */
|
||||
extern int scandir(const char *dir,
|
||||
_dirent ***namelist,
|
||||
int (*cbSelect) (const _dirent *),
|
||||
int (__cdecl *cbCompare) (const _dirent **,
|
||||
const _dirent **));
|
||||
|
||||
/* Function to compare two `struct dirent's alphabetically. */
|
||||
extern int __cdecl alphasort (const _dirent **ppDE1, const _dirent **ppDEe2);
|
||||
/* extern int versionsort (const _dirent **ppDE1, const _dirent **ppDEe2); */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* defined(_DIRENT_H) */
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: error.h *
|
||||
* *
|
||||
* Description: DOS/WIN32 port of the GNU CoreUtils library error funct. *
|
||||
* *
|
||||
* Notes: Gotcha: *
|
||||
* The Windows SDK also contains a file called error.h *
|
||||
* See C:\Program Files\Microsoft SDKs\Windows\v7.0\INCLUDE *
|
||||
* *
|
||||
* History: *
|
||||
* 2012-10-21 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _ERROR_H_
|
||||
#define _ERROR_H_
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
extern void error(int status, int errnum, const char *format, ...);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,30 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: fadvise.h *
|
||||
* *
|
||||
* Description: WIN32 makeshift version of Coreutils' fadvise.h. *
|
||||
* *
|
||||
* Notes: Gives hints to the kernel about future uses of a file. *
|
||||
* Define constants, and replace functions by void macros. *
|
||||
* *
|
||||
* History: *
|
||||
* 2012-10-17 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
enum fadvice_t {
|
||||
FADVISE_NORMAL,
|
||||
FADVISE_SEQUENTIAL,
|
||||
FADVISE_NOREUSE,
|
||||
FADVISE_DONTNEED,
|
||||
FADVISE_WILLNEED,
|
||||
FADVISE_RANDOM
|
||||
};
|
||||
|
||||
/* void fdadvise(int fd, off_t offset, off_t len, fadvice_t advice) */
|
||||
#define fdadvise(fd, offset, len, advice)
|
||||
|
||||
/* void fadvise(FILE *fp, fadvice_t advice) */
|
||||
#define fadvise(fp, advice)
|
|
@ -0,0 +1,40 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: fcntl.h *
|
||||
* *
|
||||
* Description: MsvcLibX extensions to fcntl.h. *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2017-02-16 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2017 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _MSVCLIBX_FCNTL_H
|
||||
#define _MSVCLIBX_FCNTL_H 1
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#include <fcntl.h> /* Include MSVC's own <fcntl.h> file */
|
||||
|
||||
/* Microsoft defines _open() in io.h */
|
||||
#include <io.h>
|
||||
|
||||
#if defined(_MSDOS)
|
||||
#define open _open
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32)
|
||||
extern int openA(const char *, int, ...); /* MsvcLibX ANSI version of open */
|
||||
extern int openU(const char *, int, ...); /* MsvcLibX UTF-8 version of open */
|
||||
#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
|
||||
#define open openU
|
||||
#else /* _ANSI_SOURCE */
|
||||
#define open openA
|
||||
#endif /* defined(_UTF8_SOURCE) */
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
#endif /* defined(_MSVCLIBX_FCNTL_H) */
|
|
@ -0,0 +1,50 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: fnmatch.h *
|
||||
* *
|
||||
* Description: DOS/WIN32 port of standard C library's fnmatch.h. *
|
||||
* *
|
||||
* Notes: Reference for fnmatch and glob: *
|
||||
* http://www.cs.utah.edu/dept/old/texinfo/glibc-manual-0.02/library_9.html *
|
||||
* *
|
||||
* History: *
|
||||
* 2012-01-17 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _FNMATCH_H
|
||||
#define _FNMATCH_H 1
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Bits set in the FLAGS argument to fnmatch() */
|
||||
#define FNM_PATHNAME 0x01 /* Wildcards don't match '/' or '\\' */
|
||||
#define FNM_FILE_NAME FNM_PATHNAME /* Equivalent GNU name */
|
||||
#define FNM_NOESCAPE 0x02 /* Backslashes don't quote special chars (Irrelevant in DOS/Windows) */
|
||||
#define FNM_PERIOD 0x04 /* Wildcards don't match leading dots */
|
||||
#define FNM_LEADING_DIR 0x08 /* Match up to the first '/' or '\\' */
|
||||
#define FNM_CASEFOLD 0x10 /* Case-insentitive comparison */
|
||||
|
||||
/* Values returned by fnmatch() */
|
||||
#define FNM_MATCH 0 /* Non standard, but makes fnmatch.c more readable */
|
||||
#define FNM_NOMATCH 1
|
||||
|
||||
/* Value returned by fnmatch() if unsupported */
|
||||
#define FNM_NOSYS (-1)
|
||||
|
||||
/* Match NAME against the filename pattern PATTERN,
|
||||
returning zero if it matches, FNM_NOMATCH if not. */
|
||||
extern int fnmatch(const char *pszPattern, const char *pszName, int iFlags);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* !defined(_FNMATCH_H) */
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Dieter Baron and Thomas Klausner.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $
|
||||
*/
|
||||
|
||||
#ifndef _GETOPT_H_
|
||||
#define _GETOPT_H_
|
||||
|
||||
/*
|
||||
* Gnu like getopt_long() and BSD4.4 getsubopt()/optreset extensions
|
||||
*/
|
||||
#define no_argument 0
|
||||
#define required_argument 1
|
||||
#define optional_argument 2
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct option {
|
||||
/* name of long option */
|
||||
const char *name;
|
||||
/*
|
||||
* one of no_argument, required_argument, and optional_argument:
|
||||
* whether option takes an argument
|
||||
*/
|
||||
int has_arg;
|
||||
/* if not NULL, set *flag to val when option found */
|
||||
int *flag;
|
||||
/* if flag not NULL, value to set *flag to; else return value */
|
||||
int val;
|
||||
};
|
||||
|
||||
int getopt_long(int, char * const *, const char *,
|
||||
const struct option *, int *);
|
||||
|
||||
extern int optreset;
|
||||
extern char *optarg;
|
||||
extern int opterr;
|
||||
extern int optind;
|
||||
extern int optopt;
|
||||
|
||||
#ifdef __cplusplus
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* !_GETOPT_H_ */
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename iconv.h *
|
||||
* *
|
||||
* Description: WIN32 port of standard C library's iconv() *
|
||||
* *
|
||||
* Notes: Define here a number of routines, that will eventually *
|
||||
* be used by iconv(). *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-27 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _ICONV_H
|
||||
#define _ICONV_H 1
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(_MSDOS)
|
||||
|
||||
/* Count the number of characters (not bytes!) in a string */
|
||||
/* For now, assume the # of characters is the same as the # of bytes */
|
||||
/* TO DO: Add support for DOS code pages! */
|
||||
#define CountCharacters(string, cp) (int)strlen(string)
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
int ConvertString(char *buf, size_t nBytes, UINT cpFrom, UINT cpTo, LPCSTR lpDefaultChar);
|
||||
int CountCharacters(const char *string, UINT cp);
|
||||
char *DupAndConvert(const char *string, UINT cpFrom, UINT cpTo, LPCSTR lpDefaultChar);
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
#endif /* !defined(_ICONV_H) */
|
||||
|
|
@ -0,0 +1,314 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename inttypes.h *
|
||||
* *
|
||||
* Description ISO C9x compliant inttypes.h for Microsoft Visual Studio *
|
||||
* *
|
||||
* Notes TO DO: Move imaxdiv to its own C file. *
|
||||
* *
|
||||
* History *
|
||||
* 2014-02-07 JFL Added definitions for PRIdMAX and PRIiMAX. *
|
||||
* 2016-01-07 JFL Restructured and improved support for MS-DOS. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif
|
||||
|
||||
#ifndef _MSC_INTTYPES_H_
|
||||
#define _MSC_INTTYPES_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* 7.8 Format conversion of integer types */
|
||||
|
||||
typedef struct {
|
||||
intmax_t quot;
|
||||
intmax_t rem;
|
||||
} imaxdiv_t;
|
||||
|
||||
/* 7.8.1 Macros for format specifiers */
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_FORMAT_MACROS) /* [ See footnote 185 at page 198 */
|
||||
|
||||
#if defined(_WIN64)
|
||||
#define __I64_PREFIX "I64"
|
||||
#define __I32_PREFIX "I32"
|
||||
#define __PTR_PREFIX "I64"
|
||||
#define __MAX_PREFIX "I64"
|
||||
#elif defined(_WIN32)
|
||||
#define __I64_PREFIX "I64"
|
||||
#define __I32_PREFIX "I32"
|
||||
#define __PTR_PREFIX "I32"
|
||||
#define __MAX_PREFIX "I64"
|
||||
#elif defined(_MSDOS)
|
||||
#define __I64_PREFIX "ll" /* MSVC 1.5 actually ignores the second l */
|
||||
#define __I32_PREFIX "l"
|
||||
#if defined(_M_I86CM) || defined(_M_I86LM) || defined(_M_I86HM) /* Long pointer memory models */
|
||||
#define __PTR_PREFIX "l"
|
||||
#else /* Short pointer memory models */
|
||||
#define __PTR_PREFIX ""
|
||||
#endif
|
||||
#define __MAX_PREFIX "l"
|
||||
#endif
|
||||
|
||||
/* printf macros for integers */
|
||||
#define PRId8 "d"
|
||||
#define PRIi8 "i"
|
||||
#define PRIo8 "o"
|
||||
#define PRIu8 "u"
|
||||
#define PRIx8 "x"
|
||||
#define PRIX8 "X"
|
||||
|
||||
#define PRIdLEAST8 "d"
|
||||
#define PRIiLEAST8 "i"
|
||||
#define PRIoLEAST8 "o"
|
||||
#define PRIuLEAST8 "u"
|
||||
#define PRIxLEAST8 "x"
|
||||
#define PRIXLEAST8 "X"
|
||||
|
||||
#define PRIdFAST8 "d"
|
||||
#define PRIiFAST8 "i"
|
||||
#define PRIoFAST8 "o"
|
||||
#define PRIuFAST8 "u"
|
||||
#define PRIxFAST8 "x"
|
||||
#define PRIXFAST8 "X"
|
||||
|
||||
#define PRId16 "hd"
|
||||
#define PRIi16 "hi"
|
||||
#define PRIo16 "ho"
|
||||
#define PRIu16 "hu"
|
||||
#define PRIx16 "hx"
|
||||
#define PRIX16 "hX"
|
||||
|
||||
#define PRIdLEAST16 PRId16
|
||||
#define PRIiLEAST16 PRIi16
|
||||
#define PRIoLEAST16 PRIo16
|
||||
#define PRIuLEAST16 PRIu16
|
||||
#define PRIxLEAST16 PRIx16
|
||||
#define PRIXLEAST16 PRIX16
|
||||
|
||||
#define PRIdFAST16 PRId16
|
||||
#define PRIiFAST16 PRIi16
|
||||
#define PRIoFAST16 PRIo16
|
||||
#define PRIuFAST16 PRIu16
|
||||
#define PRIxFAST16 PRIx16
|
||||
#define PRIXFAST16 PRIX16
|
||||
|
||||
#define PRId32 __I32_PREFIX "d"
|
||||
#define PRIi32 __I32_PREFIX "i"
|
||||
#define PRIo32 __I32_PREFIX "o"
|
||||
#define PRIu32 __I32_PREFIX "u"
|
||||
#define PRIx32 __I32_PREFIX "x"
|
||||
#define PRIX32 __I32_PREFIX "X"
|
||||
|
||||
#define PRIdLEAST32 PRId32
|
||||
#define PRIiLEAST32 PRIi32
|
||||
#define PRIoLEAST32 PRIo32
|
||||
#define PRIuLEAST32 PRIu32
|
||||
#define PRIxLEAST32 PRIx32
|
||||
#define PRIXLEAST32 PRIX32
|
||||
|
||||
#define PRIdFAST32 PRId32
|
||||
#define PRIiFAST32 PRIi32
|
||||
#define PRIoFAST32 PRIo32
|
||||
#define PRIuFAST32 PRIu32
|
||||
#define PRIxFAST32 PRIx32
|
||||
#define PRIXFAST32 PRIX32
|
||||
|
||||
#define PRId64 __I64_PREFIX "d"
|
||||
#define PRIi64 __I64_PREFIX "i"
|
||||
#define PRIo64 __I64_PREFIX "o"
|
||||
#define PRIu64 __I64_PREFIX "u"
|
||||
#define PRIx64 __I64_PREFIX "x"
|
||||
#define PRIX64 __I64_PREFIX "X"
|
||||
|
||||
#define PRIdLEAST64 PRId64
|
||||
#define PRIiLEAST64 PRIi64
|
||||
#define PRIoLEAST64 PRIo64
|
||||
#define PRIuLEAST64 PRIu64
|
||||
#define PRIxLEAST64 PRIx64
|
||||
#define PRIXLEAST64 PRIX64
|
||||
|
||||
#define PRIdFAST64 PRId64
|
||||
#define PRIiFAST64 PRIi64
|
||||
#define PRIoFAST64 PRIo64
|
||||
#define PRIuFAST64 PRIu64
|
||||
#define PRIxFAST64 PRIx64
|
||||
#define PRIXFAST64 PRIX64
|
||||
|
||||
#define PRIdMAX __MAX_PREFIX "d"
|
||||
#define PRIiMAX __MAX_PREFIX "i"
|
||||
#define PRIoMAX __MAX_PREFIX "o"
|
||||
#define PRIuMAX __MAX_PREFIX "u"
|
||||
#define PRIxMAX __MAX_PREFIX "x"
|
||||
#define PRIXMAX __MAX_PREFIX "X"
|
||||
|
||||
#define PRIdPTR __PTR_PREFIX "d"
|
||||
#define PRIiPTR __PTR_PREFIX "i"
|
||||
#define PRIoPTR __PTR_PREFIX "o"
|
||||
#define PRIuPTR __PTR_PREFIX "u"
|
||||
#define PRIxPTR __PTR_PREFIX "x"
|
||||
#define PRIXPTR __PTR_PREFIX "X"
|
||||
|
||||
/* scanf macros for integers */
|
||||
#define SCNd8 "d"
|
||||
#define SCNi8 "i"
|
||||
#define SCNo8 "o"
|
||||
#define SCNu8 "u"
|
||||
#define SCNx8 "x"
|
||||
#define SCNX8 "X"
|
||||
|
||||
#define SCNdLEAST8 SCNd8
|
||||
#define SCNiLEAST8 SCNi8
|
||||
#define SCNoLEAST8 SCNo8
|
||||
#define SCNuLEAST8 SCNu8
|
||||
#define SCNxLEAST8 SCNx8
|
||||
#define SCNXLEAST8 SCNX8
|
||||
|
||||
#define SCNdFAST8 SCNd8
|
||||
#define SCNiFAST8 SCNi8
|
||||
#define SCNoFAST8 SCNo8
|
||||
#define SCNuFAST8 SCNu8
|
||||
#define SCNxFAST8 SCNx8
|
||||
#define SCNXFAST8 SCNX8
|
||||
|
||||
#define SCNd16 "hd"
|
||||
#define SCNi16 "hi"
|
||||
#define SCNo16 "ho"
|
||||
#define SCNu16 "hu"
|
||||
#define SCNx16 "hx"
|
||||
#define SCNX16 "hX"
|
||||
|
||||
#define SCNdLEAST16 SCNd16
|
||||
#define SCNiLEAST16 SCNi16
|
||||
#define SCNoLEAST16 SCNo16
|
||||
#define SCNuLEAST16 SCNu16
|
||||
#define SCNxLEAST16 SCNx16
|
||||
#define SCNXLEAST16 SCNX16
|
||||
|
||||
#define SCNdFAST16 SCNd16
|
||||
#define SCNiFAST16 SCNi16
|
||||
#define SCNoFAST16 SCNo16
|
||||
#define SCNuFAST16 SCNu16
|
||||
#define SCNxFAST16 SCNx16
|
||||
#define SCNXFAST16 SCNX16
|
||||
|
||||
#define SCNd32 __I32_PREFIX "d"
|
||||
#define SCNi32 __I32_PREFIX "i"
|
||||
#define SCNo32 __I32_PREFIX "o"
|
||||
#define SCNu32 __I32_PREFIX "u"
|
||||
#define SCNx32 __I32_PREFIX "x"
|
||||
#define SCNX32 __I32_PREFIX "X"
|
||||
|
||||
#define SCNdLEAST32 SCNd32
|
||||
#define SCNiLEAST32 SCNi32
|
||||
#define SCNoLEAST32 SCNo32
|
||||
#define SCNuLEAST32 SCNu32
|
||||
#define SCNxLEAST32 SCNx32
|
||||
#define SCNXLEAST32 SCNX32
|
||||
|
||||
#define SCNdFAST32 SCNd32
|
||||
#define SCNiFAST32 SCNi32
|
||||
#define SCNoFAST32 SCNo32
|
||||
#define SCNuFAST32 SCNu32
|
||||
#define SCNxFAST32 SCNx32
|
||||
#define SCNXFAST32 SCNX32
|
||||
|
||||
#define SCNd64 __I64_PREFIX "d"
|
||||
#define SCNi64 __I64_PREFIX "i"
|
||||
#define SCNo64 __I64_PREFIX "o"
|
||||
#define SCNu64 __I64_PREFIX "u"
|
||||
#define SCNx64 __I64_PREFIX "x"
|
||||
#define SCNX64 __I64_PREFIX "X"
|
||||
|
||||
#define SCNdLEAST64 SCNd64
|
||||
#define SCNiLEAST64 SCNi64
|
||||
#define SCNoLEAST64 SCNo64
|
||||
#define SCNuLEAST64 SCNu64
|
||||
#define SCNxLEAST64 SCNx64
|
||||
#define SCNXLEAST64 SCNX64
|
||||
|
||||
#define SCNdFAST64 SCNd64
|
||||
#define SCNiFAST64 SCNi64
|
||||
#define SCNoFAST64 SCNo64
|
||||
#define SCNuFAST64 SCNu64
|
||||
#define SCNxFAST64 SCNx64
|
||||
#define SCNXFAST64 SCNX64
|
||||
|
||||
#define SCNdMAX __MAX_PREFIX "d"
|
||||
#define SCNiMAX __MAX_PREFIX "i"
|
||||
#define SCNoMAX __MAX_PREFIX "o"
|
||||
#define SCNuMAX __MAX_PREFIX "u"
|
||||
#define SCNxMAX __MAX_PREFIX "x"
|
||||
#define SCNXMAX __MAX_PREFIX "X"
|
||||
|
||||
#define SCNdPTR __PTR_PREFIX "d"
|
||||
#define SCNiPTR __PTR_PREFIX "i"
|
||||
#define SCNoPTR __PTR_PREFIX "o"
|
||||
#define SCNuPTR __PTR_PREFIX "u"
|
||||
#define SCNxPTR __PTR_PREFIX "x"
|
||||
#define SCNXPTR __PTR_PREFIX "X"
|
||||
|
||||
#endif /* __STDC_FORMAT_MACROS ] */
|
||||
|
||||
/* 7.8.2 Functions for greatest-width integer types */
|
||||
|
||||
/* 7.8.2.1 imaxabs() */
|
||||
#if defined(_WIN32)
|
||||
#define imaxabs _abs64
|
||||
#elif defined(_MSDOS)
|
||||
#define imaxabs abs
|
||||
#endif
|
||||
|
||||
/* 7.8.2.2 imaxdiv() */
|
||||
|
||||
/* This is modified version of div() function from Microsoft's div.c found */
|
||||
/* in %MSVC.NET%\crt\src\div.c */
|
||||
#if defined(_MSDOS) && !defined(STATIC_IMAXDIV) && !defined(__cplusplus)
|
||||
/* MSVC 1.52 compiler for MS-DOS does not support inline for C */
|
||||
extern imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom);
|
||||
#else
|
||||
#ifdef STATIC_IMAXDIV /* [ */
|
||||
static
|
||||
#else /* STATIC_IMAXDIV ][ */
|
||||
_inline
|
||||
#endif /* STATIC_IMAXDIV ] */
|
||||
imaxdiv_t __cdecl imaxdiv(intmax_t numer, intmax_t denom) {
|
||||
imaxdiv_t result;
|
||||
|
||||
result.quot = numer / denom;
|
||||
result.rem = numer % denom;
|
||||
|
||||
if (numer < 0 && result.rem > 0) {
|
||||
/* did division wrong; must fix up */
|
||||
++result.quot;
|
||||
result.rem -= denom;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
#endif /* defined(_MSDOS) && !defined(STATIC_IMAXDIV) && !defined(__cplusplus) */
|
||||
|
||||
/* 7.8.2.3 strtoimax() and strtoumax() */
|
||||
#if defined(_WIN32)
|
||||
#define strtoimax _strtoi64
|
||||
#define strtoumax _strtoui64
|
||||
#elif defined(_MSDOS)
|
||||
#define strtoimax strtol
|
||||
#define strtoumax strtoul
|
||||
#endif
|
||||
|
||||
/* 7.8.2.4 wcstoimax() and wcstoumax() */
|
||||
#if defined(_WIN32)
|
||||
#define wcstoimax _wcstoi64
|
||||
#define wcstoumax _wcstoui64
|
||||
#elif defined(_MSDOS)
|
||||
#define wcstoimax wcstol
|
||||
#define wcstoumax wcstoul
|
||||
#endif
|
||||
|
||||
#endif /* _MSC_INTTYPES_H_ */
|
|
@ -0,0 +1,22 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: libgen.h *
|
||||
* *
|
||||
* Description: DOS/WIN32 port of standard C library's libgen.h. *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2016-09-08 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _LIBGEN_H
|
||||
#define _LIBGEN_H
|
||||
|
||||
char *basename(char *pszPathname); /* Modifies pathname; Not thread-safe */
|
||||
char *dirname(char *pszPathname); /* Modifies pathname; Not thread-safe */
|
||||
|
||||
#endif /* !defined(_LIBGEN_H) */
|
|
@ -0,0 +1,54 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: limits.h *
|
||||
* *
|
||||
* Description: MsvcLibX extensions to limits.h. *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-06-30 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _MSVCLIBX_LIMITS_H
|
||||
#define _MSVCLIBX_LIMITS_H 1
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#include <limits.h> /* Include MSVC's own <limits.h> file */
|
||||
|
||||
/************************ MS-DOS-specific definitions ************************/
|
||||
|
||||
#ifdef _MSDOS /* Automatically defined when targeting an MS-DOS application */
|
||||
|
||||
#define PATH_MAX 255 /* Many APIs actually limit it to 128 bytes, but longer paths paths are legal. */
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
/************************ Win32-specific definitions *************************/
|
||||
|
||||
#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */
|
||||
|
||||
#undef PATH_MAX
|
||||
|
||||
#define ANSI_PATH_MAX 260 /* Number of ANSI characters, including final NUL ( = Windef.h MAX_PATH) */
|
||||
#define UNICODE_PATH_MAX 32768 /* Number of Unicode characters, including final NUL */
|
||||
#define UTF8_PATH_MAX (4 * UNICODE_PATH_MAX) /* Worst UTF-8 case is 4 bytes / Unicode char */
|
||||
|
||||
#define PATH_MAX UNICODE_PATH_MAX /* MsvcLibX uses Unicode internally for file management */
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
/************************* OS/2-specific definitions *************************/
|
||||
|
||||
#ifdef _OS2 /* Automatically defined when targeting an OS/2 application? */
|
||||
|
||||
#endif /* defined(_OS2) */
|
||||
|
||||
/********************** End of OS-specific definitions ***********************/
|
||||
|
||||
#endif /* defined(_MSVCLIBX_LIMITS_H) */
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: netdb.h *
|
||||
* *
|
||||
* Description: Network definitions *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2012-01-24 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _NETDB_H
|
||||
#define _NETDB_H 1
|
||||
|
||||
/* Absolute file name for network data base files. */
|
||||
#define _PATH_HOSTS "C:/Windows/System32/drivers/etc/hosts"
|
||||
#define _PATH_NETWORKS "C:/Windows/System32/drivers/etc/networks"
|
||||
#define _PATH_PROTOCOLS "C:/Windows/System32/drivers/etc/protocols"
|
||||
#define _PATH_SERVICES "C:/Windows/System32/drivers/etc/services"
|
||||
|
||||
#endif /* _NETDB_H */
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: process.h *
|
||||
* *
|
||||
* Description: MsvcLibX extensions to process.h. *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-03-27 JFL Created this file. *
|
||||
* 2015-11-15 JFL Visual Studio 2015 moved this file to the Windows Kit UCRT.
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _MSVCLIBX_PROCESS_H
|
||||
#define _MSVCLIBX_PROCESS_H 1
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#include <process.h> /* Include MSVC's own <process.h> file */
|
||||
|
||||
#if defined(_WIN32)
|
||||
extern intptr_t _spawnvpU(int iMode, const char *pszCommand, char *const *argv);
|
||||
#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
|
||||
#define _spawnvp _spawnvpU
|
||||
#else /* _ANSI_SOURCE */
|
||||
#define _spawnvp _spawnvp
|
||||
#endif /* defined(_UTF8_SOURCE) */
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
#endif /* defined(_MSVCLIBX_PROCESS_H) */
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
#ifndef _HSREGEX_H_
|
||||
#define _HSREGEX_H_
|
||||
#ifndef _HSREGEX_H
|
||||
#define _HSREGEX_H /* never again */
|
||||
|
||||
#include <sys/types.h> /* JFL 2012-01-24 Added definition of types used below */
|
||||
#pragma comment( lib, "regex.lib" )
|
||||
|
||||
/* ========= begin header generated by ././mkh ========= */
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* === regex2.h === */
|
||||
#ifdef WIN32
|
||||
#define API_EXPORT(type) __declspec(dllexport) type __stdcall
|
||||
#elif defined(__GNUC__) && __GNUC__ >= 4
|
||||
#define API_EXPORT(type) __attribute__ ((visibility("default"))) type
|
||||
#else
|
||||
#define API_EXPORT(type) type
|
||||
#endif
|
||||
|
||||
typedef off_t regoff_t;
|
||||
typedef struct {
|
||||
int re_magic;
|
||||
size_t re_nsub; /* number of parenthesized subexpressions */
|
||||
const char *re_endp; /* end pointer for REG_PEND */
|
||||
struct re_guts *re_g; /* none of your business :-) */
|
||||
} regex_t;
|
||||
typedef struct {
|
||||
regoff_t rm_so; /* start of match */
|
||||
regoff_t rm_eo; /* end of match */
|
||||
} regmatch_t;
|
||||
|
||||
|
||||
/* === regcomp.c === */
|
||||
API_EXPORT(int) regcomp(regex_t *, const char *, int);
|
||||
#define REG_BASIC 0000
|
||||
#define REG_EXTENDED 0001
|
||||
#define REG_ICASE 0002
|
||||
#define REG_NOSUB 0004
|
||||
#define REG_NEWLINE 0010
|
||||
#define REG_NOSPEC 0020
|
||||
#define REG_PEND 0040
|
||||
#define REG_DUMP 0200
|
||||
|
||||
|
||||
/* === regerror.c === */
|
||||
#define REG_OKAY 0
|
||||
#define REG_NOMATCH 1
|
||||
#define REG_BADPAT 2
|
||||
#define REG_ECOLLATE 3
|
||||
#define REG_ECTYPE 4
|
||||
#define REG_EESCAPE 5
|
||||
#define REG_ESUBREG 6
|
||||
#define REG_EBRACK 7
|
||||
#define REG_EPAREN 8
|
||||
#define REG_EBRACE 9
|
||||
#define REG_BADBR 10
|
||||
#define REG_ERANGE 11
|
||||
#define REG_ESPACE 12
|
||||
#define REG_BADRPT 13
|
||||
#define REG_EMPTY 14
|
||||
#define REG_ASSERT 15
|
||||
#define REG_INVARG 16
|
||||
#define REG_ATOI 255 /* convert name to number (!) */
|
||||
#define REG_ITOA 0400 /* convert number to name (!) */
|
||||
API_EXPORT(size_t) regerror(int, const regex_t *, char *, size_t);
|
||||
|
||||
|
||||
/* === regexec.c === */
|
||||
API_EXPORT(int) regexec(const regex_t *, const char *, size_t, regmatch_t [], int);
|
||||
#define REG_NOTBOL 00001
|
||||
#define REG_NOTEOL 00002
|
||||
#define REG_STARTEND 00004
|
||||
#define REG_TRACE 00400 /* tracing of execution */
|
||||
#define REG_LARGE 01000 /* force large representation */
|
||||
#define REG_BACKR 02000 /* force use of backref code */
|
||||
|
||||
|
||||
/* === regfree.c === */
|
||||
API_EXPORT(void) regfree(regex_t *);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
/* ========= end header generated by ././mkh ========= */
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,125 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: reparsept.h *
|
||||
* *
|
||||
* Description: Definitions for WIN32 reparse points. *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-28 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Reparse point iocontrol data buffer */
|
||||
/* See http://msdn.microsoft.com/en-us/library/cc232006.aspx */
|
||||
/* and http://msdn.microsoft.com/en-us/library/cc232007.aspx */
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/* NTFS reparse point definitions */
|
||||
|
||||
/* Constants from http://msdn.microsoft.com/en-us/library/dd541667.aspx */
|
||||
/* Some, but not all, of them also defined in recent versions of winnt.h. */
|
||||
/* Since the list varies a lot, redefine them one by one as needed */
|
||||
|
||||
#ifndef IO_REPARSE_TAG_RESERVED_ZERO
|
||||
#define IO_REPARSE_TAG_RESERVED_ZERO 0x00000000 /* Reserved reparse tag value */
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_RESERVED_ONE
|
||||
#define IO_REPARSE_TAG_RESERVED_ONE 0x00000001 /* Reserved reparse tag value */
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_MOUNT_POINT
|
||||
#define IO_REPARSE_TAG_MOUNT_POINT 0xA0000003 /* Used for mount point support */
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_HSM
|
||||
#define IO_REPARSE_TAG_HSM 0xC0000004 /* Obsolete. Used by legacy Hierarchical Storage Manager Product */
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_DRIVER_EXTENDER
|
||||
#define IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005 /* Home server drive extender */
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_HSM2
|
||||
#define IO_REPARSE_TAG_HSM2 0x80000006 /* Obsolete. Used by legacy Hierarchical Storage Manager Product */
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_SIS
|
||||
#define IO_REPARSE_TAG_SIS 0x80000007 /* Used by single-instance storage (SIS) filter driver. Server-side interpretation only, not meaningful over the wire */
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_WIM
|
||||
#define IO_REPARSE_TAG_WIM 0x80000008 /* Mounted Windows boot Image File? */
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_CSV
|
||||
#define IO_REPARSE_TAG_CSV 0x80000009 /* Cluster Shared Volume? */
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_DFS
|
||||
#define IO_REPARSE_TAG_DFS 0x8000000A /* Used by the DFS filter. The DFS is described in the Distributed File System (DFS): Referral Protocol Specification [MS-DFSC]. Server-side interpretation only, not meaningful over the wire */
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_FILTER_MANAGER
|
||||
#define IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B /* Used by filter manager test harness */
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_SYMLINK
|
||||
#define IO_REPARSE_TAG_SYMLINK 0xA000000C /* Used for symbolic link support */
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_DFSR
|
||||
#define IO_REPARSE_TAG_DFSR 0x80000012 /* Used by the DFS filter. The DFS is described in [MS-DFSC]. Server-side interpretation only, not meaningful over the wire */
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_DEDUP
|
||||
#define IO_REPARSE_TAG_DEDUP 0x80000013 /* Mounted deduplicated volume? */
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_NFS
|
||||
#define IO_REPARSE_TAG_NFS 0x80000014 /* Mounted NFS share? */
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#define IO_REPARSE_TAG_DRIVER_EXTENDER 0x80000005 /* Home server drive extender */
|
||||
#define IO_REPARSE_TAG_FILTER_MANAGER 0x8000000B /* Used by filter manager test harness */
|
||||
#endif
|
||||
|
||||
#pragma pack(1)
|
||||
typedef struct _REPARSE_READ_BUFFER {
|
||||
DWORD ReparseTag;
|
||||
WORD ReparseDataLength;
|
||||
WORD Reserved;
|
||||
UCHAR DataBuffer[1];
|
||||
} REPARSE_READ_BUFFER, *PREPARSE_READ_BUFFER;
|
||||
#define REPARSE_READ_BUFFER_HEADER_SIZE (sizeof(REPARSE_READ_BUFFER) - sizeof(UCHAR))
|
||||
|
||||
typedef struct _REPARSE_SYMLINK_READ_BUFFER {
|
||||
DWORD ReparseTag;
|
||||
WORD ReparseDataLength;
|
||||
WORD Reserved;
|
||||
WORD SubstituteNameOffset;
|
||||
WORD SubstituteNameLength;
|
||||
WORD PrintNameOffset;
|
||||
WORD PrintNameLength;
|
||||
ULONG Flags;
|
||||
WCHAR PathBuffer[1];
|
||||
} SYMLINK_READ_BUFFER, *PSYMLINK_READ_BUFFER;
|
||||
#define SYMLINK_READ_BUFFER_HEADER_SIZE (sizeof(SYMLINK_READ_BUFFER) - sizeof(WCHAR))
|
||||
|
||||
typedef struct _REPARSE_MOUNTPOINT_READ_BUFFER {
|
||||
DWORD ReparseTag;
|
||||
WORD ReparseDataLength;
|
||||
WORD Reserved;
|
||||
WORD SubstituteNameOffset;
|
||||
WORD SubstituteNameLength;
|
||||
WORD PrintNameOffset;
|
||||
WORD PrintNameLength;
|
||||
WCHAR PathBuffer[1];
|
||||
} MOUNTPOINT_READ_BUFFER, *PMOUNTPOINT_READ_BUFFER;
|
||||
#define MOUNTPOINT_READ_BUFFER_HEADER_SIZE (sizeof(MOUNTPOINT_READ_BUFFER) - sizeof(WCHAR))
|
||||
|
||||
typedef struct _REPARSE_MOUNTPOINT_WRITE_BUFFER {
|
||||
DWORD ReparseTag;
|
||||
DWORD ReparseDataLength;
|
||||
WORD Reserved;
|
||||
WORD ReparseTargetLength;
|
||||
WORD ReparseTargetMaximumLength;
|
||||
WORD Reserved1;
|
||||
WCHAR ReparseTarget[1];
|
||||
} MOUNTPOINT_WRITE_BUFFER, *PMOUNTPOINT_WRITE_BUFFER;
|
||||
#define MOUNTPOINT_WRITE_BUFFER_HEADER_SIZE (sizeof(MOUNTPOINT_WRITE_BUFFER) - sizeof(WCHAR))
|
||||
#pragma pack()
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: stdbool.h *
|
||||
* *
|
||||
* Description: Standard boolean definitions *
|
||||
* *
|
||||
* Notes: Set standard values. May need to be adapted for C++? *
|
||||
* *
|
||||
* History: *
|
||||
* 2012-10-17 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _STDBOOL_H
|
||||
#define _STDBOOL_H
|
||||
|
||||
/* #define bool int /* Spec says _Bool */
|
||||
typedef int bool;
|
||||
#define true 1
|
||||
#define false 0
|
||||
#define __bool_true_false_are_defined 1
|
||||
|
||||
#endif
|
|
@ -0,0 +1,322 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename stdint.h *
|
||||
* *
|
||||
* Description ISO C9x compliant stdint.h for Microsoft Visual Studio *
|
||||
* *
|
||||
* Notes *
|
||||
* *
|
||||
* ISO C9x compliant stdint.h for Microsoft Visual Studio *
|
||||
* Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 *
|
||||
* *
|
||||
* Copyright (c) 2006-2008 Alexander Chemeris *
|
||||
* *
|
||||
* Redistribution and use in source and binary forms, with or without *
|
||||
* modification, are permitted provided that the following conditions are met: *
|
||||
* *
|
||||
* 1. Redistributions of source code must retain the above copyright notice, *
|
||||
* this list of conditions and the following disclaimer. *
|
||||
* *
|
||||
* 2. Redistributions in binary form must reproduce the above copyright *
|
||||
* notice, this list of conditions and the following disclaimer in the *
|
||||
* documentation and/or other materials provided with the distribution. *
|
||||
* *
|
||||
* 3. The name of the author may be used to endorse or promote products *
|
||||
* derived from this software without specific prior written permission. *
|
||||
* *
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED*
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF *
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO *
|
||||
* EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, *
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,*
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; *
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, *
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR *
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF *
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. *
|
||||
* *
|
||||
* History *
|
||||
* 2008-07-17 AC Initial implementation by Alexander Chemeris. *
|
||||
* 2011-05-23 JFL Added support for 16-bits compilers for MS-DOS. *
|
||||
* 2011-05-28 JFL Added support for 16-bits compilers for MS-DOS. *
|
||||
* 2012-01-18 JFL Added error messages if target is not DOS or Windows. *
|
||||
* 2015-12-04 JFL Define _UINTPTR_T_DEFINED to tell MSVC99 it's done already*
|
||||
* *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#error "Use this header only with Microsoft Visual C++ compilers!"
|
||||
#endif /* _MSC_VER */
|
||||
|
||||
#ifndef _MSC_STDINT_H_
|
||||
#define _MSC_STDINT_H_
|
||||
|
||||
#if _MSC_VER > 1000
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
#include <limits.h>
|
||||
|
||||
/*
|
||||
// For Visual Studio 6 in C++ mode wrap <wchar.h> include with 'extern "C++" {}'
|
||||
// or compiler give many errors like this:
|
||||
// error C2733: second C linkage of overloaded function 'wmemchr' not allowed
|
||||
*/
|
||||
/* 2015-12-04 JFL Bug fix: With VS14/VC19, MSVC's wchar.h includes inttypes.h,
|
||||
which in turn includes this stdint.h, causing loop issues */
|
||||
#if (_MSC_VER < 1900) && defined(_WIN32) /* Both WIN32 and WIN64 */
|
||||
# if (_MSC_VER < 1300) && defined(__cplusplus)
|
||||
extern "C++" {
|
||||
# endif
|
||||
# include <wchar.h>
|
||||
# if (_MSC_VER < 1300) && defined(__cplusplus)
|
||||
}
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/* Define _W64 macros to mark types changing their size, like intptr_t. */
|
||||
#ifndef _W64
|
||||
# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300
|
||||
# define _W64 __w64
|
||||
# else
|
||||
# define _W64
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* 7.18.1 Integer types */
|
||||
|
||||
#ifndef _INTEGRAL_MAX_BITS
|
||||
#define _INTEGRAL_MAX_BITS 32
|
||||
#endif
|
||||
|
||||
/* 7.18.1.1 Exact-width integer types */
|
||||
#if defined(_WIN32) /* Both WIN32 and WIN64 */
|
||||
typedef __int8 int8_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#elif defined(_MSDOS) /* MS-DOS */
|
||||
typedef char int8_t;
|
||||
typedef short int16_t;
|
||||
typedef long int32_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef unsigned long uint32_t;
|
||||
#else
|
||||
#error "I don't know what the integer types are in this case!"
|
||||
#endif
|
||||
|
||||
/* 7.18.1.2 Minimum-width integer types */
|
||||
typedef int8_t int_least8_t;
|
||||
typedef int16_t int_least16_t;
|
||||
typedef int32_t int_least32_t;
|
||||
#ifdef LLONG_MAX
|
||||
typedef int64_t int_least64_t;
|
||||
#endif
|
||||
typedef uint8_t uint_least8_t;
|
||||
typedef uint16_t uint_least16_t;
|
||||
typedef uint32_t uint_least32_t;
|
||||
#ifdef LLONG_MAX
|
||||
typedef uint64_t uint_least64_t;
|
||||
#endif
|
||||
|
||||
/* 7.18.1.3 Fastest minimum-width integer types */
|
||||
typedef int8_t int_fast8_t;
|
||||
typedef int16_t int_fast16_t;
|
||||
typedef int32_t int_fast32_t;
|
||||
#ifdef LLONG_MAX
|
||||
typedef int64_t int_fast64_t;
|
||||
#endif
|
||||
typedef uint8_t uint_fast8_t;
|
||||
typedef uint16_t uint_fast16_t;
|
||||
typedef uint32_t uint_fast32_t;
|
||||
#ifdef LLONG_MAX
|
||||
typedef uint64_t uint_fast64_t;
|
||||
#endif
|
||||
|
||||
/* 7.18.1.4 Integer types capable of holding object pointers */
|
||||
#if defined(_WIN64) /* _WIN64 */
|
||||
# define _POINTER_BITS 64
|
||||
typedef __int64 intptr_t;
|
||||
typedef unsigned __int64 uintptr_t;
|
||||
#elif defined(_WIN32) /* _WIN32 */
|
||||
# define _POINTER_BITS 32
|
||||
typedef _W64 int intptr_t;
|
||||
typedef _W64 unsigned int uintptr_t;
|
||||
#elif defined(_MSDOS) /* _MSDOS */
|
||||
# if defined(_M_I86TM) || defined(_M_I86SM) /* Tiny or short memory models */
|
||||
# define _POINTER_BITS 16
|
||||
typedef int intptr_t;
|
||||
typedef unsigned int uintptr_t;
|
||||
# else /* Compact, medium, large or huge memory models */
|
||||
# define _POINTER_BITS 32
|
||||
typedef long intptr_t;
|
||||
typedef unsigned long uintptr_t;
|
||||
# endif
|
||||
#else
|
||||
#error "I don't know what the pointer types are in this case!"
|
||||
#endif /* _WIN64 */
|
||||
#define _INTPTR_T_DEFINED
|
||||
#define _UINTPTR_T_DEFINED /* Prevent MSVC99 from redefining it */
|
||||
|
||||
/* 7.18.1.5 Greatest-width integer types */
|
||||
#ifdef LLONG_MAX
|
||||
typedef int64_t intmax_t;
|
||||
typedef uint64_t uintmax_t;
|
||||
#else
|
||||
typedef int32_t intmax_t;
|
||||
typedef uint32_t uintmax_t;
|
||||
#endif
|
||||
|
||||
|
||||
/* 7.18.2 Limits of specified-width integer types */
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) /* See footnote 220 at page 257 and footnote 221 at page 259 */
|
||||
|
||||
#ifdef _MSDOS
|
||||
#define _I8_MIN SCHAR_MIN /* minimum signed 8 bit value */
|
||||
#define _I8_MAX SCHAR_MAX /* maximum signed 8 bit value */
|
||||
#define _UI8_MAX UCHAR_MAX /* maximum unsigned 8 bit value */
|
||||
|
||||
#define _I16_MIN SHRT_MIN /* minimum signed 16 bit value */
|
||||
#define _I16_MAX SHRT_MAX /* maximum signed 16 bit value */
|
||||
#define _UI16_MAX USHRT_MAX /* maximum unsigned 16 bit value */
|
||||
|
||||
#define _I32_MIN LONG_MIN /* minimum signed 32 bit value */
|
||||
#define _I32_MAX LONG_MAX /* maximum signed 32 bit value */
|
||||
#define _UI32_MAX ULONG_MAX /* maximum unsigned 32 bit value */
|
||||
#endif
|
||||
|
||||
/* 7.18.2.1 Limits of exact-width integer types */
|
||||
#define INT8_MIN ((int8_t)_I8_MIN)
|
||||
#define INT8_MAX _I8_MAX
|
||||
#define INT16_MIN ((int16_t)_I16_MIN)
|
||||
#define INT16_MAX _I16_MAX
|
||||
#define INT32_MIN ((int32_t)_I32_MIN)
|
||||
#define INT32_MAX _I32_MAX
|
||||
#ifdef LLONG_MAX
|
||||
#define INT64_MIN ((int64_t)_I64_MIN)
|
||||
#define INT64_MAX _I64_MAX
|
||||
#endif
|
||||
#define UINT8_MAX _UI8_MAX
|
||||
#define UINT16_MAX _UI16_MAX
|
||||
#define UINT32_MAX _UI32_MAX
|
||||
#ifdef LLONG_MAX
|
||||
#define UINT64_MAX _UI64_MAX
|
||||
#endif
|
||||
|
||||
/* 7.18.2.2 Limits of minimum-width integer types */
|
||||
#define INT_LEAST8_MIN INT8_MIN
|
||||
#define INT_LEAST8_MAX INT8_MAX
|
||||
#define INT_LEAST16_MIN INT16_MIN
|
||||
#define INT_LEAST16_MAX INT16_MAX
|
||||
#define INT_LEAST32_MIN INT32_MIN
|
||||
#define INT_LEAST32_MAX INT32_MAX
|
||||
#ifdef LLONG_MAX
|
||||
#define INT_LEAST64_MIN INT64_MIN
|
||||
#define INT_LEAST64_MAX INT64_MAX
|
||||
#endif
|
||||
#define UINT_LEAST8_MAX UINT8_MAX
|
||||
#define UINT_LEAST16_MAX UINT16_MAX
|
||||
#define UINT_LEAST32_MAX UINT32_MAX
|
||||
#ifdef LLONG_MAX
|
||||
#define UINT_LEAST64_MAX UINT64_MAX
|
||||
#endif
|
||||
|
||||
/* 7.18.2.3 Limits of fastest minimum-width integer types */
|
||||
#define INT_FAST8_MIN INT8_MIN
|
||||
#define INT_FAST8_MAX INT8_MAX
|
||||
#define INT_FAST16_MIN INT16_MIN
|
||||
#define INT_FAST16_MAX INT16_MAX
|
||||
#define INT_FAST32_MIN INT32_MIN
|
||||
#define INT_FAST32_MAX INT32_MAX
|
||||
#ifdef LLONG_MAX
|
||||
#define INT_FAST64_MIN INT64_MIN
|
||||
#define INT_FAST64_MAX INT64_MAX
|
||||
#endif
|
||||
#define UINT_FAST8_MAX UINT8_MAX
|
||||
#define UINT_FAST16_MAX UINT16_MAX
|
||||
#define UINT_FAST32_MAX UINT32_MAX
|
||||
#ifdef LLONG_MAX
|
||||
#define UINT_FAST64_MAX UINT64_MAX
|
||||
#endif
|
||||
|
||||
/* 7.18.2.4 Limits of integer types capable of holding object pointers */
|
||||
#define INTPTR_MIN INT##_POINTER_BITS##MIN
|
||||
#define INTPTR_MAX INT##_POINTER_BITS##_MAX
|
||||
#define UINTPTR_MAX UINT##_POINTER_BITS##_MAX
|
||||
|
||||
/* 7.18.2.5 Limits of greatest-width integer types */
|
||||
#ifdef LLONG_MAX
|
||||
#define INTMAX_MIN INT64_MIN
|
||||
#define INTMAX_MAX INT64_MAX
|
||||
#define UINTMAX_MAX UINT64_MAX
|
||||
#else
|
||||
#define INTMAX_MIN INT32_MIN
|
||||
#define INTMAX_MAX INT32_MAX
|
||||
#define UINTMAX_MAX UINT32_MAX
|
||||
#endif
|
||||
|
||||
/* 7.18.3 Limits of other integer types */
|
||||
#define PTRDIFF_MIN _I##_POINTER_BITS##_MIN
|
||||
#define PTRDIFF_MAX _I##_POINTER_BITS##_MAX
|
||||
|
||||
#define SIG_ATOMIC_MIN INT_MIN
|
||||
#define SIG_ATOMIC_MAX INT_MAX
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# define SIZE_MAX _UI##_POINTER_BITS##_MAX
|
||||
#endif
|
||||
|
||||
/* WCHAR_MIN and WCHAR_MAX are also defined in <wchar.h> */
|
||||
#ifndef WCHAR_MIN
|
||||
# define WCHAR_MIN 0
|
||||
#endif
|
||||
#ifndef WCHAR_MAX
|
||||
# define WCHAR_MAX _UI16_MAX
|
||||
#endif
|
||||
|
||||
#define WINT_MIN 0
|
||||
#define WINT_MAX _UI16_MAX
|
||||
|
||||
#endif /* __STDC_LIMIT_MACROS */
|
||||
|
||||
|
||||
/* 7.18.4 Limits of other integer types */
|
||||
|
||||
#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) /* See footnote 224 at page 260 */
|
||||
|
||||
/* 7.18.4.1 Macros for minimum-width integer constants */
|
||||
|
||||
#define INT8_C(val) val##i8
|
||||
#define INT16_C(val) val##i16
|
||||
#define INT32_C(val) val##i32
|
||||
#ifdef LLONG_MAX
|
||||
#define INT64_C(val) val##i64
|
||||
#endif
|
||||
|
||||
#define UINT8_C(val) val##ui8
|
||||
#define UINT16_C(val) val##ui16
|
||||
#define UINT32_C(val) val##ui32
|
||||
#ifdef LLONG_MAX
|
||||
#define UINT64_C(val) val##ui64
|
||||
#endif
|
||||
|
||||
/* 7.18.4.2 Macros for greatest-width integer constants */
|
||||
#ifdef LLONG_MAX
|
||||
#define INTMAX_C INT64_C
|
||||
#define UINTMAX_C UINT64_C
|
||||
#else
|
||||
#define INTMAX_C INT32_C
|
||||
#define UINTMAX_C UINT32_C
|
||||
#endif
|
||||
|
||||
#endif /* __STDC_CONSTANT_MACROS */
|
||||
|
||||
|
||||
#endif /* _MSC_STDINT_H_ */
|
|
@ -0,0 +1,125 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: stdio.h *
|
||||
* *
|
||||
* Description: MsvcLibX extensions to stdio.h. *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-06-03 JFL Created this file. *
|
||||
* 2015-11-15 JFL Visual Studio 2015 moved this file to the Windows Kit UCRT.
|
||||
* 2015-12-09 JFL Alias fputs to fputsU, and vfprintf to vfprintfU. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _MSVCLIBX_stdio_H
|
||||
#define _MSVCLIBX_stdio_H 1
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#include <stdio.h> /* Include MSVC's own <stdio.h> file */
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define snprintf _snprintf /* This one _is_ standard */
|
||||
#define popen _popen /* This one _is_ standard */
|
||||
#define pclose _pclose /* This one _is_ standard */
|
||||
|
||||
/************************ MS-DOS-specific definitions ************************/
|
||||
|
||||
#ifdef _MSDOS /* Automatically defined when targeting an MS-DOS application */
|
||||
|
||||
/* Define functions fseeko and ftello */
|
||||
#if defined(_LARGEFILE_SOURCE)
|
||||
#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
|
||||
/* TO DO: Windows 95 has extended functions for handling 64-bits files sizes */
|
||||
#else
|
||||
#endif
|
||||
/* For now, use the MSVC 32-bits functions in all cases */
|
||||
#define fseeko fseek
|
||||
#define ftello ftell
|
||||
#endif
|
||||
|
||||
/* Define standard 64-bits functions */
|
||||
#if defined(_LARGEFILE_SOURCE64)
|
||||
#define fseeko64 _fseek
|
||||
#define ftello64 _ftell
|
||||
#endif
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
/************************ Win32-specific definitions *************************/
|
||||
|
||||
#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */
|
||||
|
||||
#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
|
||||
#define vfprintf vfprintfU /* For outputing UTF-8 strings */
|
||||
#define fprintf fprintfU /* For outputing UTF-8 strings */
|
||||
#define printf printfU /* For outputing UTF-8 strings */
|
||||
#define fputs fputsU /* For outputing UTF-8 strings */
|
||||
/* The UTF-8 output routines are defined in iconv.c */
|
||||
extern int vfprintfU(FILE *f, const char *pszFormat, va_list vl);
|
||||
extern int fprintfU(FILE *f, const char *pszFormat, ...);
|
||||
extern int printfU(const char *pszFormat, ...);
|
||||
extern int fputsU(const char *buf, FILE *f);
|
||||
extern UINT codePage;
|
||||
#endif
|
||||
|
||||
/* Define functions fseeko and ftello */
|
||||
#if defined(_LARGEFILE_SOURCE)
|
||||
#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
|
||||
#define fseeko _fseeki64 /* _CONCAT(_fseeki64,_NS_SUFFIX) */
|
||||
#define ftello _ftelli64 /* _CONCAT(_ftelli64,_NS_SUFFIX) */
|
||||
#else
|
||||
#define fseeko fseek
|
||||
#define ftello ftell
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Define standard 64-bits functions */
|
||||
#if defined(_LARGEFILE_SOURCE64)
|
||||
#define fseeko64 _fseeki64 /* _CONCAT(_fseeki64,_NS_SUFFIX) */
|
||||
#define ftello64 _ftelli64 /* _CONCAT(_ftelli64,_NS_SUFFIX) */
|
||||
#endif
|
||||
|
||||
#define fileno _fileno /* Avoid a warning about the deprecated name */
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
/************************* OS/2-specific definitions *************************/
|
||||
|
||||
#ifdef _OS2 /* Automatically defined when targeting an OS/2 application? */
|
||||
|
||||
/* Define functions fseeko and ftello */
|
||||
#if defined(_LARGEFILE_SOURCE)
|
||||
#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
|
||||
#else
|
||||
#endif
|
||||
#define fseeko fseek
|
||||
#define ftello ftell
|
||||
#endif
|
||||
|
||||
/* Define standard 64-bits functions */
|
||||
#if defined(_LARGEFILE_SOURCE64)
|
||||
/* For now, hide the fact that DOS does not support 64-bits lengths */
|
||||
#define fseeko64 _fseek
|
||||
#define ftello64 _ftell
|
||||
#endif
|
||||
|
||||
#endif /* defined(_OS2) */
|
||||
|
||||
/********************** End of OS-specific definitions ***********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* defined(_MSVCLIBX_stdio_H) */
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: stdlib.h *
|
||||
* *
|
||||
* Description: MsvcLibX extensions to stdlib.h. *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2016-09-13 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _MSVCLIBX_stdlib_H
|
||||
#define _MSVCLIBX_stdlib_H 1
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#include <stdlib.h> /* Include MSVC's own <stdlib.h> file */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/************************ MS-DOS-specific definitions ************************/
|
||||
|
||||
#ifdef _MSDOS /* Automatically defined when targeting an MS-DOS application */
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
/************************ Win32-specific definitions *************************/
|
||||
|
||||
#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */
|
||||
|
||||
extern char *_fullpathU(char *absPath, const char *relPath, size_t maxLength);
|
||||
|
||||
#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
|
||||
#define _fullpath _fullpathU /* For processing UTF-8 pathnames */
|
||||
#endif
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
/********************** End of OS-specific definitions ***********************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* defined(_MSVCLIBX_stdlib_H) */
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
/* CoreUtils global system configuration definitions */
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: time.h *
|
||||
* *
|
||||
* Description: MsvcLibX extensions to time.h. *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-06-04 JFL Created this file. *
|
||||
* 2015-11-15 JFL Visual Studio 2015 moved this file to the Windows Kit UCRT.
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _MSVCLIBX_TIME_H
|
||||
#define _MSVCLIBX_TIME_H 1
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <time.h> /* Include MSVC's own <time.h> file */
|
||||
|
||||
|
||||
#ifdef _MSDOS
|
||||
|
||||
/* Check for the definition of _STRUCT_TIMESPEC before using clock_gettime().
|
||||
If it's not defined, use time() instead, which is supported by all OSs. */
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "sys\msvcTime.h" /* for struct timespec */
|
||||
|
||||
typedef int clockid_t;
|
||||
/* Supported values for clockid_t */
|
||||
#define CLOCK_REALTIME 0
|
||||
|
||||
int clock_gettime(clockid_t clock_id, struct timespec *tp);
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
#endif /* defined(_MSVCLIBX_TIME_H) */
|
||||
|
|
@ -0,0 +1,182 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: unistd.h *
|
||||
* *
|
||||
* Description: DOS/WIN32 port of standard C library's unistd.h. *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2012-01-18 JFL Created this file. *
|
||||
* 2012-10-17 JFL Added standard functions getcwd, chdir, getpid, access. *
|
||||
* Added Microsoft-specific functions getdrive, chdrive. *
|
||||
* 2013-03-27 JFL Updated getpid() and added getppid(). *
|
||||
* 2014-02-03 JFL Added readlink(). *
|
||||
* 2014-03-20 JFL Restructured Windows link management functions into Wide *
|
||||
* and MultiByte versions, and changed the Unicode and Ansi *
|
||||
* versions to macros. *
|
||||
* 2014-06-30 JFL Moved PATH_MAX definition to limits.h. *
|
||||
* 2016-08-25 JFL Implemented ResolveLinksA(). *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _UNISTD_H
|
||||
#define _UNISTD_H
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#error This include file is designed for use with the Microsoft C tools only.
|
||||
#endif
|
||||
|
||||
#include "msvclibx.h" /* Generate a library search record to load MsvcLibX.lib. */
|
||||
#include "sys/msvcTypes.h" /* Define pid_t and getppid(). */
|
||||
#include "msvcDirent.h" /* Define pid_t and getppid(). */
|
||||
#include <direct.h> /* For functions like _chdir() and _getcwd() */
|
||||
#include <process.h> /* For _getpid() */
|
||||
|
||||
/* Microsoft tools think these are non standard, but they are standard! */
|
||||
/* #define getcwd _getcwd */
|
||||
/* #define chdir _chdir */
|
||||
/* Actually use the improved versions in MsvcLibX */
|
||||
#undef getcwd /* MSVC _does_ define a getcwd macro, in addition to the getcwd function! */
|
||||
#if defined(_MSDOS)
|
||||
#define getcwd(path, size) _getcwd(path, (int)(size)) /* Use MSVC LIB's own, changing argument 2 type */
|
||||
#elif defined(_WIN32)
|
||||
#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
|
||||
#define getcwd getcwdU
|
||||
#define _getdcwd _getdcwdU
|
||||
#define chdir chdirU
|
||||
#else /* _ANSI_SOURCE */
|
||||
#define getcwd getcwdA
|
||||
#define _getdcwd _getdcwdA
|
||||
#define chdir chdirA
|
||||
#endif
|
||||
char *getcwdA(char *buf, size_t bufSize); /* Can't use the getcwd name, as MSVC has an incompatible prototype for it */
|
||||
char *_getdcwdA(int iDrive, char *buf, int iBuflen);
|
||||
char *getcwdU(char *buf, size_t bufSize); /* Can't use the getcwd name, as MSVC has an incompatible prototype for it */
|
||||
char *_getdcwdU(int iDrive, char *buf, int iBuflen);
|
||||
#endif /* defined(_MSDOS) */
|
||||
int chdir(const char *path);
|
||||
|
||||
/* These are non standard indeed, but the leading _ is annoying */
|
||||
#define getdrive _getdrive
|
||||
#define chdrive _chdrive
|
||||
|
||||
#include <io.h> /* For low level I/O functions like read() & write() */
|
||||
|
||||
/* Microsoft tools think access is non standard, but it is standard! */
|
||||
#if defined(_MSDOS)
|
||||
#define access _access
|
||||
#elif defined(_WIN32)
|
||||
#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
|
||||
#define access _accessU
|
||||
int _accessU(const char *pszFilename, int iAccessMode);
|
||||
#else /* _ANSI_SOURCE */
|
||||
#define access _access
|
||||
#endif
|
||||
#endif
|
||||
#define F_OK 0 /* test for the existence of the file */
|
||||
#define X_OK 1 /* test for execute permission */
|
||||
#define R_OK 2 /* test for read permission */
|
||||
#define W_OK 4 /* test for read permission */
|
||||
|
||||
/* getpid() and getppid() */
|
||||
#define getpid() ((pid_t)(_getpid()))
|
||||
pid_t getppid(void); /* Get parent PID */
|
||||
/* Contrary to in Unix, the above functions can fail in Windows. In this case they return INVALID_PID. */
|
||||
#define INVALID_PID ((pid_t)-1L)
|
||||
|
||||
/* Path management */
|
||||
#if defined(_WIN32)
|
||||
#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
|
||||
#define realpath realpathU
|
||||
#define CompactPath CompactPathU
|
||||
#else /* _ANSI_SOURCE */
|
||||
#define realpath realpathA
|
||||
#define CompactPath CompactPathA
|
||||
#endif
|
||||
#endif /* defined(_WIN32) */
|
||||
char *realpath(const char *path, char *buf); /* Posix routine, normally defined in stdlib.h. Output buf must contain PATH_MAX bytes */
|
||||
int CompactPath(const char *path, char *outbuf, size_t bufsize); /* A proprietary subroutine, that cleans up . and .. parts. */
|
||||
|
||||
/* Signed size type */
|
||||
#ifndef _SSIZE_T_DEFINED
|
||||
#if defined(_MSDOS)
|
||||
typedef int ssize_t;
|
||||
#elif defined(_WIN32)
|
||||
#include <stdint.h>
|
||||
#ifdef _WIN64
|
||||
typedef __int64 ssize_t;
|
||||
#else
|
||||
typedef _W64 int ssize_t;
|
||||
#endif /* defined(_WIN64) */
|
||||
#endif /* defined(_WIN32) */
|
||||
#define _SSIZE_T_DEFINED
|
||||
#endif /* !_SSIZE_T_DEFINED */
|
||||
|
||||
/* Link management functions */
|
||||
#if defined(_WIN32)
|
||||
#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
|
||||
#define readlink readlinkU
|
||||
#define symlink symlinkU
|
||||
#define symlinkd symlinkdU
|
||||
#define junction junctionU
|
||||
#define GetReparseTag GetReparseTagU
|
||||
#define ResolveLinks ResolveLinksU
|
||||
#else /* _ANSI_SOURCE */
|
||||
#define readlink readlinkA
|
||||
#define symlink symlinkA
|
||||
#define symlinkd symlinkdA
|
||||
#define junction junctionA
|
||||
#define GetReparseTag GetReparseTagA
|
||||
#define ResolveLinks ResolveLinksA
|
||||
#endif
|
||||
ssize_t readlinkW(const WCHAR *path, WCHAR *buf, size_t bufsiz); /* Posix routine readlink - Wide char version */
|
||||
ssize_t readlinkM(const char *path, char *buf, size_t bufsiz, UINT cp); /* Posix routine readlink - Multibyte char version */
|
||||
#define readlinkA(path, buf, bufsiz) readlinkM(path, buf, bufsiz, CP_ACP) /* Posix routine readlink - ANSI version */
|
||||
#define readlinkU(path, buf, bufsiz) readlinkM(path, buf, bufsiz, CP_UTF8) /* Posix routine readlink - UTF-8 version */
|
||||
int symlinkW(const WCHAR *targetname, const WCHAR *newlinkname); /* Posix routine symlink - Wide char version */
|
||||
int symlinkM(const char *targetname, const char *newlinkname, UINT cp); /* Posix routine symlink - Multibyte char version */
|
||||
#define symlinkA(target, newlink) symlinkM(target, newlink, CP_ACP) /* Posix routine symlink - ANSI version */
|
||||
#define symlinkU(target, newlink) symlinkM(target, newlink, CP_UTF8) /* Posix routine symlink - UTF-8 version */
|
||||
int symlinkdW(const WCHAR *targetname, const WCHAR *newlinkname); /* MsvcLibX Create an NTFS symlinkd - Wide char version */
|
||||
int symlinkdM(const char *targetname, const char *newlinkname, UINT cp); /* MsvcLibX Create an NTFS symlinkd - Multibyte char version */
|
||||
#define symlinkdA(target, newlink) symlinkdM(target, newlink, CP_ACP) /* MsvcLibX Create an NTFS symlinkd - ANSI version */
|
||||
#define symlinkdU(target, newlink) symlinkdM(target, newlink, CP_UTF8) /* MsvcLibX Create an NTFS symlinkd - UTF-8 version */
|
||||
int junctionW(const WCHAR *targetname, const WCHAR *junctionName); /* MsvcLibX Create an NTFS junction - Wide char version */
|
||||
int junctionM(const char *targetname, const char *junctionName, UINT cp); /* MsvcLibX Create an NTFS junction - Multibyte char version */
|
||||
#define junctionA(target, newjunc) junctionM(target, newjunc, CP_ACP) /* MsvcLibX Create an NTFS junction - ANSI version */
|
||||
#define junctionU(target, newjunc) junctionM(target, newjunc, CP_UTF8) /* MsvcLibX Create an NTFS junction - UTF-8 version */
|
||||
DWORD GetReparseTagW(const WCHAR *path); /* MsvcLibX Get a Repase Point tag - Wide char version */
|
||||
DWORD GetReparseTagM(const char *path, UINT cp); /* MsvcLibX Get a Repase Point tag - MultiByte char version */
|
||||
#define GetReparseTagA(path) GetReparseTagM(path, CP_ACP) /* MsvcLibX Get a Repase Point tag - ANSI version */
|
||||
#define GetReparseTagU(path) GetReparseTagM(path, CP_UTF8) /* MsvcLibX Get a Repase Point tag - ANSI version */
|
||||
int ResolveLinksA(const char *path, char *buf, size_t bufsize); /* Resolve pathnames with symlinks, symlinkds, and junctions */
|
||||
int ResolveLinksU(const char *path, char *buf, size_t bufsize); /* Resolve pathnames with symlinks, symlinkds, and junctions */
|
||||
#ifndef ELOOP
|
||||
/*
|
||||
// Unix defines ELOOP as errno 40.
|
||||
// MS Visual C++ 1.52 for DOS is standard up to errno 34, then diverges up to errno 36.
|
||||
// Many errnos within the list are actually unused, and for them _sys_errlist[] = "".
|
||||
// MS Visual C++ 9 for Windows is standard up to errno 34, then diverges up to errno 43.
|
||||
// Also MSVC9 does not define errno:
|
||||
// 15 // The posix standard ENOTBLK "Block device required"
|
||||
// 26 // The posix standard ETXTBSY "Text file busy"
|
||||
// 35 // Positioned between standard ERANGE and EDEADLK
|
||||
// 37 // Positioned between standard EDEADLK and ENAMETOOLONG
|
||||
// 43 // Positioned last, after standard ENOTEMPTY
|
||||
// The _sys_errlist[] pointer for all the above points to a single string "Unknown error".
|
||||
*/
|
||||
#define ELOOP 35 /* Using the first available slot */ /* Update _sys_errlist[ELOOP] accordingly in any routine that generates ELOOP! */
|
||||
#endif /* !defined(ELOOP) */
|
||||
#define SYMLOOP_MAX 31 /* Maximum depth of symbolic name resolution, to avoid stack overflows. Windows is documented to allow 31: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365460(v=vs.85).aspx */
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
/* Standard file descriptor numbers, for low level I/O functions */
|
||||
#define STDIN_FILENO 0 /* Standard input file number */
|
||||
#define STDOUT_FILENO 1 /* Standard output file number */
|
||||
#define STDERR_FILENO 2 /* Standard error file number */
|
||||
|
||||
#endif /* _UNISTD_H */
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: utime.h *
|
||||
* *
|
||||
* Description: DOS/WIN32 adaptation of standard C library's utime.h. *
|
||||
* *
|
||||
* Notes: The Unix standard now standardizes utime.h location in *
|
||||
* the include directory itself. *
|
||||
* Microsoft put it in the include/sys subdirectory. *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-12-13 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _MSVXLIBX_UTIME_H
|
||||
#define _MSVXLIBX_UTIME_H
|
||||
|
||||
/* In MS-DOS, simply use MSVC's sys/utime.h. */
|
||||
|
||||
#ifdef _MSDOS
|
||||
|
||||
#include <sys/utime.h>
|
||||
|
||||
#define lutime utime /* There are no links in MS-DOS, so lutime() is the same as utime() */
|
||||
|
||||
#endif /* _MSDOS */
|
||||
|
||||
|
||||
/* In Windows, we use MSVC's sys/utime.h, but redefine the utime*() functions. */
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include "msvclibx.h" /* Generate a library search record to load MsvcLibX.lib. */
|
||||
|
||||
/* Save the initial definition and value of __STDC__ */
|
||||
#ifdef __STDC__
|
||||
#define _UTIME__STDC__WAS_DEFINED 1
|
||||
#pragma push_macro("__STDC__")
|
||||
#undef __STDC__
|
||||
#else
|
||||
#define _UTIME__STDC__WAS_DEFINED 0
|
||||
#endif
|
||||
|
||||
#define __STDC__ 1 /* Prevents <sys/utime.h> from defining structures and functions without _ */
|
||||
|
||||
#include <sys/utime.h>
|
||||
|
||||
#ifdef _USE_32BIT_TIME_T
|
||||
#define utimbuf __utimbuf32
|
||||
#define utime _utime32x
|
||||
#error "32-bits time_t not supported in MsvcLibX' utime."
|
||||
#else
|
||||
#define utimbuf __utimbuf64
|
||||
#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
|
||||
#define utime utimeU
|
||||
#define lutime lutimeU
|
||||
#else /* _ANSI_SOURCE */
|
||||
#define utime utimeA
|
||||
#define lutime lutimeA
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Our redefinition in utime.c */
|
||||
int utimeA(const char * pszFilename, const struct utimbuf * pUtimbuf);
|
||||
int lutimeA(const char * pszFilename, const struct utimbuf * pUtimbuf);
|
||||
int utimeU(const char * pszFilename, const struct utimbuf * pUtimbuf);
|
||||
int lutimeU(const char * pszFilename, const struct utimbuf * pUtimbuf);
|
||||
int utimeW(const WCHAR * pszFilename, const struct utimbuf * pUtimbuf);
|
||||
int lutimeW(const WCHAR * pszFilename, const struct utimbuf * pUtimbuf);
|
||||
int futime(int fd, const struct utimbuf * pUtimbuf);
|
||||
|
||||
#undef __STDC__
|
||||
|
||||
/* Restore the initial definition and value of __STDC__ */
|
||||
#if _UTIME__STDC__WAS_DEFINED
|
||||
#pragma pop_macro("__STDC__")
|
||||
#endif
|
||||
#undef _UTIME__STDC__WAS_DEFINED
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
||||
#endif /* _MSVXLIBX_UTIME_H */
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: windows.h *
|
||||
* *
|
||||
* Description: Define MsvcLibX' extensions to the WIN32 API functions *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2016-09-12 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _MSVCLIBX_WINDOWS_H
|
||||
#define _MSVCLIBX_WINDOWS_H 1
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h> /* Include Windows SDK's own windows.h */
|
||||
|
||||
/****************** Define UTF-8 versions of WIN32 routines ******************/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
DWORD WINAPI GetFileAttributesU(LPCTSTR lpFileName);
|
||||
BOOL WINAPI GetFileAttributesExU(LPCTSTR lpFileName, GET_FILEEX_INFO_LEVELS fInfoLevelId, LPVOID lpFileInformation);
|
||||
DWORD WINAPI GetFullPathNameU(LPCTSTR lpName, DWORD nBufferLength, LPTSTR lpBuf, LPTSTR *lpFilePart);
|
||||
DWORD WINAPI GetLongPathNameU(LPCTSTR lpShortName, LPTSTR lpBuf, DWORD nBufferLength);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/********** Redefine the legacy names to point to the UTF-8 version **********/
|
||||
|
||||
#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
|
||||
|
||||
#undef GetFileAttributes
|
||||
#define GetFileAttributes GetFileAttributesU
|
||||
|
||||
#undef GetFileAttributesEx
|
||||
#define GetFileAttributesEx GetFileAttributesExU
|
||||
|
||||
#undef GetFullPathName
|
||||
#define GetFullPathName GetFullPathNameU
|
||||
|
||||
#undef GetLongPathName
|
||||
#define GetLongPathName GetLongPathNameU
|
||||
|
||||
#endif /* defined(_UTF8_SOURCE) ... */
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
#endif /* defined(_MSVCLIBX_WINDOWS_H) */
|
|
@ -0,0 +1,19 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: error.h *
|
||||
* *
|
||||
* Description: DOS/WIN32 port of the GNU CoreUtils library xfreopen func.*
|
||||
* *
|
||||
* Notes: msvclibx: Implement using freopen or _setmode. *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-10 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#include "msvclibx.h" /* Generate a library search record to load MsvcLibX.lib. */
|
||||
|
||||
extern FILE *xfreopen(const char *filename, const char *mode, FILE *stream);
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename MsvcLibX.h *
|
||||
* *
|
||||
* Description MsvcLibX-specific definitions *
|
||||
* *
|
||||
* Notes Generates a library search record to load MsvcLibX.lib. *
|
||||
* *
|
||||
* History: *
|
||||
* 2013 JFL Created this file. *
|
||||
* 2014-05-30 JFL Added macros to work around the lack of a #include_next. *
|
||||
* 2015-11-15 JFL Added macro UCRT_INCLUDE_FILE for Visual Studio 2015. *
|
||||
* 2016-09-15 JFL Added macro WINSDK_INCLUDE_FILE for Windows SDK. *
|
||||
* 2016-09-20 JFL Added workaround preventing warnings in WIN95 builds. *
|
||||
* 2016-09-28 JFL Can also be included by MS' Resource Compiler. *
|
||||
* 2017-02-05 JFL Changed the UTF-8 programs initialization method. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Generate a library search record to load MsvcLibX.lib */
|
||||
|
||||
#ifndef _MSVCLIBX_H_
|
||||
#define _MSVCLIBX_H_
|
||||
|
||||
#if !(defined(_MSC_VER) || defined(RC_INVOKED))
|
||||
#error The msvclibx library is designed for use with the Microsoft Visual C/C++ tools only.
|
||||
#endif
|
||||
|
||||
/* Compute the OS-specific suffix */
|
||||
#if defined(_WIN64)
|
||||
# define _MSVCLIBX_LIB_OS_SUFFIX "w64"
|
||||
#elif defined(_WIN95)
|
||||
# define _MSVCLIBX_LIB_OS_SUFFIX "w95"
|
||||
#elif defined(_WIN32)
|
||||
# define _MSVCLIBX_LIB_OS_SUFFIX "w32"
|
||||
#elif defined(_MSDOS)
|
||||
# if defined(_M_I86TM)
|
||||
# define _MSVCLIBX_LIB_OS_SUFFIX "dt"
|
||||
# elif defined(_M_I86SM)
|
||||
# define _MSVCLIBX_LIB_OS_SUFFIX "ds"
|
||||
# elif defined(_M_I86LM)
|
||||
# define _MSVCLIBX_LIB_OS_SUFFIX "dl"
|
||||
# else
|
||||
# error No msvclibx.lib version yet for this DOS memory model.
|
||||
# endif
|
||||
#else
|
||||
# error No msvclibx.lib version for this target OS.
|
||||
#endif
|
||||
|
||||
/* Compute the debug-mode-specific suffix */
|
||||
#if defined(_DEBUG)
|
||||
# define _MSVCLIBX_LIB_DBG_SUFFIX "d"
|
||||
#else
|
||||
# define _MSVCLIBX_LIB_DBG_SUFFIX ""
|
||||
#endif
|
||||
|
||||
/* Generate the OS-and-debug-mode-specific library name */
|
||||
#define _MSVCLIBX_LIB "MsvcLibX" _MSVCLIBX_LIB_OS_SUFFIX _MSVCLIBX_LIB_DBG_SUFFIX ".lib"
|
||||
//#pragma message("Adding pragma comment(lib, \"" _MSVCLIBX_LIB "\")")
|
||||
#pragma comment(lib, _MSVCLIBX_LIB)
|
||||
|
||||
/* Library-specific routine used internally by many standard routines */
|
||||
#if defined(_WIN32)
|
||||
extern int Win32ErrorToErrno(); /* Converts the last WIN32 error to a Posix error code */
|
||||
#ifndef ELOOP /* Defined in VS10's errno.h, but not in VS9 */
|
||||
#define ELOOP 114
|
||||
#endif
|
||||
/* Convert an ANSI or UTF-8 or OEM pathname to a Unicode string. Defined in mb2wpath.c. */
|
||||
typedef unsigned int UINT; /* Defined in windef.h */
|
||||
typedef const char* LPCSTR; /* Defined in winnt.h */
|
||||
#ifndef _WCHAR_T_DEFINED
|
||||
typedef unsigned short wchar_t; /* Defined in crtdefs.h */
|
||||
#define _WCHAR_T_DEFINED
|
||||
#endif
|
||||
typedef wchar_t* LPWSTR; /* Defined in winnt.h */
|
||||
extern int MultiByteToWidePath(UINT nCodePage, LPCSTR pszName, LPWSTR pwszName, int nWideBufSize);
|
||||
#endif
|
||||
/* Count the number of elements in an array */
|
||||
#define COUNTOF(array) (sizeof(array)/sizeof(array[0]))
|
||||
|
||||
/* Workaround for missing __pragma() directive in old versions of Visual Studio */
|
||||
#if defined(_WIN32) && defined(_MSC_VER) && (_MSC_VER <= 1400) /* For Visual C++ versions up to Visual Studio 2005 */
|
||||
#define __pragma(x)
|
||||
#endif /* (_MSC_VER <= 1400) */
|
||||
|
||||
/* Macros for working around the lack of a #include_next directive */
|
||||
#define MSVCLIBX_CONCAT1(a,b) a##b /* Concatenate the raw arguments */
|
||||
#define MSVCLIBX_CONCAT(a,b) MSVCLIBX_CONCAT1(a,b) /* Substitute the arguments, then concatenate the values */
|
||||
#define MSVCLIBX_STRINGIZE1(x) #x /* Convert the raw argument to a string */
|
||||
#define MSVCLIBX_STRINGIZE(x) MSVCLIBX_STRINGIZE1(x) /* Substitute the argument, then convert its value to a string */
|
||||
/* Up to VS2013, both kinds of include files were in the same directory. Then in VS2015, they were split in two dirs. */
|
||||
#define MSVC_INCLUDE_FILE(relpath) MSVCLIBX_STRINGIZE(MSVCLIBX_CONCAT(MSVCINCLUDE,MSVCLIBX_CONCAT(/,relpath))) /* C compiler include files */
|
||||
#define UCRT_INCLUDE_FILE(relpath) MSVCLIBX_STRINGIZE(MSVCLIBX_CONCAT(UCRTINCLUDE,MSVCLIBX_CONCAT(/,relpath))) /* C runtime library include files */
|
||||
#define WINSDK_INCLUDE_FILE(relpath) MSVCLIBX_STRINGIZE(MSVCLIBX_CONCAT(WSDKINCLUDE,MSVCLIBX_CONCAT(/,relpath))) /* Windows SDK include files */
|
||||
|
||||
/* Support for external linker symbols */
|
||||
#if defined(_WIN64)
|
||||
#define PUBLIC_SYMBOL_NAME(s) s
|
||||
#else /* _MSDOS or _WIN32 */
|
||||
#define PUBLIC_SYMBOL_NAME(s) _##s
|
||||
#endif
|
||||
|
||||
/* Support for UTF-8 command lines */
|
||||
#if defined(_WIN32)
|
||||
#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
|
||||
/* Force linking in MsvcLibX' UTF-8 initialization module */
|
||||
#pragma comment(linker, "/include:" MSVCLIBX_STRINGIZE(PUBLIC_SYMBOL_NAME(_initU)))
|
||||
#endif /* defined(_UTF8_SOURCE) ... */
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
/* Prevent an incompatibility with <winsock.h>. See MsvcLibX' "sys/time.h" for explanations. */
|
||||
#define _WINSOCKAPI_ /* Prevent the inclusion of winsock.h in windows.h */
|
||||
|
||||
#endif /* _MSVCLIBX_H_ */
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename sys/param.h *
|
||||
* *
|
||||
* Description DOS/WIN32 port of standard C library's sys/param.h. *
|
||||
* *
|
||||
* Notes *
|
||||
* *
|
||||
* History *
|
||||
* 2014-06-10 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _SYS_PARAM_H
|
||||
#define _SYS_PARAM_H
|
||||
|
||||
|
||||
#ifdef _MSDOS
|
||||
|
||||
#define _POSIX_ARG_MAX 127 /* Maximum command line size */
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/* #include MSVC_INCLUDE_FILE(sys\param.h) /* Include MSVC's own <sys/param.h> file */
|
||||
|
||||
#define _POSIX_ARG_MAX 8191
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
#endif /* !defined(_SYS_PARAM_H) */
|
||||
|
|
@ -0,0 +1,422 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: stat.h *
|
||||
* *
|
||||
* Description: MsvcLibX extensions to sys/stat.h. *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-06 JFL Moved stat extensions from dirent.h. *
|
||||
* 2014-02-26 JFL Added proprietary routines for managing file times. *
|
||||
* 2014-03-24 JFL Added a mechanism to also include MSVC's own sys/stat.h. *
|
||||
* Renamed this file from statx.h to sys/stat.h. *
|
||||
* 2014-05-27 JFL Added dummy definitions for S_TYPEISSHM() & S_TYPEISTMO().*
|
||||
* 2014-06-03 JFL Moved struct timespec definition to sys/time.h. *
|
||||
* 2014-06-06 JFL Moved mode_t & off*_t definition to sys/types.h. *
|
||||
* Moved fseeko* & ftello* functions definitions to stdio.h. *
|
||||
* 2014-06-24 JFL Added fstat and fstat64 external references. *
|
||||
* 2015-11-15 JFL Visual Studio 2015 moved this file to the Windows Kit UCRT.
|
||||
* 2016-09-15 JFL Fixed a warning in Visual Studio 2015. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _MSVCLIBX_STAT_H
|
||||
#define _MSVCLIBX_STAT_H 1
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#include "sys/msvcTypes.h"
|
||||
#include <sys/stat.h> /* Include MSVC's own <sys/stat.h> file */
|
||||
#include "msvcDirent.h" /* For dirent2stat() arguments definitions */
|
||||
#include "msvcTime.h" /* for time_t definition */
|
||||
#include "sys/msvcTime.h" /* for timespec definition */
|
||||
/* Include MsvcLibX's <direct.h> override, to avoid conflict with the standard mkdir defined here,
|
||||
should <direct.h> be manually included later on in the C source */
|
||||
#include <direct.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/************************ MS-DOS-specific definitions ************************/
|
||||
|
||||
#ifdef _MSDOS /* Automatically defined when targeting an MS-DOS application */
|
||||
|
||||
/* Define stat and fstat to use 32 or 64 file lengths, as defined by _FILE_OFFSET_BITS */
|
||||
/* #undef stat /* Not normally defined by MSVC */
|
||||
/* #undef fstat /* Not normally defined by MSVC */
|
||||
#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
|
||||
/* TO DO: Windows 95 has extended functions for handling 64-bits files sizes */
|
||||
#else
|
||||
#endif
|
||||
/* For now, use the MSVC 32-bits functions in all cases */
|
||||
#define stat _stat
|
||||
#define fstat _fstat
|
||||
#define lstat stat
|
||||
|
||||
/* Define standard 64-bits structures and functions */
|
||||
#if defined(_LARGEFILE_SOURCE64)
|
||||
/* For now, hide the fact that DOS does not support 64-bits lengths */
|
||||
#define off64_t _off_t
|
||||
#define stat64 _stat
|
||||
#define fstat64 _fstat
|
||||
#define lstat64 stat64
|
||||
#endif
|
||||
|
||||
/* Proprietary function for recovering available infos without calling stat */
|
||||
extern int dirent2stat(struct dirent *pDE, struct _stat *pStat);
|
||||
#define dirent2stat64 dirent2stat /* The current versions are the same */
|
||||
#define _DIRENT2STAT_DEFINED 1
|
||||
|
||||
/* MS-DOS always reports local file times. MsvcLibX DOS version generates a
|
||||
pseudo GMT time for files using mktime(), which can then be undone by localtime(). */
|
||||
#define LocalFileTime localtime
|
||||
|
||||
/* Proprietary function for converting a DOS date/time to a Posix time_t */
|
||||
extern time_t Filetime2Timet(uint16_t date, uint16_t time);
|
||||
/* Proprietary function for generating a string with the local file time, in the ISO 8601 date/time format */
|
||||
extern char *Filetime2String(uint16_t date, uint16_t time, char *pBuf, size_t nBufSize);
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
/************************ Win32-specific definitions *************************/
|
||||
|
||||
#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */
|
||||
|
||||
/* Visual C++ sys/stat.h defines a series of _statXY functions and structures:
|
||||
XY = 32 st_*time is 32-bits __time32_t & st_size is 32-bits _off_t
|
||||
XY = 32i64 st_*time is 32-bits __time32_t & st_size is 64-bits __int64
|
||||
XY = 64i32 st_*time is 64-bits __time64_t & st_size is 32-bits _off_t
|
||||
XY = 64 st_*time is 64-bits __time64_t & st_size is 64-bits __int64
|
||||
Then it defines additional _statZ macros generating _statXY, based on:
|
||||
XY = 32 if _USE_32BIT_TIME_T defined & Z is ""
|
||||
XY = 32i64 if _USE_32BIT_TIME_T defined & Z is i64
|
||||
XY = 64i32 if _USE_32BIT_TIME_T undefined & Z is ""
|
||||
XY = 64 if _USE_32BIT_TIME_T undefined & Z is i64
|
||||
Special case: In 64-bits windows, _USE_32BIT_TIME_T defined is ignored and #undef(ined)
|
||||
*/
|
||||
|
||||
/* Define stat and fstat to use 32 or 64 file lengths, as defined by _FILE_OFFSET_BITS */
|
||||
/* #undef stat /* Not normally defined by MSVC */
|
||||
/* #undef fstat /* Not normally defined by MSVC */
|
||||
|
||||
#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
|
||||
#define _STAT_FILE_SIZE 64
|
||||
#define _STAT_SUFFIX i64
|
||||
#else
|
||||
#define _STAT_FILE_SIZE 32
|
||||
#define _STAT_SUFFIX
|
||||
#endif
|
||||
|
||||
#define _USE_EXTENDED_STAT_STRUCT 1
|
||||
|
||||
#define _VALUEOF(a) a /* Get the token value */
|
||||
#define _CONCAT2T(a,b) a##b /* Concatenate two tokens (does not expand their values) */
|
||||
#define _CONCAT3T(a,b,c) a##b##c /* Concatenate three tokens (does not expand their values) */
|
||||
#define _CONCAT4T(a,b,c,d) a##b##c##d /* Concatenate four tokens (does not expand their values) */
|
||||
#define _CONCAT(a,b) _CONCAT2T(a,b) /* Concatenate two tokens values */
|
||||
#define _CONCAT3(a,b,c) _CONCAT3T(a,b,c) /* Concatenate three tokens values */
|
||||
#define _CONCAT4(a,b,c,d) _CONCAT4T(a,b,c,d) /* Concatenate four tokens values */
|
||||
#define _CON_STAT_CAT1(pre,post) pre##stat##post
|
||||
#define _CON_STAT_CAT(pre,post) _CON_STAT_CAT1(pre,post)
|
||||
|
||||
/* Define what stat, fstat, lstat, stat64 macros would be,
|
||||
if we were to use MSVC's own stat structures and routines */
|
||||
/* Avoid concatenating tokens _stat and _fstat, as these are already macros
|
||||
that would be expanded, and we do not want this as this stage. */
|
||||
#define _MSVC_stat _CON_STAT_CAT(_ , _STAT_SUFFIX)
|
||||
#define _MSVC_fstat _CON_STAT_CAT(_f, _STAT_SUFFIX)
|
||||
#define _MSVC_lstat _CON_STAT_CAT(_l, _STAT_SUFFIX)
|
||||
#define _MSVC_stat64 _CON_STAT_CAT(_ , i64)
|
||||
#define _MSVC_lstat64 _CON_STAT_CAT(_l, i64)
|
||||
|
||||
#ifdef _USE_32BIT_TIME_T
|
||||
#define _lstat _lstat32
|
||||
#define _lstati64 _lstat32i64
|
||||
#define _lstat_ns _lstat32_ns
|
||||
#define _lstati64_ns _lstat32i64_ns
|
||||
#else
|
||||
#define _lstat _lstat64i32
|
||||
#define _lstati64 _lstat64
|
||||
#define _lstat_ns _lstat64i32_ns
|
||||
#define _lstati64_ns _lstat64_ns
|
||||
#endif
|
||||
|
||||
#if !_USE_EXTENDED_STAT_STRUCT
|
||||
#define _NS_SUFFIX
|
||||
#else /* _USE_EXTENDED_STAT_STRUCT */
|
||||
#define _MSVCLIBX_STAT_DEFINED 1
|
||||
#define _NS_SUFFIX _ns
|
||||
/* Define what stat, fstat, lstat, stat64 macros and structures would be,
|
||||
if we were to use MsvcLibX extended stat structures and routines */
|
||||
#define _LIBX_stat _CONCAT(_MSVC_stat,_ns)
|
||||
#define _LIBX_stat64 _CONCAT(_MSVC_stat64,_ns)
|
||||
#include "msvcDebugm.h"
|
||||
#pragma message("Defining type struct " VALUEIZE(_LIBX_stat))
|
||||
struct _LIBX_stat {
|
||||
/* MSVC standard stat structure fields */
|
||||
_dev_t st_dev;
|
||||
_ino_t st_ino;
|
||||
unsigned short st_mode;
|
||||
short st_nlink;
|
||||
short st_uid;
|
||||
short st_gid;
|
||||
_dev_t st_rdev;
|
||||
off_t st_size;
|
||||
/* End of MSVC standard stat structure fields */
|
||||
struct timespec st_ctim; /* File creation date/time, w. ns resolution */
|
||||
struct timespec st_mtim; /* File modification date/time, w. ns resolution */
|
||||
struct timespec st_atim; /* File access date/time, w. ns resolution */
|
||||
unsigned int st_Win32Attrs; /* Win32 file attributes */
|
||||
unsigned int st_ReparseTag; /* Reparse point tag */
|
||||
};
|
||||
/* Compatibility with old Unix fields */
|
||||
#define st_ctime st_ctim.tv_sec
|
||||
#define st_mtime st_mtim.tv_sec
|
||||
#define st_atime st_atim.tv_sec
|
||||
/* Compatibility with intermediate Unix fields */
|
||||
#define st_ctimensec st_ctim.tv_nsec /* Nanosecond part of the file creation time */
|
||||
#define st_mtimensec st_mtim.tv_nsec /* Nanosecond part of the file modification time */
|
||||
#define st_atimensec st_atim.tv_nsec /* Nanosecond part of the file access time */
|
||||
|
||||
#if (_STAT_FILE_SIZE != 64) /* Else it's the same as struct stat */
|
||||
#pragma message("Defining type struct " VALUEIZE(_LIBX_stat64))
|
||||
struct _LIBX_stat64 {
|
||||
/* MSVC standard stat structure fields */
|
||||
_dev_t st_dev;
|
||||
_ino_t st_ino;
|
||||
unsigned short st_mode;
|
||||
short st_nlink;
|
||||
short st_uid;
|
||||
short st_gid;
|
||||
_dev_t st_rdev;
|
||||
off64_t st_size;
|
||||
/* End of MSVC standard stat structure fields */
|
||||
struct timespec st_ctim; /* File creation date/time, w. ns resolution */
|
||||
struct timespec st_mtim; /* File modification date/time, w. ns resolution */
|
||||
struct timespec st_atim; /* File access date/time, w. ns resolution */
|
||||
unsigned int st_Win32Attrs; /* Win32 file attributes */
|
||||
unsigned int st_ReparseTag; /* Reparse point tag */
|
||||
};
|
||||
#endif
|
||||
#endif /* !_USE_EXTENDED_STAT_STRUCT */
|
||||
|
||||
/* Define standard stat, fstat, lstat macros */
|
||||
#define stat _CONCAT(_MSVC_stat,_NS_SUFFIX)
|
||||
#define fstat _CONCAT(_MSVC_fstat,_NS_SUFFIX)
|
||||
#define lstat _CONCAT(_MSVC_lstat,_NS_SUFFIX)
|
||||
|
||||
/* Reference standard stat, fstat, lstat functions that we redefine */
|
||||
#if _USE_EXTENDED_STAT_STRUCT /* Else we'll use MSVC's version */
|
||||
extern int stat(const char *path, struct stat *buf);
|
||||
extern int fstat(int nFile, struct stat *buf);
|
||||
#endif
|
||||
extern int lstat(const char *path, struct stat *buf);
|
||||
|
||||
/* Define standard 64-bits macros and functions */
|
||||
#if defined(_LARGEFILE_SOURCE64)
|
||||
#define stat64 _CONCAT(_stati64,_NS_SUFFIX)
|
||||
#define fstat64 _CONCAT(_fstati64,_NS_SUFFIX)
|
||||
#define lstat64 _CONCAT(_lstati64,_NS_SUFFIX)
|
||||
|
||||
#if (_STAT_FILE_SIZE != 64) /* Else they're the same as functions stat & lstat */
|
||||
#if _USE_EXTENDED_STAT_STRUCT /* Else we'll use MSVC's version */
|
||||
extern int stat64(const char *path, struct stat64 *buf);
|
||||
extern int fstat64(int nFile, struct stat *buf);
|
||||
#endif
|
||||
extern int lstat64(const char *path, struct stat64 *buf);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Proprietary function for recovering dirent infos without calling stat */
|
||||
/* Note: MSDOS has a single stat version, and its dirent2stat implementation is in dirent.c */
|
||||
#ifdef _USE_32BIT_TIME_T
|
||||
#if (_STAT_FILE_SIZE != 64) /* Else if _STAT_FILE_SIZE=64, then struct _stat32_ns isn't defined */
|
||||
extern int _CONCAT(_dirent2_stat32,_NS_SUFFIX)(struct dirent *pDE, struct _CONCAT(_stat32,_NS_SUFFIX) *pStat);
|
||||
#endif
|
||||
extern int _CONCAT(_dirent2_stat32i64,_NS_SUFFIX)(struct dirent *pDE, struct _CONCAT(_stat32i64,_NS_SUFFIX) *pStat);
|
||||
#else
|
||||
#if (_STAT_FILE_SIZE != 64) /* Else if _STAT_FILE_SIZE=64, then struct _stat64i32_ns isn't defined */
|
||||
extern int _CONCAT(_dirent2_stat64i32,_NS_SUFFIX)(struct dirent *pDE, struct _CONCAT(_stat64i32,_NS_SUFFIX) *pStat);
|
||||
#endif
|
||||
extern int _CONCAT(_dirent2_stat64,_NS_SUFFIX)(struct dirent *pDE, struct _CONCAT(_stat64,_NS_SUFFIX) *pStat);
|
||||
#endif
|
||||
#define dirent2stat _CONCAT(_dirent2,stat)
|
||||
#define _DIRENT2STAT_DEFINED 1
|
||||
|
||||
#define unlink _CONCAT(_unlink_, stat)
|
||||
#define rmdir _CONCAT(_rmdir_, stat)
|
||||
extern int unlink(const char *path);
|
||||
extern int rmdir(const char *path);
|
||||
|
||||
/* Proprietary function for generating a printable local file time,
|
||||
using Windows' specific algorithm, to match cmd.exe dir output. */
|
||||
extern struct tm *LocalFileTime(const time_t *pt);
|
||||
|
||||
/* Proprietary function for converting a Win32 FILETIME to a Posix time_t */
|
||||
extern time_t Filetime2Timet(const FILETIME *pFT);
|
||||
/* Proprietary function for converting a Posix time_t to a Win32 FILETIME */
|
||||
extern void Timet2Filetime(time_t s, FILETIME *pFT);
|
||||
|
||||
/* Proprietary function for converting a Win32 FILETIME to a Posix {time_t,nanosecond} */
|
||||
extern void Filetime2Timespec(const FILETIME *pFT, struct timespec *pTS);
|
||||
/* Proprietary function for converting a Posix {time_t,nanosecond} to a Win32 FILETIME */
|
||||
extern void Timespec2Filetime(const struct timespec *pTS, FILETIME *pFT);
|
||||
|
||||
/* Proprietary function for generating a string with the local file time, in the ISO 8601 date/time format */
|
||||
extern char *Filetime2String(const FILETIME *pFT, char *pBuf, size_t nBufSize);
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
/************************* OS/2-specific definitions *************************/
|
||||
|
||||
#ifdef _OS2 /* Automatically defined when targeting an OS/2 application? */
|
||||
|
||||
/* Define stat and fstat to use 32 or 64 file lengths, as defined by _FILE_OFFSET_BITS */
|
||||
/* #undef stat /* Not normally defined by MSVC */
|
||||
/* #undef fstat /* Not normally defined by MSVC */
|
||||
#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
|
||||
/* TO DO: Windows 95 has extended functions for handling 64-bits files sizes */
|
||||
#else
|
||||
#endif
|
||||
/* For now, use the MSVC 32-bits functions in all cases */
|
||||
#define off_t _off_t
|
||||
#define stat _stat
|
||||
#define fstat _fstat
|
||||
#define lstat stat
|
||||
|
||||
/* Define standard 64-bits functions */
|
||||
#if defined(_LARGEFILE_SOURCE64)
|
||||
/* For now, hide the fact that DOS does not support 64-bits lengths */
|
||||
#define off64_t _off_t
|
||||
#define stat64 _stat
|
||||
#define fstat64 _fstat
|
||||
#define lstat64 stat64
|
||||
#endif
|
||||
|
||||
/* Proprietary function for recovering available infos without calling stat */
|
||||
/* extern int dirent2stat(struct dirent *pDE, struct _stat *pStat); */
|
||||
/* #define dirent2stat64 dirent2stat /* The current versions are the same */
|
||||
/* #define _DIRENT2STAT_DEFINED 1 */
|
||||
|
||||
/* To do: Check if OS/2 uses local or GMT times, and implement LocalFileTime() if needed. */
|
||||
#define LocalFileTime localtime
|
||||
|
||||
#endif /* defined(_OS2) */
|
||||
|
||||
/********************** End of OS-specific definitions ***********************/
|
||||
|
||||
#define lchmod chmod /* MSVC is buggy and chmod() applies to the link itself */
|
||||
|
||||
/* Structure stat standard st_mode values not defined in DOS/Windows' sys/stat.h */
|
||||
/* Must match the d_type field types in dirent.h. */
|
||||
/* #define S_IFMT 0xF000 /* Mask for the 4-bit file type */
|
||||
#define S_IFIFO 0x1000 /* FIFO */
|
||||
/* #define S_IFCHR 0x2000 /* Character device */
|
||||
/* #define S_IFDIR 0x4000 /* Directory */
|
||||
#define S_IFBLK 0x6000 /* Block device */
|
||||
/* #define S_IFREG 0x8000 /* Regular file */
|
||||
#define S_IFLNK 0xA000 /* Symbolic link */
|
||||
#define S_IFSOCK 0xC000 /* Socket */
|
||||
|
||||
/* Structure stat standard st_mode type test macros */
|
||||
/* The existence of these macros can be used to test for the OS support of the feature */
|
||||
#define S_ISTYPE(m, TYPE) ((m & S_IFMT) == TYPE)
|
||||
/* Both DOS and Windows support these file types */
|
||||
#define S_ISCHR(m) S_ISTYPE(m, S_IFCHR) /* Test for a character device */
|
||||
#define S_ISDIR(m) S_ISTYPE(m, S_IFDIR) /* Test for a directory */
|
||||
#define S_ISREG(m) S_ISTYPE(m, S_IFREG) /* Test for a regular file */
|
||||
#ifdef _WIN32 /* Only Windows supports these */
|
||||
#define S_ISLNK(m) S_ISTYPE(m, S_IFLNK) /* Test for a symbolic link */
|
||||
#endif
|
||||
#if 0 /* Only Unix supports these? At least MsvcLibX does not support them now. */
|
||||
#define S_ISBLK(m) S_ISTYPE(m, S_IFBLK) /* Test for a block device */
|
||||
#define S_ISFIFO(m) S_ISTYPE(m, S_IFIFO) /* Test for a pipe or FIFO */
|
||||
#define S_ISSOCK(m) S_ISTYPE(m, S_IFSOCK) /* Test for a socket */
|
||||
#endif
|
||||
|
||||
#define S_ISBLK(m) 0 /* Test for a block device */
|
||||
#define S_ISCTG(m) 0 /* Test for a high performance ("contiguous data") file */
|
||||
#define S_ISDOOR(m) 0 /* Test for a door */
|
||||
#define S_ISFIFO(m) 0 /* Test for a pipe or FIFO */
|
||||
#define S_ISMPB(m) 0 /* Test for a multiplexed block device */
|
||||
#define S_ISMPC(m) 0 /* Test for a multiplexed character device */
|
||||
#define S_ISNWK(m) 0 /* Test for a network special file (HP-UX) */
|
||||
#define S_ISPORT(m) 0 /* Test for a port */
|
||||
#define S_ISSOCK(m) 0 /* Test for a socket */
|
||||
#define S_ISWHT(m) 0 /* Test for a whiteout (4.4BSD) */
|
||||
|
||||
|
||||
/* Other optional file types that some operating systems support */
|
||||
#define S_TYPEISMQ(pStat) 0 /* Test for a message queue */
|
||||
#define S_TYPEISSEM(pStat) 0 /* Test for a semaphore */
|
||||
#define S_TYPEISSHM(pStat) 0 /* Test for a shared memory object */
|
||||
#define S_TYPEISTMO(pStat) 0 /* Test for a typed memory object */
|
||||
|
||||
/* Structure stat standard st_mode flags */
|
||||
#define S_ISUID 04000 /* Set UID bit */
|
||||
#define S_ISGID 02000 /* Set-group-ID bit */
|
||||
#define S_ISVTX 01000 /* Sticky bit */
|
||||
|
||||
#define S_IRWXU 0700 /* Mask for file owner permissions */
|
||||
#define S_IRUSR 0400 /* Owner has read permission. Alias S_IREAD */
|
||||
#define S_IWUSR 0200 /* Owner has write permission. Alias S_IWRITE */
|
||||
#define S_IXUSR 0100 /* Owner has execute permission. Alias S_IEXEC */
|
||||
|
||||
#define S_IRWXG 070 /* Mask for group permissions */
|
||||
#define S_IRGRP 040 /* Group has read permission */
|
||||
#define S_IWGRP 020 /* Group has write permission */
|
||||
#define S_IXGRP 010 /* Group has execute permission */
|
||||
|
||||
#define S_IRWXO 07 /* Mask for permissions for others (not in group) */
|
||||
#define S_IROTH 04 /* Others have read permission */
|
||||
#define S_IWOTH 02 /* Others have write permission */
|
||||
#define S_IXOTH 01 /* Others have execute permission */
|
||||
|
||||
#define S_IRWXUGO 00777 /* S_IRWXU|S_IRWXG|S_IRWXO */
|
||||
#define S_IALLUGO 07777 /* S_ISUID|S_ISGID|S_ISVTX|S_IRWXUGO */
|
||||
#define S_IRUGO 00444 /* S_IRUSR|S_IRGRP|S_IROTH */
|
||||
#define S_IWUGO 00222 /* S_IWUSR|S_IWGRP|S_IWOTH */
|
||||
#define S_IXUGO 00111 /* S_IXUSR|S_IXGRP|S_IXOTH */
|
||||
|
||||
/* Structure stat extensions for DOS/Windows file attributes */
|
||||
#define S_IFVOLID 0xF000 /* Volume ID pseudo-file, defined in FAT root dir */
|
||||
#define S_ISVOLID(m) S_ISTYPE(m, S_IFVOLID) /* Test for a FAT volume ID */
|
||||
#define S_HIDDEN 01 /* Reuse permissions bit not used in DOS/Windows */
|
||||
#define S_ARCHIVE 02 /* Reuse permissions bit not used in DOS/Windows */
|
||||
#define S_SYSTEM 04 /* Reuse permissions bit not used in DOS/Windows */
|
||||
#define S_COMPRESSED 010 /* Reuse permissions bit not used in DOS/Windows */
|
||||
#define S_ENCRYPTED 020 /* Reuse permissions bit not used in DOS/Windows */
|
||||
#define S_NOT_CONTENT_INDEXED 040 /* Reuse permissions bit not used in DOS/Windows */
|
||||
#define S_OFFLINE 01000 /* Reuse sticky bit, not used in DOS/Windows */
|
||||
#define S_SPARSE_FILE 02000 /* Reuse GID bit, not used in DOS/Windows */
|
||||
#define S_MOUNT_POINT 04000 /* Reuse UID bit, not used in DOS/Windows */
|
||||
/* #define S_TEMPORARY /* Reuse UID bit, not used in DOS/Windows */
|
||||
/* #define S_VIRTUAL /* No bit left for this one */
|
||||
|
||||
#if defined(_MSDOS)
|
||||
#define _mkdirx(path, mode) _mkdir(path)
|
||||
#elif defined(_WIN32)
|
||||
#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
|
||||
#define _mkdirx(path, mode) mkdirU(path, mode)
|
||||
#else /* _ANSI_SOURCE */
|
||||
#define _mkdirx(path, mode) mkdirA(path, mode)
|
||||
#endif /* defined(_UTF8_SOURCE) */
|
||||
extern int mkdirU(const char *path, mode_t mode);
|
||||
extern int mkdirA(const char *path, mode_t mode);
|
||||
#endif /* defined(_MSDOS) */
|
||||
#define mkdir(path, mode) _mkdirx(path, mode)
|
||||
|
||||
/* Special values for futimens() and utimensat(). Must not be in [0...((10^9)-1)] */
|
||||
#define UTIME_NOW 1000000001
|
||||
#define UTIME_OMIT 1000000002
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* defined(_MSVCLIBX_STAT_H) */
|
||||
|
|
@ -0,0 +1,114 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename sys/time.h *
|
||||
* *
|
||||
* Description DOS/WIN32 port of standard C library's sys/time.h. *
|
||||
* *
|
||||
* Notes MUST be included before any direct or indirect inclusion *
|
||||
* of <windows.h>, as this sys/time.h file has a definition *
|
||||
* of struct timeval conflicting with that in <winsock.h>, *
|
||||
* and as a workaround it defines _WINSOCKAPI_ to prevent *
|
||||
* <windows.h> from loading <winsock.h>. *
|
||||
* *
|
||||
* The same conflict exists with <winsock2.h>, but this one *
|
||||
* is not loaded automatically, and hence should not be *
|
||||
* visible to Unix apps built with the MsvcLibX library. *
|
||||
* *
|
||||
* History *
|
||||
* 2014-02-11 JFL Created this file. *
|
||||
* 2014-05-30 JFL Added the workaround for the conflict with <winsock.h>. *
|
||||
* 2014-06-03 JFL Moved struct timespec definition from sys/stat.h. *
|
||||
* Added macros TIMEVAL_TO_TIMESPEC & TIMESPEC_TO_TIMEVAL. *
|
||||
* 2016-07-06 JFL Avoid error if winsocks2.h has been previously included. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#include <time.h> /* for time_t definition */
|
||||
|
||||
#ifndef _SYS_TIME_H
|
||||
#define _SYS_TIME_H
|
||||
|
||||
#ifdef _MSDOS
|
||||
/* MS-DOS only has a 2-second resolution on file times.
|
||||
Use the existence of macro _STRUCT_TIMEVAL to test if it's possible
|
||||
to use utimes(), else use utime(), which is supported by all OSs */
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/* There's a conflict with the timeval definition in winsock.h, which uses
|
||||
a long instead of a time_t for tv_sec. See:
|
||||
C:\Pgm64\Microsoft SDKs\Windows\v7.0\INCLUDE\winsock.h
|
||||
*/
|
||||
#define _WINSOCKAPI_ /* Prevent the inclusion of winsock.h in windows.h */
|
||||
/* Could also #define WIN32_LEAN_AND_MEAN /* Avoid including many optional Windows features, including winsock.h */
|
||||
|
||||
#include <windows.h> /* For WCHAR */
|
||||
|
||||
#ifndef _STRUCT_TIMEVAL
|
||||
#define _STRUCT_TIMEVAL 1
|
||||
|
||||
#ifndef _WINSOCK2API_ /* Prevent compilation errors if winsocks2.h has been previously included */
|
||||
/* A time value with microsecond precision */
|
||||
struct timeval {
|
||||
time_t tv_sec; /* Seconds */
|
||||
int tv_usec; /* Signed count of microseconds */
|
||||
};
|
||||
#endif /* _WINSOCK2API */
|
||||
|
||||
#endif /* !defined(_STRUCT_TIMEVAL) */
|
||||
|
||||
/* 2015-12-04 JFL Bug fix: With VS14/VC19, the UCRT defines timespec, with a long tv_nsec */
|
||||
#ifndef _UCRT
|
||||
#ifndef _STRUCT_TIMESPEC
|
||||
#define _STRUCT_TIMESPEC
|
||||
|
||||
/* A time value with nanosecond precision */
|
||||
struct timespec {
|
||||
time_t tv_sec; /* Seconds */
|
||||
int tv_nsec; /* Signed count of nanoseconds */
|
||||
};
|
||||
#define _TIMESPEC_DEFINED /* Some packages test this before redefining it */
|
||||
|
||||
#endif /* !defined(_STRUCT_TIMESPEC) */
|
||||
#endif /* !defined(_UCRT) */
|
||||
|
||||
#define TIMEVAL_TO_TIMESPEC(ptv, pts) { \
|
||||
(pts)->tv_sec = (ptv)->tv_sec; \
|
||||
(pts)->tv_nsec = (ptv)->tv_usec * 1000; \
|
||||
}
|
||||
#define TIMESPEC_TO_TIMEVAL(ptv, pts) { \
|
||||
(ptv)->tv_sec = (pts)->tv_sec; \
|
||||
(ptv)->tv_usec = (pts)->tv_nsec / 1000; \
|
||||
}
|
||||
|
||||
/* Change the file access time to tvp[0] and its modification time to tvp[1]. */
|
||||
int utimesA(const char *file, const struct timeval tvp[2]);
|
||||
int utimesU(const char *file, const struct timeval tvp[2]);
|
||||
int utimesW(const WCHAR *file, const struct timeval tvp[2]);
|
||||
|
||||
/* Same as 'utimes', but does not follow symbolic links. */
|
||||
int lutimesA(const char *path, const struct timeval tvp[2]);
|
||||
int lutimesU(const char *path, const struct timeval tvp[2]);
|
||||
int lutimesW(const WCHAR *path, const struct timeval tvp[2]);
|
||||
|
||||
/* Same as 'utimes', but takes an open file descriptor instead of a name. */
|
||||
int futimes(int fd, const struct timeval tvp[2]);
|
||||
|
||||
#if defined(_UTF8_SOURCE) || defined(_BSD_SOURCE) || defined(_GNU_SOURCE)
|
||||
#define utimes utimesU
|
||||
#define lutimes lutimesU
|
||||
#else /* _ANSI_SOURCE */
|
||||
#define utimes utimesA
|
||||
#define lutimes lutimesA
|
||||
#endif
|
||||
|
||||
/* Get the current date and time into a struct timeval */
|
||||
int gettimeofday(struct timeval *ptv, void *pTimeZone);
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
#endif /* !defined(_SYS_TIME_H) */
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: sys/utsname.h *
|
||||
* *
|
||||
* Description: Defines structure utsname and function uname(). *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-05-30 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _SYS_UTSNAME_H
|
||||
#define _SYS_UTSNAME_H 1
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
struct utsname {
|
||||
char *sysname; /* Name of this implementation of the operating system */
|
||||
char *nodename; /* Name of this node on the network */
|
||||
char *release; /* Current release level of this implementation */
|
||||
char *version; /* Current version level of this release */
|
||||
char *machine; /* Name of the hardware type on which the system is running */
|
||||
};
|
||||
|
||||
int uname(struct utsname *);
|
||||
|
||||
#endif /* _SYS_UTSNAME_H */
|
|
@ -0,0 +1,99 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: sys/types.h *
|
||||
* *
|
||||
* Description: Add missing definitions in MSVC's sys/types.h. *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-05-26 JFL Created this file. *
|
||||
* 2014-06-06 JFL Moved mode_t & off*_t definitions here, from sys\stat.h. *
|
||||
* 2015-11-15 JFL Visual Studio 2015 moved this file to the Windows Kit UCRT.
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _MSVCLIBX_SYS_TYPES_H
|
||||
#define _MSVCLIBX_SYS_TYPES_H 1
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#include <sys\types.h> /* Include MSVC's own <sys/types.h> file */
|
||||
|
||||
/************************ MS-DOS-specific definitions ************************/
|
||||
|
||||
#ifdef _MSDOS /* Automatically defined when targeting an MS-DOS application */
|
||||
|
||||
|
||||
|
||||
/* File offset type */
|
||||
/* For now, use the MSVC 32-bits functions in all cases */
|
||||
#define off_t _off_t
|
||||
|
||||
typedef int pid_t; /* The pid is the PSP segment. MSVC's process.h defines it as int. */
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
/************************ Win32-specific definitions *************************/
|
||||
|
||||
#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */
|
||||
|
||||
/* File offset types */
|
||||
#define off64_t __int64 /* Don't use a typedef because MSVC's _fseeki64 doesn't like it */
|
||||
|
||||
#if defined(_FILE_OFFSET_BITS) && (_FILE_OFFSET_BITS == 64)
|
||||
#define off_t off64_t
|
||||
#else
|
||||
#define off_t _off_t
|
||||
#endif
|
||||
|
||||
typedef unsigned long DWORD; /* Don't include <windows.h> to get DWORD definition, as this draws too much,
|
||||
including things we want to override in other parts of MsvcLibX */
|
||||
|
||||
typedef DWORD pid_t; /* Windows defines it as a DWORD */
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
||||
/************************* OS/2-specific definitions *************************/
|
||||
|
||||
#ifdef _OS2 /* Automatically defined when targeting an OS/2 application? */
|
||||
|
||||
/* File offset type */
|
||||
/* For now, use the MSVC 32-bits functions in all cases */
|
||||
#define off_t _off_t
|
||||
|
||||
|
||||
#endif /* defined(_OS2) */
|
||||
|
||||
/********************** End of OS-specific definitions ***********************/
|
||||
|
||||
/* Signed size type */
|
||||
#ifndef _SSIZE_T_DEFINED
|
||||
#if defined(_MSDOS)
|
||||
typedef int ssize_t;
|
||||
#elif defined(_WIN32)
|
||||
#include <stdint.h>
|
||||
#ifdef _WIN64
|
||||
typedef __int64 ssize_t;
|
||||
#else
|
||||
typedef _W64 int ssize_t;
|
||||
#endif /* defined(_WIN64) */
|
||||
#endif /* defined(_WIN32) */
|
||||
#define _SSIZE_T_DEFINED
|
||||
#endif /* !_SSIZE_T_DEFINED */
|
||||
|
||||
/* MsvcLibX handles uid_t and gid_t in pwd.c and grp.c */
|
||||
typedef int gid_t;
|
||||
typedef int uid_t;
|
||||
|
||||
/* MsvcLibX uses mode_t in sys/stat.h */
|
||||
typedef int mode_t;
|
||||
#define HAVE_MODE_T
|
||||
|
||||
/* File link counts type (not used by MsvcLibX so far) */
|
||||
typedef int nlink_t; /* Is short in some Unix versions */
|
||||
|
||||
#endif /* !defined(_MSVCLIBX_SYS_TYPES_H) */
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename GetFileAttributes.c *
|
||||
* *
|
||||
* Description: UTF-8 version of WIN32's GetFileAttributes() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2016-09-12 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */
|
||||
|
||||
#include <windows.h> /* Also includes MsvcLibX' WIN32 UTF-8 extensions */
|
||||
#include "msvcLimits.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: GetFileAttributesU |
|
||||
| |
|
||||
| Description: Get atributes for a UTF-8 path. |
|
||||
| |
|
||||
| Parameters: See WIN32's GetFileAttributes() |
|
||||
| |
|
||||
| Return value: The file attributes flags |
|
||||
| |
|
||||
| Notes: |
|
||||
| |
|
||||
| History: |
|
||||
| 2014-07-02 JFL Created this routine |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
DWORD WINAPI GetFileAttributesU(LPCTSTR lpFileName) {
|
||||
WCHAR *pwszName;
|
||||
DWORD dwAttrs;
|
||||
int n;
|
||||
|
||||
/* Allocate a buffer large enough for any Unicode pathname */
|
||||
pwszName = (void *)LocalAlloc(LMEM_FIXED, UNICODE_PATH_MAX * sizeof(WCHAR));
|
||||
if (!pwszName) return 0;
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
lpFileName, /* lpMultiByteStr, */
|
||||
pwszName, /* lpWideCharStr, */
|
||||
UNICODE_PATH_MAX /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
LocalFree((HLOCAL)pwszName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the file attributes, using the Unicode version of the function */
|
||||
dwAttrs = GetFileAttributesW(pwszName);
|
||||
|
||||
/* Cleanup and return */
|
||||
LocalFree((HLOCAL)pwszName);
|
||||
return dwAttrs;
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename GetFileAttributesEx.c *
|
||||
* *
|
||||
* Description: UTF-8 version of WIN32's GetFileAttributesEx() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2016-09-12 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */
|
||||
|
||||
#include <windows.h> /* Also includes MsvcLibX' WIN32 UTF-8 extensions */
|
||||
#include "msvcLimits.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: GetFileAttributesExU |
|
||||
| |
|
||||
| Description: Get file information for a UTF-8 pathname. |
|
||||
| |
|
||||
| Parameters: See WIN32's GetFileAttributesEx() |
|
||||
| |
|
||||
| Return value: 1 = done, or 0 if error |
|
||||
| |
|
||||
| Notes: Sets the file length, dates, attributes, etc. |
|
||||
| |
|
||||
| History: |
|
||||
| 2016-09-12 JFL Created this routine. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
BOOL WINAPI GetFileAttributesExU(
|
||||
LPCTSTR lpFileName,
|
||||
GET_FILEEX_INFO_LEVELS fInfoLevelId,
|
||||
LPVOID lpFileInformation
|
||||
) {
|
||||
WIN32_FILE_ATTRIBUTE_DATA *lpFileData = lpFileInformation;
|
||||
WCHAR *pwszName;
|
||||
BOOL bDone;
|
||||
int n;
|
||||
|
||||
/* Allocate a buffer large enough for any Unicode pathname */
|
||||
pwszName = (void *)LocalAlloc(LMEM_FIXED, UNICODE_PATH_MAX * sizeof(WCHAR));
|
||||
if (!pwszName) return 0;
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
lpFileName, /* lpMultiByteStr, */
|
||||
pwszName, /* lpWideCharStr, */
|
||||
UNICODE_PATH_MAX /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
LocalFree((HLOCAL)pwszName);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Get the file information, using the Unicode version of the function */
|
||||
bDone = GetFileAttributesExW(pwszName, fInfoLevelId, lpFileData);
|
||||
|
||||
/* Cleanup and return */
|
||||
LocalFree((HLOCAL)pwszName);
|
||||
return bDone;
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename GetFullPathName.c *
|
||||
* *
|
||||
* Description: UTF-8 version of WIN32's GetFullPathName() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2016-09-12 JFL Created this file, from the routine in truename.c. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */
|
||||
|
||||
#include <windows.h> /* Also includes MsvcLibX' WIN32 UTF-8 extensions */
|
||||
#include "msvcLimits.h"
|
||||
#include "msvcDebugm.h" /* MsvcLibX debugging macros */
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: GetFullPathNameU |
|
||||
| |
|
||||
| Description: Get the absolute pathname for a relative UTF-8 path. |
|
||||
| |
|
||||
| Parameters: See WIN32's GetFullPathName() |
|
||||
| |
|
||||
| Return value: The length of the full pathname, or 0 if error |
|
||||
| |
|
||||
| Notes: Warning: Windows' GetFullPathname trims trailing dots and |
|
||||
| spaces from the path. |
|
||||
| This derived function reproduces the bug. |
|
||||
| The caller MUST add trailing dots & spaces back if needed.|
|
||||
| |
|
||||
| History: |
|
||||
| 2014-02-07 JFL Created this routine. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
DWORD WINAPI GetFullPathNameU(LPCTSTR lpName, DWORD nBufferLength, LPTSTR lpBuf, LPTSTR *lpFilePart) {
|
||||
WCHAR wszName[MAX_PATH];
|
||||
WCHAR wszBuf[MAX_PATH];
|
||||
char szName[MAX_PATH*4]; /* Worst case for UTF-8 is 4 bytes/Unicode character */
|
||||
int n;
|
||||
DWORD dwResult;
|
||||
WCHAR *wlpFilePart;
|
||||
|
||||
DEBUG_ENTER(("GetFullPathNameU(\"%s\", %d, %p, %p);\n", lpName, nBufferLength, lpBuf, lpFilePart));
|
||||
|
||||
n = MultiByteToWideChar(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
lpName, /* lpMultiByteStr, */
|
||||
lstrlen(lpName)+1, /* cbMultiByte, */
|
||||
wszName, /* lpWideCharStr, */
|
||||
MAX_PATH /* cchWideChar, */
|
||||
);
|
||||
if (!n) RETURN_INT_COMMENT(0, ("Failed to convert the name to Unicode\n"));
|
||||
|
||||
dwResult = GetFullPathNameW(wszName, MAX_PATH, wszBuf, &wlpFilePart);
|
||||
if (!dwResult) RETURN_INT_COMMENT(0, ("GetFullPathNameW() failed\n"));
|
||||
|
||||
/* nRead = UnicodeToBytes(pwStr, len, buf, bufsize); */
|
||||
n = WideCharToMultiByte(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
wszBuf, /* lpWideCharStr, */
|
||||
(int)dwResult + 1, /* cchWideChar, */
|
||||
lpBuf, /* lpMultiByteStr, */
|
||||
(int)nBufferLength, /* cbMultiByte, */
|
||||
NULL, /* lpDefaultChar, */
|
||||
NULL /* lpUsedDefaultChar */
|
||||
);
|
||||
if (!n) RETURN_INT_COMMENT(0, ("Failed to convert the full name from Unicode\n"));
|
||||
|
||||
if (lpFilePart) { /* Convert the file part, and get the length of the converted string */
|
||||
int m; /* Length of the converted string */
|
||||
m = WideCharToMultiByte(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
wlpFilePart, /* lpWideCharStr, */
|
||||
lstrlenW(wlpFilePart), /* cchWideChar, */
|
||||
szName, /* lpMultiByteStr, */
|
||||
sizeof(szName), /* cbMultiByte, */
|
||||
NULL, /* lpDefaultChar, */
|
||||
NULL /* lpUsedDefaultChar */
|
||||
);
|
||||
/* (n-1) is the length of the full UTF-8 pathname */
|
||||
/* So ((n-1) - m) is the offset of the file part in the full UTF-8 pathname */
|
||||
*lpFilePart = lpBuf + (n - 1) - m;
|
||||
}
|
||||
|
||||
RETURN_INT_COMMENT(n-1, ("\"%s\" \"%s\"\n", lpBuf, lpFilePart?*lpFilePart:"(NULL)"));
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename GetLongPathName.c *
|
||||
* *
|
||||
* Description: UTF-8 version of WIN32's GetLongPathName() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2016-09-12 JFL Created this file, from the routine in truename.c. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */
|
||||
|
||||
#include <windows.h> /* Also includes MsvcLibX' WIN32 UTF-8 extensions */
|
||||
#include "msvcLimits.h"
|
||||
#include "msvcDebugm.h" /* MsvcLibX debugging macros */
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: GetLongPathNameU |
|
||||
| |
|
||||
| Description: Get the long pathname for a short UTF-8 path. |
|
||||
| |
|
||||
| Parameters: See WIN32's GetLongPathName() |
|
||||
| |
|
||||
| Return value: The length of the full pathname, or 0 if error |
|
||||
| |
|
||||
| Notes: |
|
||||
| |
|
||||
| History: |
|
||||
| 2015-12-18 JFL Created this routine. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
DWORD WINAPI GetLongPathNameU(LPCTSTR lpShortName, LPTSTR lpBuf, DWORD nBufferLength) {
|
||||
WCHAR wszShortName[MAX_PATH];
|
||||
WCHAR wszBuf[MAX_PATH];
|
||||
int n;
|
||||
DWORD dwResult;
|
||||
|
||||
DEBUG_ENTER(("GetLongPathNameU(\"%s\", %p, %d);\n", lpShortName, lpBuf, nBufferLength));
|
||||
|
||||
n = MultiByteToWideChar(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
lpShortName, /* lpMultiByteStr, */
|
||||
lstrlen(lpShortName)+1, /* cbMultiByte, */
|
||||
wszShortName, /* lpWideCharStr, */
|
||||
MAX_PATH /* cchWideChar, */
|
||||
);
|
||||
if (!n) RETURN_INT_COMMENT(0, ("Failed to convert the short name to Unicode\n"));
|
||||
|
||||
dwResult = GetLongPathNameW(wszShortName, wszBuf, MAX_PATH);
|
||||
if (!dwResult) RETURN_INT_COMMENT(0, ("GetLongPathNameW() failed\n"));
|
||||
|
||||
/* nRead = UnicodeToBytes(pwStr, len, buf, bufsize); */
|
||||
n = WideCharToMultiByte(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
wszBuf, /* lpWideCharStr, */
|
||||
(int)dwResult + 1, /* cchWideChar, */
|
||||
lpBuf, /* lpMultiByteStr, */
|
||||
(int)nBufferLength, /* cbMultiByte, */
|
||||
NULL, /* lpDefaultChar, */
|
||||
NULL /* lpUsedDefaultChar */
|
||||
);
|
||||
if (!n) RETURN_INT_COMMENT(0, ("Failed to convert the Long name from Unicode\n"));
|
||||
|
||||
RETURN_INT_COMMENT(n-1, ("\"%s\"\n", lpBuf));
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename access.c *
|
||||
* *
|
||||
* Description: WIN32 UTF-8 version of access *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-03-24 JFL Created this module. *
|
||||
* 2014-07-02 JFL Added support for pathnames >= 260 characters. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#include <errno.h>
|
||||
#include <io.h>
|
||||
#include "msvcStdio.h"
|
||||
#include "msvclibx.h"
|
||||
#include "msvcDebugm.h"
|
||||
#include "msvcLimits.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function access |
|
||||
| |
|
||||
| Description UTF-8 version of access |
|
||||
| |
|
||||
| Parameters char *pszName File name |
|
||||
| int iMode Access mode to test |
|
||||
| |
|
||||
| Returns File handle |
|
||||
| |
|
||||
| Notes |
|
||||
| |
|
||||
| History |
|
||||
| 2014-03-24 JFL Created this routine. |
|
||||
| 2014-07-02 JFL Added support for pathnames >= 260 characters. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
int _accessU(const char *pszName, int iMode) {
|
||||
WCHAR wszName[PATH_MAX];
|
||||
int n;
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
pszName, /* lpMultiByteStr, */
|
||||
wszName, /* lpWideCharStr, */
|
||||
COUNTOF(wszName) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return _waccess(wszName, iMode);
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename basename.c *
|
||||
* *
|
||||
* Description Get the file name part of a file pathname *
|
||||
* *
|
||||
* Notes Uses a static buffer in some cases. Not thread safe! *
|
||||
* Posix spec authorizes this, and also authorizes to modify *
|
||||
* the input string, which we do. => Always do an strdup() *
|
||||
* before calling basename(), and call basename(copy). *
|
||||
* *
|
||||
* History *
|
||||
* 2016-09-08 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ 2005 security warnings */
|
||||
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include "msvcStdlib.h"
|
||||
#include "msvcLibgen.h"
|
||||
#include "msvcLimits.h"
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
char *basename(char *pszPathname) {
|
||||
char *pszPath = pszPathname;
|
||||
size_t len;
|
||||
char *pc;
|
||||
char *pc2;
|
||||
|
||||
/* A NULL pathname is assumed to refer to the current directory */
|
||||
if (!pszPathname) return ".";
|
||||
/* Skip the drive if present */
|
||||
len = strlen(pszPathname);
|
||||
if ((len >= 2) && (pszPathname[1] == ':')) {
|
||||
pszPath += 2;
|
||||
len -= 2;
|
||||
}
|
||||
if (!len) return ".";
|
||||
/* Remove trailing path separators */
|
||||
while ((len > 1) && ((pszPath[len-1] == '\\') || (pszPath[len-1] == '/'))) {
|
||||
pszPath[--len] = '\0';
|
||||
}
|
||||
/* Find the beginning of the file name */
|
||||
pc = strrchr(pszPath, '\\');
|
||||
pc2 = strrchr(pszPath, '/');
|
||||
if (pc2 > pc) pc = pc2;
|
||||
if (pc) pc += 1; else pc = pszPath;
|
||||
if (!*pc) return pszPath; /* No file name left. This is the root directory */
|
||||
/* Done */
|
||||
return pc;
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename chdir.c *
|
||||
* *
|
||||
* Description: WIN32 port of standard C library's chdir() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-28 JFL Created this module. *
|
||||
* 2014-07-02 JFL Added support for pathnames >= 260 characters. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */
|
||||
|
||||
/* Microsoft C libraries include files */
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
/* MsvcLibX library extensions */
|
||||
#include "msvcStdio.h"
|
||||
#include "msvcUnistd.h"
|
||||
#include "msvcIconv.h"
|
||||
#include "msvcDebugm.h"
|
||||
#include "msvcLimits.h"
|
||||
#include "sys/msvcTypes.h"
|
||||
|
||||
#if defined(_MSDOS)
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
| *
|
||||
| Function: chdir |
|
||||
| |
|
||||
| Description: Change directory, overcoming the 64-character DOS limit |
|
||||
| |
|
||||
| Parameters: char *pszDir Target directory pathname |
|
||||
| |
|
||||
| Returns: 0=Done; Else OS error code. |
|
||||
| |
|
||||
| Notes: Unfortunately this works only in a DOS box within Win9X. |
|
||||
| |
|
||||
| History: |
|
||||
| 2000-12-04 JFL Initial implementation. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
int chdir(const char *pszDir)
|
||||
{
|
||||
char szBuf[64];
|
||||
char *pszBuf = szBuf;
|
||||
char *pc;
|
||||
int iDirLen;
|
||||
int iStrLen;
|
||||
int iErr = 0;
|
||||
|
||||
iDirLen = strlen(pszDir);
|
||||
/* Copy the drive letter if specified, and leave it ahead of the buffer. */
|
||||
if ((iDirLen>2) && (pszDir[1]==':'))
|
||||
{
|
||||
szBuf[0] = pszDir[0];
|
||||
szBuf[1] = ':';
|
||||
pszDir += 2;
|
||||
pszBuf += 2;
|
||||
}
|
||||
/* Repeat relative moves down the directory tree */
|
||||
while (iDirLen > 60)
|
||||
{
|
||||
pc = strchr(pszDir+45, '\\'); /* There has to be one in segment [45:60]. */
|
||||
iStrLen = pc-pszDir; /* Segment length */
|
||||
strncpy(pszBuf, pszDir, iStrLen); /* Copy until the \ found */
|
||||
pszBuf[iStrLen] = '\0';
|
||||
iErr = chdir(szBuf);
|
||||
if (iErr) return iErr;
|
||||
pszDir += iStrLen+1;
|
||||
iDirLen -= iStrLen+1;
|
||||
} ;
|
||||
|
||||
if (iDirLen)
|
||||
{
|
||||
strcpy(pszBuf, pszDir);
|
||||
iErr = chdir(szBuf);
|
||||
}
|
||||
|
||||
return iErr;
|
||||
}
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: chdir |
|
||||
| |
|
||||
| Description: Set the current directory, encoded in UTF-8 |
|
||||
| |
|
||||
| Parameters: const char *pszDir Target directory pathname |
|
||||
| |
|
||||
| Returns: 0=Done; Else OS error code. |
|
||||
| |
|
||||
| History: |
|
||||
| 2014-02-28 JFL Created this routine |
|
||||
| 2014-07-02 JFL Added support for pathnames >= 260 characters. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
int chdirA(const char *pszDir) {
|
||||
WCHAR wszDir[PATH_MAX];
|
||||
BOOL bDone;
|
||||
int n;
|
||||
DEBUG_PRINTF(("chdir(\"%s\");\n", pszDir));
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(CP_ACP, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
pszDir, /* lpMultiByteStr, */
|
||||
wszDir, /* lpWideCharStr, */
|
||||
COUNTOF(wszDir) /* cchWideChar, */
|
||||
);
|
||||
bDone = SetCurrentDirectoryW(wszDir);
|
||||
if (!bDone) {
|
||||
errno = Win32ErrorToErrno();
|
||||
}
|
||||
return bDone ? 0 : -1;
|
||||
}
|
||||
|
||||
int chdirU(const char *pszDir) {
|
||||
WCHAR wszDir[PATH_MAX];
|
||||
BOOL bDone;
|
||||
int n;
|
||||
DEBUG_PRINTF(("chdir(\"%s\");\n", pszDir));
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
pszDir, /* lpMultiByteStr, */
|
||||
wszDir, /* lpWideCharStr, */
|
||||
COUNTOF(wszDir) /* cchWideChar, */
|
||||
);
|
||||
bDone = SetCurrentDirectoryW(wszDir);
|
||||
if (!bDone) {
|
||||
errno = Win32ErrorToErrno();
|
||||
}
|
||||
return bDone ? 0 : -1;
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: clock_gettime.c *
|
||||
* *
|
||||
* Description: WIN32 port of standard C library's clock_gettime(). *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-06-04 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
|
||||
|
||||
#ifdef _MSDOS
|
||||
|
||||
/* Check for the definition of _STRUCT_TIMESPEC before using clock_gettime().
|
||||
If it's not defined, use time() instead, which is supported by all OSs. */
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN /* Avoid lots of unnecessary inclusions */
|
||||
#include <windows.h>
|
||||
#include "msvcTime.h"
|
||||
#include "sys/msvcStat.h" /* For MsvcLibX's Filetime2Timespec */
|
||||
|
||||
int clock_gettime(clockid_t clock_id, struct timespec *pTS) {
|
||||
FILETIME ft;
|
||||
if (clock_id != CLOCK_REALTIME) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
GetSystemTimeAsFileTime(&ft);
|
||||
Filetime2Timespec(&ft, pTS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
|
@ -0,0 +1,23 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: debugv.c *
|
||||
* *
|
||||
* Description: Define debug variables used by MsvcLibX.lib in debug mode *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2013-03-27 JFL jf.larvoire@hp.com created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#include "msvcDebugm.h"
|
||||
|
||||
#if defined(_DEBUG)
|
||||
|
||||
DEBUG_GLOBALS
|
||||
|
||||
#endif /* !defined(_DEBUG) */
|
||||
|
|
@ -0,0 +1,709 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: dirent.c *
|
||||
* *
|
||||
* Description: DOS/WIN32 port of standard C library's dirent.h functions *
|
||||
* *
|
||||
* Notes: TO DO: Make Wide & MultiByte versions of scandir 4 Windows*
|
||||
* *
|
||||
* There are also remains of an OS/2 implementation here. *
|
||||
* It's not maintained anymore. Left in as a historic *
|
||||
* reference, in the unlikely case somebody needs it. *
|
||||
* *
|
||||
* History: *
|
||||
* 2012-01-09 JFL Created this file, based on dirc and other programs. *
|
||||
* 2012-01-19 JFL Added standard errno management. *
|
||||
* 2012-05-22 JFL Fixed a bug in the DOS version, which failed if the *
|
||||
* directory name was longer than 12 bytes. *
|
||||
* 2012-05-23 JFL Fixed opendir to return errors as per the C lib spec. *
|
||||
* 2013-02-12 JFL Added code to filter reparse points, and keep only *
|
||||
* real junctions and symlinks. *
|
||||
* 2013-02-13 JFL Moved dirent2stat() to lstat.c, as there must actually *
|
||||
* be 4 WIN32 versions, for the four versions of struct stat.*
|
||||
* 2013-02-26 JFL Moved the proprietary file time management routines to *
|
||||
* the new filetime.c module. *
|
||||
* 2014-02-27 JFL Changed the WIN32 output name encoding to UTF-8. *
|
||||
* 2014-03-20 JFL Restructured Windows opendir and readdir functions into *
|
||||
* Wide and MultiByte versions, and changed the Unicode and *
|
||||
* Ansi versions to macros. *
|
||||
* 2014-03-24 JFL Renamed "statx.h" as the standard <sys/stat.h>. *
|
||||
* 2015-12-14 JFL Bug fix: WIN32 readdirW always read the root on "D:". *
|
||||
* Bug fix: DOS opendir failed on root dirs, like "D:\". *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#define _UTF8_SOURCE /* Generate the UTF-8 version of WIN32 printf & scandir */
|
||||
|
||||
#include "msvcDirent.h" /* Include our associated .h, in the same dir as this .c. Do not use <>. */
|
||||
#ifndef _DIRENT_FOR_DOS_WINDOWS
|
||||
#error "This requires MsvcLibX own version of dirent.h for DOS/Windows"
|
||||
#endif
|
||||
/* Microsoft C libraries include files */
|
||||
#include <io.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <errno.h>
|
||||
/* MsvcLibX library extensions */
|
||||
#include "msvcUnistd.h" /* For readlink() */
|
||||
#include "sys/msvcStat.h" /* For Filetime2String() */
|
||||
#include "msvcDebugm.h" /* Use our house debugging framework */
|
||||
#include "msvcLimits.h" /* Use our house debugging framework */
|
||||
|
||||
/*****************************************************************************\
|
||||
* *
|
||||
* MS_DOS Version *
|
||||
* *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifdef _MSDOS
|
||||
|
||||
#define OFFSET_OF(pointer) ((uint16_t)(uint32_t)(void far *)pointer)
|
||||
#define SEGMENT_OF(pointer) ((uint16_t)(((uint32_t)(void far *)pointer) >> 16))
|
||||
|
||||
void put_dta(char *p_dta) { /* Set the MS-DOS Disk Transfer Address */
|
||||
union REGS inreg;
|
||||
union REGS outreg;
|
||||
struct SREGS sregs;
|
||||
|
||||
inreg.h.ah = 0x1a;
|
||||
inreg.x.dx = OFFSET_OF(p_dta);
|
||||
sregs.ds = SEGMENT_OF(p_dta);
|
||||
|
||||
intdosx(&inreg, &outreg, &sregs);
|
||||
}
|
||||
|
||||
#define CF 0x0001 /* Carry flag bit mask */
|
||||
|
||||
int get_file_attributes(const char *name, unsigned *pAttr) { /* Get File Attributes */
|
||||
union REGS inreg;
|
||||
union REGS outreg;
|
||||
struct SREGS sregs;
|
||||
|
||||
inreg.x.ax = 0x4300;
|
||||
inreg.x.dx = OFFSET_OF(name);
|
||||
sregs.ds = SEGMENT_OF(name);
|
||||
|
||||
intdosx(&inreg, &outreg, &sregs);
|
||||
|
||||
if (CF & outreg.x.cflag) {
|
||||
errno = outreg.x.ax;
|
||||
return errno;
|
||||
}
|
||||
|
||||
*pAttr = outreg.x.cx;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Workaround for a VMWare player shared folders bug:
|
||||
DOS function 4e (search next) sometimes returns several times the same entry. */
|
||||
static fileinfo previousFI;
|
||||
#ifdef _DEBUG
|
||||
static int report_workaround(char *s) {
|
||||
DEBUG_PRINTF((s));
|
||||
return 1;
|
||||
}
|
||||
#define REPORT_WORKAROUND(args) report_workaround args
|
||||
#else
|
||||
#define REPORT_WORKAROUND(args) 1
|
||||
#endif
|
||||
|
||||
int srch1st(char *pszFile, uint16_t wAttr, fileinfo *pInfo) { /* Search first matching file */
|
||||
union REGS inreg;
|
||||
union REGS outreg;
|
||||
struct SREGS sregs;
|
||||
|
||||
DEBUG_ENTER(("srch1st(\"%s\", 0x%04X, 0x%p);\n", pszFile, wAttr, pInfo));
|
||||
|
||||
/* Make sure the DTA is assigned before calling DOS functions 4E and 4F */
|
||||
put_dta((char *)pInfo);
|
||||
|
||||
inreg.h.ah = 0x4e;
|
||||
inreg.x.cx = wAttr;
|
||||
inreg.x.dx = OFFSET_OF(pszFile);
|
||||
sregs.ds = SEGMENT_OF(pszFile);
|
||||
|
||||
intdosx(&inreg, &outreg, &sregs);
|
||||
|
||||
if (CF & outreg.x.cflag) {
|
||||
DEBUG_LEAVE(("return %d; // DOS error code\n", outreg.x.ax));
|
||||
return (int)(outreg.x.ax);
|
||||
}
|
||||
|
||||
previousFI = *pInfo; /* Save it for the workaround for the VMWare player bug */
|
||||
|
||||
DEBUG_LEAVE(("return 0; // Success\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
int srchnext(fileinfo *pInfo) { /* Search next matching file */
|
||||
union REGS inreg;
|
||||
union REGS outreg;
|
||||
|
||||
DEBUG_ENTER(("srchnext(0x%p);\n", pInfo));
|
||||
|
||||
/* Make sure the DTA is assigned before calling DOS functions 4E and 4F */
|
||||
put_dta((char *)pInfo);
|
||||
|
||||
inreg.h.ah = 0x4f;
|
||||
|
||||
do {
|
||||
intdos(&inreg, &outreg);
|
||||
|
||||
if (CF & outreg.x.cflag) {
|
||||
DEBUG_LEAVE(("return %d; // DOS error code\n", outreg.x.ax));
|
||||
return(outreg.x.ax);
|
||||
}
|
||||
} while ((!strncmp(previousFI.fiFileName, pInfo->fiFileName, sizeof(previousFI)))
|
||||
&& REPORT_WORKAROUND(("// Skipped one duplicate entry\n")));
|
||||
|
||||
previousFI = *pInfo; /* Save it for the workaround for the VMWare player bug */
|
||||
|
||||
DEBUG_LEAVE(("return 0; // Success\n"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
DIR *opendir(const char *name) { /* Open a directory */
|
||||
DIR *pDir = NULL;
|
||||
size_t lName;
|
||||
unsigned attr;
|
||||
char *pszWildCards = "\\*.*";
|
||||
char *pszCopy;
|
||||
DEBUG_ENTER(("opendir(\"%s\");\n", name));
|
||||
lName = strlen(name);
|
||||
if (lName == 0) {
|
||||
opendir_noent:
|
||||
errno = ENOENT;
|
||||
opendir_failed:
|
||||
if (!_sys_errlist[ENOTDIR][0]) _sys_errlist[ENOTDIR] = "Not a directory"; /* Workaround for the missing entry in MSVC list */
|
||||
if (pDir) free(pDir);
|
||||
DEBUG_LEAVE(("return NULL; // errno=%d - %s\n", errno, strerror(errno)));
|
||||
return NULL;
|
||||
}
|
||||
pDir = (DIR *)malloc(sizeof(DIR) + lName + 5); /* + 5 for wildcards suffix */
|
||||
if (!pDir) goto opendir_failed;
|
||||
/* Work on a copy of the directory name */
|
||||
pszCopy = (char *)(pDir + 1);
|
||||
strcpy(pszCopy, name);
|
||||
/* First change: Except for the root, Remove the trailing \s, which confuses get_file_attributes() */
|
||||
while ((lName > 1) && (name[lName-1] == '\\') && (name[lName-2] != ':')) pszCopy[--lName] = '\0';
|
||||
if (get_file_attributes(pszCopy, &attr)) goto opendir_noent;
|
||||
if (!(attr & _A_SUBDIR)) {
|
||||
errno = ENOTDIR;
|
||||
goto opendir_failed;
|
||||
}
|
||||
if (name[lName-1] == '\\') pszWildCards += 1; /* Avoid duplicating the \ */
|
||||
strcpy(pszCopy+lName, pszWildCards);
|
||||
pDir->first = 1;
|
||||
DEBUG_LEAVE(("return 0x%p;\n", pDir));
|
||||
return pDir;
|
||||
}
|
||||
|
||||
int closedir(DIR *pDir) { /* Close the directory. Return 0 if successful, -1 if not. */
|
||||
DEBUG_PRINTF(("closedir(0x%p);\n", pDir));
|
||||
if (pDir) free(pDir);
|
||||
return 0;
|
||||
}
|
||||
|
||||
_dirent *readdir(DIR *pDir) { /* Read a directory entry. Return pDir, or NULL for EOF or error. */
|
||||
int iErr;
|
||||
_dirent *pDirent = &pDir->sDirent;
|
||||
fileinfo *pFI = (fileinfo *)(pDirent->d_reserved); /* Address of the fileinfo structure embedded there */
|
||||
#ifdef _DEBUG
|
||||
char szTime[40];
|
||||
#endif
|
||||
|
||||
DEBUG_ENTER(("readdir(0x%p);\n", pDir));
|
||||
if (pDir->first) { /* First search */
|
||||
iErr = srch1st((char *)(pDir+1), 0x3F, pFI);
|
||||
pDir->first = 0;
|
||||
} else {
|
||||
iErr = srchnext(pFI);
|
||||
}
|
||||
if (!iErr) {
|
||||
pDirent->d_type = DT_REG; /* A normal file by default */
|
||||
if (pDirent->d_attribs & _A_SUBDIR) pDirent->d_type = DT_DIR; /* Subdirectory */
|
||||
if (pDirent->d_attribs & _A_VOLID) pDirent->d_type = DT_VOLID; /* Volume ID file */
|
||||
DEBUG_LEAVE(("return 0x%p; // %s %02X %10ld %s\n",
|
||||
pDirent,
|
||||
Filetime2String(pDirent->d_date, pDirent->d_time, szTime, sizeof(szTime)),
|
||||
pDirent->d_attribs,
|
||||
pDirent->d_filesize,
|
||||
pDirent->d_name));
|
||||
return &pDir->sDirent;
|
||||
}
|
||||
switch (iErr) { /* Correct a few errors that do not map well to C library errors */
|
||||
case ESRCH: iErr = ENOTDIR; break;
|
||||
case EXDEV: iErr = 0; break; /* End of files is NOT an error */
|
||||
}
|
||||
if (iErr) {
|
||||
errno = iErr; /* MS-DOS' errno.h maps C-library errnos to DOS' errors */
|
||||
DEBUG_LEAVE(("return NULL; // errno=%d - %s\n", errno, strerror(errno)));
|
||||
} else {
|
||||
DEBUG_LEAVE(("return NULL; // End of directory\n"));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
/*****************************************************************************\
|
||||
* *
|
||||
* WIN32 Version *
|
||||
* *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/* Requires including windows.h and especially the kernel section */
|
||||
|
||||
DIR *opendirW(const WCHAR *wszName) { /* Open a directory - Wide char version */
|
||||
DIR *pDir;
|
||||
int err;
|
||||
DWORD dw;
|
||||
DEBUG_CODE(
|
||||
char szUtf8[UTF8_PATH_MAX];
|
||||
)
|
||||
|
||||
DEBUG_WSTR2UTF8(wszName, szUtf8, sizeof(szUtf8));
|
||||
DEBUG_ENTER(("opendir(\"%s\");\n", szUtf8));
|
||||
|
||||
dw = GetFileAttributesW(wszName);
|
||||
err = 0;
|
||||
if (dw == INVALID_FILE_ATTRIBUTES) {
|
||||
err = errno = Win32ErrorToErrno();
|
||||
} else {
|
||||
if (!(dw & _A_SUBDIR)) {
|
||||
err = errno = ENOTDIR;
|
||||
}
|
||||
}
|
||||
if (err) {
|
||||
RETURN_CONST_COMMENT(NULL, ("errno=%d - %s\n", errno, strerror(errno)));
|
||||
}
|
||||
if (lstrlenW(wszName) >= sizeof(pDir->wszDirName)) {
|
||||
errno = ENAMETOOLONG;
|
||||
RETURN_CONST_COMMENT(NULL, ("errno=%d - %s\n", errno, strerror(errno)));
|
||||
}
|
||||
pDir = malloc(sizeof(DIR));
|
||||
if (!pDir) {
|
||||
errno = ENOMEM;
|
||||
RETURN_CONST_COMMENT(NULL, ("errno=%d - %s\n", errno, strerror(errno)));
|
||||
}
|
||||
pDir->hFindFile = INVALID_HANDLE_VALUE;
|
||||
lstrcpyW(pDir->wszDirName, wszName);
|
||||
DEBUG_LEAVE(("return 0x%p; // Success\n", pDir));
|
||||
return pDir;
|
||||
}
|
||||
|
||||
DIR *opendirM(const char *name, UINT cp) { /* Open a directory - MultiByte char version */
|
||||
WCHAR wszName[PATH_MAX];
|
||||
int n;
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
name, /* lpMultiByteStr, */
|
||||
wszName, /* lpWideCharStr, */
|
||||
COUNTOF(wszName) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
DEBUG_PRINTF(("opendirM(\"%s\"); // Can't convert name to Unicode: errno=%d - %s\n", name, errno, strerror(errno)));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return opendirW(wszName);
|
||||
}
|
||||
|
||||
int closedir(DIR *pDir) { /* Close the directory. Return 0 if successful, -1 if not. */
|
||||
DEBUG_PRINTF(("closedir(0x%p);\n", pDir));
|
||||
if (pDir) {
|
||||
if (pDir->hFindFile != INVALID_HANDLE_VALUE) FindClose(pDir->hFindFile);
|
||||
pDir->hFindFile = INVALID_HANDLE_VALUE;
|
||||
free(pDir);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Read a directory entry. Return pDir, or NULL for EOF or error. Wide char version. */
|
||||
_dirent *readdirW(DIR *pDir) {
|
||||
int iErr = 0;
|
||||
_dirent *pDirent = &pDir->sDirent;
|
||||
int bIsJunction = FALSE;
|
||||
int bIsMountPoint = FALSE;
|
||||
DWORD dwTag = 0; /* Reparse points tag */
|
||||
DWORD dwAttr;
|
||||
int n;
|
||||
DEBUG_CODE(
|
||||
char szTime[40];
|
||||
char szUtf8[UTF8_PATH_MAX];
|
||||
)
|
||||
|
||||
DEBUG_ENTER(("readdir(0x%p);\n", pDir));
|
||||
|
||||
if (pDir->hFindFile == INVALID_HANDLE_VALUE) {
|
||||
WCHAR wszPattern[MAX_PATH+5];
|
||||
lstrcpyW(wszPattern, pDir->wszDirName);
|
||||
n = lstrlenW(wszPattern);
|
||||
if (n && (wszPattern[n-1] != L'\\') && (wszPattern[n-1] != L':')) wszPattern[n++] = L'\\';
|
||||
lstrcpyW(wszPattern+n, L"*.*");
|
||||
pDir->hFindFile = FindFirstFileW(wszPattern, &pDir->wfd);
|
||||
if (pDir->hFindFile == INVALID_HANDLE_VALUE) {
|
||||
iErr = Win32ErrorToErrno();
|
||||
if (!iErr) iErr = ENOENT;
|
||||
}
|
||||
} else {
|
||||
iErr = !FindNextFileW(pDir->hFindFile, &pDir->wfd);
|
||||
if (iErr) {
|
||||
iErr = Win32ErrorToErrno();
|
||||
if (!iErr) iErr = ENOENT;
|
||||
}
|
||||
}
|
||||
if (iErr) {
|
||||
switch (iErr) { /* Correct a few errors that do not map well to C library errors */
|
||||
case ESRCH: iErr = ENOTDIR; break;
|
||||
case EXDEV: iErr = 0; break; /* End of files is NOT an error */
|
||||
}
|
||||
if (iErr) {
|
||||
errno = iErr; /* Windows' errno.h maps C-library errnos to Windows' errors */
|
||||
DEBUG_LEAVE(("return NULL; // errno=%d - %s\n", errno, strerror(errno)));
|
||||
} else {
|
||||
DEBUG_LEAVE(("return NULL; // End of directory\n"));
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Set the standard fields */
|
||||
lstrcpyW((WCHAR *)(pDirent->d_name), pDir->wfd.cFileName);
|
||||
dwAttr = pDir->wfd.dwFileAttributes;
|
||||
check_attr_again:
|
||||
if (dwAttr & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||
/* JUNCTIONs and SYMLINKDs both have the FILE_ATTRIBUTE_DIRECTORY flag also set.
|
||||
// Test the FILE_ATTRIBUTE_REPARSE_POINT flag first, to make sure they're seen as symbolic links.
|
||||
//
|
||||
// All symlinks are reparse points, but not all reparse points are symlinks. */
|
||||
dwTag = pDir->wfd.dwReserved0; /* No need to call GetReparseTag(), we got it already. */
|
||||
switch (dwTag) {
|
||||
case IO_REPARSE_TAG_MOUNT_POINT: /* NTFS junction or mount point */
|
||||
{ /* We must read the link to distinguish junctions from mount points. */
|
||||
WCHAR wszPath[PATH_MAX];
|
||||
WCHAR wszBuf[PATH_MAX];
|
||||
ssize_t n = lstrlenW(pDir->wszDirName);
|
||||
if ((n + 1 + lstrlenW(pDir->wfd.cFileName)) >= PATH_MAX) {
|
||||
errno = ENAMETOOLONG; /* DIRNAME\LINKNAME won't fit in wszPath[] */
|
||||
DEBUG_LEAVE(("return NULL; // errno=%d - %s\n", errno, strerror(errno)));
|
||||
}
|
||||
bIsMountPoint = TRUE;
|
||||
lstrcpyW(wszPath, pDir->wszDirName);
|
||||
if (n && (wszPath[n-1] != L'\\')) wszPath[n++] = L'\\';
|
||||
lstrcpyW(wszPath+n, pDir->wfd.cFileName);
|
||||
n = readlinkW(wszPath, wszBuf, COUNTOF(wszBuf));
|
||||
/* Junction targets are absolute pathnames, starting with a drive letter. Ex: C: */
|
||||
/* readlink() fails if the reparse point does not target a valid pathname */
|
||||
if (n < 0) goto this_is_not_a_symlink; /* This is not a junction. */
|
||||
bIsJunction = TRUE; /* Else this is a junction. Fall through to the symlink case. */
|
||||
}
|
||||
case IO_REPARSE_TAG_SYMLINK: /* NTFS symbolic link */
|
||||
pDirent->d_type = DT_LNK; /* Symbolic link */
|
||||
break;
|
||||
default: /* Anything else is definitely not like a Unix symlink */
|
||||
this_is_not_a_symlink:
|
||||
dwAttr &= ~FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
goto check_attr_again;
|
||||
}
|
||||
} else if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
|
||||
pDirent->d_type = DT_DIR; /* Subdirectory */
|
||||
else if (dwAttr & FILE_ATTRIBUTE_DEVICE)
|
||||
pDirent->d_type = DT_CHR; /* Device (we don't know if character or block) */
|
||||
else
|
||||
pDirent->d_type = DT_REG; /* A normal file by default */
|
||||
|
||||
/* Set the OS-specific extensions */
|
||||
lstrcpyW((WCHAR *)(pDirent->d_shortname), pDir->wfd.cAlternateFileName);
|
||||
pDirent->d_attribs = dwAttr;
|
||||
pDirent->d_ReparseTag = dwTag;
|
||||
pDirent->d_CreationTime = pDir->wfd.ftCreationTime;
|
||||
pDirent->d_LastAccessTime = pDir->wfd.ftLastAccessTime;
|
||||
pDirent->d_LastWriteTime = pDir->wfd.ftLastWriteTime;
|
||||
(*(ULARGE_INTEGER *)&(pDirent->d_filesize)).LowPart = pDir->wfd.nFileSizeLow;
|
||||
(*(ULARGE_INTEGER *)&(pDirent->d_filesize)).HighPart = pDir->wfd.nFileSizeHigh;
|
||||
|
||||
DEBUG_WSTR2UTF8((WCHAR *)(pDirent->d_name), szUtf8, sizeof(szUtf8));
|
||||
DEBUG_LEAVE(("return 0x%p; // %s 0x%05X %10lld %s\n",
|
||||
pDirent,
|
||||
Filetime2String(&pDirent->d_LastWriteTime, szTime, sizeof(szTime)),
|
||||
(int)(pDirent->d_attribs),
|
||||
pDirent->d_filesize,
|
||||
szUtf8));
|
||||
return &(pDir->sDirent);
|
||||
}
|
||||
|
||||
/* Read a directory entry. Return pDir, or NULL for EOF or error. MultiByte char version. */
|
||||
_dirent *readdirM(DIR *pDir, UINT cp) {
|
||||
_dirent *pDirent;
|
||||
int n;
|
||||
char *pszDefaultChar;
|
||||
|
||||
pDirent = readdirW(pDir);
|
||||
if (!pDirent) return NULL;
|
||||
|
||||
/* Convert the name field back to MultiByte encoding */
|
||||
pszDefaultChar = (cp == CP_UTF8) ? NULL : "?";
|
||||
n = WideCharToMultiByte(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
pDir->wfd.cFileName, /* lpWideCharStr, */
|
||||
lstrlenW(pDir->wfd.cFileName)+1, /* cchWideChar, */
|
||||
pDirent->d_name, /* lpMultiByteStr, */
|
||||
sizeof(pDirent->d_name), /* cbMultiByte, */
|
||||
pszDefaultChar, /* lpDefaultChar, */
|
||||
NULL /* lpUsedDefaultChar */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
DEBUG_PRINTF(("readdirM(0x%p); // Error converting name back from Unicode. errno=%d - %s\n", pDir, errno, strerror(errno)));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Convert the short name field back to MultiByte encoding */
|
||||
n = WideCharToMultiByte(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
pDir->wfd.cAlternateFileName, /* lpWideCharStr, */
|
||||
lstrlenW(pDir->wfd.cAlternateFileName)+1, /* cchWideChar, */
|
||||
pDirent->d_shortname, /* lpMultiByteStr, */
|
||||
sizeof(pDirent->d_shortname), /* cbMultiByte, */
|
||||
pszDefaultChar, /* lpDefaultChar, */
|
||||
NULL /* lpUsedDefaultChar */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
DEBUG_PRINTF(("readdirM(0x%p); // Error converting short name back from Unicode. errno=%d - %s\n", pDir, errno, strerror(errno)));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pDirent;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************\
|
||||
* *
|
||||
* OS/2 1.x Version *
|
||||
* *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifdef _OS2
|
||||
|
||||
/* Requires including os2.h at the beginning of this file, and before that
|
||||
defining the INCL_DOSFILEMGR constant to enable the necessary section */
|
||||
|
||||
int SetDirent(DIR *pDir) { /* Convert the FILEFINDBUF to a dirent structure */
|
||||
char *pc;
|
||||
_dirent *pDirent = &pDir->sDirent;
|
||||
FILEFINDBUF *pbuf = &pDir->buf;
|
||||
|
||||
pbuf->achName[pbuf->cchName] = '\0';
|
||||
pc = strrchr(pbuf->achName, '\\'); /* Directory separator character */
|
||||
if (!pc)
|
||||
pc = &pbuf->achName[0];
|
||||
else
|
||||
pc += 1; /* Skip the \ */
|
||||
|
||||
pDirent->d_name = malloc(strlen(pc)+1);
|
||||
if (!pDirent->d_name) return ENOMEM;
|
||||
strcpy(pDirent->d_name, pc);
|
||||
pDirent->attribs = pbuf->attrFile;
|
||||
pDirent->d_type = Atype2Dtype(pDirent->attribs);
|
||||
pDirent->time = *(uint16_t *)&pbuf->ftimeLastWrite;
|
||||
pDirent->date = *(uint16_t *)&pbuf->fdateLastWrite;
|
||||
pDirent->filesize = pbuf->cbFile;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int srch1st(char *pszFile, uint8_t bAttrReq, uint8_t bAttrCmp, DIR *pDir) { /* Search first matching file */
|
||||
int n;
|
||||
int err;
|
||||
|
||||
pDir->hDir = -1;
|
||||
|
||||
n = 1; /* Get one file */
|
||||
err = DosFindFirst2(pszFile, &pDir->hDir, bAttrReq & 0x7F, &pDir->buf,
|
||||
sizeof(FILEFINDBUF), &n, FIL_STANDARD, 0L);
|
||||
if (err || !n) return 1;
|
||||
|
||||
return SetDirent(pDir);
|
||||
}
|
||||
|
||||
int srchnext(DIR *pDir) { /* Search next matching file */
|
||||
int n;
|
||||
int err;
|
||||
|
||||
n = 1; /* Get one file */
|
||||
err = DosFindNext(pDir->hDir, &pDir->buf, sizeof(FILEFINDBUF), &n);
|
||||
if (err || !n) return 1;
|
||||
|
||||
return SetDirent(&buf);
|
||||
}
|
||||
|
||||
int srchdone(DIR *pDir) {
|
||||
int err;
|
||||
|
||||
err = DosFindClose(pDir->hDir);
|
||||
pDir->hDir = -1;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
DIR *opendir(const char *name) { /* Open a directory */
|
||||
DIR *pDir;
|
||||
DEBUG_ENTER(("opendir(\"%s\");\n", name));
|
||||
err = _access(name, 0);
|
||||
/* To do: Get the file attributes, and check that it's a directory */
|
||||
if (err) {
|
||||
DEBUG_LEAVE(("return NULL; // errno=%d - %s\n", errno, strerror(errno)));
|
||||
return NULL;
|
||||
}
|
||||
pDir = malloc(sizeof(DIR));
|
||||
if (pDir) {
|
||||
pDir->hDir = -1;
|
||||
pDir->bAttrReq = _A_HIDDEN | _A_SYSTEM | _A_SUBDIR;
|
||||
pDir->bAttrCmp = 0;
|
||||
strcpy(pDir->sDirent.d_name, name);
|
||||
}
|
||||
DEBUG_LEAVE(("return 0x%p;\n", pDir));
|
||||
return pDir;
|
||||
}
|
||||
|
||||
int closedir(DIR *pDir) { /* Close the directory. Return 0 if successful, -1 if not. */
|
||||
DEBUG_PRINTF(("closedir(0x%p);\n", pDir));
|
||||
if (pDir) {
|
||||
srchdone(pDir);
|
||||
free(pDir);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
_dirent *readdir(DIR *pDir) { /* Read a directory entry. Return pDir, or NULL for EOF or error. */
|
||||
int iErr;
|
||||
DEBUG_ENTER(("readdir(0x%p);\n", pDir));
|
||||
if (pDir->hDir == -1) {
|
||||
iErr = srch1st(pDir->sDirent.d_name, pDir->bAttrReq, pDir->bAttrCmp, pDir);
|
||||
} else {
|
||||
iErr = srchnext(pDir);
|
||||
}
|
||||
if (iErr) {
|
||||
DEBUG_LEAVE(("return NULL; // OS/2 found nothing\n",
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEBUG_LEAVE(("return 0x%p; // OS/2 found: %04X %04X %02X %10lld %s\n",
|
||||
&pDir->sDirent
|
||||
(int)(pDirent->time),
|
||||
(int)(pDirent->date),
|
||||
(int)(pDirent->attribs),
|
||||
pDirent->filesize,
|
||||
pDirent->d_name));
|
||||
|
||||
|
||||
return &pDir->sDirent;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/*****************************************************************************\
|
||||
* *
|
||||
* End of OS-specific opendir/readdir/closedir versions *
|
||||
* *
|
||||
\*****************************************************************************/
|
||||
|
||||
/*****************************************************************************\
|
||||
* *
|
||||
* Function: scandir *
|
||||
* *
|
||||
* Description: Select entries in a directory *
|
||||
* *
|
||||
* Arguments: const char *name Directory name *
|
||||
* _dirent ***namelist where to store the result array *
|
||||
* int (*cbSelect)() Selection callback function *
|
||||
* int (*cbCompare)() Comparison function for sorting it *
|
||||
* *
|
||||
* Return value: # of entries in the array, or -1 if error. *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2012-01-11 JFL Initial implementation *
|
||||
* *
|
||||
\*****************************************************************************/
|
||||
|
||||
#pragma warning(disable:4706) /* Ignore the "assignment within conditional expression" warning */
|
||||
int scandir(const char *pszName,
|
||||
_dirent ***resultList,
|
||||
int (*cbSelect) (const _dirent *),
|
||||
int (__cdecl *cbCompare) (const _dirent **,
|
||||
const _dirent **)) {
|
||||
int n = 0;
|
||||
DIR *pDir;
|
||||
_dirent *pDirent;
|
||||
_dirent *pDirent2;
|
||||
_dirent **pList = NULL;
|
||||
_dirent **pList2;
|
||||
|
||||
DEBUG_ENTER(("scandir(\"%s\", 0x%p, 0x%p, 0x%p);\n", pszName, resultList, cbSelect, cbCompare));
|
||||
|
||||
pDir = opendir(pszName);
|
||||
if (!pDir) {
|
||||
DEBUG_LEAVE(("return -1; // errno=%d\n", errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (pDirent = readdir(pDir)) {
|
||||
if (cbSelect && !cbSelect(pDirent)) continue; /* We don't want this one. Continue search. */
|
||||
/* OK, we've selected this one. So append a copy of this _dirent to the list. */
|
||||
n += 1;
|
||||
pList2 = (_dirent **)realloc(pList, n * sizeof(_dirent *));
|
||||
pDirent2 = malloc(sizeof(_dirent));
|
||||
if (!pList2 || !pDirent2) {
|
||||
if (pDirent2) free(pDirent2);
|
||||
for (n-=1; n>0; ) free(pList[--n]);
|
||||
/* errno = ENOMEM; /* Out of memory. Should already be set by malloc failure */
|
||||
DEBUG_LEAVE(("return -1; // errno=%d\n", errno));
|
||||
return -1;
|
||||
}
|
||||
*pDirent2 = *pDirent;
|
||||
pList = pList2;
|
||||
pList[n-1] = pDirent2;
|
||||
}
|
||||
|
||||
closedir(pDir);
|
||||
|
||||
/* 2016-09-23 JFL I don't understand why this warning still fires, so leaving it enabled for now */
|
||||
#ifdef M_I86TM /* This warning appears only when compiling for the DOS tiny memory model ?!? */
|
||||
/* #pragma warning(disable:4220) /* Ignore the "varargs matches remaining parameters" warning */
|
||||
#endif
|
||||
if (cbCompare) qsort(pList, n, sizeof(_dirent *), cbCompare);
|
||||
#ifdef M_I86TM
|
||||
#pragma warning(default:4220) /* Ignore the "varargs matches remaining parameters" warning */
|
||||
#endif
|
||||
*resultList = pList;
|
||||
DEBUG_LEAVE(("return %d;\n", n));
|
||||
return n;
|
||||
}
|
||||
#pragma warning(default:4706)
|
||||
|
||||
int __cdecl alphasort(const _dirent **ppDE1, const _dirent **ppDE2) {
|
||||
int ret;
|
||||
/* Sort names a-la Windows, that is case insensitive */
|
||||
ret = _strnicmp((*ppDE1)->d_name, (*ppDE2)->d_name, NAME_MAX);
|
||||
if (ret) return ret;
|
||||
/* For the remote chance that we're accessing a Unix share */
|
||||
ret = _strnicmp((*ppDE1)->d_name, (*ppDE2)->d_name, NAME_MAX);
|
||||
if (ret) return ret;
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,74 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename dirname.c *
|
||||
* *
|
||||
* Description Get the parent directory name of a file pathname *
|
||||
* *
|
||||
* Notes Uses a static buffer in some cases. Not thread safe! *
|
||||
* Posix spec authorizes this, and also authorizes to modify *
|
||||
* the input string, which we do. => Always do an strdup() *
|
||||
* before calling dirname(), and call dirname(copy). *
|
||||
* *
|
||||
* History *
|
||||
* 2016-09-08 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ 2005 security warnings */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include "msvcLibgen.h"
|
||||
#include "msvcLimits.h"
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
char szLastDriveDirName[4] = "C:.";
|
||||
|
||||
char *dirname(char *pszPathname) {
|
||||
char *pszPath = pszPathname;
|
||||
size_t len;
|
||||
char *pc;
|
||||
char *pc2;
|
||||
|
||||
/* A NULL pathname is assumed to refer to the current directory */
|
||||
if (!pszPathname) return szLastDriveDirName + 2; /* "." */
|
||||
/* Skip the drive if present */
|
||||
len = strlen(pszPathname);
|
||||
if (!len) return szLastDriveDirName + 2; /* "." */
|
||||
if ((len >= 2) && (pszPathname[1] == ':')) {
|
||||
pszPath += 2;
|
||||
len -= 2;
|
||||
if (!len) {
|
||||
szLastDriveDirName[0] = pszPathname[0]; /* Warning: Not thread safe! */
|
||||
return szLastDriveDirName; /* "D:." */
|
||||
}
|
||||
}
|
||||
/* Remove trailing path separators */
|
||||
while ((len > 1) && ((pszPath[len-1] == '\\') || (pszPath[len-1] == '/'))) {
|
||||
pszPath[--len] = '\0';
|
||||
}
|
||||
/* Remove the file name */
|
||||
pc = strrchr(pszPath, '\\');
|
||||
pc2 = strrchr(pszPath, '/');
|
||||
if (pc2 > pc) pc = pc2;
|
||||
if (pc) pc += 1; else pc = pszPath;
|
||||
*pc = '\0';
|
||||
len = pc - pszPath;
|
||||
if (!len) {
|
||||
strcpy(pc, "."); /* Yes, the spec says that the dirname of .. is . */
|
||||
len = 1;
|
||||
}
|
||||
/* Remove trailing path separators */
|
||||
while ((len > 1) && ((pszPath[len-1] == '\\') || (pszPath[len-1] == '/'))) {
|
||||
pszPath[--len] = '\0';
|
||||
}
|
||||
/* Done */
|
||||
return pszPathname;
|
||||
}
|
|
@ -0,0 +1,120 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename err2errno.c *
|
||||
* *
|
||||
* Description: Convert a WIN32 error to a Unix errno *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-17 JFL Created this module. *
|
||||
* 2016-10-05 JFL Fixed compatibility with Visual Studio 2003 and older. *
|
||||
* Removed a few useless special cases, and added EZERO case.*
|
||||
* Make sure the global errno is _not_ changed by this funct.*
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* Microsoft C libraries include files */
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
/* MsvcLibX library extensions */
|
||||
#include "msvcDebugm.h"
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: Win32ErrorToErrno |
|
||||
| |
|
||||
| Description: Convert a Win32 system error code to a Posix errno |
|
||||
| |
|
||||
| Parameters: DWORD dwError The Win32 error code |
|
||||
| |
|
||||
| Returns: The corresponding Posix errno |
|
||||
| |
|
||||
| Notes: There's no 1-to-1 correspondance between Windows and |
|
||||
| Posix errors. This routine attempts to convert codes for |
|
||||
| the most likely errors for MsvcLibX. |
|
||||
| Please add those you encounter, that end up in the |
|
||||
| default category, and incorrectly return EIO by default. |
|
||||
| |
|
||||
| Does not change errno. (Contrary to _dosmaperr, etc) |
|
||||
| You must set errno thereafter if desired. |
|
||||
| |
|
||||
| History: |
|
||||
| 2014-02-05 JFL Created this routine |
|
||||
| 2014-03-05 JFL Added the default call to _get_errno_from_oserr(). |
|
||||
| 2015-12-07 JFL Use the new error conversion routine name in the UCRT. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#if defined(_UCRT) /* Visual Studio 14 and later */
|
||||
#define _get_errno_from_oserr __acrt_errno_from_os_error /* The name changed in the UCRT */
|
||||
#endif
|
||||
|
||||
#if (_MSC_VER < 1400) /* Anything older than Visual Studio 8 (= VS 2003 and older) */
|
||||
#pragma message("Defining our own _get_errno_from_oserr()")
|
||||
extern void __cdecl _dosmaperr(unsigned long);
|
||||
int _get_errno_from_oserr(unsigned long dwErr) {
|
||||
_dosmaperr(dwErr); /* Sets errno from WIN32 error */
|
||||
return errno;
|
||||
}
|
||||
#else
|
||||
/* Equivalent function in MSVC library. Does not know about symlink errors. */
|
||||
extern int __cdecl _get_errno_from_oserr(unsigned long oserrno);
|
||||
#endif
|
||||
|
||||
int Win32ErrorToErrno() {
|
||||
DWORD dwError = GetLastError();
|
||||
|
||||
DEBUG_CODE({
|
||||
LPVOID lpMsgBuf;
|
||||
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
|
||||
NULL, dwError, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
|
||||
(LPTSTR)&lpMsgBuf, 0, NULL);
|
||||
DEBUG_PRINTF(("// Win32 error %d (0x%X): %s", dwError, dwError, lpMsgBuf ? lpMsgBuf : "Unknown\n"));
|
||||
LocalFree( lpMsgBuf );
|
||||
});
|
||||
|
||||
switch (dwError) {
|
||||
case ERROR_SUCCESS:
|
||||
return 0;
|
||||
case ERROR_PRIVILEGE_NOT_HELD: /* Not running with the SE_CREATE_SYMBOLIC_LINK_NAME privilege */
|
||||
case ERROR_REPARSE_ATTRIBUTE_CONFLICT:
|
||||
return EACCES;
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
return E2BIG;
|
||||
case ERROR_FILE_EXISTS:
|
||||
case ERROR_ALREADY_EXISTS:
|
||||
return EEXIST;
|
||||
case ERROR_WRITE_PROTECT:
|
||||
return EROFS;
|
||||
case ERROR_HANDLE_DISK_FULL:
|
||||
return ENOSPC;
|
||||
case ERROR_NOT_A_REPARSE_POINT:
|
||||
case ERROR_REPARSE_TAG_MISMATCH:
|
||||
case ERROR_INVALID_FLAGS:
|
||||
case ERROR_INVALID_PARAMETER:
|
||||
return EINVAL;
|
||||
case ERROR_INVALID_REPARSE_DATA:
|
||||
case ERROR_REPARSE_TAG_INVALID:
|
||||
return EBADF; /* Not supposed to happen in Posix OSs, but may happen when experimenting with junction() IOCTLs. */
|
||||
case ERROR_NO_UNICODE_TRANSLATION:
|
||||
return EILSEQ;
|
||||
default: {
|
||||
int errno0, errno1;
|
||||
errno0 = errno; /* Preserve the initial errno */
|
||||
errno1 = _get_errno_from_oserr(dwError); /* Let MSVC library decide. May change errno. */
|
||||
errno = errno0; /* Restore the initial errno */
|
||||
return errno1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename filetime.c *
|
||||
* *
|
||||
* Description: MsvcLibX internal routines for managing file times *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-26 JFL Created this module. *
|
||||
* 2014-03-24 JFL Renamed "statx.h" as the standard <sys/stat.h>. *
|
||||
* 2014-07-03 JFL Filetime2String: Output time with <EFBFBD>s precision if possib. *
|
||||
* 2016-09-13 JFL Fixed a warning. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#include "msvcTime.h" /* Define time_t */
|
||||
#include "sys/msvcStat.h"
|
||||
|
||||
#ifdef _MSDOS
|
||||
|
||||
/*
|
||||
Convert a DOS date/time to a Unix time_t
|
||||
DOS dates start from January 1, 1980. DOS times have a 2-second resolution.
|
||||
A Unix time_t is the number of 1-second intervals since January 1, 1970.
|
||||
time_ts are expressed in the GMT time zone. DOS times in the current local time.
|
||||
*/
|
||||
time_t Filetime2Timet(uint16_t date, uint16_t time) {
|
||||
unsigned int year, month, day, hour, minute, second;
|
||||
struct tm stm;
|
||||
|
||||
/* Decode fields */
|
||||
year = 1980 + ((date & 0xFE00) >> 9);
|
||||
month = (date & 0x1E0) >> 5;
|
||||
day = date & 0x1F;
|
||||
hour = (time & 0xF800) >> 11;
|
||||
minute = (time & 0x7E0) >> 5;
|
||||
second = 2 * (time & 0x1F);
|
||||
|
||||
stm.tm_year = (int)year - 1900;
|
||||
stm.tm_mon = (int)month - 1;
|
||||
stm.tm_mday = (int)day;
|
||||
stm.tm_hour = (int)hour;
|
||||
stm.tm_min = (int)minute;
|
||||
stm.tm_sec = (int)second;
|
||||
stm.tm_isdst = -1; /* Let mktime decide if DST is in effect or not */
|
||||
|
||||
return mktime(&stm);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* Older version of the same, trying to generate the time_t manually.
|
||||
Did not handle DST well */
|
||||
time_t Filetime2Timet(uint16_t date, uint16_t time) {
|
||||
unsigned int year, month, day, hour, minute, second;
|
||||
unsigned int olympiads; /* 4-year periods */
|
||||
unsigned long t = 0;
|
||||
|
||||
/* Decode fields */
|
||||
year = 1980 + ((date & 0xFE00) >> 9);
|
||||
month = (date & 0x1E0) >> 5;
|
||||
day = date & 0x1F;
|
||||
hour = (time & 0xF800) >> 11;
|
||||
minute = (time & 0x7E0) >> 5;
|
||||
second = 2 * (time & 0x1F);
|
||||
|
||||
/* Count days */
|
||||
year -= 1970; /* Start of Unix time_t epoch */
|
||||
olympiads = year / 4;
|
||||
year = year % 4;
|
||||
t = olympiads * (365 + 365 + 366 + 365);
|
||||
switch (year) {
|
||||
case 3: t += 366;
|
||||
case 2: t += 365;
|
||||
case 1: t += 365;
|
||||
}
|
||||
switch (month) {
|
||||
case 12: t += 30;
|
||||
case 11: t += 31;
|
||||
case 10: t += 30;
|
||||
case 9: t += 31;
|
||||
case 8: t += 31;
|
||||
case 7: t += 30;
|
||||
case 6: t += 31;
|
||||
case 5: t += 30;
|
||||
case 4: t += 31;
|
||||
case 3: t += (year == 2) ? 29 : 28;
|
||||
case 2: t += 31;
|
||||
}
|
||||
t += day-1;
|
||||
|
||||
/* Count seconds */
|
||||
t *= 24;
|
||||
t += hour;
|
||||
t *= 60;
|
||||
t += minute;
|
||||
t *= 60;
|
||||
t += second;
|
||||
|
||||
/* Correct for the timezone (As DOS returns local times, but time_t is UTC-based) */
|
||||
t += timezone;
|
||||
|
||||
/* Still need correction for DST */
|
||||
|
||||
return (time_t)t;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Generate a string with the local file time, in the ISO 8601 date/time format */
|
||||
char *Filetime2String(uint16_t date, uint16_t time, char *pBuf, size_t nBufSize) {
|
||||
unsigned int year, month, day, hour, minute, second;
|
||||
|
||||
/* Decode fields */
|
||||
year = 1980 + ((date & 0xFE00) >> 9);
|
||||
month = (date & 0x1E0) >> 5;
|
||||
day = date & 0x1F;
|
||||
hour = (time & 0xF800) >> 11;
|
||||
minute = (time & 0x7E0) >> 5;
|
||||
second = 2 * (time & 0x1F);
|
||||
|
||||
if (nBufSize >= 20) {
|
||||
sprintf(pBuf, "%04d-%02d-%02d %02d:%02d:%02d", year, month, day, hour, minute, second);
|
||||
} else {
|
||||
return "Buffer too small";
|
||||
}
|
||||
return pBuf;
|
||||
}
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: LocalFileTime |
|
||||
| |
|
||||
| Description: Convert a file GMT time to the local struct tm to display |
|
||||
| |
|
||||
| Parameters: const time_t *t The file GMT time_t |
|
||||
| |
|
||||
| Returns: struct tm * |
|
||||
| |
|
||||
| Notes: This routine is a replacement for Posix' localtime(), |
|
||||
| using Windows' specific algorithm for generating local |
|
||||
| file times. |
|
||||
| |
|
||||
| Windows displays file times based on the current |
|
||||
| difference between the local time and GMT. |
|
||||
| Linux displays file times as the local time when the |
|
||||
| the file was created. |
|
||||
| The two times shown may be different if DST was different |
|
||||
| then and now. (Ex: Displaying in winter the date/time of |
|
||||
| a file created the previous summer.) |
|
||||
| The advantage of Windows' method is that apparent |
|
||||
| relative times will always be correct, even for files |
|
||||
| created around the winter/summer time transitions. |
|
||||
| The advantage of Linux method is that the time displayed |
|
||||
| for a file never changes. The drawback is that files |
|
||||
| created 1 hour apart around the Winter/summer time |
|
||||
| transition may be shown with the exact same time. |
|
||||
| |
|
||||
| History: |
|
||||
| 2014-02-26 JFL Created this routine |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
Convert a Windows FILETIME to a Unix time_t.
|
||||
A FILETIME is the number of 100-nanosecond intervals since January 1, 1601.
|
||||
A time_t is the number of 1-second intervals since January 1, 1970.
|
||||
Both Windows and Linux file times are expressed in the GMT time zone.
|
||||
*/
|
||||
time_t Filetime2Timet(const FILETIME *pFT) {
|
||||
ULARGE_INTEGER ull;
|
||||
ull.LowPart = pFT->dwLowDateTime;
|
||||
ull.HighPart = pFT->dwHighDateTime;
|
||||
return ull.QuadPart / 10000000ULL - 11644473600ULL;
|
||||
}
|
||||
|
||||
/* Convert a Unix time_t to a Windows FILETIME */
|
||||
void Timet2Filetime(time_t t, FILETIME *pFT) {
|
||||
ULARGE_INTEGER ull;
|
||||
ull.QuadPart = (t * 10000000ULL) + 116444736000000000ULL;
|
||||
pFT->dwLowDateTime = ull.LowPart;
|
||||
pFT->dwHighDateTime = ull.HighPart;
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
Convert a Windows FILETIME to a Unix struct timespec.
|
||||
A FILETIME is the number of 100-nanosecond intervals since January 1, 1601.
|
||||
A struct timespec contains a time_t and a number of nanoseconds.
|
||||
Both Windows and Linux file times are expressed in the GMT time zone.
|
||||
*/
|
||||
void Filetime2Timespec(const FILETIME *pFT, struct timespec *pTS) {
|
||||
ULARGE_INTEGER ull;
|
||||
ull.LowPart = pFT->dwLowDateTime;
|
||||
ull.HighPart = pFT->dwHighDateTime;
|
||||
pTS->tv_sec = (time_t)(ull.QuadPart / 10000000ULL - 11644473600ULL);
|
||||
pTS->tv_nsec = (int)(ull.QuadPart % 10000000ULL) * 100;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Convert a Unix time_t to a Windows FILETIME */
|
||||
void Timespec2Filetime(const struct timespec *pTS, FILETIME *pFT) {
|
||||
ULARGE_INTEGER ull;
|
||||
ull.QuadPart = (pTS->tv_sec * 10000000ULL) + 116444736000000000ULL + (pTS->tv_nsec / 100);
|
||||
pFT->dwLowDateTime = ull.LowPart;
|
||||
pFT->dwHighDateTime = ull.HighPart;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Convert a file GMT time to a struct tm with the local time to display */
|
||||
struct tm *LocalFileTime(const time_t *pt) {
|
||||
FILETIME ft, lft;
|
||||
time_t lt;
|
||||
|
||||
Timet2Filetime(*pt, &ft);
|
||||
FileTimeToLocalFileTime(&ft, &lft);
|
||||
lt = Filetime2Timet(&lft);
|
||||
return gmtime(<);
|
||||
}
|
||||
|
||||
/* Generate a string with the local file time, in the ISO 8601 date/time format */
|
||||
/* 2014-07-03 Output time with <20>s precision if possible */
|
||||
char *Filetime2String(const FILETIME *pFT, char *pBuf, size_t nBufSize) {
|
||||
FILETIME lft;
|
||||
SYSTEMTIME sTime;
|
||||
|
||||
FileTimeToLocalFileTime(pFT, &lft);
|
||||
FileTimeToSystemTime(&lft, &sTime);
|
||||
if (nBufSize >= 20) {
|
||||
wsprintf(pBuf, "%04d-%02d-%02d %02d:%02d:%02d", sTime.wYear, sTime.wMonth, sTime.wDay,
|
||||
sTime.wHour, sTime.wMinute, sTime.wSecond);
|
||||
if (nBufSize >= 27) {
|
||||
ULARGE_INTEGER uli;
|
||||
int iFraction; /* Fraction of a second */
|
||||
uli.LowPart = lft.dwLowDateTime;
|
||||
uli.HighPart = lft.dwHighDateTime;
|
||||
iFraction = (int)(uli.QuadPart % 10000000); /* FILETIME has 100ns resolution */
|
||||
iFraction /= 10; /* Convert 100ns resolution to 1<>s resolution */
|
||||
wsprintf(pBuf+19, ".%06d", iFraction);
|
||||
} else if (nBufSize >= 24) {
|
||||
wsprintf(pBuf+19, ".%03d", sTime.wMilliseconds);
|
||||
}
|
||||
} else {
|
||||
return NULL; /* Buffer too small */
|
||||
}
|
||||
return pBuf;
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,124 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: fnmatch.c *
|
||||
* *
|
||||
* Description: DOS/WIN32 port of standard C library's fnmatch() *
|
||||
* *
|
||||
* Notes: TO DO: Manage FNM_PATHNAME, FNM_PERIOD, FNM_LEADING_DIR. *
|
||||
* *
|
||||
* History: *
|
||||
* 2012-01-17 JFL Created this file. *
|
||||
* 2013-03-10 JFL In DOS/Windows, the pattern "*.*" actually means "*". *
|
||||
* 2014-02-13 JFL Removed warnings. *
|
||||
* 2014-02-14 JFL In DOS/Windows, the pattern "*." means no extension. *
|
||||
* 2014-02-17 JFL Wildcards match the empty string. *
|
||||
* 2014-02-20 JFL Fixed "*." pattern matching. *
|
||||
* 2014-02-28 JFL Added support for UTF-8 pathnames. *
|
||||
* 2014-03-05 JFL In debug mode, hide recursive calls. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
|
||||
#include "msvcFnmatch.h" /* Include our associated .h, in the same dir as this .c. Do not use <>. */
|
||||
#include "msvcDebugm.h"
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#pragma warning(disable:4706) /* Ignore the "assignment within conditional expression" warning */
|
||||
int fnmatch(const char *pszPattern, const char *pszName, int iFlags) {
|
||||
char cp, cn;
|
||||
size_t l;
|
||||
const char *pc;
|
||||
int iErr;
|
||||
DEBUG_CODE(
|
||||
int iHideRecursions = FALSE;
|
||||
)
|
||||
|
||||
DEBUG_ENTER(("fnmatch(\"%s\", \"%s\", 0x%x);\n", pszPattern, pszName, iFlags));
|
||||
|
||||
DEBUG_CODE(if(DEBUG_IS_ON() && !XDEBUG_IS_ON()) iHideRecursions = TRUE;)
|
||||
|
||||
/* Special case in DOS/Windows: "*.*" will actually match any name, even without a dot */
|
||||
if (!strcmp(pszPattern, "*.*")) pszPattern = "*";
|
||||
|
||||
/* Special case in DOS/Windows: "anything." means anything without extension */
|
||||
l = strlen(pszPattern);
|
||||
if (l && (pszPattern[l-1] == '.')) {
|
||||
int i;
|
||||
int lName = (int)strlen(pszName);
|
||||
/* First eliminate the case of forbidden extensions <==> A '.' anywhere before the last character */
|
||||
for (i=0; i<(lName-1); i++) { /* Search for a '.' in the name */
|
||||
if (pszName[i] == '.') RETURN_CONST_COMMENT(FNM_NOMATCH, ("Forbidden extension found\n"));
|
||||
}
|
||||
/* If the name doesn't end with a dot, Remove the pattern's trailing '.' */
|
||||
if (lName && (pszName[lName-1] != '.')) {
|
||||
char *pszPattern2;
|
||||
pszPattern2 = _strdup(pszPattern);
|
||||
pszPattern2[--l] = '\0';
|
||||
/* Recursively do the pattern matching with the new pattern */
|
||||
DEBUG_CODE(if (iHideRecursions) iDebug -= 1;)
|
||||
iErr = fnmatch(pszPattern2, pszName, iFlags);
|
||||
DEBUG_CODE(if (iHideRecursions) iDebug += 1;)
|
||||
free(pszPattern2);
|
||||
RETURN_INT(iErr);
|
||||
}
|
||||
}
|
||||
|
||||
for ( ; (cp = *pszPattern) && (cn = *pszName); pszPattern++, pszName++) {
|
||||
XDEBUG_PRINTF(("// cp='%c' cn='%c'\n", cp, cn));
|
||||
switch (cp) {
|
||||
case '?':
|
||||
if (cn == '.') RETURN_CONST_COMMENT(FNM_NOMATCH, ("? does not match a .\n"));
|
||||
break; /* Anything else matches. Continue analysing the pattern. */
|
||||
case '*':
|
||||
cp = *(++pszPattern);
|
||||
if (!cp) RETURN_CONST_COMMENT(FNM_MATCH, ("'*' matches whatever remains in the string\n"));
|
||||
for ( ; cn = *pszName; pszName++) {
|
||||
DEBUG_CODE(if (iHideRecursions) iDebug -= 1;)
|
||||
iErr = fnmatch(pszPattern, pszName, iFlags);
|
||||
DEBUG_CODE(if (iHideRecursions) iDebug += 1;)
|
||||
if (iErr == FNM_MATCH) RETURN_CONST(FNM_MATCH);
|
||||
}
|
||||
RETURN_CONST_COMMENT(FNM_NOMATCH, ("No tail string matches the remainder of the pattern\n"));
|
||||
default:
|
||||
if (iFlags & FNM_CASEFOLD) {
|
||||
cp = (char)toupper(cp);
|
||||
cn = (char)toupper(cn);
|
||||
}
|
||||
if (cp != cn) RETURN_CONST_COMMENT(FNM_NOMATCH, ("Character mismatch\n"));
|
||||
break; /* The character matches. Continue analysing the pattern. */
|
||||
}
|
||||
}
|
||||
/* '*' and '?' match the empty string */
|
||||
if (*pszPattern && !*pszName) {
|
||||
int bOnlyWildCards = TRUE;
|
||||
for (pc=pszPattern; cp=*pc; pc++) {
|
||||
if ((cp != '*') && (cp != '?')) {
|
||||
bOnlyWildCards = FALSE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (bOnlyWildCards) {
|
||||
RETURN_CONST_COMMENT(FNM_MATCH, ("WildCards match the empty string\n"));
|
||||
}
|
||||
}
|
||||
|
||||
/* Special case in DOS/Windows: trailing dot allowed in pattern */
|
||||
if ((*pszPattern == '.') && (!*(pszPattern+1)) && (!*pszName)) RETURN_CONST_COMMENT(FNM_MATCH, ("trailing dot matches empty string\n"));
|
||||
|
||||
if (*pszPattern || *pszName) RETURN_CONST_COMMENT(FNM_NOMATCH, ("Something remains that did not match\n"));
|
||||
|
||||
RETURN_CONST_COMMENT(FNM_MATCH, ("Complete match\n"));
|
||||
}
|
||||
#pragma warning(default:4706)
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename fstat.c *
|
||||
* *
|
||||
* Description: Redefinitions of standard C library's fstat() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-06-24 JFL Created this module. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */
|
||||
|
||||
/* Microsoft C libraries include files */
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
/* MsvcLibX library extensions */
|
||||
#include "sys/msvcStat.h"
|
||||
#include "msvcDebugm.h"
|
||||
|
||||
|
||||
#if defined(_MSDOS)
|
||||
|
||||
/* Nothing needs to be redefined */
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
/* ------------ Display the *stat* macro values at compile time ------------ */
|
||||
|
||||
#pragma message(MACRODEF(_MSVC_stat))
|
||||
#pragma message(MACRODEF(_MSVC_fstat))
|
||||
#pragma message(MACRODEF(_MSVC_lstat))
|
||||
#pragma message(MACRODEF(_MSVC_stat64))
|
||||
|
||||
#if _MSVCLIBX_STAT_DEFINED
|
||||
#pragma message(MACRODEF(_LIBX_stat))
|
||||
#pragma message(MACRODEF(_LIBX_stat64))
|
||||
#endif
|
||||
|
||||
#pragma message(MACRODEF(stat))
|
||||
#pragma message(MACRODEF(fstat))
|
||||
#pragma message(MACRODEF(lstat))
|
||||
|
||||
#if defined(_LARGEFILE_SOURCE64)
|
||||
#pragma message(MACRODEF(stat64))
|
||||
#pragma message(MACRODEF(fstat64))
|
||||
#pragma message(MACRODEF(lstat64))
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: fstat |
|
||||
| |
|
||||
| Description: Redefine the standard _fstatXY() functions |
|
||||
| |
|
||||
| Parameters: int nFile The file handle |
|
||||
| struct stat *buf Output buffer |
|
||||
| |
|
||||
| Returns: 0 = Success, -1 = Failure |
|
||||
| |
|
||||
| Notes: See sys/stat.h for a description of how the stat and fstat|
|
||||
| macros work. |
|
||||
| |
|
||||
| History: |
|
||||
| 2014-06-24 JFL Created this routine |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
int fstat(int nFile, struct stat *pStat) {
|
||||
int iErr;
|
||||
struct _MSVC_stat msStat;
|
||||
DEBUG_CODE(
|
||||
struct tm *pTime;
|
||||
char szTime[100];
|
||||
)
|
||||
|
||||
DEBUG_ENTER((STRINGIZE(fstat) "(%d, 0x%p);\n", nFile, pStat));
|
||||
|
||||
iErr = _MSVC_fstat(nFile, &msStat);
|
||||
if (!iErr) {
|
||||
ZeroMemory(pStat, sizeof(struct stat));
|
||||
pStat->st_mode = msStat.st_mode;
|
||||
pStat->st_size = msStat.st_size;
|
||||
pStat->st_ctime =
|
||||
#undef st_ctime
|
||||
msStat.st_ctime;
|
||||
pStat->st_mtime =
|
||||
#undef st_mtime
|
||||
msStat.st_mtime;
|
||||
pStat->st_atime =
|
||||
#undef st_atime
|
||||
msStat.st_atime;
|
||||
DEBUG_CODE(
|
||||
pTime = LocalFileTime(&(msStat.st_mtime));
|
||||
strftime(szTime, sizeof(szTime), "%Y-%m-%d %H:%M:%S", pTime);
|
||||
)
|
||||
RETURN_INT_COMMENT(0, ("%s mode = 0x%04X size = %I64d bytes\n", szTime, pStat->st_mode, (__int64)(pStat->st_size)));
|
||||
}
|
||||
/* TO DO: Get the nanosecond time resolution using Windows functions */
|
||||
|
||||
RETURN_INT_COMMENT(iErr, ("%s\n", strerror(errno)));
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename fstat64.c *
|
||||
* *
|
||||
* Description: Redefinitions of standard C library's fstat64() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-06-24 JFL Created this module. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* st_*time is 64-bits __time64_t & st_size is 64-bits __off64_t */
|
||||
|
||||
#undef _USE_32BIT_TIME_T
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include "fstat.c"
|
|
@ -0,0 +1,21 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename fstat64i32.c *
|
||||
* *
|
||||
* Description: Redefinitions of standard C library's fstat64i32() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-06-24 JFL Created this module. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* st_*time is 64-bits __time64_t & st_size is 32-bits __off32_t */
|
||||
|
||||
#undef _USE_32BIT_TIME_T
|
||||
#define _FILE_OFFSET_BITS 32
|
||||
|
||||
#include "fstat.c"
|
|
@ -0,0 +1,68 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename fullpath.c *
|
||||
* *
|
||||
* Description Get the absolute pathname for a relative UTF-8 path *
|
||||
* *
|
||||
* Notes *
|
||||
* *
|
||||
* History *
|
||||
* 2016-09-13 JFL Created this module with routine from truename.c. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <malloc.h>
|
||||
#include "msvcLimits.h"
|
||||
|
||||
#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */
|
||||
|
||||
#include "msvcWindows.h" /* Also includes MsvcLibX' WIN32 UTF-8 extensions */
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: _fullpathU |
|
||||
| |
|
||||
| Description: Get the absolute pathname for a relative UTF-8 path |
|
||||
| |
|
||||
| Parameters: See MSVC's _fullpath() in stdlib.h |
|
||||
| |
|
||||
| Return value: Pointer to the full pathname, or NULL if error |
|
||||
| |
|
||||
| Notes: Warning: Windows' GetFullPathname and MSVC's _fullpath |
|
||||
| trim trailing dots and spaces from the path. |
|
||||
| This derived function reproduces the bug. |
|
||||
| The caller MUST add trailing dots & spaces back if needed.|
|
||||
| |
|
||||
| History: |
|
||||
| 2014-03-25 JFL Created this routine. |
|
||||
| 2017-01-30 JFL Fixed bug when the output buffer is allocated here. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
char *_fullpathU(char *absPath, const char *relPath, size_t maxLength) {
|
||||
char *absPath0 = absPath;
|
||||
DWORD n;
|
||||
if (!absPath) { /* Then allocate a buffer for the output string */
|
||||
maxLength = UTF8_PATH_MAX;
|
||||
absPath = malloc(maxLength); /* Worst case for UTF-8 is 4 bytes/Unicode character */
|
||||
if (!absPath) return NULL;
|
||||
}
|
||||
n = GetFullPathNameU(relPath, (DWORD)maxLength, absPath, NULL);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
if (!absPath0) free(absPath);
|
||||
return NULL;
|
||||
}
|
||||
if (!absPath0) absPath = realloc(absPath, strlen(absPath) + 1);
|
||||
return absPath;
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename getcwd.c *
|
||||
* *
|
||||
* Description: WIN32 port of standard C library's getcwd() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-28 JFL Created this module. *
|
||||
* 2014-07-02 JFL Added support for pathnames >= 260 characters. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */
|
||||
|
||||
/* Microsoft C libraries include files */
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
/* MsvcLibX library extensions */
|
||||
#include "msvcUnistd.h"
|
||||
#include "msvcDebugm.h"
|
||||
#include "msvcLimits.h"
|
||||
|
||||
#if defined(_MSDOS)
|
||||
|
||||
/* DOS own getcwd() is OK. */
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: getcwd |
|
||||
| |
|
||||
| Description: Get the current directory, encoded in UTF-8 |
|
||||
| |
|
||||
| Parameters: char *buf Buffer for the output |
|
||||
| size_t bufSize Buffer size |
|
||||
| |
|
||||
| Returns: The converted string size. -1=error, and errno set. |
|
||||
| |
|
||||
| Notes: We can't use the getcwd name, as MSVC has an incompatible |
|
||||
| prototype for it. So a getcwd macro calls this routine. |
|
||||
| |
|
||||
| History: |
|
||||
| 2014-02-28 JFL Created this routine |
|
||||
| 2014-07-02 JFL Added support for pathnames >= 260 characters. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
char *getcwdA(char *buf, size_t bufSize) {
|
||||
int n;
|
||||
WCHAR wbuf[PATH_MAX];
|
||||
DWORD dwSize;
|
||||
|
||||
dwSize = GetCurrentDirectoryW(COUNTOF(wbuf), wbuf);
|
||||
if (!dwSize) {
|
||||
errno = Win32ErrorToErrno();
|
||||
DEBUG_PRINTF(("getcwd(0x%p, %d); // Error: GetCurrentDirectoryW() Failed\n", buf, bufSize));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n = WideCharToMultiByte(CP_ACP, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
wbuf, /* lpWideCharStr, */
|
||||
dwSize+1, /* cchWideChar, */
|
||||
buf, /* lpMultiByteStr, */
|
||||
(int)bufSize, /* cbMultiByte, */
|
||||
NULL, /* lpDefaultChar, */
|
||||
NULL /* lpUsedDefaultChar */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
DEBUG_PRINTF(("getcwd(0x%p, %d); // Error: WideCharToMultiByte() Failed\n", buf, bufSize));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEBUG_PRINTF(("getcwd(0x%p, %d); // \"%s\"\n", buf, bufSize, buf));
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *getcwdU(char *buf, size_t bufSize) {
|
||||
int n;
|
||||
WCHAR wbuf[PATH_MAX];
|
||||
DWORD dwSize;
|
||||
|
||||
dwSize = GetCurrentDirectoryW(COUNTOF(wbuf), wbuf);
|
||||
if (!dwSize) {
|
||||
errno = Win32ErrorToErrno();
|
||||
DEBUG_PRINTF(("getcwd(0x%p, %d); // Error: GetCurrentDirectoryW() Failed\n", buf, bufSize));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
n = WideCharToMultiByte(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
wbuf, /* lpWideCharStr, */
|
||||
dwSize+1, /* cchWideChar, */
|
||||
buf, /* lpMultiByteStr, */
|
||||
(int)bufSize, /* cbMultiByte, */
|
||||
NULL, /* lpDefaultChar, */
|
||||
NULL /* lpUsedDefaultChar */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
DEBUG_PRINTF(("getcwd(0x%p, %d); // Error: WideCharToMultiByte() Failed\n", buf, bufSize));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
DEBUG_PRINTF(("getcwd(0x%p, %d); // \"%s\"\n", buf, bufSize, buf));
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *_getdcwdA(int iDrive, char *buf, int iBuflen) {
|
||||
char *pBuf;
|
||||
int iDrive0 = _getdrive();
|
||||
if (iDrive && (iDrive != iDrive0)) _chdrive(iDrive);
|
||||
pBuf = getcwdA(buf, iBuflen);
|
||||
if (iDrive && (iDrive != iDrive0)) _chdrive(iDrive0);
|
||||
DEBUG_CODE(
|
||||
if (pBuf) {
|
||||
DEBUG_PRINTF(("_getdcwd(%d, 0x%p, %d); // \"%s\"\n", iDrive, buf, iBuflen, pBuf));
|
||||
} else {
|
||||
DEBUG_PRINTF(("_getdcwd(%d, 0x%p, %d); // Failed\n", iDrive, buf, iBuflen, pBuf));
|
||||
}
|
||||
)
|
||||
return pBuf;
|
||||
}
|
||||
|
||||
char *_getdcwdU(int iDrive, char *buf, int iBuflen) {
|
||||
char *pBuf;
|
||||
int iDrive0 = _getdrive();
|
||||
if (iDrive && (iDrive != iDrive0)) _chdrive(iDrive);
|
||||
pBuf = getcwdU(buf, iBuflen);
|
||||
if (iDrive && (iDrive != iDrive0)) _chdrive(iDrive0);
|
||||
DEBUG_CODE(
|
||||
if (pBuf) {
|
||||
DEBUG_PRINTF(("_getdcwd(%d, 0x%p, %d); // \"%s\"\n", iDrive, buf, iBuflen, pBuf));
|
||||
} else {
|
||||
DEBUG_PRINTF(("_getdcwd(%d, 0x%p, %d); // Failed\n", iDrive, buf, iBuflen, pBuf));
|
||||
}
|
||||
)
|
||||
return pBuf;
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
|
@ -0,0 +1,500 @@
|
|||
/*-
|
||||
* Copyright (c) 2000 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Dieter Baron and Thomas Klausner.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
|
||||
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $NetBSD: getopt_long.c,v 1.11 2009/04/14 17:34:41 joerg Exp $
|
||||
* 2016-09-15 JFL Adapted v 1.11 for use in the MsvcLibX library
|
||||
*/
|
||||
|
||||
/* 2016-09-15 JFL Begin changes */
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "msvcGetopt.h"
|
||||
|
||||
#ifndef _DIAGASSERT
|
||||
#ifdef NDEBUG
|
||||
#define _DIAGASSERT(test)
|
||||
#else
|
||||
#define _DIAGASSERT(test) assert(test)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#undef __UNCONST
|
||||
#define __UNCONST(a) ((void *)/*(size_t)*/(const void *)(a))
|
||||
|
||||
static const char *progname;
|
||||
|
||||
/* Replacement for warnx(3) for systems without it. */
|
||||
static void warnx(const char *fmt, ...) {
|
||||
va_list ap;
|
||||
|
||||
va_start(ap, fmt);
|
||||
if (progname)
|
||||
(void) fprintf(stderr, "%s: ", progname);
|
||||
if (fmt)
|
||||
(void) vfprintf(stderr, fmt, ap);
|
||||
(void) fprintf(stderr, "\n");
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#define REPLACE_GETOPT
|
||||
|
||||
/* 2016-09-15 JFL End of changes */
|
||||
|
||||
#ifdef REPLACE_GETOPT
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(getopt,_getopt)
|
||||
#endif
|
||||
int opterr = 1; /* if error message should be printed */
|
||||
int optind = 1; /* index into parent argv vector */
|
||||
int optopt = '?'; /* character checked for validity */
|
||||
char *optarg; /* argument associated with option */
|
||||
#endif
|
||||
#if !HAVE_DECL_OPTRESET
|
||||
int optreset; /* reset getopt */
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(getopt_long,_getopt_long)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define IGNORE_FIRST (*options == '-' || *options == '+')
|
||||
#define PRINT_ERROR ((opterr) && ((*options != ':') \
|
||||
|| (IGNORE_FIRST && options[1] != ':')))
|
||||
#define IS_POSIXLY_CORRECT (getenv("POSIXLY_CORRECT") != NULL)
|
||||
#define PERMUTE (!IS_POSIXLY_CORRECT && !IGNORE_FIRST)
|
||||
/* XXX: GNU ignores PC if *options == '-' */
|
||||
#define IN_ORDER (!IS_POSIXLY_CORRECT && *options == '-')
|
||||
|
||||
/* return values */
|
||||
#define BADCH (int)'?'
|
||||
#define BADARG ((IGNORE_FIRST && options[1] == ':') \
|
||||
|| (*options == ':') ? (int)':' : (int)'?')
|
||||
#define INORDER (int)1
|
||||
|
||||
#define EMSG ""
|
||||
|
||||
static int getopt_internal(int, char **, const char *);
|
||||
static int gcd(int, int);
|
||||
static void permute_args(int, int, int, char **);
|
||||
|
||||
static const char *place = EMSG; /* option letter processing */
|
||||
|
||||
/* XXX: set optreset to 1 rather than these two */
|
||||
static int nonopt_start = -1; /* first non option argument (for permute) */
|
||||
static int nonopt_end = -1; /* first option after non options (for permute) */
|
||||
|
||||
/* Error messages */
|
||||
static const char recargchar[] = "option requires an argument -- %c";
|
||||
static const char recargstring[] = "option requires an argument -- %s";
|
||||
static const char ambig[] = "ambiguous option -- %.*s";
|
||||
static const char noarg[] = "option doesn't take an argument -- %.*s";
|
||||
static const char illoptchar[] = "unknown option -- %c";
|
||||
static const char illoptstring[] = "unknown option -- %s";
|
||||
|
||||
|
||||
/*
|
||||
* Compute the greatest common divisor of a and b.
|
||||
*/
|
||||
static int
|
||||
gcd(int a, int b)
|
||||
{
|
||||
int c;
|
||||
|
||||
c = a % b;
|
||||
while (c != 0) {
|
||||
a = b;
|
||||
b = c;
|
||||
c = a % b;
|
||||
}
|
||||
|
||||
return b;
|
||||
}
|
||||
|
||||
/*
|
||||
* Exchange the block from nonopt_start to nonopt_end with the block
|
||||
* from nonopt_end to opt_end (keeping the same order of arguments
|
||||
* in each block).
|
||||
*/
|
||||
static void
|
||||
permute_args(int panonopt_start, int panonopt_end, int opt_end, char **nargv)
|
||||
{
|
||||
int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
|
||||
char *swap;
|
||||
|
||||
_DIAGASSERT(nargv != NULL);
|
||||
|
||||
/*
|
||||
* compute lengths of blocks and number and size of cycles
|
||||
*/
|
||||
nnonopts = panonopt_end - panonopt_start;
|
||||
nopts = opt_end - panonopt_end;
|
||||
ncycle = gcd(nnonopts, nopts);
|
||||
cyclelen = (opt_end - panonopt_start) / ncycle;
|
||||
|
||||
for (i = 0; i < ncycle; i++) {
|
||||
cstart = panonopt_end+i;
|
||||
pos = cstart;
|
||||
for (j = 0; j < cyclelen; j++) {
|
||||
if (pos >= panonopt_end)
|
||||
pos -= nnonopts;
|
||||
else
|
||||
pos += nopts;
|
||||
swap = nargv[pos];
|
||||
nargv[pos] = nargv[cstart];
|
||||
nargv[cstart] = swap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* getopt_internal --
|
||||
* Parse argc/argv argument vector. Called by user level routines.
|
||||
* Returns -2 if -- is found (can be long option or end of options marker).
|
||||
*/
|
||||
static int
|
||||
getopt_internal(int nargc, char **nargv, const char *options)
|
||||
{
|
||||
char *oli; /* option letter list index */
|
||||
int optchar;
|
||||
|
||||
_DIAGASSERT(nargv != NULL);
|
||||
_DIAGASSERT(options != NULL);
|
||||
|
||||
optarg = NULL;
|
||||
|
||||
/*
|
||||
* XXX Some programs (like rsyncd) expect to be able to
|
||||
* XXX re-initialize optind to 0 and have getopt_long(3)
|
||||
* XXX properly function again. Work around this braindamage.
|
||||
*/
|
||||
if (optind == 0)
|
||||
optind = 1;
|
||||
|
||||
if (optreset)
|
||||
nonopt_start = nonopt_end = -1;
|
||||
start:
|
||||
if (optreset || !*place) { /* update scanning pointer */
|
||||
optreset = 0;
|
||||
if (optind >= nargc) { /* end of argument vector */
|
||||
place = EMSG;
|
||||
if (nonopt_end != -1) {
|
||||
/* do permutation, if we have to */
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
optind, nargv);
|
||||
optind -= nonopt_end - nonopt_start;
|
||||
}
|
||||
else if (nonopt_start != -1) {
|
||||
/*
|
||||
* If we skipped non-options, set optind
|
||||
* to the first of them.
|
||||
*/
|
||||
optind = nonopt_start;
|
||||
}
|
||||
nonopt_start = nonopt_end = -1;
|
||||
return -1;
|
||||
}
|
||||
if ((*(place = nargv[optind]) != '-')
|
||||
|| (place[1] == '\0')) { /* found non-option */
|
||||
place = EMSG;
|
||||
if (IN_ORDER) {
|
||||
/*
|
||||
* GNU extension:
|
||||
* return non-option as argument to option 1
|
||||
*/
|
||||
optarg = nargv[optind++];
|
||||
return INORDER;
|
||||
}
|
||||
if (!PERMUTE) {
|
||||
/*
|
||||
* if no permutation wanted, stop parsing
|
||||
* at first non-option
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
/* do permutation */
|
||||
if (nonopt_start == -1)
|
||||
nonopt_start = optind;
|
||||
else if (nonopt_end != -1) {
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
optind, nargv);
|
||||
nonopt_start = optind -
|
||||
(nonopt_end - nonopt_start);
|
||||
nonopt_end = -1;
|
||||
}
|
||||
optind++;
|
||||
/* process next argument */
|
||||
goto start;
|
||||
}
|
||||
if (nonopt_start != -1 && nonopt_end == -1)
|
||||
nonopt_end = optind;
|
||||
if (place[1] && *++place == '-') { /* found "--" */
|
||||
place++;
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
if ((optchar = (int)*place++) == (int)':' ||
|
||||
(oli = strchr(options + (IGNORE_FIRST ? 1 : 0), optchar)) == NULL) {
|
||||
/* option letter unknown or ':' */
|
||||
if (!*place)
|
||||
++optind;
|
||||
if (PRINT_ERROR)
|
||||
warnx(illoptchar, optchar);
|
||||
optopt = optchar;
|
||||
return BADCH;
|
||||
}
|
||||
if (optchar == 'W' && oli[1] == ';') { /* -W long-option */
|
||||
/* XXX: what if no long options provided (called by getopt)? */
|
||||
if (*place)
|
||||
return -2;
|
||||
|
||||
if (++optind >= nargc) { /* no arg */
|
||||
place = EMSG;
|
||||
if (PRINT_ERROR)
|
||||
warnx(recargchar, optchar);
|
||||
optopt = optchar;
|
||||
return BADARG;
|
||||
} else /* white space */
|
||||
place = nargv[optind];
|
||||
/*
|
||||
* Handle -W arg the same as --arg (which causes getopt to
|
||||
* stop parsing).
|
||||
*/
|
||||
return -2;
|
||||
}
|
||||
if (*++oli != ':') { /* doesn't take argument */
|
||||
if (!*place)
|
||||
++optind;
|
||||
} else { /* takes (optional) argument */
|
||||
optarg = NULL;
|
||||
if (*place) /* no white space */
|
||||
optarg = __UNCONST(place);
|
||||
/* XXX: disable test for :: if PC? (GNU doesn't) */
|
||||
else if (oli[1] != ':') { /* arg not optional */
|
||||
if (++optind >= nargc) { /* no arg */
|
||||
place = EMSG;
|
||||
if (PRINT_ERROR)
|
||||
warnx(recargchar, optchar);
|
||||
optopt = optchar;
|
||||
return BADARG;
|
||||
} else
|
||||
optarg = nargv[optind];
|
||||
}
|
||||
place = EMSG;
|
||||
++optind;
|
||||
}
|
||||
/* dump back option letter */
|
||||
return optchar;
|
||||
}
|
||||
|
||||
#ifdef REPLACE_GETOPT
|
||||
/*
|
||||
* getopt --
|
||||
* Parse argc/argv argument vector.
|
||||
*
|
||||
* [eventually this will replace the real getopt]
|
||||
*/
|
||||
int
|
||||
getopt(int nargc, char * const *nargv, const char *options)
|
||||
{
|
||||
int retval;
|
||||
|
||||
_DIAGASSERT(nargv != NULL);
|
||||
_DIAGASSERT(options != NULL);
|
||||
|
||||
retval = getopt_internal(nargc, __UNCONST(nargv), options);
|
||||
if (retval == -2) {
|
||||
++optind;
|
||||
/*
|
||||
* We found an option (--), so if we skipped non-options,
|
||||
* we have to permute.
|
||||
*/
|
||||
if (nonopt_end != -1) {
|
||||
permute_args(nonopt_start, nonopt_end, optind,
|
||||
(char **)nargv);
|
||||
optind -= nonopt_end - nonopt_start;
|
||||
}
|
||||
nonopt_start = nonopt_end = -1;
|
||||
retval = -1;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* getopt_long --
|
||||
* Parse argc/argv argument vector.
|
||||
*/
|
||||
int
|
||||
getopt_long(int nargc, char * const *nargv, const char *options,
|
||||
const struct option *long_options, int *idx)
|
||||
{
|
||||
int retval;
|
||||
|
||||
#define IDENTICAL_INTERPRETATION(_x, _y) \
|
||||
(long_options[(_x)].has_arg == long_options[(_y)].has_arg && \
|
||||
long_options[(_x)].flag == long_options[(_y)].flag && \
|
||||
long_options[(_x)].val == long_options[(_y)].val)
|
||||
|
||||
_DIAGASSERT(nargv != NULL);
|
||||
_DIAGASSERT(options != NULL);
|
||||
_DIAGASSERT(long_options != NULL);
|
||||
/* idx may be NULL */
|
||||
|
||||
retval = getopt_internal(nargc, __UNCONST(nargv), options);
|
||||
if (retval == -2) {
|
||||
char *current_argv, *has_equal;
|
||||
size_t current_argv_len;
|
||||
int i, ambiguous, match;
|
||||
|
||||
current_argv = __UNCONST(place);
|
||||
match = -1;
|
||||
ambiguous = 0;
|
||||
|
||||
optind++;
|
||||
place = EMSG;
|
||||
|
||||
if (*current_argv == '\0') { /* found "--" */
|
||||
/*
|
||||
* We found an option (--), so if we skipped
|
||||
* non-options, we have to permute.
|
||||
*/
|
||||
if (nonopt_end != -1) {
|
||||
permute_args(nonopt_start, nonopt_end,
|
||||
optind, __UNCONST(nargv));
|
||||
optind -= nonopt_end - nonopt_start;
|
||||
}
|
||||
nonopt_start = nonopt_end = -1;
|
||||
return -1;
|
||||
}
|
||||
if ((has_equal = strchr(current_argv, '=')) != NULL) {
|
||||
/* argument found (--option=arg) */
|
||||
current_argv_len = has_equal - current_argv;
|
||||
has_equal++;
|
||||
} else
|
||||
current_argv_len = strlen(current_argv);
|
||||
|
||||
for (i = 0; long_options[i].name; i++) {
|
||||
/* find matching long option */
|
||||
if (strncmp(current_argv, long_options[i].name,
|
||||
current_argv_len))
|
||||
continue;
|
||||
|
||||
if (strlen(long_options[i].name) ==
|
||||
(unsigned)current_argv_len) {
|
||||
/* exact match */
|
||||
match = i;
|
||||
ambiguous = 0;
|
||||
break;
|
||||
}
|
||||
if (match == -1) /* partial match */
|
||||
match = i;
|
||||
else if (!IDENTICAL_INTERPRETATION(i, match))
|
||||
ambiguous = 1;
|
||||
}
|
||||
if (ambiguous) {
|
||||
/* ambiguous abbreviation */
|
||||
if (PRINT_ERROR)
|
||||
warnx(ambig, (int)current_argv_len,
|
||||
current_argv);
|
||||
optopt = 0;
|
||||
return BADCH;
|
||||
}
|
||||
if (match != -1) { /* option found */
|
||||
if (long_options[match].has_arg == no_argument
|
||||
&& has_equal) {
|
||||
if (PRINT_ERROR)
|
||||
warnx(noarg, (int)current_argv_len,
|
||||
current_argv);
|
||||
/*
|
||||
* XXX: GNU sets optopt to val regardless of
|
||||
* flag
|
||||
*/
|
||||
if (long_options[match].flag == NULL)
|
||||
optopt = long_options[match].val;
|
||||
else
|
||||
optopt = 0;
|
||||
return BADARG;
|
||||
}
|
||||
if (long_options[match].has_arg == required_argument ||
|
||||
long_options[match].has_arg == optional_argument) {
|
||||
if (has_equal)
|
||||
optarg = has_equal;
|
||||
else if (long_options[match].has_arg ==
|
||||
required_argument) {
|
||||
/*
|
||||
* optional argument doesn't use
|
||||
* next nargv
|
||||
*/
|
||||
optarg = nargv[optind++];
|
||||
}
|
||||
}
|
||||
if ((long_options[match].has_arg == required_argument)
|
||||
&& (optarg == NULL)) {
|
||||
/*
|
||||
* Missing argument; leading ':'
|
||||
* indicates no error should be generated
|
||||
*/
|
||||
if (PRINT_ERROR)
|
||||
warnx(recargstring, current_argv);
|
||||
/*
|
||||
* XXX: GNU sets optopt to val regardless
|
||||
* of flag
|
||||
*/
|
||||
if (long_options[match].flag == NULL)
|
||||
optopt = long_options[match].val;
|
||||
else
|
||||
optopt = 0;
|
||||
--optind;
|
||||
return BADARG;
|
||||
}
|
||||
} else { /* unknown option */
|
||||
if (PRINT_ERROR)
|
||||
warnx(illoptstring, current_argv);
|
||||
optopt = 0;
|
||||
return BADCH;
|
||||
}
|
||||
if (long_options[match].flag) {
|
||||
*long_options[match].flag = long_options[match].val;
|
||||
retval = 0;
|
||||
} else
|
||||
retval = long_options[match].val;
|
||||
if (idx)
|
||||
*idx = match;
|
||||
}
|
||||
return retval;
|
||||
#undef IDENTICAL_INTERPRETATION
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename getppid.c *
|
||||
* *
|
||||
* Description: WIN32 port of standard C library's getppid() *
|
||||
* *
|
||||
* Notes: TO DO: Add a DOS version, using the PSP for the pid. *
|
||||
* *
|
||||
* During the development of this routine, I found a bug *
|
||||
* in Windows SDK's tlhelp32.h include file in WIN64: *
|
||||
* If packcking has been changed somewhere before including *
|
||||
* tlhelp32.h, either due to a #pragma pack directive, or to *
|
||||
* a compiler /Zp option, it will generate a PROCESSENTRY32 *
|
||||
* structure with the wrong size. Then anything can happen, *
|
||||
* including Process32First failures, or even crashes. *
|
||||
* *
|
||||
* History: *
|
||||
* 2013-03-27 JFL Created this module. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#include "msvcUnistd.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#pragma pack(push,8) /* Work around a bug in tlhelp32.h in WIN64, which generates the wrong structure if packing has been changed */
|
||||
#include <tlhelp32.h>
|
||||
#pragma pack(pop)
|
||||
|
||||
/*
|
||||
pid_t getpid(void) {
|
||||
return (pid_t)GetCurrentProcessId();
|
||||
}
|
||||
*/
|
||||
|
||||
pid_t getppid(void) {
|
||||
pid_t ppid = INVALID_PID;
|
||||
pid_t pid = getpid();
|
||||
HANDLE h;
|
||||
BOOL bFound;
|
||||
PROCESSENTRY32 pe = {0};
|
||||
|
||||
h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
if (h == INVALID_HANDLE_VALUE) {
|
||||
return ppid;
|
||||
}
|
||||
|
||||
pe.dwSize = sizeof(PROCESSENTRY32);
|
||||
for (bFound=Process32First(h, &pe); bFound; bFound=Process32Next(h, &pe)) {
|
||||
if ((pid_t)(pe.th32ProcessID) == pid) {
|
||||
ppid = pe.th32ParentProcessID;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CloseHandle(h);
|
||||
|
||||
return ppid;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename gettimeofday.c *
|
||||
* *
|
||||
* Description DOS/WIN32 port of standard C library's gettimeofday(). *
|
||||
* *
|
||||
* Notes *
|
||||
* *
|
||||
* History *
|
||||
* 2014-06-04 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#include "msvclibx.h"
|
||||
|
||||
#include "msvcTime.h"
|
||||
#include "sys/msvcTime.h"
|
||||
|
||||
#ifdef _MSDOS
|
||||
/* MS-DOS only has a 1-second resolution on system time.
|
||||
Use the existence of macro _STRUCT_TIMEVAL to test if it's possible
|
||||
to use gettimeofday(), else use time(), which is supported by all OSs */
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
||||
/* Get the current date and time into a struct timeval */
|
||||
int gettimeofday(struct timeval *ptv, void *pTimeZone) {
|
||||
struct timespec ts;
|
||||
int iErr;
|
||||
if (pTimeZone) pTimeZone = _timezone; /* Ignore it, and prevent compilation warning */
|
||||
iErr = clock_gettime(CLOCK_REALTIME, &ts);
|
||||
if (iErr) return iErr;
|
||||
TIMESPEC_TO_TIMEVAL(ptv, &ts);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
|
@ -0,0 +1,229 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename iconv.c *
|
||||
* *
|
||||
* Description: WIN32 port of standard C library's iconv() *
|
||||
* *
|
||||
* Notes: Define here a number of routines, that will eventually *
|
||||
* be used by iconv(). *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-27 JFL Created this module. *
|
||||
* 2015-12-09 JFL Added routines fputsU and vfprintfU. *
|
||||
* 2016-09-13 JFL Fixed warnings in fputsU. Do not change the input buffer. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
/* Microsoft C libraries include files */
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
/* MsvcLibX library extensions */
|
||||
#include "msvcIconv.h"
|
||||
#include "msvcDebugm.h"
|
||||
#include "msvcLimits.h"
|
||||
|
||||
#if defined(_MSDOS)
|
||||
|
||||
/* TO DO: Add support for DOS code pages! */
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: ConvertString |
|
||||
| |
|
||||
| Description: Convert a string from one MBCS encoding to another |
|
||||
| |
|
||||
| Parameters: char *buf Buffer containg a NUL-terminated string |
|
||||
| size_t nBytes Buffer size |
|
||||
| UINT cpFrom Initial Windows code page identifier |
|
||||
| UINT cpTo Final Windows code page identifier |
|
||||
| LPCSTR lpDfltC Pointer to the Default Character to use |
|
||||
| (NULL = Use the default default!) |
|
||||
| |
|
||||
| Returns: The converted string size. -1=error, and errno set. |
|
||||
| |
|
||||
| Notes: See the list of Windows code page identifiers there: |
|
||||
| http://msdn.microsoft.com/en-us/library/windows/desktop/dd317756(v=vs.85).aspx
|
||||
| |
|
||||
| History: |
|
||||
| 2014-02-27 JFL Created this routine |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
int ConvertString(char *buf, size_t nBytes, UINT cpFrom, UINT cpTo, LPCSTR lpDefaultChar) {
|
||||
int n = (int)lstrlen(buf);
|
||||
if (cpFrom != cpTo) {
|
||||
WCHAR *pWBuf = (WCHAR *)malloc(sizeof(WCHAR)*nBytes);
|
||||
if (!pWBuf) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
n = MultiByteToWideChar(cpFrom, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
buf, /* lpMultiByteStr, */
|
||||
n+1, /* cbMultiByte, +1 to copy the final NUL */
|
||||
pWBuf, /* lpWideCharStr, */
|
||||
(int)nBytes /* cchWideChar, */
|
||||
);
|
||||
n = WideCharToMultiByte(cpTo, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
pWBuf, /* lpWideCharStr, */
|
||||
n, /* cchWideChar, */
|
||||
buf, /* lpMultiByteStr, */
|
||||
(int)nBytes, /* cbMultiByte, */
|
||||
lpDefaultChar, /* lpDefaultChar, */
|
||||
NULL /* lpUsedDefaultChar */
|
||||
);
|
||||
free(pWBuf);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
n -= 1; /* Output string size, not counting the final NUL */
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
char *DupAndConvert(const char *string, UINT cpFrom, UINT cpTo, LPCSTR lpDefaultChar) {
|
||||
int nBytes;
|
||||
char *pBuf;
|
||||
nBytes = 4 * ((int)lstrlen(string) + 1); /* Worst case for the size needed */
|
||||
pBuf = (char *)malloc(nBytes);
|
||||
if (!pBuf) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
lstrcpy(pBuf, string);
|
||||
nBytes = ConvertString(pBuf, nBytes, cpFrom, cpTo, lpDefaultChar);
|
||||
if (nBytes == -1) {
|
||||
free(pBuf);
|
||||
return NULL;
|
||||
}
|
||||
pBuf = realloc(pBuf, nBytes+1);
|
||||
return pBuf;
|
||||
}
|
||||
|
||||
int CountCharacters(const char *string, UINT cp) {
|
||||
int n;
|
||||
WCHAR *pWBuf;
|
||||
|
||||
n = (int)lstrlen(string);
|
||||
if (!n) return 0;
|
||||
|
||||
pWBuf = (WCHAR *)malloc(sizeof(WCHAR)*n);
|
||||
if (!pWBuf) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
}
|
||||
|
||||
n = MultiByteToWideChar(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
string, /* lpMultiByteStr, */
|
||||
n, /* cbMultiByte, */
|
||||
pWBuf, /* lpWideCharStr, */
|
||||
n /* cchWideChar, */
|
||||
);
|
||||
free(pWBuf);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
UINT codePage = 0;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Functions: fputsU, vfprintfU, fprintfU, printfU |
|
||||
| |
|
||||
| Description: Output UTF-8 strings |
|
||||
| |
|
||||
| Parameters: Same as fputs, vfprintf, fprintf, printf |
|
||||
| |
|
||||
| Returns: Same as fputs, vfprintf, fprintf, printf |
|
||||
| |
|
||||
| Notes: Converts the string to the output code page if needed. |
|
||||
| |
|
||||
| History: |
|
||||
| 2014-02-27 JFL Created fprintfU and printfU. |
|
||||
| 2015-12-09 JFL Restructured them over vfprintfU, itself over fputsU. |
|
||||
| 2016-09-13 JFL Fixed warnings. |
|
||||
| Do not change the input buffer. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Make sure we're calling Microsoft routines, not our aliases */
|
||||
#undef printf
|
||||
#undef fprintf
|
||||
#undef vfprintf
|
||||
#undef fputs
|
||||
|
||||
int fputsU(const char *buf, FILE *f) { /* fputs a UTF-8 string */
|
||||
int iRet;
|
||||
char *pBuf = NULL;
|
||||
|
||||
if (!codePage) codePage = GetConsoleOutputCP();
|
||||
if (codePage != CP_UTF8) {
|
||||
pBuf = DupAndConvert(buf, CP_UTF8, codePage, NULL);
|
||||
} else {
|
||||
pBuf = (char *)buf;
|
||||
}
|
||||
if (pBuf) { /* If no error, and something to output */
|
||||
iRet = fputs(pBuf, f);
|
||||
if ((iRet >= 0) && DEBUG_IS_ON()) fflush(f); /* Slower, but ensures we get everything before crashes! */
|
||||
if (pBuf != buf) free(pBuf);
|
||||
} else {
|
||||
iRet = -1; /* Could not convert the string to output */
|
||||
}
|
||||
return iRet; /* Return the error (n<0) or success (n>=0) */
|
||||
}
|
||||
|
||||
int vfprintfU(FILE *f, const char *pszFormat, va_list vl) { /* vfprintf UTF-8 strings */
|
||||
int n;
|
||||
char buf[UNICODE_PATH_MAX + 4096];
|
||||
|
||||
n = _vsnprintf(buf, sizeof(buf), pszFormat, vl);
|
||||
if (n > 0) { /* If no error (n>=0), and something to output (n>0), do output */
|
||||
int iErr = fputsU(buf, f);
|
||||
if (iErr < 0) n = iErr;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int fprintfU(FILE *f, const char *pszFormat, ...) { /* fprintf UTF-8 strings */
|
||||
va_list vl;
|
||||
int n;
|
||||
|
||||
va_start(vl, pszFormat);
|
||||
n = vfprintfU(f, pszFormat, vl);
|
||||
va_end(vl);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
int printfU(const char *pszFormat, ...) { /* printf UTF-8 strings */
|
||||
va_list vl;
|
||||
int n;
|
||||
|
||||
va_start(vl, pszFormat);
|
||||
n = vfprintfU(stdout, pszFormat, vl);
|
||||
va_end(vl);
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
|
@ -0,0 +1,432 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename lstat.c *
|
||||
* *
|
||||
* Description: WIN32 port of standard C library's lstat() *
|
||||
* Also contains unlink() and rmdir(), which do use lstat. *
|
||||
* *
|
||||
* Notes: TO DO: Make 3 versions for Windows: ANSI, WSTR, UTF8 *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-06 JFL Created this module. *
|
||||
* 2014-02-12 JFL Added code to filter reparse points, and keep only *
|
||||
* real junctions and symlinks. *
|
||||
* 2014-02-13 JFL Moved dirent2stat() from dirent.c, as there must actually *
|
||||
* be 4 WIN32 versions, for the four versions of struct stat.*
|
||||
* 2014-02-28 JFL Added support for UTF-8 pathnames. *
|
||||
* 2014-03-24 JFL Renamed "statx.h" as the standard <sys/stat.h>. *
|
||||
* 2014-06-30 JFL Added support for 32K Unicode paths. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */
|
||||
|
||||
/* Microsoft C libraries include files */
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
/* MsvcLibX library extensions */
|
||||
#include "msvclibx.h"
|
||||
#include <sys/msvcStat.h>
|
||||
#include "msvcDirent.h"
|
||||
#include "msvcUnistd.h" /* For ResolveLinks() definition */
|
||||
#include "msvcDebugm.h"
|
||||
#include "msvcLimits.h"
|
||||
|
||||
#if defined(_MSDOS)
|
||||
/* Make sure it's only defined it in one of the lstatxxx versions */
|
||||
#if !defined(_USE_32BIT_TIME_T) && (_FILE_OFFSET_BITS == 32)
|
||||
|
||||
int dirent2stat(_dirent *pDirent, struct _stat *pStat) {
|
||||
memset(pStat, 0, sizeof(struct stat));
|
||||
|
||||
/* Set times */
|
||||
pStat->st_mtime = Filetime2Timet(pDirent->d_date, pDirent->d_time);
|
||||
/* Size */
|
||||
pStat->st_size = pDirent->d_filesize;
|
||||
/* Standard attributes */
|
||||
pStat->st_mode |= (pDirent->d_type << 12); /* Set the 4-bit type field */
|
||||
pStat->st_mode |= _S_IREAD | _S_IWRITE | _S_IEXEC; /* Assume it's fully accessible */
|
||||
if (pDirent->d_attribs & _A_RDONLY) pStat->st_mode &= ~_S_IWRITE;
|
||||
/* DOS-specific attributes */
|
||||
if (pDirent->d_attribs & _A_HIDDEN) pStat->st_mode |= S_HIDDEN;
|
||||
if (pDirent->d_attribs & _A_ARCH) pStat->st_mode |= S_ARCHIVE;
|
||||
if (pDirent->d_attribs & _A_SYSTEM) pStat->st_mode |= S_SYSTEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(_USE_32BIT_TIME_T) && (_FILE_OFFSET_BITS == 32) */
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/* ------------ Display the *stat* macro values at compile time ------------ */
|
||||
|
||||
#pragma message(MACRODEF(_MSVC_stat))
|
||||
#pragma message(MACRODEF(_MSVC_fstat))
|
||||
#pragma message(MACRODEF(_MSVC_lstat))
|
||||
#pragma message(MACRODEF(_MSVC_stat64))
|
||||
|
||||
#if _MSVCLIBX_STAT_DEFINED
|
||||
#pragma message(MACRODEF(_LIBX_stat))
|
||||
#pragma message(MACRODEF(_LIBX_stat64))
|
||||
#endif
|
||||
|
||||
#pragma message(MACRODEF(stat))
|
||||
#pragma message(MACRODEF(fstat))
|
||||
#pragma message(MACRODEF(lstat))
|
||||
|
||||
#if 0
|
||||
#pragma message(MACRODEF(_lstat))
|
||||
#pragma message(MACRODEF(_lstati64))
|
||||
#if _MSVCLIBX_STAT_DEFINED
|
||||
#pragma message(MACRODEF(_lstat_ns))
|
||||
#pragma message(MACRODEF(_lstati64_ns))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined(_LARGEFILE_SOURCE64)
|
||||
#pragma message(MACRODEF(stat64))
|
||||
#pragma message(MACRODEF(fstat64))
|
||||
#pragma message(MACRODEF(lstat64))
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: lstat |
|
||||
| |
|
||||
| Description: Common definition of all _lstatXY() functions |
|
||||
| |
|
||||
| Parameters: const char *path The symlink name |
|
||||
| struct stat *buf Output buffer |
|
||||
| |
|
||||
| Returns: 0 = Success, -1 = Failure |
|
||||
| |
|
||||
| Notes: See statx.h for a description of how the stat and lstat |
|
||||
| macros work. |
|
||||
| |
|
||||
| History: |
|
||||
| 2014-02-06 JFL Created this routine |
|
||||
| 2014-02-28 JFL Added support for UTF-8 pathnames. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
int lstat(const char *path, struct stat *pStat) {
|
||||
BOOL bDone;
|
||||
DWORD dwAttr;
|
||||
WIN32_FILE_ATTRIBUTE_DATA fileData;
|
||||
unsigned __int64 qwSize;
|
||||
int bIsJunction = FALSE;
|
||||
int bIsMountPoint = FALSE;
|
||||
DWORD dwTag = 0;
|
||||
DEBUG_CODE(
|
||||
char szTime[100];
|
||||
)
|
||||
WCHAR wszName[UNICODE_PATH_MAX];
|
||||
int n;
|
||||
|
||||
DEBUG_ENTER((STRINGIZE(lstat) "(\"%s\", 0x%p);\n", path, pStat));
|
||||
|
||||
#if USE_MSVC_STAT
|
||||
dwAttr = GetFileAttributes(path);
|
||||
DEBUG_PRINTF(("GetFileAttributes() = 0x%lX\n", dwAttr));
|
||||
if (dwAttr == INVALID_FILE_ATTRIBUTES) {
|
||||
errno = ENOENT;
|
||||
RETURN_INT_COMMENT(-1, ("File does not exist\n"));
|
||||
}
|
||||
|
||||
if (!(dwAttr & FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||
int iErr = stat(path, pStat);
|
||||
RETURN_INT(iErr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
path, /* lpMultiByteStr, */
|
||||
wszName, /* lpWideCharStr, */
|
||||
UNICODE_PATH_MAX /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno)));
|
||||
}
|
||||
|
||||
bDone = GetFileAttributesExW(wszName, GetFileExInfoStandard, &fileData);
|
||||
if (!bDone) {
|
||||
errno = Win32ErrorToErrno();
|
||||
RETURN_INT_COMMENT(-1, ("GetFileAttributesEx(); // Failed\n"));
|
||||
}
|
||||
XDEBUG_PRINTF(("GetFileAttributesEx(); // Success\n"));
|
||||
dwAttr = fileData.dwFileAttributes;
|
||||
XDEBUG_PRINTF(("dwFileAttributes = 0x%lX\n", dwAttr));
|
||||
DEBUG_CODE_IF_ON(Filetime2String(&fileData.ftLastWriteTime, szTime, sizeof(szTime)););
|
||||
XDEBUG_PRINTF(("ftLastWriteTime = %s\n", szTime));
|
||||
qwSize = ((unsigned __int64)fileData.nFileSizeHigh << 32) | fileData.nFileSizeLow;
|
||||
XDEBUG_PRINTF(("nFileSize = %I64d\n", qwSize));
|
||||
|
||||
ZeroMemory(pStat, sizeof(struct stat));
|
||||
/* Set times */
|
||||
#if _MSVCLIBX_STAT_DEFINED
|
||||
Filetime2Timespec(&fileData.ftCreationTime, &(pStat->st_ctim)); /* Windows = Create time; Unix = Permissions change time */
|
||||
Filetime2Timespec(&fileData.ftLastWriteTime, &(pStat->st_mtim));
|
||||
Filetime2Timespec(&fileData.ftLastAccessTime, &(pStat->st_atim));
|
||||
#else
|
||||
Filetime2Timet(&fileData.ftCreationTime, &(pStat->st_ctime)); /* Windows = Create time; Unix = Permissions change time */
|
||||
Filetime2Timet(&fileData.ftLastWriteTime, &(pStat->st_mtime));
|
||||
Filetime2Timet(&fileData.ftLastAccessTime, &(pStat->st_atime));
|
||||
#endif
|
||||
/* Size */
|
||||
/* NOTE: There is loss of data here if the file size is > 2GB, and off_t is 32-bits */
|
||||
pStat->st_size = (off_t)qwSize;
|
||||
#if (_STAT_FILE_SIZE < 64)
|
||||
#define _MAX_FILE_SIZE 0x7FFFFFFFL
|
||||
if (qwSize > _MAX_FILE_SIZE) pStat->st_size = (off_t)_MAX_FILE_SIZE;
|
||||
#endif
|
||||
/* Standard attributes */
|
||||
/* File type */
|
||||
check_attr_again:
|
||||
if (dwAttr & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||
/* JUNCTIONs and SYMLINKDs both have the FILE_ATTRIBUTE_DIRECTORY flag also set.
|
||||
// Test the FILE_ATTRIBUTE_REPARSE_POINT flag first, to make sure they're seen as symbolic links.
|
||||
//
|
||||
// All symlinks are reparse points, but not all reparse points are symlinks. */
|
||||
dwTag = GetReparseTagU(path);
|
||||
switch (dwTag) {
|
||||
case IO_REPARSE_TAG_MOUNT_POINT: /* NTFS junction or mount point */
|
||||
{ /* We must read the link to distinguish junctions from mount points. */
|
||||
WCHAR wbuf[UNICODE_PATH_MAX];
|
||||
ssize_t n;
|
||||
bIsMountPoint = TRUE;
|
||||
n = readlinkW(wszName, wbuf, UNICODE_PATH_MAX);
|
||||
/* Junction targets are absolute pathnames, starting with a drive letter. Ex: C: */
|
||||
/* readlink() fails if the reparse point does not target a valid pathname */
|
||||
if (n < 0) goto this_is_not_a_symlink; /* This is not a junction. */
|
||||
bIsJunction = TRUE; /* Else this is a junction. Fall through to the symlink case. */
|
||||
}
|
||||
case IO_REPARSE_TAG_SYMLINK: /* NTFS symbolic link */
|
||||
pStat->st_mode |= S_IFLNK; /* Symbolic link */
|
||||
break;
|
||||
default: /* Anything else is definitely not like a Unix symlink */
|
||||
this_is_not_a_symlink:
|
||||
dwAttr &= ~FILE_ATTRIBUTE_REPARSE_POINT;
|
||||
goto check_attr_again;
|
||||
}
|
||||
} else if (dwAttr & FILE_ATTRIBUTE_DIRECTORY)
|
||||
pStat->st_mode |= S_IFDIR; /* Subdirectory */
|
||||
else if (dwAttr & FILE_ATTRIBUTE_DEVICE)
|
||||
pStat->st_mode |= S_IFCHR; /* Device (we don't know if character or block) */
|
||||
else
|
||||
pStat->st_mode |= S_IFREG; /* A normal file by default */
|
||||
/* pStat->st_mode |= (pDirent->d_type << 12); /* Set the 4-bit type field */
|
||||
pStat->st_mode |= _S_IREAD | _S_IWRITE | _S_IEXEC; /* Assume it's fully accessible */
|
||||
if (dwAttr & FILE_ATTRIBUTE_READONLY) pStat->st_mode &= ~_S_IWRITE;
|
||||
/* DOS-specific attributes */
|
||||
if (dwAttr & FILE_ATTRIBUTE_HIDDEN) pStat->st_mode |= S_HIDDEN;
|
||||
if (dwAttr & FILE_ATTRIBUTE_ARCHIVE) pStat->st_mode |= S_ARCHIVE;
|
||||
if (dwAttr & FILE_ATTRIBUTE_SYSTEM) pStat->st_mode |= S_SYSTEM;
|
||||
/* Windows-specific attributes */
|
||||
if (dwAttr & FILE_ATTRIBUTE_COMPRESSED) pStat->st_mode |= S_COMPRESSED;
|
||||
if (dwAttr & FILE_ATTRIBUTE_ENCRYPTED) pStat->st_mode |= S_ENCRYPTED;
|
||||
if (dwAttr & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) pStat->st_mode |= S_NOT_CONTENT_INDEXED;
|
||||
if (dwAttr & FILE_ATTRIBUTE_OFFLINE) pStat->st_mode |= S_OFFLINE;
|
||||
if (dwAttr & FILE_ATTRIBUTE_SPARSE_FILE) pStat->st_mode |= S_SPARSE_FILE;
|
||||
if (bIsMountPoint) pStat->st_mode |= S_MOUNT_POINT; /* Will allow to distinguish junctions from mount points */
|
||||
/* if (dwAttr & FILE_ATTRIBUTE_TEMPORARY) pStat->st_mode |= S_TEMPORARY; */
|
||||
/* if (dwAttr & FILE_ATTRIBUTE_VIRTUAL) pStat->st_mode |= S_VIRTUAL; */
|
||||
#if _MSVCLIBX_STAT_DEFINED
|
||||
pStat->st_Win32Attrs = dwAttr;
|
||||
pStat->st_ReparseTag = dwTag;
|
||||
#endif
|
||||
|
||||
RETURN_INT_COMMENT(0, ("%s mode = 0x%04X size = %I64d bytes\n", szTime, pStat->st_mode, qwSize));
|
||||
}
|
||||
|
||||
#if !USE_MSVC_STAT
|
||||
int stat(const char *path, struct stat *pStat) {
|
||||
char buf[UTF8_PATH_MAX];
|
||||
int iErr;
|
||||
|
||||
DEBUG_ENTER((STRINGIZE(stat) "(\"%s\", 0x%p);\n", path, pStat));
|
||||
|
||||
iErr = ResolveLinksU(path, buf, sizeof(buf));
|
||||
if (!iErr) lstat(buf, pStat);
|
||||
|
||||
RETURN_INT(iErr);
|
||||
}
|
||||
#endif /* !USE_MSVC_STAT */
|
||||
|
||||
int dirent2stat(_dirent *pDirent, struct stat *pStat) {
|
||||
memset(pStat, 0, sizeof(struct stat));
|
||||
|
||||
/* Set times */
|
||||
#if _MSVCLIBX_STAT_DEFINED
|
||||
Filetime2Timespec(&pDirent->d_CreationTime, &(pStat->st_ctim)); /* Windows = Create time; Unix = Permissions change time */
|
||||
Filetime2Timespec(&pDirent->d_LastWriteTime, &(pStat->st_mtim));
|
||||
Filetime2Timespec(&pDirent->d_LastAccessTime, &(pStat->st_atim));
|
||||
#else
|
||||
Filetime2Timet(&pDirent->d_CreationTime, &(pStat->st_ctime)); /* Windows = Create time; Unix = Permissions change time */
|
||||
Filetime2Timet(&pDirent->d_LastWriteTime, &(pStat->st_mtime));
|
||||
Filetime2Timet(&pDirent->d_LastAccessTime, &(pStat->st_atime));
|
||||
#endif
|
||||
/* Size */
|
||||
/* NOTE: There is loss of data here if the file size is > 2GB, and off_t is 32-bits */
|
||||
pStat->st_size = (off_t)(pDirent->d_filesize);
|
||||
#if (_STAT_FILE_SIZE < 64)
|
||||
#define _MAX_FILE_SIZE 0x7FFFFFFFL
|
||||
if (pDirent->d_filesize > _MAX_FILE_SIZE) pStat->st_size = (off_t)_MAX_FILE_SIZE;
|
||||
#endif
|
||||
/* Standard attributes */
|
||||
pStat->st_mode |= (pDirent->d_type << 12); /* Set the 4-bit type field */
|
||||
pStat->st_mode |= _S_IREAD | _S_IWRITE | _S_IEXEC; /* Assume it's fully accessible */
|
||||
if (pDirent->d_attribs & FILE_ATTRIBUTE_READONLY) pStat->st_mode &= ~_S_IWRITE;
|
||||
/* DOS-specific attributes */
|
||||
if (pDirent->d_attribs & FILE_ATTRIBUTE_HIDDEN) pStat->st_mode |= S_HIDDEN;
|
||||
if (pDirent->d_attribs & FILE_ATTRIBUTE_ARCHIVE) pStat->st_mode |= S_ARCHIVE;
|
||||
if (pDirent->d_attribs & FILE_ATTRIBUTE_SYSTEM) pStat->st_mode |= S_SYSTEM;
|
||||
/* Windows-specific attributes */
|
||||
if (pDirent->d_attribs & FILE_ATTRIBUTE_COMPRESSED) pStat->st_mode |= S_COMPRESSED;
|
||||
if (pDirent->d_attribs & FILE_ATTRIBUTE_ENCRYPTED) pStat->st_mode |= S_ENCRYPTED;
|
||||
if (pDirent->d_attribs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) pStat->st_mode |= S_NOT_CONTENT_INDEXED;
|
||||
if (pDirent->d_attribs & FILE_ATTRIBUTE_OFFLINE) pStat->st_mode |= S_OFFLINE;
|
||||
if (pDirent->d_attribs & FILE_ATTRIBUTE_SPARSE_FILE) pStat->st_mode |= S_SPARSE_FILE;
|
||||
/* Special case of junction and mount points */
|
||||
if (pDirent->d_ReparseTag) pStat->st_mode |= S_MOUNT_POINT;
|
||||
/* if (pDirent->d_attribs & FILE_ATTRIBUTE_TEMPORARY) pStat->st_mode |= S_TEMPORARY; */
|
||||
/* if (pDirent->d_attribs & FILE_ATTRIBUTE_VIRTUAL) pStat->st_mode |= S_VIRTUAL; */
|
||||
#if _MSVCLIBX_STAT_DEFINED
|
||||
pStat->st_Win32Attrs = pDirent->d_attribs;
|
||||
pStat->st_ReparseTag = pDirent->d_ReparseTag;
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: unlink |
|
||||
| |
|
||||
| Description: Remove a file or a symbolic link |
|
||||
| |
|
||||
| Parameters: const char *path The file or symlink name |
|
||||
| |
|
||||
| Returns: 0 = Success, -1 = Failure |
|
||||
| |
|
||||
| Notes: |
|
||||
| |
|
||||
| History: |
|
||||
| 2014-02-17 JFL Created this routine |
|
||||
| 2014-02-28 JFL Added support for UTF-8 pathnames. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
int unlink(const char *path) {
|
||||
int iErr;
|
||||
BOOL bDone;
|
||||
struct stat st;
|
||||
WCHAR wszName[UNICODE_PATH_MAX];
|
||||
int n;
|
||||
|
||||
DEBUG_ENTER(("unlink(\"%s\");\n", path));
|
||||
|
||||
iErr = lstat(path, &st);
|
||||
if (iErr) RETURN_INT(iErr);
|
||||
|
||||
if ((!S_ISREG(st.st_mode)) && (!S_ISLNK(st.st_mode))) {
|
||||
errno = ENOENT;
|
||||
RETURN_INT_COMMENT(-1, ("Pathname exists, but is not a file or a link\n"));
|
||||
}
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
path, /* lpMultiByteStr, */
|
||||
wszName, /* lpWideCharStr, */
|
||||
UNICODE_PATH_MAX /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno)));
|
||||
}
|
||||
|
||||
#if _MSVCLIBX_STAT_DEFINED
|
||||
if (S_ISLNK(st.st_mode) && (st.st_Win32Attrs & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
/* This link is a junction or a symlinkd */
|
||||
bDone = RemoveDirectoryW(wszName);
|
||||
} else
|
||||
#endif
|
||||
bDone = DeleteFileW(wszName);
|
||||
|
||||
if (bDone) {
|
||||
RETURN_INT_COMMENT(0, ("Success\n"));
|
||||
} else {
|
||||
errno = Win32ErrorToErrno();
|
||||
RETURN_INT_COMMENT(-1, ("Failed\n"));
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: rmdir |
|
||||
| |
|
||||
| Description: Remove a directory |
|
||||
| |
|
||||
| Parameters: const char *path The directory name |
|
||||
| |
|
||||
| Returns: 0 = Success, -1 = Failure |
|
||||
| |
|
||||
| Notes: |
|
||||
| |
|
||||
| History: |
|
||||
| 2014-03-05 JFL Created this routine with support for UTF-8 pathnames. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
int rmdir(const char *path) {
|
||||
int iErr;
|
||||
BOOL bDone;
|
||||
struct stat st;
|
||||
WCHAR wszName[UNICODE_PATH_MAX];
|
||||
int n;
|
||||
|
||||
DEBUG_ENTER(("rmdir(\"%s\");\n", path));
|
||||
|
||||
iErr = lstat(path, &st);
|
||||
if (iErr) RETURN_INT(iErr);
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
RETURN_INT_COMMENT(-1, ("Pathname exists, but is not a directory\n"));
|
||||
}
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
path, /* lpMultiByteStr, */
|
||||
wszName, /* lpWideCharStr, */
|
||||
UNICODE_PATH_MAX /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno)));
|
||||
}
|
||||
|
||||
bDone = RemoveDirectoryW(wszName);
|
||||
|
||||
if (bDone) {
|
||||
RETURN_INT_COMMENT(0, ("Success\n"));
|
||||
} else {
|
||||
errno = Win32ErrorToErrno();
|
||||
RETURN_INT_COMMENT(-1, ("Failed\n"));
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* _WIN32 */
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename lstat32.c *
|
||||
* *
|
||||
* Description: Redefinitions of standard C library's lstat32() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-14 JFL Created this module. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _WIN64 /* WIN64 does not support 32-bits time_t */
|
||||
|
||||
/* st_*time is 32-bits __time32_t & st_size is 32-bits __off32_t */
|
||||
|
||||
#define _USE_32BIT_TIME_T
|
||||
#define _FILE_OFFSET_BITS 32
|
||||
|
||||
#include "lstat.c"
|
||||
#endif
|
|
@ -0,0 +1,24 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename lstat32i64.c *
|
||||
* *
|
||||
* Description: Redefinitions of standard C library's lstat32i64() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-14 JFL Created this module. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#ifndef _WIN64 /* WIN64 does not support 32-bits time_t */
|
||||
|
||||
/* st_*time is 32-bits __time32_t & st_size is 64-bits __off64_t */
|
||||
|
||||
#define _USE_32BIT_TIME_T
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include "lstat.c"
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename lstat.c *
|
||||
* *
|
||||
* Description: Redefinitions of standard C library's lstat() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-14 JFL Created this module. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* st_*time is 64-bits __time64_t & st_size is 64-bits __off64_t */
|
||||
|
||||
#undef _USE_32BIT_TIME_T
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
|
||||
#include "lstat.c"
|
|
@ -0,0 +1,21 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename lstat64i32.c *
|
||||
* *
|
||||
* Description: Redefinitions of standard C library's lstat64i32() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-14 JFL Created this module. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
/* st_*time is 64-bits __time64_t & st_size is 32-bits __off32_t */
|
||||
|
||||
#undef _USE_32BIT_TIME_T
|
||||
#define _FILE_OFFSET_BITS 32
|
||||
|
||||
#include "lstat.c"
|
|
@ -0,0 +1,225 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename main.c *
|
||||
* *
|
||||
* Description: Main routine for WIN32 UTF-8 programs *
|
||||
* *
|
||||
* Notes: TO DO: Also set the environment with _setenvp() ? *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-03-03 JFL Created this module. *
|
||||
* 2016-09-20 JFL Bug fix: Empty arguments "" did not get recorded. *
|
||||
* 2017-02-05 JFL Redesigned to override libc's _setargv(). This avoids *
|
||||
* having to encapsulate the main() routine with one here. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _UTF8_SOURCE
|
||||
#define _CRT_SECURE_NO_WARNINGS /* Avoid depreciation warnings */
|
||||
|
||||
#include "msvclibx.h"
|
||||
#include "msvcStdio.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include "msvcIconv.h" /* For MsvcLibX' codePage global variable */
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function BreakArgLine |
|
||||
| |
|
||||
| Description Break the Windows command line into standard C arguments |
|
||||
| |
|
||||
| Parameters LPSTR pszCmdLine NUL-terminated argument line |
|
||||
| char *pszArg[] Array of arguments pointers |
|
||||
| |
|
||||
| Returns int argc Number of arguments found. -1 = Error |
|
||||
| |
|
||||
| Notes MSVC library startup \" parsing rule is: |
|
||||
| 2N backslashes + " ==> N backslashes and begin/end quote |
|
||||
| 2N+1 backslashes + " ==> N backslashes + literal " |
|
||||
| N backslashes ==> N backslashes |
|
||||
| |
|
||||
| History |
|
||||
| 1993-10-05 JFL Initial implementation within devmain(). |
|
||||
| 1994-04-14 JFL Extracted from devmain, and created this routine. |
|
||||
| 1995-04-07 JFL Extracted from llkinit.c. |
|
||||
| 1996-09-26 JFL Adapted to Win32 programs. |
|
||||
| 1996-12-11 JFL Use Windows string routines. |
|
||||
| 2001-09-18 JFL Set argv[0] with actual module file name. |
|
||||
| Manage quoted strings as a single argument. |
|
||||
| 2001-09-25 JFL Only process \x inside strings. |
|
||||
| 2014-03-04 JFL Removed the C-style \-quoting of characters, which was |
|
||||
| convenient, but incompatible with MSVC argument parsing. |
|
||||
| Removed the limitation on the # of arguments. |
|
||||
| Made the code compatible with ANSI and UTF-8 encodings. |
|
||||
| 2017-02-05 JFL Check memory allocation errors, and if so return -1. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
int BreakArgLine(LPSTR pszCmdLine, char ***pppszArg) {
|
||||
int i, j;
|
||||
int argc = 0;
|
||||
char c, c0;
|
||||
char *pszCopy;
|
||||
int iString = FALSE; /* TRUE = string mode; FALSE = non-string mode */
|
||||
int nBackslash = 0;
|
||||
char **ppszArg;
|
||||
int iArg = FALSE; /* TRUE = inside an argument; FALSE = between arguments */
|
||||
|
||||
ppszArg = (char **)malloc((argc+1)*sizeof(char *));
|
||||
if (!ppszArg) return -1;
|
||||
|
||||
/* Make a local copy of the argument line */
|
||||
/* Break down the local copy into standard C arguments */
|
||||
|
||||
pszCopy = malloc(lstrlen(pszCmdLine) + 1);
|
||||
if (!pszCopy) return -1;
|
||||
/* Copy the string, managing quoted characters */
|
||||
for (i=0, j=0, c0='\0'; ; i++) {
|
||||
c = pszCmdLine[i];
|
||||
if (!c) { /* End of argument line */
|
||||
for ( ; nBackslash; nBackslash--) pszCopy[j++] = '\\'; /* Output pending \s */
|
||||
pszCopy[j++] = c;
|
||||
break;
|
||||
}
|
||||
if ((!iArg) && (c != ' ') && (c != '\t')) { /* Beginning of a new argument */
|
||||
iArg = TRUE;
|
||||
ppszArg[argc++] = pszCopy+j;
|
||||
ppszArg = (char **)realloc(ppszArg, (argc+1)*sizeof(char *));
|
||||
if (!ppszArg) return -1;
|
||||
pszCopy[j] = c0 = '\0';
|
||||
}
|
||||
if (c == '\\') { /* Escaped character in string (maybe) */
|
||||
nBackslash += 1;
|
||||
continue;
|
||||
}
|
||||
if (c == '"') {
|
||||
if (nBackslash & 1) { /* Output N/2 \ and a literal " */
|
||||
for (nBackslash >>= 1; nBackslash; nBackslash--) pszCopy[j++] = '\\';
|
||||
pszCopy[j++] = c0 = c;
|
||||
continue;
|
||||
}
|
||||
if (nBackslash) { /* Output N/2 \ and switch string mode */
|
||||
for (nBackslash >>= 1; nBackslash; nBackslash--) pszCopy[j++] = '\\';
|
||||
}
|
||||
iString = !iString;
|
||||
continue;
|
||||
}
|
||||
for ( ; nBackslash; nBackslash--) pszCopy[j++] = '\\'; /* Output pending \s */
|
||||
if ((!iString) && ((c == ' ') || (c == '\t'))) { /* End of an argument */
|
||||
iArg = FALSE;
|
||||
c = '\0';
|
||||
}
|
||||
pszCopy[j++] = c0 = c;
|
||||
}
|
||||
|
||||
ppszArg[argc] = NULL;
|
||||
*pppszArg = ppszArg;
|
||||
|
||||
return argc;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function _setargv |
|
||||
| |
|
||||
| Description Msft standard CRT routine for parsing the command line. |
|
||||
| |
|
||||
| Parameters char *_acmdln Command line parameters. |
|
||||
| |
|
||||
| Returns __argc = Number of arguments. -1 = Error. |
|
||||
| __argv = Array of arguments |
|
||||
| _pgmptr = The program pathname |
|
||||
| |
|
||||
| Notes When linked in, replaces the default routine from the CRT.|
|
||||
| |
|
||||
| History |
|
||||
| 2001-09-25 JFL Created this routine |
|
||||
| 2016-12-31 JFL Changed the return type from void to int, else the WIN64 |
|
||||
| version fails with message: |
|
||||
| runtime error R6008 - not enough space for arguments |
|
||||
| 2017-02-05 JFL Adapted for UTF-8 arguments initialization. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Global CRT variables defined in stdlib.h */
|
||||
/* Do not include stdlib.h here, to avoid getting unwanted macros hiding these */
|
||||
_CRTIMP extern int __argc;
|
||||
_CRTIMP extern char **__argv;
|
||||
_CRTIMP extern char *_acmdln;
|
||||
_CRTIMP extern char *_pgmptr;
|
||||
|
||||
int _initU(void); /* Forward reference */
|
||||
|
||||
int _setargv(void) {
|
||||
int err = _initU();
|
||||
if (err) return err;
|
||||
__argc = BreakArgLine(_acmdln, &__argv);
|
||||
_pgmptr = __argv[0];
|
||||
return __argc;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function _initU |
|
||||
| |
|
||||
| Description UTF-8 program initializations |
|
||||
| |
|
||||
| Parameters None |
|
||||
| |
|
||||
| Returns 0=Success. -1 = Error. |
|
||||
| _acmdln = UTF-8 command line |
|
||||
| codePage = Console Code Page |
|
||||
| |
|
||||
| Notes Forcibly linked in C programs that define _UTF8_SOURCE, |
|
||||
| etc, which drags in _setargv() above with it. |
|
||||
| |
|
||||
| History |
|
||||
| 2017-02-05 JFL Adapted from the abandonned _mainU0 routine. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
int _initU(void) {
|
||||
LPWSTR lpwCommandLine;
|
||||
int n;
|
||||
WCHAR wc;
|
||||
|
||||
/* Get the Unicode command line */
|
||||
lpwCommandLine = GetCommandLineW();
|
||||
/* Trim tail spaces */
|
||||
n = lstrlenW(lpwCommandLine);
|
||||
while (n && ((wc = lpwCommandLine[n-1]) != L'\0') && ((wc == L' ') || (wc == L'\t'))) lpwCommandLine[--n] = L'\0';
|
||||
/* Allocate space for the UTF8 copy */
|
||||
n += 1; /* Count the final NUL */
|
||||
_acmdln = malloc(4 * n); /* Worst case */
|
||||
if (!_acmdln) return -1; /* Memory allocation failed */
|
||||
/* Convert the Unicode command line to UTF-8 */
|
||||
n = WideCharToMultiByte(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
lpwCommandLine, /* lpWideCharStr, */
|
||||
n, /* cchWideChar, */
|
||||
_acmdln, /* lpMultiByteStr, */
|
||||
(4 * n), /* cbMultiByte, */
|
||||
NULL, /* lpDefaultChar, */
|
||||
NULL /* lpUsedDefaultChar */
|
||||
);
|
||||
if (!n) {
|
||||
#undef fprintf /* Use the real fprintf, to avoid further conversion errors! */
|
||||
fprintf(stderr, "Warning: Can't convert the argument line to UTF-8\n");
|
||||
_acmdln[0] = '\0';
|
||||
}
|
||||
realloc(_acmdln, n+1); /* Resize the memory block to fit the UTF-8 line */
|
||||
/* Should not fail since we make it smaller */
|
||||
|
||||
/* Record the console code page, to allow converting the output accordingly */
|
||||
codePage = GetConsoleOutputCP();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename mb2wpath.c *
|
||||
* *
|
||||
* Description: WIN32 utility routine MultiByteToWidePath() *
|
||||
* *
|
||||
* Notes: Used to overcome the 260-byte limitation of many Windows *
|
||||
* file management APIs. *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-07-01 JFL Created this module. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _UTF8_SOURCE /* Generate the UTF-8 version of printf routines */
|
||||
|
||||
#include "msvclibx.h"
|
||||
#include "msvcDebugm.h"
|
||||
|
||||
#if defined(_WIN32)
|
||||
|
||||
#include <windows.h>
|
||||
#include <direct.h> /* For _getdrive() */
|
||||
|
||||
int MultiByteToWidePath(
|
||||
UINT nCodePage,
|
||||
LPCSTR pszName,
|
||||
LPWSTR pwszName,
|
||||
int nWideBufSize
|
||||
) {
|
||||
int n;
|
||||
int iNameLength = lstrlen(pszName);
|
||||
DEBUG_CODE(
|
||||
LPWSTR pwszName0 = pwszName;
|
||||
);
|
||||
|
||||
if (iNameLength >= MAX_PATH) { /* Then processing this pathname requires prepending a special prefix */
|
||||
/* See http://msdn.microsoft.com/en-us/library/windows/desktop/aa365247(v=vs.85).aspx */
|
||||
if (!strncmp(pszName, "\\\\?\\", 4)) { /* The name is in the Win32 file namespace */
|
||||
/* Do nothing, the "\\?\" extended-length prefix is already there */
|
||||
} else if (!strncmp(pszName, "\\\\.\\", 4)) { /* The name is in the Win32 device namespace */
|
||||
/* Do nothing, devices names should not be changed */
|
||||
} else if (!strncmp(pszName, "\\\\", 2)) { /* The name is a UNC path */
|
||||
/* Then prepend it with "\\?\UNC\" to get 32K Unicode paths instead of 260-byte ANSI paths */
|
||||
lstrcpyW(pwszName, L"\\\\?\\UNC\\");
|
||||
pwszName += 8;
|
||||
nWideBufSize -= 8;
|
||||
pszName += 2; /* Skip the initial \\ in the UNC name */
|
||||
iNameLength -= 2;
|
||||
} else if (pszName[0] == '\\') { /* The name is an absolute path with no drive */
|
||||
/* Then prepend it with "\\?\" to get 32K Unicode paths instead of 260-byte ANSI paths */
|
||||
lstrcpyW(pwszName, L"\\\\?\\");
|
||||
/* And also add the drive, as it's required in the Win32 file namespace */
|
||||
pwszName[4] = L'@' + (wchar_t)_getdrive(); /* _getdrive() returns 1 for drive A, 2 for B, etc */
|
||||
pwszName[5] = L':';
|
||||
pwszName += 6;
|
||||
nWideBufSize -= 6;
|
||||
} else if (pszName[0] && (pszName[1] == ':') && (pszName[2] == '\\')) { /* The name is an absolute path */
|
||||
/* Then prepend it with "\\?\" to get 32K Unicode paths instead of 260-byte ANSI paths */
|
||||
lstrcpyW(pwszName, L"\\\\?\\");
|
||||
pwszName += 4;
|
||||
nWideBufSize -= 4;
|
||||
} /* Else this is a relative pathname. Extended-length is not supported for them. */
|
||||
}
|
||||
|
||||
n = MultiByteToWideChar(nCodePage, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
pszName, /* lpMultiByteStr, */
|
||||
iNameLength+1, /* cbMultiByte, */ /* +1 to include the final NUL */
|
||||
pwszName, /* lpWideCharStr, */
|
||||
nWideBufSize /* cchWideChar, */
|
||||
);
|
||||
DEBUG_CODE(
|
||||
if (pwszName != pwszName0) {
|
||||
char szUtf8[UTF8_PATH_MAX];
|
||||
DEBUG_WSTR2UTF8(pwszName0, szUtf8, sizeof(szUtf8));
|
||||
DEBUG_PRINTF(("MultiByteToWidePath(); // Long name changed to \"%s\"\n", szUtf8));
|
||||
}
|
||||
);
|
||||
return n;
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename mkdir.c *
|
||||
* *
|
||||
* Description: WIN32 UTF-8 version of mkdir *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-03-04 JFL Created this module. *
|
||||
* 2014-03-24 JFL Renamed "statx.h" as the standard <sys/stat.h>. *
|
||||
* 2014-07-02 JFL Added support for pathnames >= 260 characters. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
/* Microsoft C libraries include files */
|
||||
#include <stdio.h>
|
||||
#include <direct.h> /* For _mkdir() */
|
||||
#include <errno.h>
|
||||
/* MsvcLibX library extensions */
|
||||
#include <sys/msvcStat.h>
|
||||
#include "msvclibx.h"
|
||||
#include "msvcLimits.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function mkdir |
|
||||
| |
|
||||
| Description UTF-8 version of mkdir |
|
||||
| |
|
||||
| Parameters char *pszName File name |
|
||||
| mode_t iMode File permission bits |
|
||||
| |
|
||||
| Returns 0 = Success; -1 = Error and errno set. |
|
||||
| |
|
||||
| Notes |
|
||||
| |
|
||||
| History |
|
||||
| 2014-03-04 JFL Created this routine. |
|
||||
| 2014-07-02 JFL Added support for pathnames >= 260 characters. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#pragma warning(disable:4100) /* Ignore the "unreferenced formal parameter" warning */
|
||||
|
||||
int mkdirU(const char *pszName, mode_t iMode) {
|
||||
WCHAR wszName[PATH_MAX];
|
||||
int n;
|
||||
BOOL bDone;
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
pszName, /* lpMultiByteStr, */
|
||||
wszName, /* lpWideCharStr, */
|
||||
COUNTOF(wszName) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
bDone = CreateDirectoryW(wszName, NULL);
|
||||
if (!bDone) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mkdirA(const char *pszName, mode_t iMode) {
|
||||
WCHAR wszName[PATH_MAX];
|
||||
int n;
|
||||
BOOL bDone;
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(CP_ACP, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
pszName, /* lpMultiByteStr, */
|
||||
wszName, /* lpWideCharStr, */
|
||||
COUNTOF(wszName) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
bDone = CreateDirectoryW(wszName, NULL);
|
||||
if (!bDone) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename mkdtemp.c *
|
||||
* *
|
||||
* Description: WIN32 port of standard C library's mkdtemp() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-13 JFL Created this module. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include "msvcUnistd.h"
|
||||
|
||||
char *mkdtemp(char *pszName) {
|
||||
char *pszXXX, *pc;
|
||||
int iErr = 0;
|
||||
char *base32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
||||
int i;
|
||||
|
||||
/* Find the XXX placeholder at the end of the string */
|
||||
for (pszXXX=pszName; pszXXX && *pszXXX; pszXXX++) ;
|
||||
while ((pszXXX > pszName) && (*(pszXXX-1) == 'X')) pszXXX--;
|
||||
if (!pszXXX || (*pszXXX != 'X')) {
|
||||
errno = EINVAL;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Seed the random number generator */
|
||||
srand((unsigned)getpid() + ((unsigned)time(NULL) << 10));
|
||||
|
||||
/* Try random file names until one file gets successfully created */
|
||||
for (i=0; i<10; i++) {
|
||||
for (pc = pszXXX; *pc; pc++) {
|
||||
*pc = base32[rand() % 32];
|
||||
}
|
||||
iErr = _mkdir(pszName);
|
||||
if (!iErr) break;
|
||||
}
|
||||
|
||||
return iErr ? NULL : pszName;
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename mkstemp.c *
|
||||
* *
|
||||
* Description: WIN32 port of standard C library's mkstemp() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-03-03 JFL Created this module. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#include "msvcUnistd.h"
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
#include <io.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
int mkstemp(char *pszName) {
|
||||
char *pszXXX, *pc;
|
||||
int hFile = -1;
|
||||
char *base32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
||||
|
||||
/* Find the XXX placeholder at the end of the string */
|
||||
for (pszXXX=pszName; pszXXX && *pszXXX; pszXXX++) ;
|
||||
while ((pszXXX > pszName) && (*(pszXXX-1) == 'X')) pszXXX--;
|
||||
if (!pszXXX || (*pszXXX != 'X')) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Seed the random number generator */
|
||||
srand((unsigned)getpid() + ((unsigned)time(NULL) << 10));
|
||||
|
||||
/* Try random file names until one file gets successfully created */
|
||||
while (hFile == -1) {
|
||||
for (pc = pszXXX; *pc; pc++) {
|
||||
*pc = base32[rand() % 32];
|
||||
}
|
||||
hFile = _open(pszName, O_CREAT|O_EXCL|O_RDWR, S_IREAD|S_IWRITE);
|
||||
}
|
||||
|
||||
return hFile;
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename open.c *
|
||||
* *
|
||||
* Description: WIN32 UTF-8 version of open *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2017-02-16 JFL Created this module. *
|
||||
* *
|
||||
* Copyright 2017 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _UTF8_SOURCE /* Generate the UTF-8 version of printf routines */
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#include <errno.h>
|
||||
#include "msvclibx.h"
|
||||
#include "msvcFcntl.h"
|
||||
#include "msvcDebugm.h"
|
||||
#include "msvcLimits.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function open |
|
||||
| |
|
||||
| Description UTF-8 or ANSI file name open(), with long path support |
|
||||
| |
|
||||
| Parameters char *pszName File name |
|
||||
| int iFlags Opening mode |
|
||||
| int iPerm Permission mode for file creation |
|
||||
| |
|
||||
| Returns File number |
|
||||
| |
|
||||
| Notes Prefixes long names with "\\?\" to enable long path suppt.|
|
||||
| |
|
||||
| History |
|
||||
| 2017-02-16 JFL Created this routine. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
int openM(UINT cp, const char *pszName, int iFlags, int iPerm) {
|
||||
WCHAR wszName[UNICODE_PATH_MAX];
|
||||
int n;
|
||||
int iFile;
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
pszName, /* lpMultiByteStr, */
|
||||
wszName, /* lpWideCharStr, */
|
||||
COUNTOF(wszName) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* return _wopen(wszName, iFlags, iPerm); */
|
||||
DEBUG_PRINTF(("_wopen(\"%s\", 0x%X, 0x%X);\n", pszName, iFlags, iPerm));
|
||||
iFile = _wopen(wszName, iFlags, iPerm);
|
||||
DEBUG_PRINTF((" return %d;\n", iFile));
|
||||
return iFile;
|
||||
}
|
||||
|
||||
#pragma warning(disable:4212) /* Ignore the "nonstandard extension used : function declaration used ellipsis" warning */
|
||||
|
||||
int openA(const char *pszName, int iFlags, int iPerm) {
|
||||
return openM(CP_ACP, pszName, iFlags, iPerm);
|
||||
}
|
||||
|
||||
int openU(const char *pszName, int iFlags, int iPerm) {
|
||||
return openM(CP_UTF8, pszName, iFlags, iPerm);
|
||||
}
|
||||
|
||||
#pragma warning(default:4212) /* Restore the "nonstandard extension used : function declaration used ellipsis" warning */
|
||||
|
||||
#endif /* defined(_WIN32) */
|
|
@ -0,0 +1,509 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename readlink.c *
|
||||
* *
|
||||
* Description: WIN32 port of standard C library's readlink() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-03 JFL Created this module. *
|
||||
* 2014-02-27 JFL Changed the output name encoding to UTF-8. *
|
||||
* 2014-03-02 JFL Split the functions into a WSTR and an UTF-8 version. *
|
||||
* 2014-03-11 JFL Bug fix in junctions targets relativization. *
|
||||
* 2014-03-13 JFL Allow reading junctions targets in first level shares. *
|
||||
* 2014-03-19 JFL Split routine ReadReparsePointW() from readlinkW(). *
|
||||
* 2014-03-20 JFL Restructured Windows readlink function into Wide and *
|
||||
* MultiByte versions, and changed the Unicode and Ansi *
|
||||
* versions to macros. *
|
||||
* 2014-07-03 JFL Added support for pathnames >= 260 characters. *
|
||||
* 2016-09-09 JFL Fixed a crash in debug mode, due to stack overflows. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */
|
||||
|
||||
#include "msvcUnistd.h"
|
||||
#pragma comment(lib, "Mpr.lib")
|
||||
|
||||
#include <errno.h>
|
||||
#include "msvcDebugm.h"
|
||||
#include "msvcLimits.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include "msvcReparsept.h"
|
||||
|
||||
/* Get the Reparse Point Tag for a mount point - Wide char version */
|
||||
/* See http://msdn.microsoft.com/en-us/library/windows/desktop/aa365511(v=vs.85).aspx */
|
||||
DWORD GetReparseTagW(const WCHAR *pwszPath) {
|
||||
HANDLE hFind;
|
||||
WIN32_FIND_DATAW findFileData;
|
||||
DWORD dwTag = 0;
|
||||
|
||||
hFind = FindFirstFileW(pwszPath, &findFileData);
|
||||
if (hFind == INVALID_HANDLE_VALUE ) return 0;
|
||||
CloseHandle(hFind);
|
||||
if (findFileData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||
dwTag = findFileData.dwReserved0;
|
||||
}
|
||||
return dwTag;
|
||||
}
|
||||
|
||||
/* Get the Reparse Point Tag for a mount point - MultiByte char version */
|
||||
DWORD GetReparseTagM(const char *path, UINT cp) {
|
||||
WCHAR wszPath[PATH_MAX];
|
||||
int n;
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
path, /* lpMultiByteStr, */
|
||||
wszPath, /* lpWideCharStr, */
|
||||
COUNTOF(wszPath) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
DEBUG_PRINTF(("GetReparseTagM(\"%s\", %d); // Conversion to Unicode failed. errno=%d - %s\n", path, cp, errno, strerror(errno)));
|
||||
return 0;
|
||||
}
|
||||
return GetReparseTagW(wszPath);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: readlink |
|
||||
| |
|
||||
| Description: WIN32 port of standard C library's readlink() |
|
||||
| |
|
||||
| Parameters: const TCHAR *path The link name |
|
||||
| TCHAR *buf Buffer for the link target |
|
||||
| size_t bufsize Number of TCHAR in buf |
|
||||
| |
|
||||
| Returns: >0 = Link target size in TCHARS, Success, -1 = Failure |
|
||||
| |
|
||||
| Notes: Supports NTFS link types: symlink, symlinkd, junction. |
|
||||
| |
|
||||
| Converts junction targets to relative links if possible. |
|
||||
| |
|
||||
| On network drives, junctions that cannot be resolved on |
|
||||
| the client side are returned unchanged: readlink() |
|
||||
| returns the link name as its own target. This allows |
|
||||
| resolving pathnames with such junctions successfully, |
|
||||
| and still accessing files behind these junctions. |
|
||||
| Note that this is incompatible with Unix, which fails |
|
||||
| with errno = ELOOP if a link points to itself. |
|
||||
| Windows-aware applications supporting this can detect |
|
||||
| this case by comparing linkName and targetName when |
|
||||
| readlink() succeeds. |
|
||||
| Function ResolveLinks() in resolvelinks.c relies on this. |
|
||||
| |
|
||||
| Using XDEBUG macros to debug readlink() itself, |
|
||||
| and DEBUG macros to display information useful for |
|
||||
| debugging applications using readlink(). |
|
||||
| |
|
||||
| History: |
|
||||
| 2014-02-04 JFL Created this routine |
|
||||
| 2014-02-18 JFL Fix junctions targets on network drives. |
|
||||
| Convert junction targets to relative paths, if they're |
|
||||
| on the same drive as the junction itself. |
|
||||
| 2014-03-11 JFL Bug fix in junctions targets relativization: Use a case- |
|
||||
| insensitive path comparison. |
|
||||
| 2014-03-13 JFL Allow reading junctions targets in \\server\Public shares.|
|
||||
| 2014-03-19 JFL Split routine ReadReparsePointW() from readlinkW(). |
|
||||
| Fail in case a junction target is on another server drive.|
|
||||
| |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#pragma warning(disable:4706) /* Ignore the "assignment within conditional expression" warning */
|
||||
|
||||
/* Get the reparse point target, and return the tag. 0=failure */
|
||||
DWORD ReadReparsePointW(const WCHAR *path, WCHAR *buf, size_t bufsize) {
|
||||
DWORD dwAttr;
|
||||
HANDLE hLink;
|
||||
BOOL done;
|
||||
DWORD dwRead;
|
||||
char iobuf[MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
|
||||
DWORD dwFlagsAndAttributes;
|
||||
DWORD dwTag;
|
||||
WCHAR *pwStr;
|
||||
PREPARSE_READ_BUFFER pIoctlBuf;
|
||||
PMOUNTPOINT_READ_BUFFER pMountpointBuf;
|
||||
PSYMLINK_READ_BUFFER pSymlinkBuf;
|
||||
unsigned short offset, len = 0;
|
||||
DEBUG_CODE(
|
||||
char *pszUtf8;
|
||||
)
|
||||
|
||||
DEBUG_WSTR2NEWUTF8(path, pszUtf8);
|
||||
DEBUG_ENTER(("ReadReparsePointW(\"%s\", 0x%p, %d);\n", pszUtf8, buf, bufsize));
|
||||
DEBUG_FREEUTF8(pszUtf8);
|
||||
|
||||
dwAttr = GetFileAttributesW(path);
|
||||
XDEBUG_PRINTF(("GetFileAttributes() = 0x%lX\n", dwAttr));
|
||||
if (dwAttr == INVALID_FILE_ATTRIBUTES) {
|
||||
errno = ENOENT;
|
||||
RETURN_INT_COMMENT(0, ("File does not exist\n"));
|
||||
}
|
||||
|
||||
if (!(dwAttr & FILE_ATTRIBUTE_REPARSE_POINT)) {
|
||||
errno = EINVAL;
|
||||
RETURN_INT_COMMENT(0, ("File is not a link\n"));
|
||||
}
|
||||
|
||||
dwFlagsAndAttributes = FILE_FLAG_OPEN_REPARSE_POINT;
|
||||
if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) dwFlagsAndAttributes |= FILE_FLAG_BACKUP_SEMANTICS;
|
||||
hLink = CreateFileW(path, /* lpFileName, */
|
||||
0, /* dwDesiredAccess, */
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode, */
|
||||
NULL, /* lpSecurityAttributes, */
|
||||
OPEN_EXISTING, /* dwCreationDisposition, */
|
||||
dwFlagsAndAttributes, /* dwFlagsAndAttributes, */
|
||||
NULL /* hTemplateFile */
|
||||
);
|
||||
XDEBUG_PRINTF(("CreateFile() = 0x%lX\n", hLink));
|
||||
if (hLink == INVALID_HANDLE_VALUE) {
|
||||
errno = EPERM;
|
||||
RETURN_INT_COMMENT(0, ("Cannot open the link\n"));
|
||||
}
|
||||
|
||||
done = DeviceIoControl(hLink, /* hDevice, */
|
||||
FSCTL_GET_REPARSE_POINT, /* dwIoControlCode, */
|
||||
NULL, /* lpInBuffer, */
|
||||
0, /* nInBufferSize, */
|
||||
iobuf, /* lpOutBuffer, */
|
||||
sizeof(iobuf), /* nOutBufferSize, */
|
||||
&dwRead, /* lpBytesReturned, */
|
||||
NULL /* lpOverlapped */
|
||||
);
|
||||
CloseHandle(hLink);
|
||||
|
||||
if (!done) {
|
||||
errno = EPERM;
|
||||
RETURN_INT_COMMENT(0, ("DeviceIoControl() failed\n"));
|
||||
}
|
||||
|
||||
XDEBUG_PRINTF(("DeviceIoControl() returned %d bytes\n", dwRead));
|
||||
|
||||
/* Make sur the header tag & length fields are valid */
|
||||
if (dwRead < 8) {
|
||||
errno = EBADF;
|
||||
RETURN_INT_COMMENT(0, ("Invalid reparse data buffer\n"));
|
||||
}
|
||||
pIoctlBuf = (PREPARSE_READ_BUFFER)iobuf;
|
||||
dwTag = pIoctlBuf->ReparseTag;
|
||||
DEBUG_CODE_IF_ON(
|
||||
char *pType = "";
|
||||
switch (dwTag) {
|
||||
case IO_REPARSE_TAG_RESERVED_ZERO: pType = "Reserved"; break;
|
||||
case IO_REPARSE_TAG_RESERVED_ONE: pType = "Reserved"; break;
|
||||
case IO_REPARSE_TAG_MOUNT_POINT: pType = "Mount point or junction"; break;
|
||||
case IO_REPARSE_TAG_HSM: pType = "Hierarchical Storage Manager"; break;
|
||||
case IO_REPARSE_TAG_DRIVER_EXTENDER: pType = "Home server drive extender"; break;
|
||||
case IO_REPARSE_TAG_HSM2: pType = "Hierarchical Storage Manager Product #2"; break;
|
||||
case IO_REPARSE_TAG_SIS: pType = "Single-instance storage filter driver"; break;
|
||||
case IO_REPARSE_TAG_WIM: pType = "Windows boot Image File"; break;
|
||||
case IO_REPARSE_TAG_CSV: pType = "Cluster Shared Volume"; break;
|
||||
case IO_REPARSE_TAG_DFS: pType = "Distributed File System"; break;
|
||||
case IO_REPARSE_TAG_FILTER_MANAGER: pType = "Filter manager test harness"; break;
|
||||
case IO_REPARSE_TAG_SYMLINK: pType = "Symbolic link"; break;
|
||||
case IO_REPARSE_TAG_DFSR: pType = "Distributed File System R filter"; break;
|
||||
case IO_REPARSE_TAG_DEDUP: pType = "Deduplicated volume"; break;
|
||||
case IO_REPARSE_TAG_NFS: pType = "NFS share"; break;
|
||||
default: pType = "Unknown type! Please report its value and update readlink.c."; break;
|
||||
}
|
||||
DEBUG_PRINT_INDENT();
|
||||
printf("ReparseTag = 0x%04X; // %s\n", (unsigned)(dwTag), pType);
|
||||
)
|
||||
XDEBUG_PRINTF(("ReparseDataLength = 0x%04X\n", (unsigned)(pIoctlBuf->ReparseDataLength)));
|
||||
|
||||
/* Process the supported tag types */
|
||||
switch (dwTag) {
|
||||
case IO_REPARSE_TAG_SYMLINK:
|
||||
pSymlinkBuf = (PSYMLINK_READ_BUFFER)iobuf;
|
||||
XDEBUG_PRINTF(("SubstituteNameOffset = 0x%04X\n", (unsigned)(pSymlinkBuf->SubstituteNameOffset)));
|
||||
XDEBUG_PRINTF(("SubstituteNameLength = 0x%04X\n", (unsigned)(pSymlinkBuf->SubstituteNameLength)));
|
||||
XDEBUG_PRINTF(("PrintNameOffset = 0x%04X\n", (unsigned)(pSymlinkBuf->PrintNameOffset)));
|
||||
XDEBUG_PRINTF(("PrintNameLength = 0x%04X\n", (unsigned)(pSymlinkBuf->PrintNameLength)));
|
||||
XDEBUG_PRINTF(("Flags = 0x%04X\n", (unsigned)(pSymlinkBuf->Flags)));
|
||||
|
||||
pwStr = pSymlinkBuf->PathBuffer;
|
||||
offset = pSymlinkBuf->SubstituteNameOffset / 2; /* Convert byte offset to wide characters offset */
|
||||
len = pSymlinkBuf->SubstituteNameLength / 2; /* Convert bytes to wide characters count */
|
||||
break;
|
||||
|
||||
case IO_REPARSE_TAG_MOUNT_POINT: /* aka. junctions */
|
||||
pMountpointBuf = (PMOUNTPOINT_READ_BUFFER)iobuf;
|
||||
XDEBUG_PRINTF(("SubstituteNameOffset = 0x%04X\n", (unsigned)(pMountpointBuf->SubstituteNameOffset)));
|
||||
XDEBUG_PRINTF(("SubstituteNameLength = 0x%04X\n", (unsigned)(pMountpointBuf->SubstituteNameLength)));
|
||||
XDEBUG_PRINTF(("PrintNameOffset = 0x%04X\n", (unsigned)(pMountpointBuf->PrintNameOffset)));
|
||||
XDEBUG_PRINTF(("PrintNameLength = 0x%04X\n", (unsigned)(pMountpointBuf->PrintNameLength)));
|
||||
|
||||
pwStr = pMountpointBuf->PathBuffer;
|
||||
offset = pMountpointBuf->SubstituteNameOffset / 2; /* Convert byte offset to wide characters offset */
|
||||
len = pMountpointBuf->SubstituteNameLength / 2; /* Convert bytes to wide characters count */
|
||||
break;
|
||||
|
||||
default:
|
||||
errno = EINVAL;
|
||||
RETURN_INT_COMMENT(0, ("Unsupported reparse point type\n"));
|
||||
}
|
||||
if (len) {
|
||||
if (len >= bufsize) {
|
||||
errno = ENAMETOOLONG;
|
||||
RETURN_INT_COMMENT(0, ("The output buffer is too small. The link size is %d bytes.\n", len));
|
||||
}
|
||||
CopyMemory(buf, pwStr+offset, len*sizeof(WCHAR));
|
||||
}
|
||||
buf[len] = L'\0';
|
||||
|
||||
DEBUG_WSTR2NEWUTF8(buf, pszUtf8);
|
||||
DEBUG_LEAVE(("return 0x%X; // \"%s\"\n", dwTag, pszUtf8));
|
||||
DEBUG_FREEUTF8(pszUtf8);
|
||||
return dwTag;
|
||||
}
|
||||
|
||||
/* Posix routine readlink - Wide char version */
|
||||
ssize_t readlinkW(const WCHAR *path, WCHAR *buf, size_t bufsize) {
|
||||
ssize_t nRead;
|
||||
UINT drvType;
|
||||
DWORD dwTag;
|
||||
DEBUG_CODE(
|
||||
char *pszUtf8;
|
||||
)
|
||||
|
||||
DEBUG_WSTR2NEWUTF8(path, pszUtf8);
|
||||
DEBUG_ENTER(("readlink(\"%s\", 0x%p, %d);\n", pszUtf8, buf, bufsize));
|
||||
DEBUG_FREEUTF8(pszUtf8);
|
||||
|
||||
dwTag = ReadReparsePointW(path, buf, bufsize);
|
||||
if (!dwTag) {
|
||||
RETURN_INT_COMMENT(-1, ("ReadReparsePointW() failed.\n"));
|
||||
}
|
||||
|
||||
/* Special case for junctions to other local directories: Remove their '\??\' header.
|
||||
// Note: Also seen once on a symlink. I don't know why in most cases symlinks don't have it.
|
||||
// Note: These junctions begin with '\??\C:\' (or another drive letter).
|
||||
// Other types of junctions/mount points do not continue with a drive letter.
|
||||
// For example: '\??\Volume{5e58015c-ba64-4048-928d-06aa03c983f9}\' */
|
||||
nRead = lstrlenW(buf);
|
||||
#define strncmpW(s1, s2, l) (CompareStringW(LOCALE_INVARIANT, 0, s1, l, s2, l)-2)
|
||||
if ((nRead >= 7) && (!strncmpW(buf, L"\\??\\", 4))) {
|
||||
if (!strncmpW(buf+5, L":\\", 2)) {
|
||||
nRead -= 4;
|
||||
CopyMemory(buf, buf+4, (nRead+1)*sizeof(WCHAR));
|
||||
DEBUG_WSTR2NEWUTF8(buf, pszUtf8);
|
||||
XDEBUG_PRINTF(("buf = \"%s\"; // Removed '\\\\?\\': \n", pszUtf8));
|
||||
DEBUG_FREEUTF8(pszUtf8);
|
||||
} else { /* Return an error for other types, as Posix SW cannot handle them successfully. */
|
||||
errno = EINVAL;
|
||||
DEBUG_WSTR2NEWUTF8(buf+4, pszUtf8);
|
||||
DEBUG_LEAVE(("return -1; // Unsupported mount point type: %s\n", pszUtf8));
|
||||
DEBUG_FREEUTF8(pszUtf8);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fix junctions targets */
|
||||
/* Windows resolves junctions on the server side,
|
||||
but symlinks and symlinkds on the client side. */
|
||||
if (dwTag == IO_REPARSE_TAG_MOUNT_POINT) {
|
||||
char szRootDir[4] = "C:\\";
|
||||
WCHAR wszAbsPath[PATH_MAX];
|
||||
WCHAR wszAbsPath2[PATH_MAX];
|
||||
WCHAR *p1;
|
||||
WCHAR *p2;
|
||||
WCHAR *pc1 = L"A";
|
||||
WCHAR *pc2 = L"a";
|
||||
|
||||
DEBUG_WSTR2NEWUTF8(buf, pszUtf8);
|
||||
XDEBUG_PRINTF(("rawJunctionTarget = \"%s\"\n", pszUtf8));
|
||||
DEBUG_FREEUTF8(pszUtf8);
|
||||
|
||||
GetFullPathNameW(path, PATH_MAX, wszAbsPath, NULL); /* Get the drive letter in the full path */
|
||||
szRootDir[0] = (char)(wszAbsPath[0]); /* Copy the drive letter */
|
||||
drvType = GetDriveType(szRootDir);
|
||||
XDEBUG_PRINTF(("GetDriveType(\"%s\") = %d // %s drive\n", szRootDir, drvType, (drvType == DRIVE_REMOTE) ? "Network" : "Local"));
|
||||
|
||||
/* 1) On network drives, the target should reference the network drive itself,
|
||||
not a local drive on the remote machine */
|
||||
if (drvType == DRIVE_REMOTE) {
|
||||
/* Then check if the junction target is relative to the same network drive. (Not always true!) */
|
||||
int iTargetFound = FALSE;
|
||||
if (buf[0] && (buf[1] == L':')) {
|
||||
WCHAR wszLocalName[] = L"X:";
|
||||
WCHAR wszRemoteName[PATH_MAX];
|
||||
DWORD dwErr;
|
||||
DWORD dwLength = PATH_MAX;
|
||||
wszLocalName[0] = wszAbsPath[0];
|
||||
dwErr = WNetGetConnectionW(wszLocalName, wszRemoteName, &dwLength);
|
||||
if (dwErr == NO_ERROR) {
|
||||
WCHAR *pwsz;
|
||||
DEBUG_WSTR2NEWUTF8(wszRemoteName, pszUtf8);
|
||||
XDEBUG_PRINTF(("net use %c: %s\n", (char)(wszLocalName[0]), pszUtf8));
|
||||
DEBUG_FREEUTF8(pszUtf8);
|
||||
if ((wszRemoteName[0] == L'\\') && (wszRemoteName[1] == L'\\')) {
|
||||
pwsz = wcschr(wszRemoteName+2, L'\\');
|
||||
if (pwsz) {
|
||||
if ((pwsz[2] == L'$') && !pwsz[3]) { /* This is the root of a shared drive. Ex: \\server\D$ -> D: */
|
||||
char c1, c2;
|
||||
XDEBUG_PRINTF(("// Checking if it's the root of an X$ shared drive\n"));
|
||||
c1 = (char)toupper((char)pwsz[1]); /* The server-side drive letter of the network share */
|
||||
c2 = (char)toupper((char)buf[0]); /* The server-side drive letter of the junction target */
|
||||
if (c1 == c2) { /* OK, the target is in the same share drive */
|
||||
buf[0] = wszLocalName[0]; /* Make the target accessible locally */
|
||||
iTargetFound = TRUE;
|
||||
XDEBUG_PRINTF(("// Confirmed it's the root of the shared drive\n"));
|
||||
} /* Else the target is not accessible locally via its target name */
|
||||
} else { /* Heuristic: Assume the share name is an alias to the root on the network drive. Ex: \\server\DROOT -> D:\ */
|
||||
DWORD dwAttr;
|
||||
XDEBUG_PRINTF(("// Checking if it's an alias of the root of the shared drive\n"));
|
||||
buf[0] = wszAbsPath[0];
|
||||
dwAttr = GetFileAttributesW(buf);
|
||||
DEBUG_WSTR2NEWUTF8(buf, pszUtf8);
|
||||
XDEBUG_PRINTF(("GetFileAttributes(\"%s\") = 0x%lX\n", pszUtf8, dwAttr));
|
||||
DEBUG_FREEUTF8(pszUtf8);
|
||||
if (dwAttr != INVALID_FILE_ATTRIBUTES) {
|
||||
iTargetFound = TRUE;
|
||||
XDEBUG_PRINTF(("// Confirmed it's an alias of the root of the shared drive\n"));
|
||||
} else { /* Heuristic: Assume the share name is a subdirectory name on the network drive. Ex: \\server\Public -> C:\Public */
|
||||
WCHAR *pwsz2;
|
||||
XDEBUG_PRINTF(("// Checking if it's first level shared directory\n"));
|
||||
pwsz2 = wcschr(buf+3, L'\\');
|
||||
if (pwsz2) {
|
||||
CopyMemory(buf+2, pwsz2, (lstrlenW(pwsz2)+1)*sizeof(WCHAR));
|
||||
dwAttr = GetFileAttributesW(buf);
|
||||
DEBUG_WSTR2NEWUTF8(buf, pszUtf8);
|
||||
XDEBUG_PRINTF(("GetFileAttributes(\"%s\") = 0x%lX\n", pszUtf8, dwAttr));
|
||||
DEBUG_FREEUTF8(pszUtf8);
|
||||
if (dwAttr != INVALID_FILE_ATTRIBUTES) {
|
||||
iTargetFound = TRUE;
|
||||
XDEBUG_PRINTF(("// Confirmed it's a first level shared directory\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* To do:
|
||||
The above code works for network drives shared at the root level and one level below.
|
||||
Ex: N: is \\server\C$
|
||||
junction target C:\Public\Temp\target.txt on N:
|
||||
Resolves to N:\Public\Temp\target.txt
|
||||
Ex: If N: is \\server\Public, which is shared directory C:\Public,
|
||||
junction target C:\Public\Temp\target.txt on N:
|
||||
Should resolve to N:\Temp\target.txt
|
||||
Actually this could be extended by checking every possible parent path,
|
||||
to support cases where the junction is on a shared level2 or below subdirectory.
|
||||
Note that the share name is not always the same as the subdirectory
|
||||
name, nor is it even in the server's root.
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!iTargetFound) {
|
||||
#if 0 /* Initial implementation, which would have cause problems */
|
||||
lstrcpynW(buf, path, (int)bufsize); /* Report the target as identical to the source, to allow resolving it on the server side */
|
||||
buf[bufsize-1] = L'\0';
|
||||
nRead = lstrlenW(path);
|
||||
RETURN_INT_COMMENT((int)nRead, ("Cannot get to the real target, which is on another server drive.\n"));
|
||||
#else
|
||||
errno = EINVAL;
|
||||
RETURN_INT_COMMENT(-1, ("Inaccessible junction target, on another server drive.\n"));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* 2) Convert absolute junction targets to relative links, if possible.
|
||||
This is useful because junctions are often used as substitutes
|
||||
for symlinkds. But Windows always records absolute target paths,
|
||||
even when relative paths were used for creating them. */
|
||||
GetFullPathNameW(buf, PATH_MAX, wszAbsPath2, NULL);
|
||||
DEBUG_WSTR2NEWUTF8(wszAbsPath, pszUtf8);
|
||||
XDEBUG_PRINTF(("szAbsPath = \"%s\"\n", pszUtf8));
|
||||
DEBUG_FREEUTF8(pszUtf8);
|
||||
DEBUG_WSTR2NEWUTF8(wszAbsPath2, pszUtf8);
|
||||
XDEBUG_PRINTF(("szAbsPath2 = \"%s\"\n", pszUtf8));
|
||||
DEBUG_FREEUTF8(pszUtf8);
|
||||
/* Find the first (case insensitive) difference */
|
||||
for (p1=wszAbsPath, p2=wszAbsPath2; (*pc1 = *p1) && (*pc2 = *p2); p1++, p2++) {
|
||||
CharLowerW(pc1);
|
||||
CharLowerW(pc2);
|
||||
if (*pc1 != *pc2) break;
|
||||
}
|
||||
if (p1 != wszAbsPath) { /* Both are on the same drive. Can be made relative. */
|
||||
WCHAR *pc;
|
||||
/* Backtrack to the last \ */
|
||||
for ( ; *(p1-1) != L'\\'; p1--, p2--) ;
|
||||
DEBUG_WSTR2NEWUTF8(p1, pszUtf8);
|
||||
XDEBUG_PRINTF(("szRelPath1 = \"%s\"\n", pszUtf8));
|
||||
DEBUG_FREEUTF8(pszUtf8);
|
||||
DEBUG_WSTR2NEWUTF8(p2, pszUtf8);
|
||||
XDEBUG_PRINTF(("szRelPath2 = \"%s\"\n", pszUtf8));
|
||||
DEBUG_FREEUTF8(pszUtf8);
|
||||
buf[0] = '\0';
|
||||
/* Count the # of parent directories that remain in path 1 */
|
||||
for (pc=p1; *pc; pc++) if (*pc == L'\\') lstrcatW(buf, L"..\\");
|
||||
/* Append what remains in path 2 */
|
||||
lstrcatW(buf, p2);
|
||||
/* That's the relative link */
|
||||
nRead = lstrlenW(buf);
|
||||
} /* Else the drives differ. Paths cannot be relative. Don't change buf. */
|
||||
}
|
||||
|
||||
DEBUG_WSTR2NEWUTF8(buf, pszUtf8);
|
||||
DEBUG_LEAVE(("return %d; // \"%s\"\n", (int)nRead, pszUtf8));
|
||||
DEBUG_FREEUTF8(pszUtf8);
|
||||
return (int)nRead;
|
||||
}
|
||||
|
||||
#pragma warning(default:4706)
|
||||
|
||||
/* Posix routine readlink - MultiByte char version */
|
||||
ssize_t readlinkM(const char *path, char *buf, size_t bufsize, UINT cp) {
|
||||
WCHAR wszPath[PATH_MAX];
|
||||
WCHAR wszTarget[PATH_MAX];
|
||||
int n;
|
||||
ssize_t nResult;
|
||||
char *pszDefaultChar;
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
path, /* lpMultiByteStr, */
|
||||
wszPath, /* lpWideCharStr, */
|
||||
COUNTOF(wszPath) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
DEBUG_PRINTF(("readlinkM(\"%s\", ...); // Conversion to Unicode failed. errno=%d - %s\n", path, errno, strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
nResult = readlinkW(wszPath, wszTarget, PATH_MAX);
|
||||
if (nResult <= 0) return nResult;
|
||||
|
||||
pszDefaultChar = (cp == CP_UTF8) ? NULL : "?";
|
||||
n = WideCharToMultiByte(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
wszTarget, /* lpWideCharStr, */
|
||||
(int)nResult + 1, /* cchWideChar, */
|
||||
buf, /* lpMultiByteStr, */
|
||||
(int)bufsize, /* cbMultiByte, */
|
||||
pszDefaultChar, /* lpDefaultChar, */
|
||||
NULL /* lpUsedDefaultChar */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
DEBUG_PRINTF(("readlinkM(\"%s\", ...); // Conversion back from Unicode failed. errno=%d - %s\n", path, errno, strerror(errno)));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,600 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename realpath.c *
|
||||
* *
|
||||
* Description Resolve links and remove . and .. parts in pathnames *
|
||||
* *
|
||||
* Notes TO DO: Make Wide & MultiByte versions for Windows *
|
||||
* *
|
||||
* TO DO: Microsoft provides a convenient routine, for which *
|
||||
* we could provide a MultiByte version: (in MSVC's stdlib.h)*
|
||||
* char *_fullpath(char *absPath, const char *relPath, size_t maxLength); *
|
||||
* *
|
||||
* History *
|
||||
* 2014-02-10 JFL Created this module with routine ResolveLinks() for Win32.*
|
||||
* 2014-02-19 JFL Added OS-independant CompactPath() subroutine. *
|
||||
* 2014-02-20 JFL Implemented realpath() for both DOS and Windows. *
|
||||
* 2014-03-06 JFL Check for buffer overflows, and return ENAMETOOLONG. *
|
||||
* 2014-07-02 JFL Added support for pathnames >= 260 characters. *
|
||||
* 2016-08-25 JFL Added routine ResolveLinksA(). *
|
||||
* 2016-09-12 JFL Moved GetFileAttributesU() to its own module. *
|
||||
* Bug fix: Add the drive letter if it's not specified. *
|
||||
* Bug fix: Detect and report output buffer overflows. *
|
||||
* Convert short WIN32 paths to long paths. *
|
||||
* 2016-09-13 JFL Resize output buffers, to avoid wasting lots of memory. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <direct.h> /* For _getdcwd() */
|
||||
#include <ctype.h> /* For toupper() */
|
||||
#include "msvcDebugm.h"
|
||||
#include "msvcLimits.h"
|
||||
#include "msvcUnistd.h"
|
||||
#include "msvcWindows.h"
|
||||
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function CompactPath |
|
||||
| |
|
||||
| Description Remove all ., .., and extra / or \ separators in a path |
|
||||
| |
|
||||
| Parameters const char *path Pathname to cleanup |
|
||||
| char *buf Output buffer |
|
||||
| size_t bufsize Size of the output buffer |
|
||||
| |
|
||||
| Notes Allows having path = outbuf, ie. in-place compacting. |
|
||||
| Supports both relative and absolute paths. |
|
||||
| |
|
||||
| Returns 0 = success, or -1 = error, with errno set |
|
||||
| |
|
||||
| History |
|
||||
| 2014-02-19 JFL Created this routine |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
int CompactPath(const char *path, char *outbuf, size_t bufsize) {
|
||||
const char *pcIn;
|
||||
char *pcOut;
|
||||
int i, j, inSize, outSize;
|
||||
char c = '\0';
|
||||
char lastc = '\0';
|
||||
#define MAX_SUBDIRS (PATH_MAX / 2) /* Worst case is: \1\1\1\1\1\1... */
|
||||
const char *pParts[MAX_SUBDIRS];
|
||||
int lParts[MAX_SUBDIRS];
|
||||
int lPart = 0;
|
||||
int nParts = 0;
|
||||
int isAbsolute = FALSE;
|
||||
int nDotDotParts = 0;
|
||||
|
||||
pcIn = path;
|
||||
inSize = (int)strlen(path) + 1;
|
||||
pcOut = outbuf;
|
||||
outSize = (int)bufsize;
|
||||
|
||||
if (*pcIn && (pcIn[1] == ':')) { /* There's a drive letter */
|
||||
*(pcOut++) = *(pcIn++); /* Copy it */
|
||||
*(pcOut++) = *(pcIn++);
|
||||
inSize -= 2;
|
||||
outSize -= 2;
|
||||
}
|
||||
|
||||
/* Scan the input pathname, recording pointers to every part of the pathname */
|
||||
for (i=0; i<inSize; i++) {
|
||||
c = pcIn[i];
|
||||
if (c == '/') c = '\\';
|
||||
if ((c == '\\') && (lastc == '\\')) continue; /* Condense multiple \ into one */
|
||||
if ((c == '\\') && (lastc == '\0')) { /* This is an absolute pathname */
|
||||
isAbsolute = TRUE;
|
||||
lastc = c;
|
||||
continue;
|
||||
}
|
||||
if ((c != '\\') && ((lastc == '\\') || (lastc == '\0'))) { /* Beginning of a new node */
|
||||
if (nParts == MAX_SUBDIRS) {
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
pParts[nParts] = pcIn + i;
|
||||
lPart = 0;
|
||||
}
|
||||
if (c && (c != '\\')) {
|
||||
lPart += 1;
|
||||
} else { /* End of a node */
|
||||
lParts[nParts++] = lPart;
|
||||
XDEBUG_PRINTF(("pParts[%d] = \"%.*s\"\n", nParts-1, lPart, pParts[nParts-1]));
|
||||
}
|
||||
lastc = c;
|
||||
if (c == '\0') break;
|
||||
}
|
||||
|
||||
/* Eliminate . and .. parts */
|
||||
for (i=0; i<nParts; i++) {
|
||||
XDEBUG_PRINTF(("for pParts[%d] = \"%.*s\"\n", i, lParts[i], pParts[i]));
|
||||
if ((pParts[i][0] == '.') && (lParts[i] == 1)) { /* It's a . part */
|
||||
its_a_dot_part:
|
||||
XDEBUG_PRINTF(("It's a '.'. Removing part #%d\n", i));
|
||||
nParts -= 1;
|
||||
for (j=i; j<nParts; j++) {
|
||||
pParts[j] = pParts[j+1];
|
||||
lParts[j] = lParts[j+1];
|
||||
}
|
||||
i -= 1;
|
||||
continue;
|
||||
}
|
||||
if ((pParts[i][0] == '.') && (pParts[i][1] == '.') && (lParts[i] == 2)) { /* It's a .. part */
|
||||
if (i == nDotDotParts) {
|
||||
XDEBUG_PRINTF(("It's a '..', but it's at the root.\n"));
|
||||
if (isAbsolute) goto its_a_dot_part; /* .. in root is like . */
|
||||
nDotDotParts += 1; /* Else for relative paths, keep this .. */
|
||||
continue;
|
||||
}
|
||||
XDEBUG_PRINTF(("It's a '..'. Removing parts #%d and #%d\n", i-1, i));
|
||||
nParts -= 2;
|
||||
for (j=i-1; j<nParts; j++) {
|
||||
pParts[j] = pParts[j+2];
|
||||
lParts[j] = lParts[j+2];
|
||||
}
|
||||
i -= 2;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Join all remaining parts into a single path */
|
||||
if (!outSize) {
|
||||
not_compact_enough:
|
||||
errno = ENAMETOOLONG;
|
||||
return -1;
|
||||
}
|
||||
outSize -= 1; /* Leave room for the final NUL */
|
||||
if (isAbsolute) {
|
||||
if (!outSize) goto not_compact_enough;
|
||||
*(pcOut++) = '\\';
|
||||
outSize -= 1;
|
||||
}
|
||||
if (nParts) {
|
||||
/* Copy part 0 if it's not already at the right place */
|
||||
if (lParts[0] > outSize) goto not_compact_enough;
|
||||
if (pcOut != pParts[0]) strncpy(pcOut, pParts[0], lParts[0]);
|
||||
pcOut += lParts[0];
|
||||
outSize -= lParts[0];
|
||||
} else {
|
||||
if (pcOut == outbuf) {
|
||||
if (!outSize) goto not_compact_enough;
|
||||
*(pcOut++) = '.'; /* Special case for "subdir\..", which is "." and not "" */
|
||||
outSize -= 1;
|
||||
}
|
||||
}
|
||||
for (i=1; i<nParts; i++) {
|
||||
if (!outSize) goto not_compact_enough;
|
||||
*(pcOut++) = '\\';
|
||||
outSize -= 1;
|
||||
if (lParts[i] > outSize) goto not_compact_enough;
|
||||
if (pcOut != pParts[i]) strncpy(pcOut, pParts[i], lParts[i]);
|
||||
pcOut += lParts[i];
|
||||
outSize -= lParts[i];
|
||||
}
|
||||
*pcOut = '\0';
|
||||
|
||||
return (int)(pcOut - outbuf);
|
||||
}
|
||||
|
||||
|
||||
#ifdef _MSDOS
|
||||
|
||||
/* Standard C library routine realpath() */
|
||||
/* Normally defined in stdlib.h. Output buf must contain PATH_MAX bytes */
|
||||
char *realpath(const char *path, char *outbuf) {
|
||||
char *pOutbuf = outbuf;
|
||||
int iErr;
|
||||
const char *pc;
|
||||
|
||||
if (!pOutbuf) pOutbuf = malloc(PATH_MAX);
|
||||
if (!pOutbuf) {
|
||||
errno = ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Convert relative paths to absolute paths */
|
||||
pc = path;
|
||||
if (pc[0] && (pc[1] == ':')) pc += 2; /* Skip the drive letter, if any */
|
||||
if ((*pc != '/') && (*pc != '\\')) { /* This is a relative path */
|
||||
int iDrive = 0;
|
||||
if (pc != path) { /* A drive was specified */
|
||||
iDrive = _toupper(path[0]) - '@'; /* A=1, B=2, ... */
|
||||
}
|
||||
_getdcwd(iDrive, pOutbuf, PATH_MAX);
|
||||
if ((strlen(pOutbuf) + strlen(pc) + 2) > PATH_MAX) {
|
||||
realpath_failed:
|
||||
errno = ENAMETOOLONG;
|
||||
if (!outbuf) free(pOutbuf);
|
||||
return NULL;
|
||||
}
|
||||
strcat(pOutbuf, "\\");
|
||||
strcat(pOutbuf, pc);
|
||||
path = pOutbuf;
|
||||
} else if (pc == path) { /* This is an absolute path without a drive letter */
|
||||
pOutbuf[0] = (char)(_getdrive() + 0x40);
|
||||
pOutbuf[1] = ':';
|
||||
if ((strlen(path) + 3) > PATH_MAX) goto realpath_failed;
|
||||
strcpy(pOutbuf+2, path);
|
||||
path = pOutbuf;
|
||||
}
|
||||
|
||||
/* TO DO: Resolve substituted drives */
|
||||
|
||||
/* TO DO: Convert short paths to long paths, and correct the name case */
|
||||
|
||||
/* Remove useless parts in the absolute path */
|
||||
iErr = CompactPath(path, pOutbuf, PATH_MAX);
|
||||
if (iErr == -1) { /* CompactPath() sets errno */
|
||||
if (!outbuf) free(pOutbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!outbuf) pOutbuf = realloc(pOutbuf, strlen(pOutbuf) + 1);
|
||||
return pOutbuf;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h> /* Also includes MsvcLibX' WIN32 UTF-8 extensions */
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function ResolveLinks |
|
||||
| |
|
||||
| Description Resolve all link names within a pathname |
|
||||
| |
|
||||
| Parameters const char *path Pathname to resolve |
|
||||
| char *buf Output buffer |
|
||||
| size_t bufsize Size of the output buffer |
|
||||
| |
|
||||
| Notes Description of the official path resolution process: |
|
||||
| http://man7.org/linux/man-pages/man7/path_resolution.7.html
|
||||
| |
|
||||
| This function always returns a valid string in the output |
|
||||
| buffer, even when it fails. This allows displaying a clue |
|
||||
| about at which stage of the resolution things went wrong. |
|
||||
| |
|
||||
| Returns 0 = success, or -1 = error, with errno set |
|
||||
| |
|
||||
| History |
|
||||
| 2014-02-07 JFL Created this routine |
|
||||
| 2014-07-02 JFL Added support for pathnames >= 260 characters. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Linked list of previous pathnames */
|
||||
typedef struct _NAMELIST {
|
||||
struct _NAMELIST *prev;
|
||||
char *path;
|
||||
} NAMELIST;
|
||||
|
||||
/* Get the canonic name of a file, after resolving all links in its pathname */
|
||||
int ResolveLinksU1(const char *path, char *buf, size_t bufsize, NAMELIST *prev, int iDepth) {
|
||||
char target[UTF8_PATH_MAX];
|
||||
int i;
|
||||
int iErr = 0;
|
||||
DWORD dwAttr;
|
||||
char c = '\0';
|
||||
int iPath = 0;
|
||||
int bFirst = 1;
|
||||
ssize_t nRead;
|
||||
int iBuf = 0;
|
||||
NAMELIST list;
|
||||
NAMELIST *pList;
|
||||
|
||||
DEBUG_ENTER(("ResolveLinks1(\"%s\", 0x%p, %ld, 0x%p, %d);\n", path, buf, bufsize, prev, iDepth));
|
||||
|
||||
while (path[iPath]) {
|
||||
/* int iPath0 = iPath; */
|
||||
/* int iBuf0 = iBuf; */
|
||||
int iBuf1;
|
||||
/* Append the first name section to the output buffer */
|
||||
if (bFirst) {
|
||||
bFirst = 0;
|
||||
/* Special case of absolute pathnames */
|
||||
if (path[0] == '\\') {
|
||||
if ((iBuf+1U) >= bufsize) {
|
||||
resolves_too_long:
|
||||
errno = ENAMETOOLONG;
|
||||
RETURN_INT_COMMENT(-1, ("Name too long\n"));
|
||||
}
|
||||
c = buf[iBuf++] = path[iPath++]; /* Copy the root \ . */
|
||||
/* DEBUG_PRINTF(("buf[%d] = %c\n", iBuf-1, c)); */
|
||||
} else if (path[0] && (path[1] == ':')) {
|
||||
if ((iBuf+1U) >= bufsize) goto resolves_too_long;
|
||||
c = buf[iBuf++] = path[iPath++]; /* Copy the drive letter */
|
||||
/* DEBUG_PRINTF(("buf[%d] = %c\n", iBuf-1, c)); */
|
||||
if ((iBuf+1U) >= bufsize) goto resolves_too_long;
|
||||
c = buf[iBuf++] = path[iPath++]; /* and the : */
|
||||
/* DEBUG_PRINTF(("buf[%d] = %c\n", iBuf-1, c)); */
|
||||
if (path[iPath] == '\\') {
|
||||
if ((iBuf+1U) >= bufsize) goto resolves_too_long;
|
||||
c = buf[iBuf++] = path[iPath++];
|
||||
/* DEBUG_PRINTF(("buf[%d] = %c\n", iBuf-1, c)); */
|
||||
}
|
||||
} /* Else it's a relative pathname, handled in the common code below */
|
||||
} else { /* It's a continuation section in the path */
|
||||
if ((iBuf+1U) >= bufsize) goto resolves_too_long;
|
||||
buf[iBuf++] = '\\';
|
||||
}
|
||||
iBuf1 = iBuf; /* Index of the beginning of the node name we're about to add */
|
||||
for (i=0; (size_t)(iBuf+i) < (bufsize-1) ;i++) {
|
||||
c = path[iPath+i];
|
||||
if (!c) break;
|
||||
/* if (c == '/') break; */
|
||||
if (c == '\\') break;
|
||||
/* DEBUG_PRINTF(("buf[%d] = %c\n", iBuf+i, c)); */
|
||||
buf[iBuf+i] = c;
|
||||
}
|
||||
iBuf += i;
|
||||
buf[iBuf] = '\0';
|
||||
while (c && (/* (c == '/') || */ (c == '\\'))) c=path[iPath + ++i]; /* Skip extra /, if any */
|
||||
iPath += i;
|
||||
/* DEBUG_PRINTF(("// Removed %d characters from path\n", iPath - iPath0)); */
|
||||
/* Get the file type */
|
||||
dwAttr = GetFileAttributesU(buf);
|
||||
DEBUG_PRINTF(("// \"%s\" is %s\n", buf, (dwAttr == INVALID_FILE_ATTRIBUTES)?"not found":(
|
||||
(dwAttr & FILE_ATTRIBUTE_REPARSE_POINT)?"a reparse point":(
|
||||
(dwAttr & FILE_ATTRIBUTE_DIRECTORY)?"a directory":"a file"))));
|
||||
if (dwAttr == INVALID_FILE_ATTRIBUTES) {
|
||||
errno = ENOENT;
|
||||
if (path[iPath]) { /* Append the remainder of the input path, even though we know it's invalid */
|
||||
if ((iBuf+1U+lstrlen(path+iPath)) < bufsize) {
|
||||
buf[iBuf++] = '\\';
|
||||
lstrcpy(buf+iBuf, path+iPath);
|
||||
}
|
||||
}
|
||||
RETURN_INT_COMMENT(-1, ("No such file: \"%s\"\n", buf));
|
||||
}
|
||||
if (dwAttr & FILE_ATTRIBUTE_REPARSE_POINT) {
|
||||
nRead = readlinkU(buf, target, sizeof(target));
|
||||
if (nRead == -1) {
|
||||
if (errno == EINVAL) { /* This is a reparse point, but not a symlink or a junction */
|
||||
goto file_or_directory;
|
||||
}
|
||||
/* Anything else is a real error, and resolution cannot be done. */
|
||||
if (path[iPath]) { /* Append the remainder of the input path, even though we know it's invalid */
|
||||
if ((iBuf+1U+lstrlen(path+iPath)) < bufsize) {
|
||||
buf[iBuf++] = '\\';
|
||||
lstrcpy(buf+iBuf, path+iPath);
|
||||
}
|
||||
}
|
||||
RETURN_INT_COMMENT(-1, ("Dangling link: \"%s\"\n", buf));
|
||||
}
|
||||
if ((dwAttr & FILE_ATTRIBUTE_DIRECTORY) && !lstrcmp(buf, target)) {
|
||||
/* This is probably a junction pointing to an otherwise inaccessible area.
|
||||
(See readlink() header in readlink.c for details about this case.)
|
||||
Handle this junction like if it were a real directory, instead of a symlink. */
|
||||
goto file_or_directory;
|
||||
}
|
||||
if ( ((target[0] == '\\') /* || (target[0] == '/') */ )
|
||||
|| (target[1] == ':')) { /* This is an absolute pathname */
|
||||
DEBUG_PRINTF(("// Absolute link to \"%s\"\n", target));
|
||||
iBuf = (int)lstrlen(target); /* Anticipate the new position after copying */
|
||||
if ((size_t)iBuf >= bufsize) goto resolves_too_long;
|
||||
lstrcpy(buf, target);
|
||||
} else { /* This is a relative pathname */
|
||||
DEBUG_PRINTF(("// Relative link to \"%s\"\n", target));
|
||||
/* So it'll replace the tail name in the output path */
|
||||
iBuf = iBuf1; /* The index right after the last path separator */
|
||||
DEBUG_PRINTF(("AppendPath(\"%.*s\", \"%s\"); // Target tail\n", iBuf, buf, target));
|
||||
if (((size_t)iBuf+lstrlen(target)) >= bufsize) goto resolves_too_long;
|
||||
lstrcpy(buf+iBuf, target);
|
||||
iBuf = CompactPath(buf, buf, bufsize);
|
||||
}
|
||||
/* Append the remainder of the input path, if any */
|
||||
DEBUG_PRINTF(("AppendPath(\"%s\", \"%s\"); // Path tail\n", buf, path+iPath));
|
||||
if (path[iPath]) {
|
||||
if (iBuf && (buf[iBuf-1] != '\\')) {
|
||||
if ((iBuf+1U) >= bufsize) goto resolves_too_long;
|
||||
buf[iBuf++] = '\\';
|
||||
}
|
||||
if (((size_t)iBuf+lstrlen(path+iPath)) >= bufsize) goto resolves_too_long;
|
||||
lstrcpy(buf+iBuf, path+iPath);
|
||||
iBuf = CompactPath(buf, buf, bufsize);
|
||||
}
|
||||
/* Check for max depth */
|
||||
if (iDepth == SYMLOOP_MAX) {
|
||||
errno = ELOOP;
|
||||
RETURN_INT_COMMENT(-1, ("Max symlink depth reached: \"%s\"\n", buf));
|
||||
}
|
||||
/* Check for loops */
|
||||
for (pList = prev ; pList; pList = pList->prev) {
|
||||
if (!lstrcmpi(buf, pList->path)) {
|
||||
errno = ELOOP;
|
||||
RETURN_INT_COMMENT(-1, ("Loop found: \"%s\"\n", buf));
|
||||
}
|
||||
}
|
||||
/* OK, no loop, so repeat the process for that new path */
|
||||
lstrcpy(target, buf); /* Keep that as a reference in the linked list, in case there are further links */
|
||||
list.prev = prev;
|
||||
list.path = target;
|
||||
iErr = ResolveLinksU1(target, buf, bufsize, &list, iDepth+1);
|
||||
RETURN_INT_COMMENT(iErr, ("\"%s\"\n", buf));
|
||||
} else { /* It's a normal file or directory */
|
||||
file_or_directory:
|
||||
if ((path[iPath]) && !(dwAttr & FILE_ATTRIBUTE_DIRECTORY)) {
|
||||
errno = ENOTDIR;
|
||||
if ((iBuf+1U+lstrlen(path+iPath)) < bufsize) {
|
||||
buf[iBuf++] = '\\';
|
||||
lstrcpy(buf+iBuf, path+iPath);
|
||||
}
|
||||
RETURN_INT_COMMENT(-1, ("File where dir expected: \"%s\"\n", buf));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
RETURN_INT_COMMENT(0, ("Success: \"%s\"\n", buf));
|
||||
}
|
||||
|
||||
int ResolveLinksU(const char *path, char *buf, size_t bufsize) {
|
||||
char path1[UTF8_PATH_MAX];
|
||||
int nSize;
|
||||
NAMELIST root;
|
||||
int iErr;
|
||||
|
||||
DEBUG_ENTER(("ResolveLinks(\"%s\", 0x%p, %ld);\n", path, buf, bufsize));
|
||||
|
||||
buf[0] = '\0'; /* Always output a valid string */
|
||||
|
||||
if (!*path) { /* Spec says an empty pathname is invalid */
|
||||
errno = ENOENT;
|
||||
RETURN_INT_COMMENT(-1, ("Empty pathname\n"));
|
||||
}
|
||||
|
||||
/* Normalize the input path, using a single \ as path separator */
|
||||
nSize = CompactPath(path, path1, sizeof(path1));
|
||||
if (nSize == -1) { /* CompactPath() already sets errno = ENAMETOOLONG */
|
||||
RETURN_INT_COMMENT(-1, ("Path too long\n"));
|
||||
}
|
||||
if (path1[nSize-1] == '\\') { /* Spec says resolution must implicitly add a trailing dot, */
|
||||
if (nSize == sizeof(path1)) { /* to ensure that the last component is a directory. */
|
||||
errno = ENAMETOOLONG;
|
||||
RETURN_INT_COMMENT(-1, ("Path too long after adding .\n"));
|
||||
}
|
||||
path1[nSize++] = '.'; /* So add it explicitely */
|
||||
path1[nSize] = '\0';
|
||||
}
|
||||
root.path = path1;
|
||||
root.prev = NULL;
|
||||
iErr = ResolveLinksU1(path1, buf, bufsize, &root, 0);
|
||||
nSize = lstrlen(buf);
|
||||
/* Remove the final dot added above, if needed. */
|
||||
if ((nSize >= 2) && (buf[nSize-2] == '\\') && (buf[nSize-1] == '.')) buf[--nSize] = '\0';
|
||||
RETURN_INT_COMMENT(iErr, ("\"%s\"\n", buf));
|
||||
}
|
||||
|
||||
/* ANSI version of the same, built upon the UTF-8 version */
|
||||
int ResolveLinksA(const char *path, char *buf, size_t bufsize) {
|
||||
char pathU[UTF8_PATH_MAX];
|
||||
char pathU2[UTF8_PATH_MAX];
|
||||
WCHAR wszPath[PATH_MAX];
|
||||
int n;
|
||||
int iErr;
|
||||
|
||||
/* Convert the pathname to a unicode string */
|
||||
n = MultiByteToWideChar(CP_ACP, 0, path, (int)strlen(path) + 1, wszPath, PATH_MAX);
|
||||
/* Convert it back to UTF-8 characters */
|
||||
if (n) n = WideCharToMultiByte(CP_UTF8, 0, wszPath, n, pathU, UTF8_PATH_MAX, NULL, NULL);
|
||||
/* Check (unlikely) conversion errors */
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno)));
|
||||
}
|
||||
|
||||
/* Resolve the links */
|
||||
iErr = ResolveLinksU(pathU, pathU2, UTF8_PATH_MAX);
|
||||
|
||||
/* Convert the result back to ANSI */
|
||||
if (!iErr) {
|
||||
n = MultiByteToWideChar(CP_UTF8, 0, pathU2, (int)strlen(pathU2) + 1, wszPath, PATH_MAX);
|
||||
if (n) n = WideCharToMultiByte(CP_ACP, 0, wszPath, n, buf, (int)bufsize, NULL, NULL);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno)));
|
||||
}
|
||||
}
|
||||
|
||||
return iErr;
|
||||
}
|
||||
|
||||
/* Normally defined in stdlib.h. Output buf must contain PATH_MAX bytes */
|
||||
char *realpathU(const char *path, char *outbuf) {
|
||||
char *pOutbuf = outbuf;
|
||||
char *pPath1 = NULL;
|
||||
char *pPath2 = NULL;
|
||||
int iErr;
|
||||
const char *pc;
|
||||
size_t nSize;
|
||||
DEBUG_CODE(
|
||||
char *pszCause = "Out of memory";
|
||||
)
|
||||
int n;
|
||||
|
||||
DEBUG_ENTER(("realpath(\"%s\", 0x%p);\n", path, outbuf));
|
||||
|
||||
if (!pOutbuf) pOutbuf = malloc(UTF8_PATH_MAX);
|
||||
if (!pOutbuf) {
|
||||
realpathU_failed:
|
||||
if (!outbuf) free(pOutbuf);
|
||||
free(pPath1);
|
||||
free(pPath2);
|
||||
errno = ENOMEM;
|
||||
RETURN_CONST_COMMENT(NULL, ("%s\n", pszCause));
|
||||
}
|
||||
|
||||
pPath1 = malloc(UTF8_PATH_MAX);
|
||||
if (!pPath1) goto realpathU_failed;
|
||||
|
||||
pPath2 = malloc(UTF8_PATH_MAX);
|
||||
if (!pPath2) goto realpathU_failed;
|
||||
|
||||
/* Convert relative paths to absolute paths */
|
||||
pc = path;
|
||||
if (pc[0] && (pc[1] == ':')) pc += 2; /* Skip the drive letter, if any */
|
||||
if ((*pc != '/') && (*pc != '\\')) { /* This is a relative path */
|
||||
int iDrive = 0;
|
||||
if (pc != path) { /* A drive was specified */
|
||||
iDrive = toupper(path[0]) - '@'; /* A=1, B=2, ... */
|
||||
}
|
||||
_getdcwdU(iDrive, pPath1, UTF8_PATH_MAX);
|
||||
nSize = UTF8_PATH_MAX - lstrlen(pPath1);
|
||||
if ((lstrlen(pc) + 2U) > nSize) {
|
||||
errno = ENAMETOOLONG;
|
||||
DEBUG_CODE(pszCause = "Path too long after concatenating current dir");
|
||||
goto realpathU_failed;
|
||||
}
|
||||
strcat(pPath1, "\\");
|
||||
strcat(pPath1, pc);
|
||||
path = pPath1;
|
||||
} else if (pc == path) { /* This is an absolute path without a drive letter */
|
||||
pPath1[0] = (char)(_getdrive() + 0x40);
|
||||
pPath1[1] = ':';
|
||||
if (strlen(path) > (UTF8_PATH_MAX-3)) {
|
||||
errno = ENAMETOOLONG;
|
||||
DEBUG_CODE(pszCause = "Path too long after adding drive");
|
||||
goto realpathU_failed;
|
||||
}
|
||||
strcpy(pPath1+2, path);
|
||||
path = pPath1;
|
||||
}
|
||||
|
||||
/* Resolve links in the absolute path */
|
||||
iErr = ResolveLinksU(path, pPath2, UTF8_PATH_MAX);
|
||||
if (iErr == -1) {
|
||||
DEBUG_CODE(pszCause = "Resolution failed");
|
||||
goto realpathU_failed;
|
||||
}
|
||||
|
||||
/* Change short names to long names, and correct the name case */
|
||||
n = GetLongPathNameU(pPath2, pOutbuf, UTF8_PATH_MAX); /* This will NOT correct long names case */
|
||||
if (!n) {
|
||||
DEBUG_CODE(pszCause = "Can't get long pathnames";)
|
||||
goto realpathU_failed;
|
||||
}
|
||||
|
||||
DEBUG_LEAVE(("return 0x%p; // \"%s\"\n", pOutbuf, pOutbuf));
|
||||
if (!outbuf) pOutbuf = realloc(pOutbuf, strlen(pOutbuf) + 1);
|
||||
free(pPath1);
|
||||
free(pPath2);
|
||||
return pOutbuf;
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename spawn.c *
|
||||
* *
|
||||
* Description: WIN32 UTF-8 version of spawn *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-03-27 JFL Created this module. *
|
||||
* 2014-07-03 JFL Added support for pathnames >= 260 characters. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
/* Microsoft C libraries include files */
|
||||
#include <stdio.h>
|
||||
/* MsvcLibX library extensions */
|
||||
#include "msvcDebugm.h"
|
||||
#include "msvclibx.h"
|
||||
#include "msvcLimits.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include <process.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function _spawnvpU |
|
||||
| |
|
||||
| Description UTF-8 version of Microsoft's _spawnvp |
|
||||
| |
|
||||
| Parameters: int iMode Spawning mode. P_WAIT or P_NOWAIT |
|
||||
| char *pszCommand Program to start |
|
||||
| char **argv List of arguments, terminated by NULL |
|
||||
| |
|
||||
| Returns: The exit code (if P_WAIT) or the process ID (if P_NOWAIT) |
|
||||
| |
|
||||
| Notes |
|
||||
| |
|
||||
| History |
|
||||
| 2014-03-04 JFL Created this routine. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
intptr_t _spawnvpU(int iMode, const char *pszCommand, char *const *argv) {
|
||||
WCHAR wszCommand[PATH_MAX];
|
||||
WCHAR **wszArgv;
|
||||
int n;
|
||||
int nArgs;
|
||||
int iArg;
|
||||
intptr_t iRet;
|
||||
|
||||
DEBUG_CODE({
|
||||
int i;
|
||||
DEBUG_PRINTF(("_spawnvpU(%d, \"%s\", {", iMode, pszCommand));
|
||||
if (DEBUG_IS_ON()) {
|
||||
for (i=0; argv[i]; i++) {
|
||||
if (i) printf(", ");
|
||||
printf("\"%s\"", argv[i]);
|
||||
}
|
||||
printf("});\n");
|
||||
}
|
||||
})
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
pszCommand, /* lpMultiByteStr, */
|
||||
wszCommand, /* lpWideCharStr, */
|
||||
COUNTOF(wszCommand) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (nArgs=0; argv[nArgs]; nArgs++) ; /* Count the number of arguments */
|
||||
wszArgv = (WCHAR **)malloc((nArgs+1) * sizeof(WCHAR *));
|
||||
if (!wszArgv) return -1; /* errno already set by malloc */
|
||||
|
||||
for (iArg=0; argv[iArg]; iArg++) { /* Convert every argument */
|
||||
int iArgBufSize = lstrlen(argv[iArg]) + 1;
|
||||
wszArgv[iArg] = malloc(sizeof(WCHAR)*iArgBufSize);
|
||||
if (!wszArgv[iArg]) {
|
||||
while (iArg) free(wszArgv[--iArg]); /* Free the partial arg list */
|
||||
free(wszArgv);
|
||||
return -1; /* errno already set by malloc */
|
||||
}
|
||||
/* Convert the argument to a unicode string. This is not a pathname, so just do a plain conversion */
|
||||
n = MultiByteToWideChar(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
0, /* dwFlags, */
|
||||
argv[iArg], /* lpMultiByteStr, */
|
||||
iArgBufSize, /* cbMultiByte, */
|
||||
wszArgv[iArg], /* lpWideCharStr, */
|
||||
iArgBufSize /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
while (iArg >= 0) free(wszArgv[iArg--]); /* Free the partial arg list */
|
||||
free(wszArgv);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
wszArgv[nArgs] = NULL;
|
||||
|
||||
iRet = _wspawnvp(iMode, wszCommand, wszArgv);
|
||||
|
||||
while (nArgs) free(wszArgv[--nArgs]); /* Free the full arg list */
|
||||
free(wszArgv);
|
||||
return iRet;
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,54 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename strerror.c *
|
||||
* *
|
||||
* Description: WIN32 update of strerror *
|
||||
* *
|
||||
* Notes: MSVC defines error messages only up to errno 42 EILSEQ *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-03-06 JFL Created this module. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include "msvclibx.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function strerror |
|
||||
| |
|
||||
| Description UTF-8 version of strerror |
|
||||
| |
|
||||
| Parameters int errnum Error number |
|
||||
| |
|
||||
| Returns Pointer to the corresponding error message. |
|
||||
| |
|
||||
| Notes |
|
||||
| |
|
||||
| History |
|
||||
| 2014-03-06 JFL Created this routine. |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#pragma warning(disable:4100) /* Ignore the "unreferenced formal parameter" warning */
|
||||
|
||||
char *strerror(int errnum) {
|
||||
switch (errnum) {
|
||||
case ELOOP:
|
||||
return "Symbolic links loop found"; /* Workaround for the missing entry in MSVC list */
|
||||
default:
|
||||
if (errnum > _sys_nerr) errnum = _sys_nerr;
|
||||
return _sys_errlist[errnum];
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename strndup.c *
|
||||
* *
|
||||
* Description: WIN32 port of standard C library's strndup() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-13 JFL Created this module. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/* Duplicate a string, up to at most size characters */
|
||||
char *strndup(const char *s, size_t size) {
|
||||
size_t l;
|
||||
char *s2;
|
||||
l = strlen(s);
|
||||
if (l > size) l=size;
|
||||
s2 = malloc(l+1);
|
||||
if (s2) {
|
||||
strncpy(s2, s, l);
|
||||
s2[l] = '\0';
|
||||
}
|
||||
return s2;
|
||||
}
|
||||
|
|
@ -0,0 +1,396 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename strptime.c *
|
||||
* *
|
||||
* Description: WIN32 port of standard C library's strptime() *
|
||||
* *
|
||||
* Notes: *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-17 JFL Created this module. *
|
||||
* *
|
||||
\*****************************************************************************/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
/*
|
||||
* We do not implement alternate representations. However, we always
|
||||
* check whether a given modifier is allowed for a certain conversion.
|
||||
*/
|
||||
#define ALT_E 0x01
|
||||
#define ALT_O 0x02
|
||||
/* #define LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); } */
|
||||
#define LEGAL_ALT(x) { ; }
|
||||
#define TM_YEAR_BASE (1970)
|
||||
|
||||
static int conv_num(const char **, int *, int, int);
|
||||
static int strncasecmp(char *s1, char *s2, size_t n);
|
||||
|
||||
static const char *day[7] = {
|
||||
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
|
||||
"Friday", "Saturday"
|
||||
};
|
||||
static const char *abday[7] = {
|
||||
"Sun","Mon","Tue","Wed","Thu","Fri","Sat"
|
||||
};
|
||||
static const char *mon[12] = {
|
||||
"January", "February", "March", "April", "May", "June", "July",
|
||||
"August", "September", "October", "November", "December"
|
||||
};
|
||||
static const char *abmon[12] = {
|
||||
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
||||
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
|
||||
};
|
||||
static const char *am_pm[2] = {
|
||||
"AM", "PM"
|
||||
};
|
||||
|
||||
|
||||
#pragma warning(disable:4706) /* Ignore the "assignment within conditional expression" warning */
|
||||
char * strptime(const char *buf, const char *fmt, struct tm *tm)
|
||||
{
|
||||
char c;
|
||||
const char *bp;
|
||||
size_t len = 0;
|
||||
int alt_format, i, split_year = 0;
|
||||
|
||||
bp = buf;
|
||||
|
||||
while ((c = *fmt) != '\0')
|
||||
{
|
||||
/* Clear `alternate' modifier prior to new conversion. */
|
||||
alt_format = 0;
|
||||
|
||||
/* Eat up white-space. */
|
||||
if (isspace(c))
|
||||
{
|
||||
while (isspace(*bp))
|
||||
bp++;
|
||||
|
||||
fmt++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((c = *fmt++) != '%')
|
||||
goto literal;
|
||||
|
||||
|
||||
again: switch (c = *fmt++)
|
||||
{
|
||||
case '%': /* "%%" is converted to "%". */
|
||||
literal:
|
||||
if (c != *bp++)
|
||||
return (0);
|
||||
break;
|
||||
|
||||
/*
|
||||
* "Alternative" modifiers. Just set the appropriate flag
|
||||
* and start over again.
|
||||
*/
|
||||
case 'E': /* "%E?" alternative conversion modifier. */
|
||||
LEGAL_ALT(0);
|
||||
alt_format |= ALT_E;
|
||||
goto again;
|
||||
|
||||
case 'O': /* "%O?" alternative conversion modifier. */
|
||||
LEGAL_ALT(0);
|
||||
alt_format |= ALT_O;
|
||||
goto again;
|
||||
|
||||
/*
|
||||
* "Complex" conversion rules, implemented through recursion.
|
||||
*/
|
||||
case 'c': /* Date and time, using the locale's format. */
|
||||
LEGAL_ALT(ALT_E);
|
||||
if (!(bp = strptime(bp, "%x %X", tm)))
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 'D': /* The date as "%m/%d/%y". */
|
||||
LEGAL_ALT(0);
|
||||
if (!(bp = strptime(bp, "%m/%d/%y", tm)))
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 'R': /* The time as "%H:%M". */
|
||||
LEGAL_ALT(0);
|
||||
if (!(bp = strptime(bp, "%H:%M", tm)))
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 'r': /* The time in 12-hour clock representation. */
|
||||
LEGAL_ALT(0);
|
||||
if (!(bp = strptime(bp, "%I:%M:%S %p", tm)))
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 'T': /* The time as "%H:%M:%S". */
|
||||
LEGAL_ALT(0);
|
||||
if (!(bp = strptime(bp, "%H:%M:%S", tm)))
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 'X': /* The time, using the locale's format. */
|
||||
LEGAL_ALT(ALT_E);
|
||||
if (!(bp = strptime(bp, "%H:%M:%S", tm)))
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 'x': /* The date, using the locale's format. */
|
||||
LEGAL_ALT(ALT_E);
|
||||
if (!(bp = strptime(bp, "%m/%d/%y", tm)))
|
||||
return (0);
|
||||
break;
|
||||
|
||||
/*
|
||||
* "Elementary" conversion rules.
|
||||
*/
|
||||
case 'A': /* The day of week, using the locale's form. */
|
||||
case 'a':
|
||||
LEGAL_ALT(0);
|
||||
for (i = 0; i < 7; i++)
|
||||
{
|
||||
/* Full name. */
|
||||
len = strlen(day[i]);
|
||||
if (strncasecmp((char *)(day[i]), (char *)bp, len) == 0)
|
||||
break;
|
||||
|
||||
/* Abbreviated name. */
|
||||
len = strlen(abday[i]);
|
||||
if (strncasecmp((char *)(abday[i]), (char *)bp, len) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Nothing matched. */
|
||||
if (i == 7)
|
||||
return (0);
|
||||
|
||||
tm->tm_wday = i;
|
||||
bp += len;
|
||||
break;
|
||||
|
||||
case 'B': /* The month, using the locale's form. */
|
||||
case 'b':
|
||||
case 'h':
|
||||
LEGAL_ALT(0);
|
||||
for (i = 0; i < 12; i++)
|
||||
{
|
||||
/* Full name. */
|
||||
|
||||
len = strlen(mon[i]);
|
||||
if (strncasecmp((char *)(mon[i]), (char *)bp, len) == 0)
|
||||
break;
|
||||
|
||||
/* Abbreviated name. */
|
||||
len = strlen(abmon[i]);
|
||||
if (strncasecmp((char *)(abmon[i]),(char *) bp, len) == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
/* Nothing matched. */
|
||||
if (i == 12)
|
||||
return (0);
|
||||
|
||||
tm->tm_mon = i;
|
||||
bp += len;
|
||||
break;
|
||||
|
||||
case 'C': /* The century number. */
|
||||
LEGAL_ALT(ALT_E);
|
||||
if (!(conv_num(&bp, &i, 0, 99)))
|
||||
return (0);
|
||||
|
||||
if (split_year)
|
||||
{
|
||||
tm->tm_year = (tm->tm_year % 100) + (i * 100);
|
||||
} else {
|
||||
tm->tm_year = i * 100;
|
||||
split_year = 1;
|
||||
}
|
||||
break;
|
||||
|
||||
case 'd': /* The day of month. */
|
||||
case 'e':
|
||||
LEGAL_ALT(ALT_O);
|
||||
if (!(conv_num(&bp, &tm->tm_mday, 1, 31)))
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 'k': /* The hour (24-hour clock representation). */
|
||||
LEGAL_ALT(0);
|
||||
/* FALLTHROUGH */
|
||||
case 'H':
|
||||
LEGAL_ALT(ALT_O);
|
||||
if (!(conv_num(&bp, &tm->tm_hour, 0, 23)))
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 'l': /* The hour (12-hour clock representation). */
|
||||
LEGAL_ALT(0);
|
||||
/* FALLTHROUGH */
|
||||
case 'I':
|
||||
LEGAL_ALT(ALT_O);
|
||||
if (!(conv_num(&bp, &tm->tm_hour, 1, 12)))
|
||||
return (0);
|
||||
if (tm->tm_hour == 12)
|
||||
tm->tm_hour = 0;
|
||||
break;
|
||||
|
||||
case 'j': /* The day of year. */
|
||||
LEGAL_ALT(0);
|
||||
if (!(conv_num(&bp, &i, 1, 366)))
|
||||
return (0);
|
||||
tm->tm_yday = i - 1;
|
||||
break;
|
||||
|
||||
case 'M': /* The minute. */
|
||||
LEGAL_ALT(ALT_O);
|
||||
if (!(conv_num(&bp, &tm->tm_min, 0, 59)))
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 'm': /* The month. */
|
||||
LEGAL_ALT(ALT_O);
|
||||
if (!(conv_num(&bp, &i, 1, 12)))
|
||||
return (0);
|
||||
tm->tm_mon = i - 1;
|
||||
break;
|
||||
/*
|
||||
// case 'p': /* The locale's equivalent of AM/PM. */
|
||||
/* LEGAL_ALT(0);
|
||||
// /* AM? */
|
||||
/* if (strcasecmp(am_pm[0], bp) == 0)
|
||||
// {
|
||||
// if (tm->tm_hour > 11)
|
||||
// return (0);
|
||||
//
|
||||
// bp += strlen(am_pm[0]);
|
||||
// break;
|
||||
// }
|
||||
// /* PM? */
|
||||
/* else if (strcasecmp(am_pm[1], bp) == 0)
|
||||
// {
|
||||
// if (tm->tm_hour > 11)
|
||||
// return (0);
|
||||
//
|
||||
// tm->tm_hour += 12;
|
||||
// bp += strlen(am_pm[1]);
|
||||
// break;
|
||||
// }
|
||||
//
|
||||
// /* Nothing matched. */
|
||||
/* return (0);
|
||||
*/
|
||||
case 'S': /* The seconds. */
|
||||
LEGAL_ALT(ALT_O);
|
||||
if (!(conv_num(&bp, &tm->tm_sec, 0, 61)))
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 'U': /* The week of year, beginning on sunday. */
|
||||
case 'W': /* The week of year, beginning on monday. */
|
||||
LEGAL_ALT(ALT_O);
|
||||
/*
|
||||
* XXX This is bogus, as we can not assume any valid
|
||||
* information present in the tm structure at this
|
||||
* point to calculate a real value, so just check the
|
||||
* range for now.
|
||||
*/
|
||||
if (!(conv_num(&bp, &i, 0, 53)))
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 'w': /* The day of week, beginning on sunday. */
|
||||
LEGAL_ALT(ALT_O);
|
||||
if (!(conv_num(&bp, &tm->tm_wday, 0, 6)))
|
||||
return (0);
|
||||
break;
|
||||
|
||||
case 'Y': /* The year. */
|
||||
LEGAL_ALT(ALT_E);
|
||||
if (!(conv_num(&bp, &i, 0, 9999)))
|
||||
return (0);
|
||||
|
||||
tm->tm_year = i - TM_YEAR_BASE;
|
||||
break;
|
||||
|
||||
case 'y': /* The year within 100 years of the epoch. */
|
||||
LEGAL_ALT(ALT_E | ALT_O);
|
||||
if (!(conv_num(&bp, &i, 0, 99)))
|
||||
return (0);
|
||||
|
||||
if (split_year)
|
||||
{
|
||||
tm->tm_year = ((tm->tm_year / 100) * 100) + i;
|
||||
break;
|
||||
}
|
||||
split_year = 1;
|
||||
if (i <= 68)
|
||||
tm->tm_year = i + 2000 - TM_YEAR_BASE;
|
||||
else
|
||||
tm->tm_year = i + 1900 - TM_YEAR_BASE;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Miscellaneous conversions.
|
||||
*/
|
||||
case 'n': /* Any kind of white-space. */
|
||||
case 't':
|
||||
LEGAL_ALT(0);
|
||||
while (isspace(*bp))
|
||||
bp++;
|
||||
break;
|
||||
|
||||
|
||||
default: /* Unknown/unsupported conversion. */
|
||||
return (0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* LINTED functional specification */
|
||||
return ((char *)bp);
|
||||
}
|
||||
#pragma warning(default:4706)
|
||||
|
||||
|
||||
static int conv_num(const char **buf, int *dest, int llim, int ulim)
|
||||
{
|
||||
int result = 0;
|
||||
|
||||
/* The limit also determines the number of valid digits. */
|
||||
int rulim = ulim;
|
||||
|
||||
if (**buf < '0' || **buf > '9')
|
||||
return (0);
|
||||
|
||||
do {
|
||||
result *= 10;
|
||||
result += *(*buf)++ - '0';
|
||||
rulim /= 10;
|
||||
} while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9');
|
||||
|
||||
if (result < llim || result > ulim)
|
||||
return (0);
|
||||
|
||||
*dest = result;
|
||||
return (1);
|
||||
}
|
||||
|
||||
int strncasecmp(char *s1, char *s2, size_t n)
|
||||
{
|
||||
if (n == 0)
|
||||
return 0;
|
||||
|
||||
while (n-- != 0 && tolower(*s1) == tolower(*s2))
|
||||
{
|
||||
if (n == 0 || *s1 == '\0' || *s2 == '\0')
|
||||
break;
|
||||
s1++;
|
||||
s2++;
|
||||
}
|
||||
|
||||
return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2);
|
||||
}
|
|
@ -0,0 +1,455 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename symlink.c *
|
||||
* *
|
||||
* Description: WIN32 port of standard C library's symlink() *
|
||||
* *
|
||||
* Notes: Requires SE_CREATE_SYMBOLIC_LINK_NAME privilege. *
|
||||
* *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-05 JFL Created this module. *
|
||||
* 2014-03-02 JFL Split the functions into a WSTR and an UTF-8 version. *
|
||||
* 2014-03-20 JFL Restructured Windows link management functions into Wide *
|
||||
* and MultiByte versions, and changed the Unicode and Ansi *
|
||||
* versions to macros. *
|
||||
* 2014-07-03 JFL Added support for pathnames >= 260 characters. *
|
||||
* 2015-12-14 JFL Added a workaround allowing to link support for symlinks *
|
||||
* in all apps, even when targeting XP or older systems that *
|
||||
* do not support symlinks. *
|
||||
* 2016-08-25 JFL Fixed two warnings. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#define _UTF8_SOURCE /* Generate the UTF-8 version of routines */
|
||||
|
||||
#include "msvcUnistd.h"
|
||||
#pragma comment(lib, "Mpr.lib")
|
||||
|
||||
#include <errno.h>
|
||||
#include "msvcDebugm.h"
|
||||
#include "msvcLimits.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#include "msvcReparsept.h"
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: junction |
|
||||
| |
|
||||
| Description: Create an NTFS junction |
|
||||
| |
|
||||
| Parameters: const char *targetName The junction target name |
|
||||
| const char *junctionName The junction name |
|
||||
| |
|
||||
| Returns: 0 = Success, -1 = Failure |
|
||||
| |
|
||||
| Notes: Uses the undocumented FSCTL_SET_REPARSE_POINT structure |
|
||||
| Win2K uses for mount points and junctions. |
|
||||
| |
|
||||
| History: |
|
||||
| 2014-02-05 JFL Adapted from Mark Russinovitch CreateJuction sample |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
/* MsvcLibX-specific routine to create an NTFS junction - Wide char version */
|
||||
int junctionW(const WCHAR *targetName, const WCHAR *junctionName) {
|
||||
WCHAR wszReparseBuffer[PATH_MAX*3];
|
||||
WCHAR wszVolumeName[] = L"X:\\";
|
||||
WCHAR wszJunctionFullName[PATH_MAX];
|
||||
WCHAR wszFileSystem[PATH_MAX] = L"";
|
||||
WCHAR wszTargetTempName[PATH_MAX];
|
||||
WCHAR wszTargetFullName[PATH_MAX];
|
||||
WCHAR wszTargetNativeName[PATH_MAX];
|
||||
WCHAR *pwszFilePart;
|
||||
size_t lNativeName;
|
||||
HANDLE hFile;
|
||||
DWORD dwReturnedLength;
|
||||
PMOUNTPOINT_WRITE_BUFFER reparseInfo = (PMOUNTPOINT_WRITE_BUFFER)wszReparseBuffer;
|
||||
DEBUG_CODE(
|
||||
char szJunction8[UTF8_PATH_MAX];
|
||||
char szTarget8[UTF8_PATH_MAX];
|
||||
char szTemp8[UTF8_PATH_MAX];
|
||||
)
|
||||
UINT uiDriveType;
|
||||
DWORD dwFileSystemFlags;
|
||||
|
||||
DEBUG_WSTR2UTF8(junctionName, szJunction8, sizeof(szJunction8));
|
||||
DEBUG_WSTR2UTF8(targetName, szTarget8, sizeof(szTarget8));
|
||||
DEBUG_ENTER(("junction(\"%s\", \"%s\");\n", szTarget8, szJunction8));
|
||||
|
||||
/* Get the full path of the junction */
|
||||
if (!GetFullPathNameW(junctionName, PATH_MAX, wszJunctionFullName, &pwszFilePart)) {
|
||||
errno = Win32ErrorToErrno();
|
||||
RETURN_INT_COMMENT(-1, ("%s is an invalid junction name\n", junctionName));
|
||||
}
|
||||
|
||||
/* Convert relative paths to absolute paths relative to the junction. */
|
||||
/* Note: I tested creating relative targets: They can be created, but Windows can't follow them. */
|
||||
if ((targetName[0] != '\\') && (targetName[1] != ':')) {
|
||||
size_t lTempName = PATH_MAX;
|
||||
lstrcpyW(wszTargetTempName, wszJunctionFullName);
|
||||
lTempName -= lstrlenW(wszJunctionFullName);
|
||||
if (lTempName < (size_t)(lstrlenW(targetName) + 5)) {
|
||||
errno = ENAMETOOLONG;
|
||||
RETURN_INT_COMMENT(-1, ("Intermediate target name too long\n"));
|
||||
}
|
||||
lstrcatW(wszTargetTempName, L"\\..\\");
|
||||
lstrcatW(wszTargetTempName, targetName);
|
||||
if (!GetFullPathNameW(wszTargetTempName, PATH_MAX, wszTargetFullName, &pwszFilePart)) {
|
||||
errno = Win32ErrorToErrno();
|
||||
RETURN_INT_COMMENT(-1, ("%s is an invalid target directory name\n", szTarget8));
|
||||
}
|
||||
DEBUG_WSTR2UTF8(wszTargetFullName, szTemp8, sizeof(szTemp8));
|
||||
XDEBUG_PRINTF(("wszTargetFullName = \"%s\"; // After absolutization relative to the junction\n", szTemp8));
|
||||
} else { /* Already an absolute name. Just make sure it's canonic. (Without . or ..) */
|
||||
if (!GetFullPathNameW(targetName, PATH_MAX, wszTargetFullName, &pwszFilePart)) {
|
||||
errno = Win32ErrorToErrno();
|
||||
RETURN_INT_COMMENT(-1, ("%s is an invalid target directory name\n", szTarget8));
|
||||
}
|
||||
DEBUG_WSTR2UTF8(wszTargetFullName, szTemp8, sizeof(szTemp8));
|
||||
XDEBUG_PRINTF(("wszTargetFullName = \"%s\"; // After direct reabsolutization\n", szTemp8));
|
||||
}
|
||||
/* Make sure the target drive letter is upper case */
|
||||
#pragma warning(disable:4305) /* truncation from 'LPSTR' to 'WCHAR' */
|
||||
#pragma warning(disable:4306) /* conversion from 'WCHAR' to 'WCHAR *' of greater size */
|
||||
wszTargetFullName[0] = (WCHAR)CharUpperW((WCHAR *)(wszTargetFullName[0]));
|
||||
#pragma warning(default:4706)
|
||||
#pragma warning(default:4705)
|
||||
|
||||
/* Make sure that the junction is on a file system that supports reparse points (Ex: NTFS) */
|
||||
wszVolumeName[0] = wszJunctionFullName[0];
|
||||
GetVolumeInformationW(wszVolumeName, NULL, 0, NULL, NULL, &dwFileSystemFlags, wszFileSystem, sizeof(wszFileSystem)/sizeof(WCHAR));
|
||||
if (!(dwFileSystemFlags & FILE_SUPPORTS_REPARSE_POINTS)) {
|
||||
errno = EDOM;
|
||||
DEBUG_WSTR2UTF8(wszFileSystem, szTemp8, sizeof(szTemp8));
|
||||
RETURN_INT_COMMENT(-1, ("Junctions are not supported on %s volumes\n", szTemp8));
|
||||
}
|
||||
|
||||
/* On network drives, make sure the target refers to the local drive on the server */
|
||||
/* Note: The local path on the server can be inferred in simple cases, but not in the general case */
|
||||
uiDriveType = GetDriveTypeW(wszVolumeName);
|
||||
DEBUG_WSTR2UTF8(wszVolumeName, szTemp8, sizeof(szTemp8));
|
||||
XDEBUG_PRINTF(("GetDriveType(\"%s\") = %d // %s drive\n", szTemp8, uiDriveType, (uiDriveType == DRIVE_REMOTE) ? "Network" : "Local"));
|
||||
if (uiDriveType == DRIVE_REMOTE) {
|
||||
WCHAR wszLocalName[] = L"X:";
|
||||
WCHAR wszRemoteName[PATH_MAX];
|
||||
DWORD dwErr;
|
||||
DWORD dwLength = PATH_MAX;
|
||||
wszLocalName[0] = wszJunctionFullName[0];
|
||||
dwErr = WNetGetConnectionW(wszLocalName, wszRemoteName, &dwLength);
|
||||
if (dwErr == NO_ERROR) {
|
||||
WCHAR *pwsz;
|
||||
DEBUG_CODE(
|
||||
char szRemote8[UTF8_PATH_MAX];
|
||||
)
|
||||
DEBUG_WSTR2UTF8(wszRemoteName, szRemote8, sizeof(szRemote8));
|
||||
XDEBUG_PRINTF(("net use %c: %s\n", (char)(wszLocalName[0]), szRemote8));
|
||||
if ((wszRemoteName[0] == L'\\') && (wszRemoteName[1] == L'\\')) {
|
||||
pwsz = wcschr(wszRemoteName+2, L'\\');
|
||||
if (pwsz) {
|
||||
if ((pwsz[2] == L'$') && !pwsz[3]) { /* This is the root of a shared drive. Ex: \\server\D$ -> D: */
|
||||
wszTargetFullName[0] = pwsz[1]; /* Local drive name on the server */
|
||||
} else { /* Heuristic: Assume the share name is a subdirectory name on the C: drive. Ex: \\server\Public -> C:\Public */
|
||||
int lTempName = PATH_MAX;
|
||||
wszTargetTempName[0] = L'C'; /* Local drive name on the server */
|
||||
wszTargetTempName[1] = L':';
|
||||
lstrcpyW(wszTargetTempName+2, pwsz);
|
||||
lTempName -= lstrlenW(wszTargetTempName);
|
||||
if (lTempName > lstrlenW(wszTargetFullName+2)) {
|
||||
lstrcatW(wszTargetTempName, wszTargetFullName+2);
|
||||
lstrcpyW(wszTargetFullName, wszTargetTempName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
XDEBUG_PRINTF(("WNetGetConnection(\"%s\") failed: Error %d\n", szTemp8, dwErr));
|
||||
}
|
||||
}
|
||||
|
||||
/* Make the native target name */
|
||||
lNativeName = wsprintfW(wszTargetNativeName, L"\\??\\%s", wszTargetFullName );
|
||||
if ( (wszTargetNativeName[lNativeName-1] == L'\\') &&
|
||||
(wszTargetNativeName[lNativeName-2] != L':')) {
|
||||
wszTargetNativeName[lNativeName-1] = L'\0';
|
||||
lNativeName -= 1;
|
||||
}
|
||||
|
||||
/* Create the link - ignore errors since it might already exist */
|
||||
DEBUG_WSTR2UTF8(wszJunctionFullName, szJunction8, sizeof(szJunction8));
|
||||
DEBUG_WSTR2UTF8(wszTargetNativeName, szTarget8, sizeof(szTarget8));
|
||||
DEBUG_PRINTF(("// Creating junction \"%s\" -> \"%s\"\n", szJunction8, szTarget8));
|
||||
CreateDirectoryW(junctionName, NULL);
|
||||
hFile = CreateFileW(junctionName, GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
|
||||
FILE_FLAG_OPEN_REPARSE_POINT|FILE_FLAG_BACKUP_SEMANTICS, NULL );
|
||||
if (hFile == INVALID_HANDLE_VALUE) {
|
||||
errno = Win32ErrorToErrno();
|
||||
RETURN_INT_COMMENT(-1, ("Error creating %s:\n", szJunction8));
|
||||
}
|
||||
|
||||
/* Build the reparse info */
|
||||
ZeroMemory(reparseInfo, sizeof( *reparseInfo ));
|
||||
reparseInfo->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
|
||||
reparseInfo->ReparseTargetLength = (WORD)(lNativeName * sizeof(WCHAR));
|
||||
reparseInfo->ReparseTargetMaximumLength = reparseInfo->ReparseTargetLength + sizeof(WCHAR);
|
||||
reparseInfo->ReparseDataLength = reparseInfo->ReparseTargetLength + MOUNTPOINT_WRITE_BUFFER_HEADER_SIZE - 4;
|
||||
lstrcpynW(reparseInfo->ReparseTarget, wszTargetNativeName, PATH_MAX);
|
||||
|
||||
/* Set the link */
|
||||
if (!DeviceIoControl(hFile, FSCTL_SET_REPARSE_POINT, reparseInfo,
|
||||
/* reparseInfo->ReparseDataLength + 4, */
|
||||
reparseInfo->ReparseDataLength + 8,
|
||||
NULL, 0, &dwReturnedLength, NULL )) {
|
||||
errno = Win32ErrorToErrno();
|
||||
CloseHandle(hFile);
|
||||
RemoveDirectoryW(junctionName);
|
||||
RETURN_INT_COMMENT(-1, ("Error setting junction for %s:\n", szJunction8));
|
||||
}
|
||||
|
||||
CloseHandle(hFile);
|
||||
RETURN_INT_COMMENT(0, ("Created \"%s\" -> \"%s\"\n", szJunction8, szTarget8));
|
||||
}
|
||||
|
||||
/* MsvcLibX-specific routine to create an NTFS junction - MultiByte char version */
|
||||
int junctionM(const char *targetName, const char *junctionName, UINT cp) {
|
||||
WCHAR wszJunction[PATH_MAX];
|
||||
WCHAR wszTarget[PATH_MAX];
|
||||
int n;
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
junctionName, /* lpMultiByteStr, */
|
||||
wszJunction, /* lpWideCharStr, */
|
||||
COUNTOF(wszJunction) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
targetName, /* lpMultiByteStr, */
|
||||
wszTarget, /* lpWideCharStr, */
|
||||
COUNTOF(wszTarget) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
return junctionW(wszTarget, wszJunction);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: symlink |
|
||||
| |
|
||||
| Description: Create an NTFS symbolic link |
|
||||
| |
|
||||
| Parameters: const TCHAR *targetName The symlink target name |
|
||||
| const TCHAR *linkName The symlink name |
|
||||
| |
|
||||
| Returns: 0 = Success, -1 = Failure |
|
||||
| |
|
||||
| Notes: |
|
||||
| |
|
||||
| History: |
|
||||
| 2014-02-04 JFL Created this routine |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
/* Symbolic links first appeared in Vista WINVER 0x600.
|
||||
Add support for both old and new versions, by using Windows' CreateSymbolicLink
|
||||
function if it exists, or else a short stub that fails every time if not. */
|
||||
#if WINVER < 0x600 /* This mechanism is only necessary when targeting older versions of Windows */
|
||||
|
||||
typedef BOOLEAN (WINAPI *LPCREATESYMBOLICLINK)(LPCWSTR lpSymlinkName, LPCWSTR lpTargetName, DWORD dwFlags);
|
||||
|
||||
/* Default routine to use if Windows does not have CreateSymbolicLinkW */
|
||||
#pragma warning(disable:4100) /* 'dwFlags' : unreferenced formal parameter */
|
||||
BOOLEAN WINAPI DefaultCreateSymbolicLinkW(LPCWSTR lpSymlinkName, LPCWSTR lpTargetName, DWORD dwFlags) {
|
||||
DWORD dwAttr = GetFileAttributesW(lpTargetName);
|
||||
if (dwAttr != INVALID_FILE_ATTRIBUTES) { /* If the target exists */
|
||||
if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) { /* And if the target is a directory */
|
||||
/* Try creating a junction as a workaround */
|
||||
int iRet = junctionW(lpTargetName, lpSymlinkName); /* 0=Success, -1=Failure */
|
||||
return (BOOLEAN)(iRet + 1); /* 1=Success, 0=Failure */
|
||||
}
|
||||
}
|
||||
/* Else fail, as symlinks to files aren't supported by this Windows version */
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
return FALSE;
|
||||
}
|
||||
#pragma warning(default:4105)
|
||||
|
||||
/* Initialization routine. Tries using Windows' CreateSymbolicLinkW if present, else uses our default above */
|
||||
BOOLEAN WINAPI InitCreateSymbolicLink(LPCWSTR lpSymlinkName, LPCWSTR lpTargetName, DWORD dwFlags) {
|
||||
extern LPCREATESYMBOLICLINK lpCreateSymbolicLinkW;
|
||||
lpCreateSymbolicLinkW = (LPCREATESYMBOLICLINK) GetProcAddress(
|
||||
GetModuleHandle(TEXT("kernel32.dll")), "CreateSymbolicLinkW");
|
||||
if (!lpCreateSymbolicLinkW) { /* This is XP or older, not supporting symlinks */
|
||||
lpCreateSymbolicLinkW = DefaultCreateSymbolicLinkW;
|
||||
}
|
||||
return (*lpCreateSymbolicLinkW)(lpSymlinkName, lpTargetName, dwFlags);
|
||||
}
|
||||
|
||||
LPCREATESYMBOLICLINK lpCreateSymbolicLinkW = InitCreateSymbolicLink;
|
||||
|
||||
/* Make sure all uses of CreateSymbolicLinkW below go through our static pointer above */
|
||||
#undef CreateSymbolicLinkW
|
||||
#define CreateSymbolicLinkW (*lpCreateSymbolicLinkW)
|
||||
|
||||
#endif /* WINVER < 0x600 */
|
||||
|
||||
/* Posix routine symlink - Wide char version */
|
||||
int symlinkW(const WCHAR *targetName, const WCHAR *linkName) {
|
||||
DWORD dwAttr;
|
||||
BOOL done;
|
||||
DWORD dwFlags;
|
||||
int err;
|
||||
DEBUG_CODE(
|
||||
char szLink8[UTF8_PATH_MAX];
|
||||
char szTarget8[UTF8_PATH_MAX];
|
||||
)
|
||||
|
||||
DEBUG_WSTR2UTF8(linkName, szLink8, sizeof(szLink8));
|
||||
DEBUG_WSTR2UTF8(targetName, szTarget8, sizeof(szTarget8));
|
||||
DEBUG_ENTER(("symlink(\"%s\", \"%s\");\n", szTarget8, szLink8));
|
||||
|
||||
/* Work around an incompatibility between Unix and Windows:
|
||||
// Windows needs to know if the target is a file or a directory;
|
||||
// But Unix allows creating dangling links, in which case we cannot guess what type it'll be. */
|
||||
dwAttr = GetFileAttributesW(targetName);
|
||||
DEBUG_PRINTF(("GetFileAttributes() = 0x%lX\n", dwAttr));
|
||||
dwFlags = 0;
|
||||
if (dwAttr != INVALID_FILE_ATTRIBUTES) { /* File exists */
|
||||
if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) dwFlags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
|
||||
} else { /* Target does not exst. Use a heuristic: Names with trailing / or \ are directories */
|
||||
size_t len = lstrlenW(targetName);
|
||||
if (len) {
|
||||
WCHAR c = targetName[len-1];
|
||||
if ((c == L'/') || (c == L'\\')) dwFlags |= SYMBOLIC_LINK_FLAG_DIRECTORY;
|
||||
}
|
||||
}
|
||||
|
||||
done = CreateSymbolicLinkW(linkName, targetName, dwFlags);
|
||||
|
||||
if (done) {
|
||||
err = 0;
|
||||
} else {
|
||||
errno = Win32ErrorToErrno();
|
||||
err = -1;
|
||||
}
|
||||
RETURN_INT_COMMENT(err, ("%s\n", err?"Failed to create link":"Created link successfully"));
|
||||
}
|
||||
|
||||
/* Posix routine symlink - MultiByte char version */
|
||||
int symlinkM(const char *targetName, const char *linkName, UINT cp) {
|
||||
WCHAR wszLink[PATH_MAX];
|
||||
WCHAR wszTarget[PATH_MAX];
|
||||
int n;
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
linkName, /* lpMultiByteStr, */
|
||||
wszLink, /* lpWideCharStr, */
|
||||
COUNTOF(wszLink) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
targetName, /* lpMultiByteStr, */
|
||||
wszTarget, /* lpWideCharStr, */
|
||||
COUNTOF(wszTarget) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
return symlinkW(wszTarget, wszLink);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
* *
|
||||
| Function: symlinkd |
|
||||
| |
|
||||
| Description: Create an NTFS symbolic directory link |
|
||||
| |
|
||||
| Parameters: const TCHAR *targetName The symlink target name |
|
||||
| const TCHAR *linkName The symlink name |
|
||||
| |
|
||||
| Returns: 0 = Success, -1 = Failure |
|
||||
| |
|
||||
| Notes: |
|
||||
| |
|
||||
| History: |
|
||||
| 2014-03-04 JFL Created this routine |
|
||||
* *
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
/* MsvcLibX-specific routine to create an NTFS symlinkd - Wide char version */
|
||||
int symlinkdW(const WCHAR *targetName, const WCHAR *linkName) {
|
||||
BOOL done;
|
||||
int err;
|
||||
DEBUG_CODE(
|
||||
char szLink8[UTF8_PATH_MAX];
|
||||
char szTarget8[UTF8_PATH_MAX];
|
||||
)
|
||||
|
||||
DEBUG_WSTR2UTF8(linkName, szLink8, sizeof(szLink8));
|
||||
DEBUG_WSTR2UTF8(targetName, szTarget8, sizeof(szTarget8));
|
||||
DEBUG_ENTER(("symlinkd(\"%s\", \"%s\");\n", szTarget8, szLink8));
|
||||
|
||||
done = CreateSymbolicLinkW(linkName, targetName, SYMBOLIC_LINK_FLAG_DIRECTORY);
|
||||
|
||||
if (done) {
|
||||
err = 0;
|
||||
} else {
|
||||
errno = Win32ErrorToErrno();
|
||||
err = -1;
|
||||
}
|
||||
RETURN_INT_COMMENT(err, ("%s\n", err?"Failed to create link":"Created link successfully"));
|
||||
}
|
||||
|
||||
/* MsvcLibX-specific routine to create an NTFS symlinkd - MultiByte char version */
|
||||
int symlinkdM(const char *targetName, const char *linkName, UINT cp) {
|
||||
WCHAR wszLink[PATH_MAX];
|
||||
WCHAR wszTarget[PATH_MAX];
|
||||
int n;
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
linkName, /* lpMultiByteStr, */
|
||||
wszLink, /* lpWideCharStr, */
|
||||
COUNTOF(wszLink) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(cp, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
targetName, /* lpMultiByteStr, */
|
||||
wszTarget, /* lpWideCharStr, */
|
||||
COUNTOF(wszTarget) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
return symlinkdW(wszTarget, wszLink);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,79 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename: uname.c *
|
||||
* *
|
||||
* Description: Get the name of the current system. *
|
||||
* *
|
||||
* Notes: TO DO: Fix the Win32 windows version for Windows >= 8.1, *
|
||||
* as explained in MSDN's GetVersion function page. *
|
||||
* *
|
||||
* TO DO: Do not rely on PROCESSOR_ARCHITECTURE to get the *
|
||||
* processor architecture, because the WIN32 version *
|
||||
* always sees "x86", even on "AMD64" systems. *
|
||||
* *
|
||||
* TO DO: Implement sysinfo.c, moving some of the code from *
|
||||
* here to there, and use it. *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-05-30 JFL Created this file. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#include "sys/msvcTsname.h"
|
||||
#include <stdlib.h> /* For itoa() */
|
||||
|
||||
static char major[4] = {0};
|
||||
static char minor[4] = {0};
|
||||
|
||||
#ifdef _MSDOS
|
||||
|
||||
#include <dos.h>
|
||||
|
||||
static char name[16] = {0};
|
||||
|
||||
int uname(struct utsname *pun) {
|
||||
unsigned int wVersion = _bdos(0x30, 0, 0); /* int 21H ah=30H Get DOS version */
|
||||
|
||||
_itoa((int)(wVersion & 0x0F), major, 10);
|
||||
_itoa((int)((wVersion >> 8) & 0x0F), minor, 10);
|
||||
|
||||
/* Use _bdos instead of _intdosx, because even in large memory mode, static variables will be allocated in the default data segment */
|
||||
_bdos(0x5E, (unsigned short)(unsigned long)(char far *)name, 0); /* int 21H ax=5E00H ds:dx=&buf Get Machine Name */
|
||||
|
||||
pun->sysname = "MS-DOS"; /* Name of this operating system */
|
||||
pun->nodename = name; /* Name of this node on the network */ /* TO DO: Get it from LAN Manager */
|
||||
pun->release = major; /* Current release level of this implementation */
|
||||
pun->version = minor; /* Current version level of this release */
|
||||
pun->machine = "x86"; /* Name of the hardware type on which the system is running */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(_MSDOS) */
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#pragma warning(disable:4996) /* Ignore the "This function or variable may be unsafe" warning for itoa() and getenv() */
|
||||
|
||||
int uname(struct utsname *pun) {
|
||||
DWORD dwVersion = GetVersion();
|
||||
|
||||
_itoa((int)(dwVersion & 0x0F), major, 10);
|
||||
_itoa((int)((dwVersion >> 8) & 0x0F), minor, 10);
|
||||
|
||||
pun->sysname = getenv("OS"); /* Name of this operating system */
|
||||
pun->nodename = getenv("COMPUTERNAME"); /* Name of this node on the network */
|
||||
pun->release = major; /* Current release level of this implementation */
|
||||
pun->version = minor; /* Current version level of this release */
|
||||
pun->machine = getenv("PROCESSOR_ARCHITECTURE"); /* Name of the hardware type on which the system is running */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
|
@ -0,0 +1,216 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename utime.c *
|
||||
* *
|
||||
* Description Updated utime() and port of standard C library's lutime() *
|
||||
* *
|
||||
* Notes TO DO: Create W, A, U versions of ResolveLinks(), then *
|
||||
* create W, A, U versions of utime(). *
|
||||
* *
|
||||
* History *
|
||||
* 2014-02-12 JFL Created this module. *
|
||||
* 2014-06-04 JFL Fixed minors issues in debugging code. *
|
||||
* 2014-07-02 JFL Added support for pathnames >= 260 characters. *
|
||||
* 2016-08-25 JFL Added missing routine utimeA(). *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _UTF8_SOURCE /* Generate the UTF-8 version of Windows print routines */
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#include <errno.h>
|
||||
#include "sys/msvcTime.h" /* Must be included before any direct or indirect <windows.h> inclusion */
|
||||
#include "msvcUtime.h"
|
||||
#include "msvcDebugm.h"
|
||||
#include "msvcLimits.h"
|
||||
|
||||
#if defined(_DEBUG)
|
||||
#include <stdio.h>
|
||||
#endif /* defined(_DEBUG) */
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include <io.h> /* For MSVC's _get_osfhandle() */
|
||||
#include "msvcUnistd.h" /* For MsvcLibX's ResolveLinks() */
|
||||
|
||||
/* Convert a Windows FILETIME to a Unix time_t.
|
||||
A FILETIME is the number of 100-nanosecond intervals since January 1, 1601.
|
||||
A time_t is the number of 1-second intervals since January 1, 1970. */
|
||||
|
||||
time_t Filetime2Time_t(FILETIME *pFT) {
|
||||
ULARGE_INTEGER ull;
|
||||
ull.LowPart = pFT->dwLowDateTime;
|
||||
ull.HighPart = pFT->dwHighDateTime;
|
||||
return (time_t)(ull.QuadPart / 10000000ULL - 11644473600ULL);
|
||||
}
|
||||
|
||||
void Time_t2Filetime(time_t ft, FILETIME *pFT) {
|
||||
ULARGE_INTEGER ull;
|
||||
ull.QuadPart = ft + 11644473600ULL;
|
||||
ull.QuadPart *= 10000000UL;
|
||||
pFT->dwLowDateTime = ull.LowPart;
|
||||
pFT->dwHighDateTime = ull.HighPart;
|
||||
}
|
||||
|
||||
DEBUG_CODE(
|
||||
int Utimbuf2String(char *buf, size_t bufsize, const struct utimbuf *times) {
|
||||
struct tm *pTime;
|
||||
int n;
|
||||
if (!times) {
|
||||
return _snprintf(buf, bufsize, "NULL");
|
||||
}
|
||||
pTime = localtime(&(times->modtime)); /* Time of last data modification */
|
||||
n = _snprintf(buf, bufsize, "{%4d-%02d-%02d %02d:%02d:%02d, ...}",
|
||||
pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday,
|
||||
pTime->tm_hour, pTime->tm_min, pTime->tm_sec);
|
||||
return n;
|
||||
}
|
||||
);
|
||||
|
||||
/* Low level subroutine used by all the other routines below. */
|
||||
int hutime(HANDLE hFile, const struct utimbuf *times) {
|
||||
FILETIME ftLastAccess; /* last access time */
|
||||
FILETIME ftLastWrite; /* last write time */
|
||||
int iErr;
|
||||
struct utimbuf now;
|
||||
|
||||
if (!times) {
|
||||
now.actime = now.modtime = time(NULL);
|
||||
times = &now;
|
||||
}
|
||||
|
||||
Time_t2Filetime(times->actime, &ftLastAccess);
|
||||
Time_t2Filetime(times->modtime, &ftLastWrite);
|
||||
iErr = !SetFileTime(hFile, NULL, &ftLastAccess, &ftLastWrite);
|
||||
if (iErr) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Same as 'utime', but does not follow symbolic links. */
|
||||
int lutimeW(const WCHAR *path, const struct utimbuf *times) {
|
||||
DWORD dwAttr;
|
||||
DWORD dwFlagsAndAttributes;
|
||||
int iErr;
|
||||
HANDLE hLink;
|
||||
|
||||
DEBUG_CODE({
|
||||
char buf[100];
|
||||
char szUtf8[UTF8_PATH_MAX];
|
||||
Utimbuf2String(buf, sizeof(buf), times);
|
||||
DEBUG_WSTR2UTF8(path, szUtf8, sizeof(szUtf8));
|
||||
DEBUG_ENTER(("lutime(\"%s\", %s);\n", szUtf8, buf));
|
||||
});
|
||||
|
||||
dwAttr = GetFileAttributesW(path);
|
||||
if (dwAttr == INVALID_FILE_ATTRIBUTES) {
|
||||
errno = ENOENT;
|
||||
RETURN_INT_COMMENT(-1, ("File does not exist\n"));
|
||||
}
|
||||
|
||||
dwFlagsAndAttributes = FILE_FLAG_OPEN_REPARSE_POINT;
|
||||
if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) dwFlagsAndAttributes |= FILE_FLAG_BACKUP_SEMANTICS;
|
||||
hLink = CreateFileW(path, /* lpFileName, */
|
||||
FILE_WRITE_ATTRIBUTES, /* dwDesiredAccess, */
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode, */
|
||||
NULL, /* lpSecurityAttributes, */
|
||||
OPEN_EXISTING, /* dwCreationDisposition, */
|
||||
dwFlagsAndAttributes, /* dwFlagsAndAttributes, */
|
||||
NULL /* hTemplateFile */
|
||||
);
|
||||
XDEBUG_PRINTF(("CreateFile() = 0x%p\n", hLink));
|
||||
if (hLink == INVALID_HANDLE_VALUE) {
|
||||
errno = Win32ErrorToErrno();
|
||||
RETURN_INT_COMMENT(-1, ("Cannot open the pathname\n"));
|
||||
}
|
||||
|
||||
iErr = hutime(hLink, times);
|
||||
CloseHandle(hLink);
|
||||
RETURN_INT_COMMENT(iErr, ("errno = %d\n", iErr ? errno : 0));
|
||||
}
|
||||
|
||||
int lutimeA(const char *path, const struct utimbuf *times) {
|
||||
WCHAR wszPath[PATH_MAX];
|
||||
int n;
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(CP_ACP, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
path, /* lpMultiByteStr, */
|
||||
wszPath, /* lpWideCharStr, */
|
||||
COUNTOF(wszPath) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
DEBUG_ENTER(("lutimeA(\"%s\", %p);\n", path, times));
|
||||
RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno)));
|
||||
}
|
||||
return lutimeW(wszPath, times);
|
||||
}
|
||||
|
||||
int lutimeU(const char *path, const struct utimbuf *times) {
|
||||
WCHAR wszPath[PATH_MAX];
|
||||
int n;
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
path, /* lpMultiByteStr, */
|
||||
wszPath, /* lpWideCharStr, */
|
||||
COUNTOF(wszPath) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
DEBUG_ENTER(("lutimeU(\"%s\", %p);\n", path, times));
|
||||
RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno)));
|
||||
}
|
||||
return lutimeW(wszPath, times);
|
||||
}
|
||||
|
||||
/* Same as 'utime', but takes an open file descriptor instead of a name. */
|
||||
int futime(int fd, const struct utimbuf *times) {
|
||||
return hutime((HANDLE)_get_osfhandle(fd), times);
|
||||
}
|
||||
|
||||
/* Change the file access time to times->actime and its modification time to times->modtime. */
|
||||
int utimeA(const char *file, const struct utimbuf *times) {
|
||||
char buf[PATH_MAX];
|
||||
int iErr;
|
||||
|
||||
DEBUG_CODE({
|
||||
char buf[100];
|
||||
Utimbuf2String(buf, sizeof(buf), times);
|
||||
DEBUG_ENTER(("utime(\"%s\", %s);\n", file, buf));
|
||||
});
|
||||
|
||||
iErr = ResolveLinksA(file, buf, sizeof(buf));
|
||||
if (iErr) RETURN_INT_COMMENT(iErr, ("Cannot resolve the link\n"));
|
||||
|
||||
iErr = lutimeA(buf, times);
|
||||
RETURN_INT_COMMENT(iErr, ("errno = %d\n", iErr ? errno : 0));
|
||||
}
|
||||
|
||||
/* Change the file access time to times->actime and its modification time to times->modtime. */
|
||||
int utimeU(const char *file, const struct utimbuf *times) {
|
||||
char buf[UTF8_PATH_MAX];
|
||||
int iErr;
|
||||
|
||||
DEBUG_CODE({
|
||||
char buf[100];
|
||||
Utimbuf2String(buf, sizeof(buf), times);
|
||||
DEBUG_ENTER(("utime(\"%s\", %s);\n", file, buf));
|
||||
});
|
||||
|
||||
iErr = ResolveLinksU(file, buf, sizeof(buf));
|
||||
if (iErr) RETURN_INT_COMMENT(iErr, ("Cannot resolve the link\n"));
|
||||
|
||||
iErr = lutimeU(buf, times);
|
||||
RETURN_INT_COMMENT(iErr, ("errno = %d\n", iErr ? errno : 0));
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,219 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename utimes.c *
|
||||
* *
|
||||
* Description: WIN32 port of standard C library's *utimes() *
|
||||
* *
|
||||
* Notes: TO DO: Create W, A, U versions of ResolveLinks(), then *
|
||||
* create W, A, U versions of utimes(). *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-02-07 JFL Created this module. *
|
||||
* 2014-03-24 JFL Renamed "statx.h" as the standard <sys/stat.h>. *
|
||||
* 2014-06-03 JFL Added support for WIDE, ANSI and UTF8 versions. *
|
||||
* 2014-06-04 JFL Added handling of UTIME_NOW and UTIME_OMIT. *
|
||||
* 2014-07-02 JFL Added support for pathnames >= 260 characters. *
|
||||
* *
|
||||
* Copyright 2016 Hewlett Packard Enterprise Development LP *
|
||||
* Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _UTF8_SOURCE /* Generate the UTF-8 version of Windows print routines */
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#include <errno.h>
|
||||
#include "sys/msvcTime.h" /* Must be included before any direct or indirect <windows.h> inclusion */
|
||||
#include "sys/msvcStat.h"
|
||||
#include "msvcDebugm.h"
|
||||
#include "msvcLimits.h"
|
||||
|
||||
#if defined(_DEBUG)
|
||||
#include <stdio.h>
|
||||
#endif /* defined(_DEBUG) */
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <windows.h>
|
||||
#include <io.h> /* For MSVC's _get_osfhandle() */
|
||||
#include "msvcUnistd.h" /* For MsvcLibX's ResolveLinks() */
|
||||
|
||||
DEBUG_CODE(
|
||||
int Timeval2String(char *buf, size_t bufsize, const struct timeval *tvp) {
|
||||
struct tm *pTime;
|
||||
int n;
|
||||
if (tvp->tv_usec == UTIME_NOW) {
|
||||
return _snprintf(buf, bufsize, "UTIME_NOW");
|
||||
}
|
||||
if (tvp->tv_usec == UTIME_OMIT) {
|
||||
return _snprintf(buf, bufsize, "UTIME_OMIT");
|
||||
}
|
||||
pTime = localtime(&(tvp->tv_sec)); /* Time of last data modification */
|
||||
n = _snprintf(buf, bufsize, "{%4d-%02d-%02d %02d:%02d:%02d.%06d, ...}",
|
||||
pTime->tm_year + 1900, pTime->tm_mon + 1, pTime->tm_mday,
|
||||
pTime->tm_hour, pTime->tm_min, pTime->tm_sec, tvp->tv_usec);
|
||||
return n;
|
||||
}
|
||||
);
|
||||
|
||||
/* Convert a Windows FILETIME to a Unix timeval
|
||||
A FILETIME is the number of 100-nanosecond intervals since January 1, 1601.
|
||||
A time_t is the number of 1-second intervals since January 1, 1970. */
|
||||
|
||||
void Filetime2Timeval(const FILETIME *pFT, struct timeval *ptv) {
|
||||
ULARGE_INTEGER ull;
|
||||
ull.LowPart = pFT->dwLowDateTime;
|
||||
ull.HighPart = pFT->dwHighDateTime;
|
||||
ptv->tv_sec = (long)(ull.QuadPart / 10000000ULL - 11644473600ULL);
|
||||
ptv->tv_usec = (int32_t)((ull.QuadPart % 10000000ULL)/10);
|
||||
}
|
||||
|
||||
void Timeval2Filetime(const struct timeval *ptv, FILETIME *pFT) {
|
||||
ULARGE_INTEGER ull;
|
||||
struct timeval now;
|
||||
if (ptv->tv_usec == UTIME_NOW) {
|
||||
gettimeofday(&now, NULL); /* Get the current time into a struct timeval */
|
||||
DEBUG_CODE({
|
||||
char buf[100];
|
||||
Timeval2String(buf, sizeof(buf), &now);
|
||||
DEBUG_PRINTF(("// UTIME_NOW -> %s\n", buf));
|
||||
});
|
||||
ptv = &now;
|
||||
}
|
||||
ull.QuadPart = ptv->tv_sec + 11644473600ULL;
|
||||
ull.QuadPart *= 1000000UL;
|
||||
ull.QuadPart += ptv->tv_usec;
|
||||
ull.QuadPart *= 10UL;
|
||||
pFT->dwLowDateTime = ull.LowPart;
|
||||
pFT->dwHighDateTime = ull.HighPart;
|
||||
}
|
||||
|
||||
/* Low level subroutine used by all the other routines below. */
|
||||
int hutimes(HANDLE hFile, const struct timeval tvp[2]) {
|
||||
FILETIME ftLastAccess; /* last access time */
|
||||
FILETIME ftLastWrite; /* last write time */
|
||||
FILETIME *pftLastAccess = &ftLastAccess;
|
||||
FILETIME *pftLastWrite = &ftLastWrite;
|
||||
int iErr;
|
||||
|
||||
if (tvp[0].tv_usec != UTIME_OMIT) {
|
||||
Timeval2Filetime(tvp+0, pftLastAccess);
|
||||
} else {
|
||||
pftLastAccess = NULL; /* Do not set this value */
|
||||
}
|
||||
if (tvp[1].tv_usec != UTIME_OMIT) {
|
||||
Timeval2Filetime(tvp+1, pftLastWrite);
|
||||
} else {
|
||||
pftLastWrite = NULL; /* Do not set this value */
|
||||
}
|
||||
iErr = !SetFileTime(hFile, NULL, pftLastAccess, pftLastWrite);
|
||||
if (iErr) {
|
||||
errno = Win32ErrorToErrno();
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Same as 'utimes', but does not follow symbolic links. */
|
||||
int lutimesW(const WCHAR *path, const struct timeval tvp[2]) {
|
||||
DWORD dwAttr;
|
||||
DWORD dwFlagsAndAttributes;
|
||||
int iErr;
|
||||
HANDLE hLink;
|
||||
|
||||
DEBUG_CODE({
|
||||
char buf[100];
|
||||
char szUtf8[UTF8_PATH_MAX];
|
||||
Timeval2String(buf, sizeof(buf), tvp+1);
|
||||
DEBUG_WSTR2UTF8(path, szUtf8, sizeof(szUtf8));
|
||||
DEBUG_ENTER(("lutimes(\"%s\", %s);\n", szUtf8, buf));
|
||||
});
|
||||
|
||||
dwAttr = GetFileAttributesW(path);
|
||||
if (dwAttr == INVALID_FILE_ATTRIBUTES) {
|
||||
errno = ENOENT;
|
||||
RETURN_INT_COMMENT(-1, ("File does not exist\n"));
|
||||
}
|
||||
|
||||
dwFlagsAndAttributes = FILE_FLAG_OPEN_REPARSE_POINT;
|
||||
if (dwAttr & FILE_ATTRIBUTE_DIRECTORY) dwFlagsAndAttributes |= FILE_FLAG_BACKUP_SEMANTICS;
|
||||
hLink = CreateFileW(path, /* lpFileName, */
|
||||
FILE_WRITE_ATTRIBUTES, /* dwDesiredAccess, */
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE, /* dwShareMode, */
|
||||
NULL, /* lpSecurityAttributes, */
|
||||
OPEN_EXISTING, /* dwCreationDisposition, */
|
||||
dwFlagsAndAttributes, /* dwFlagsAndAttributes, */
|
||||
NULL /* hTemplateFile */
|
||||
);
|
||||
XDEBUG_PRINTF(("CreateFile() = 0x%p\n", hLink));
|
||||
if (hLink == INVALID_HANDLE_VALUE) {
|
||||
errno = Win32ErrorToErrno();
|
||||
RETURN_INT_COMMENT(-1, ("Cannot open the pathname\n"));
|
||||
}
|
||||
|
||||
iErr = hutimes(hLink, tvp);
|
||||
CloseHandle(hLink);
|
||||
RETURN_INT_COMMENT(iErr, ("errno = %d\n", iErr ? errno : 0));
|
||||
}
|
||||
|
||||
int lutimesA(const char *path, const struct timeval tvp[2]) {
|
||||
WCHAR wszPath[PATH_MAX];
|
||||
int n;
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(CP_ACP, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
path, /* lpMultiByteStr, */
|
||||
wszPath, /* lpWideCharStr, */
|
||||
COUNTOF(wszPath) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
DEBUG_ENTER(("lutimesA(\"%s\", %p);\n", path, tvp));
|
||||
RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno)));
|
||||
}
|
||||
return lutimesW(wszPath, tvp);
|
||||
}
|
||||
|
||||
int lutimesU(const char *path, const struct timeval tvp[2]) {
|
||||
WCHAR wszPath[PATH_MAX];
|
||||
int n;
|
||||
|
||||
/* Convert the pathname to a unicode string, with the proper extension prefixes if it's longer than 260 bytes */
|
||||
n = MultiByteToWidePath(CP_UTF8, /* CodePage, (CP_ACP, CP_OEMCP, CP_UTF8, ...) */
|
||||
path, /* lpMultiByteStr, */
|
||||
wszPath, /* lpWideCharStr, */
|
||||
COUNTOF(wszPath) /* cchWideChar, */
|
||||
);
|
||||
if (!n) {
|
||||
errno = Win32ErrorToErrno();
|
||||
DEBUG_ENTER(("lutimesU(\"%s\", %p);\n", path, tvp));
|
||||
RETURN_INT_COMMENT(-1, ("errno=%d - %s\n", errno, strerror(errno)));
|
||||
}
|
||||
return lutimesW(wszPath, tvp);
|
||||
}
|
||||
|
||||
/* Same as 'utimes', but takes an open file descriptor instead of a name. */
|
||||
int futimes(int fd, const struct timeval tvp[2]) {
|
||||
return hutimes((HANDLE)_get_osfhandle(fd), tvp);
|
||||
}
|
||||
|
||||
/* Change the file access time to tvp[0] and its modification time to tvp[1]. */
|
||||
int utimes(const char *file, const struct timeval tvp[2]) {
|
||||
char buf[UTF8_PATH_MAX];
|
||||
int iErr;
|
||||
|
||||
DEBUG_CODE({
|
||||
char buf[100];
|
||||
Timeval2String(buf, sizeof(buf), tvp+1);
|
||||
DEBUG_ENTER(("utimes(\"%s\", %s);\n", file, buf));
|
||||
});
|
||||
|
||||
iErr = ResolveLinksU(file, buf, sizeof(buf));
|
||||
if (iErr) RETURN_INT_COMMENT(iErr, ("Cannot resolve the link\n"));
|
||||
|
||||
iErr = lutimesU(buf, tvp);
|
||||
RETURN_INT_COMMENT(iErr, ("errno = %d\n", iErr ? errno : 0));
|
||||
}
|
||||
|
||||
#endif /* defined(_WIN32) */
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
/*****************************************************************************\
|
||||
* *
|
||||
* Filename xfreopen.c *
|
||||
* *
|
||||
* Description: WIN32 port of GNU CoreUtils library's xfreopen() *
|
||||
* *
|
||||
* Notes: The GNU CoreUtils library extends the freopen function. *
|
||||
* msvclibx: Use the standard freopen, or _setmode. *
|
||||
* *
|
||||
* History: *
|
||||
* 2014-03-03 JFL Created this module. *
|
||||
* *
|
||||
\*****************************************************************************/
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS 1 /* Avoid Visual C++ security warnings */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <io.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include "msvcXfreopen.h"
|
||||
|
||||
FILE *xfreopen(const char *filename, const char *mode, FILE *stream) {
|
||||
int iMode = 0;
|
||||
if (filename) return freopen(filename, mode, stream);
|
||||
if (strstr(mode, "r+")) {
|
||||
iMode = _O_RDWR;
|
||||
} else if (strstr(mode, "w+")) {
|
||||
iMode = _O_WRONLY | _O_CREAT | _O_TRUNC;
|
||||
} else if (strstr(mode, "a+")) {
|
||||
iMode = _O_RDWR | _O_CREAT | _O_APPEND;
|
||||
} else if (strchr(mode, 'r')) {
|
||||
iMode = _O_RDONLY;
|
||||
} else if (strchr(mode, 'w')) {
|
||||
iMode = _O_WRONLY | _O_CREAT;
|
||||
} else if (strchr(mode, 'a')) {
|
||||
iMode = _O_WRONLY | _O_CREAT | _O_APPEND;
|
||||
}
|
||||
if (strchr(mode, 'b')) {
|
||||
iMode = _O_BINARY;
|
||||
} else if (strchr(mode, 't')) {
|
||||
iMode = _O_TEXT;
|
||||
}
|
||||
_setmode(_fileno(stream), iMode);
|
||||
return stream;
|
||||
}
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SOURCE_LIST)
|
||||
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SOURCE_LIST)
|
||||
|
||||
add_library(cJson ${SOURCE_LIST})
|
||||
target_include_directories(cJson PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/inc)
|
||||
ADD_LIBRARY(cJson ${SOURCE_LIST})
|
||||
TARGET_INCLUDE_DIRECTORIES(cJson PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/inc)
|
|
@ -1,9 +1,11 @@
|
|||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
PROJECT(TDengine)
|
||||
|
||||
IF (TD_WINDOWS_64)
|
||||
IF (TD_WINDOWS)
|
||||
LIST(APPEND SRC iconv.c)
|
||||
LIST(APPEND SRC localcharset.c)
|
||||
INCLUDE_DIRECTORIES(.)
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /WX-")
|
||||
SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /WX-")
|
||||
ADD_LIBRARY(iconv ${SRC})
|
||||
ENDIF ()
|
|
@ -1,4 +1,4 @@
|
|||
/* Copyright (C) 1999-2003, 2005-2006, 2008-2009 Free Software Foundation, Inc.
|
||||
/* Copyright (C) 1999-2003, 2005-2006, 2008-2009 Free Software Foundation, Inc.
|
||||
This file is part of the GNU LIBICONV Library.
|
||||
|
||||
The GNU LIBICONV Library is free software; you can redistribute it
|
||||
|
|
|
@ -360,7 +360,7 @@ find_shared_library_fullname ()
|
|||
|
||||
ungetc (c, fp);
|
||||
shared_library_fullname = NULL; size = 0;
|
||||
len = getline (&shared_library_fullname, &size, fp);
|
||||
len = getline(&shared_library_fullname, &size, fp);
|
||||
if (len >= 0)
|
||||
{
|
||||
/* Success: filled shared_library_fullname. */
|
||||
|
|
|
@ -1,4 +1,9 @@
|
|||
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SOURCE_LIST)
|
||||
AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SOURCE_LIST)
|
||||
|
||||
add_library(lz4 ${SOURCE_LIST})
|
||||
target_include_directories(lz4 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/inc)
|
||||
IF (TD_WINDOWS)
|
||||
SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} /WX-")
|
||||
SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /WX-")
|
||||
ENDIF()
|
||||
|
||||
ADD_LIBRARY(lz4 ${SOURCE_LIST})
|
||||
TARGET_INCLUDE_DIRECTORIES(lz4 PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/inc)
|
|
@ -1,7 +1,7 @@
|
|||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
PROJECT(TDengine)
|
||||
|
||||
IF (TD_WINDOWS_64)
|
||||
IF (TD_WINDOWS)
|
||||
INCLUDE_DIRECTORIES(.)
|
||||
LIST(APPEND SRC pthread.c)
|
||||
ADD_LIBRARY(pthread ${SRC})
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
*********************************************************************/
|
||||
|
||||
/* We're building the pthreads-win32 library */
|
||||
#undef PTW32_BUILD
|
||||
#define PTW32_BUILD
|
||||
|
||||
/* Do we know about the C type sigset_t? */
|
||||
|
|
|
@ -228,6 +228,8 @@ typedef unsigned long ULONG_PTR;
|
|||
#include "config.h"
|
||||
#endif /* HAVE_PTW32_CONFIG_H */
|
||||
|
||||
#include "msvcTime.h"
|
||||
|
||||
#if !defined(NEED_FTIME)
|
||||
#include <time.h>
|
||||
#else /* NEED_FTIME */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
* pthread_mutex_consistent.c
|
||||
*
|
||||
* Description:
|
||||
|
|
|
@ -100,18 +100,19 @@
|
|||
#endif
|
||||
#endif /* PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX */
|
||||
|
||||
#if (defined(__MINGW64__) || defined(__MINGW32__)) || defined(_UWIN)
|
||||
# if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX
|
||||
/* For pid_t */
|
||||
# include <sys/types.h>
|
||||
/* Required by Unix 98 */
|
||||
# include <time.h>
|
||||
# else
|
||||
typedef int pid_t;
|
||||
# endif
|
||||
#else
|
||||
typedef int pid_t;
|
||||
#endif
|
||||
// #if (defined(__MINGW64__) || defined(__MINGW32__)) || defined(_UWIN)
|
||||
// # if PTW32_SCHED_LEVEL >= PTW32_SCHED_LEVEL_MAX
|
||||
// /* For pid_t */
|
||||
// # include <sys/types.h>
|
||||
// /* Required by Unix 98 */
|
||||
// # include <time.h>
|
||||
// # else
|
||||
// typedef int pid_t;
|
||||
// # endif
|
||||
// #else
|
||||
// typedef int pid_t;
|
||||
// #endif
|
||||
#include <sys/msvcTypes.h>
|
||||
|
||||
/* Thread scheduling policies */
|
||||
|
||||
|
|
|
@ -99,6 +99,8 @@
|
|||
#endif
|
||||
#endif /* PTW32_SEMAPHORE_LEVEL >= PTW32_SEMAPHORE_LEVEL_MAX */
|
||||
|
||||
#include "sys/msvcTypes.h"
|
||||
|
||||
#define _POSIX_SEMAPHORES
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
PROJECT(TDengine)
|
||||
|
||||
IF (TD_WINDOWS_64)
|
||||
IF (TD_WINDOWS)
|
||||
INCLUDE_DIRECTORIES(inc .)
|
||||
LIST(APPEND SRC regex.c)
|
||||
ADD_LIBRARY(regex ${SRC})
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
PROJECT(TDengine)
|
||||
|
||||
IF (TD_WINDOWS)
|
||||
INCLUDE_DIRECTORIES(inc)
|
||||
INCLUDE_DIRECTORIES(inc/sys)
|
||||
AUX_SOURCE_DIRECTORY(src SRC)
|
||||
ADD_LIBRARY(wepoll ${SRC})
|
||||
ENDIF ()
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* wepoll - epoll for Windows
|
||||
* https://github.com/piscisaureus/wepoll
|
||||
*
|
||||
* Copyright 2012-2020, Bert Belder <bertbelder@gmail.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef WEPOLL_H_
|
||||
#define WEPOLL_H_
|
||||
|
||||
#define WEPOLL_EXPORT
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
enum EPOLL_EVENTS {
|
||||
EPOLLIN = (int) (1U << 0),
|
||||
EPOLLPRI = (int) (1U << 1),
|
||||
EPOLLOUT = (int) (1U << 2),
|
||||
EPOLLERR = (int) (1U << 3),
|
||||
EPOLLHUP = (int) (1U << 4),
|
||||
EPOLLRDNORM = (int) (1U << 6),
|
||||
EPOLLRDBAND = (int) (1U << 7),
|
||||
EPOLLWRNORM = (int) (1U << 8),
|
||||
EPOLLWRBAND = (int) (1U << 9),
|
||||
EPOLLMSG = (int) (1U << 10), /* Never reported. */
|
||||
EPOLLRDHUP = (int) (1U << 13),
|
||||
EPOLLONESHOT = (int) (1U << 31)
|
||||
};
|
||||
|
||||
#define EPOLLIN (1U << 0)
|
||||
#define EPOLLPRI (1U << 1)
|
||||
#define EPOLLOUT (1U << 2)
|
||||
#define EPOLLERR (1U << 3)
|
||||
#define EPOLLHUP (1U << 4)
|
||||
#define EPOLLRDNORM (1U << 6)
|
||||
#define EPOLLRDBAND (1U << 7)
|
||||
#define EPOLLWRNORM (1U << 8)
|
||||
#define EPOLLWRBAND (1U << 9)
|
||||
#define EPOLLMSG (1U << 10)
|
||||
#define EPOLLRDHUP (1U << 13)
|
||||
#define EPOLLONESHOT (1U << 31)
|
||||
|
||||
#define EPOLL_CTL_ADD 1
|
||||
#define EPOLL_CTL_MOD 2
|
||||
#define EPOLL_CTL_DEL 3
|
||||
|
||||
typedef void* HANDLE;
|
||||
//typedef uintptr_t SOCKET;
|
||||
|
||||
typedef union epoll_data {
|
||||
void* ptr;
|
||||
int fd;
|
||||
uint32_t u32;
|
||||
uint64_t u64;
|
||||
SOCKET sock; /* Windows specific */
|
||||
HANDLE hnd; /* Windows specific */
|
||||
} epoll_data_t;
|
||||
|
||||
struct epoll_event {
|
||||
uint32_t events; /* Epoll events and flags */
|
||||
epoll_data_t data; /* User data variable */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
WEPOLL_EXPORT HANDLE epoll_create(int size);
|
||||
WEPOLL_EXPORT HANDLE epoll_create1(int flags);
|
||||
|
||||
WEPOLL_EXPORT int epoll_close(SOCKET ephnd);
|
||||
|
||||
WEPOLL_EXPORT int epoll_ctl(SOCKET ephnd,
|
||||
int op,
|
||||
SOCKET sock,
|
||||
struct epoll_event* event);
|
||||
|
||||
WEPOLL_EXPORT int epoll_wait(SOCKET ephnd,
|
||||
struct epoll_event* events,
|
||||
int maxevents,
|
||||
int timeout);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif /* WEPOLL_H_ */
|
File diff suppressed because it is too large
Load Diff
|
@ -1,8 +1,8 @@
|
|||
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
|
||||
PROJECT(TDengine)
|
||||
|
||||
IF (TD_LINUX_64)
|
||||
IF (TD_LINUX)
|
||||
INCLUDE_DIRECTORIES(inc)
|
||||
AUX_SOURCE_DIRECTORY(src SRC)
|
||||
ADD_LIBRARY(z ${SRC})
|
||||
ENDIF ()
|
||||
ENDIF ()
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue