diff --git a/cmake/define.inc b/cmake/define.inc index f6438c08736c7cc63cdd1734e016f9a0945df631..5c005b0cb5ca3355d77636484ff0d417fb9de435 100755 --- a/cmake/define.inc +++ b/cmake/define.inc @@ -29,41 +29,30 @@ 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 () +IF (TD_ARM_64) + ADD_DEFINITIONS(-D_TD_ARM_64_) + 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) - 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 () +IF (TD_ARM_32) + ADD_DEFINITIONS(-D_TD_ARM_32_) + 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_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 +64,17 @@ 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_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 +87,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 +114,11 @@ 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) ENDIF () IF (TD_WINDOWS_64) @@ -136,3 +131,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}) diff --git a/cmake/platform.inc b/cmake/platform.inc index 488786b17869c6185d40363890bd57a43637575b..4cb6262471f580f0734f5adb1526b0626d2b4854 100755 --- a/cmake/platform.inc +++ b/cmake/platform.inc @@ -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 () diff --git a/deps/CMakeLists.txt b/deps/CMakeLists.txt index f5911ca0c9e81eb3d51278cbf148014e07784125..64930b29d2880ba70348e1fd50c4bd953ba2d980 100644 --- a/deps/CMakeLists.txt +++ b/deps/CMakeLists.txt @@ -7,8 +7,9 @@ ADD_SUBDIRECTORY(regex) ADD_SUBDIRECTORY(iconv) ADD_SUBDIRECTORY(lz4) ADD_SUBDIRECTORY(cJson) -#ADD_SUBDIRECTORY(MsvcLibX) +ADD_SUBDIRECTORY(wepoll) +ADD_SUBDIRECTORY(MsvcLibX) -IF (NOT TD_WINDOWS) +IF (TD_LINUX) ADD_SUBDIRECTORY(MQTT-C) ENDIF () \ No newline at end of file diff --git a/deps/MsvcLibX/CMakeLists.txt b/deps/MsvcLibX/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7f24d34dd5f311967d1292beadb63b9136aabd52 --- /dev/null +++ b/deps/MsvcLibX/CMakeLists.txt @@ -0,0 +1,31 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.8) +PROJECT(TDengine) + +IF (TD_WINDOWS_64) + SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake) + + include(FindWindowsSDK) + get_mywindowssdk_include_dirs(${WINDOWSSDK_PREFERRED_DIR} WINSDK_INCLUDE_DIR) + get_ucrt_include_dirs(${WINDOWSSDK_PREFERRED_DIR} UCRT_INCLUDE_DIR) + + Add_Definitions("-DWSDKINCLUDE=${WINSDK_INCLUDE_DIR}") + + include(FindMSVC) + Add_Definitions("-DMSVCINCLUDE=${VC_INCLUDE_DIR}") + + IF ((NOT DEFINED UCRT_INCLUDE_DIR) OR (UCRT_INCLUDE_DIR STREQUAL "NOTFOUND")) + Message(STATUS "UCRT_INCLUDE_DIR notu found, set it to vc incude dir") + SET(UCRT_INCLUDE_DIR "${VC_INCLUDE_DIR}") + Add_Definitions("-DUCRTINCLUDE=${VC_INCLUDE_DIR}") + ELSE () + Add_Definitions("-DUCRTINCLUDE=${UCRT_INCLUDE_DIR}") + ENDIF () + + Message(STATUS "WINSDK_INCLUDE_DIR: ${WINSDK_INCLUDE_DIR}") + Message(STATUS "UCRT_INCLUDE_DIR: ${UCRT_INCLUDE_DIR}") + Message(STATUS "VC_INCLUDE_DIR: ${VC_INCLUDE_DIR}") + + INCLUDE_DIRECTORIES(include) + AUX_SOURCE_DIRECTORY(src SRC) + ADD_LIBRARY(MsvcLibXw64 ${SRC}) +ENDIF () diff --git a/deps/MsvcLibX/README.md b/deps/MsvcLibX/README.md new file mode 100644 index 0000000000000000000000000000000000000000..8f689412cbd1e1d4c4b5b89e69865998964c159f --- /dev/null +++ b/deps/MsvcLibX/README.md @@ -0,0 +1,820 @@ +MsvcLibX - A set of MSVC Library eXtensions +=========================================== + + +Introduction +------------ + +The MsvcLibX library is built upon 30 years of work. +It exists because the Microsoft Visual C/C++ library is only a subset of the +standard C library, and I wanted to port to DOS and Windows programs using some +of the missing parts. +Initially Microsoft C compilers for MS-DOS tried to be as compliant as possible +with the standard C library. Then Microsoft rewrote their library for Windows. +But when the WIN32 API became prevalent, Microsoft apparently lost interest, +and stopped porting to MS-DOS and Windows the new C include files and library +routines that got standardized over the years. +To the point that's it's now impossible to rebuild any recent Posix/Unix/Linux +program using the MSVC library. + +MsvcLibX adds a number of standard include files and library routines that I've +needed over the years. For example the directory access routines defined in +dirent.h, or the symbolic link support in unistd.h. +It also includes a number of useful routines and macros, either needed +internally to implement and debug the above, or made necessary by irresolvable +incompatibilities between Unix and Windows. + +Other major features of the MsvcLibX library are: + +* A powerful make system, based on Microsoft nmake files, that allow building + multiple versions of the same program (Ex: DOS/WIN32/WIN64) with one simple + command. And in most cases without having to write any dedicated make file. +* Support for UTF-8 sources, allowing to build programs working in any code page. +* Support for NTFS symlinks and junctions. +* Support for DOS, and Windows 95 targets, for targeting old computers. +* Support for bound DOS+Windows programs, for truly universal executables that + work in *all* versions of DOS and Windows. + +An obvious alternative exists for building Windows programs: MinGW. +But I started all this before MinGW even existed. And, surprisingly, even MinGW +still has holes in 2014, where MsvcLibX in significantly more advanced. +Another alternative is CygWin. This one is more complete, but also much more +heavyweight. Using programs built with CygWin requires installing CygWin DLLs. +Copying the program .exe from one system to the next is not sufficient. In that +sense, MinGW or MsvcLibX are much better. + +Contrary to MinGW and CygWin, MsvcLibX does not attempt to be complete, and is +unlikely to ever be. But any contribution of improvements is welcome. +Likewise, any help at contributing unique MsvcLibX features to MinGW is welcome. + +Jean-François Larvoire +2016-09-29 + + +Building the MsvcLibX library +----------------------------- + +On a recent Windows PC, with Microsoft Visual C++ compilers installed: + +- Select a base work directory. I'll call it %BASEDIR% in the examples below: + + set "HOME=%HOMEDRIVE%%HOMEPATH%" + set "BASEDIR=%HOME%\Documents\SRC" + md "%BASEDIR%" + cd "%BASEDIR%" + +- Extract the MsvcLibX archive into a work subdirectory. Ex: %BASEDIR%\MsvcLibX\ + This will put files in several subdirectories: include, src + +- Open a cmd window, and run: + + cd "%BASEDIR%\MsvcLibX\src" + configure + make + +The configure.bat script will locate your MSVC tools, and generate a config +file. It needs to be run once initially, then again if new MSVC tool versions +are installed. +The make.bat script should take care of everything, and rebuild normal and debug +versions of the MsvcLibX.lib library for all operating systems your tools support. +In the end, it defines system environment variable MSVCLIBX, necessary for +building programs using the MsvcLibX.lib library. + +Requirements: + +- Microsoft Visual C++ compiler and linker for Windows 32 and 64 bits targets. +- Microsoft Windows SDK. (May be installed along with Visual C++) + +As of 2015-12-10, I've tested the make.bat script and make files with Visual C++ +2005, 2008, 2012, and 2015, and Windows SDK 5.2, 8.1, and 10. +Support for older versions is still built-in, but I've not tested it for long. +Support for newer versions will require minor tweaks in configure.bat. +Note that configure.bat does not depend on MSVC's vcvars.bat. It will attempt +to locate and use the latest usable version of MSVC it finds in Program Files. + +Optional: + +- Microsoft Visual C++ 1.52 compiler and linker for MS-DOS targets. + If present in C:\MSVC, make.bat will also generate libraries for DOS. + Note that generating DOS versions is still more useful than it looks: + Experience has shown that the severe memory constraints under DOS are a very + good revelator of memory leaks, and other bad pointer issues. Build your + programs for DOS too if you can, and test them in a VM with Windows XP. + This takes a very small extra build time. And it'll be very much worth the time + if the Windows version appears to work, but the DOS version does not. + Visual C++ 1.52 is available on the Visual Studio 2005 CD. +- The Visual C++ 8 compiler and tools from Microsoft Visual Studio 2005. + This is the last version that allowed building programs for Windows 95/NT4. + +The MsvcLibX.lib libraries are generated in subdirectories of src, then copied +into the %BASEDIR%\MsvcLibX\lib directory, and renamed as shown in this table: + +Subdirectory | Description | Renamed as +---------------- | -------------------------------------- | ---------------- +DOS\BIN\T\ | DOS normal version, tiny memory model | MsvcLibXdt.lib +DOS\DEBUG\BIN\T\ | DOS debug version, tiny memory model | MsvcLibXdtd.lib +DOS\BIN\S\ | DOS normal version, small memory model | MsvcLibXds.lib +DOS\DEBUG\BIN\S\ | DOS debug version, small memory model | MsvcLibXdsd.lib +DOS\BIN\L\ | DOS normal version, large memory model | MsvcLibXdl.lib +DOS\DEBUG\BIN\L\ | DOS debug version, large memory model | MsvcLibXdld.lib +WIN95\ | WIN32 normal version for Windows 95 | MsvcLibXw32.lib +WIN95\DEBUG\ | WIN32 debug version for Windows 95 | MsvcLibXw32d.lib +WIN32\ | WIN32 (X86) normal version | MsvcLibXw32.lib +WIN32\DEBUG\ | WIN32 (X86) debug version | MsvcLibXw32d.lib +WIN64\ | WIN64 (AMD64) normal version | MsvcLibXw64.lib +WIN64\DEBUG\ | WIN64 (AMD64) debug version | MsvcLibXw64d.lib + + +Building programs using the MsvcLibX library +-------------------------------------------- + +Create a work directory, distinct from the MsvcLibX directories. Ex: + + set "HOME=%HOMEDRIVE%%HOMEPATH%" + set "BASEDIR=%HOME%\Documents\SRC" + md "%BASEDIR%\MyTools" + cd "%BASEDIR%\MyTools" + :# Define a variable giving the location of the MsvcLibX base directory + :# (Automatically defined if you built the library already on that same system.) + set "MSVCLIBX=%BASEDIR%\MsvcLibX" + :# Get batch files and make files from MsvcLibX sources + copy "%MSVCLIBX%\src\*.bat" + copy "%MSVCLIBX%\src\*.mak" + :# Create the configuration file (To be done just once) + configure + :# Compile and link your C or C++ program. + :# Ex, for the dirc.c sample, to create all dirc.exe versions, type: + make dirc.exe + :# If there is any error, the dirc.log file will pop up. + :# If there's no error, it's possible to check for warnings by reading dirc.log: + notepad dirc.log + :# All generated object files, listings, executables, etc, are in + :# target-OS-specific subdirectories, like for the MsvcLibX builds above. + :# They're automatically linked with the corresponding (renamed) MsvcLibX*.lib. + +make.bat will generate WIN32 (X86) and WIN64 (AMD64) versions by default, +and put them respectively in the WIN32\ and WIN64\ subdirectories. +It will also generate a DOS version in DOS\ if MSVC 1.52 is installed. +It will also generate a WIN95 version in WIN95\ if MSVC 8 (aka. 2005) is installed. +Run `make -?` get a help screen for make.bat. + +Note that the configure.bat and make.bat scripts are actually independent of the +rest of the MsvcLibX library. They can be used to easily build any console +programs for DOS and Windows, without loading the Visual Studio GUI. + +An exe.bat script is a front-end to make.bat, saving a few characters to type: +`exe dirc` <==> `make dirc.exe` + + +Building Linux versions of the same programs +-------------------------------------------- + +Install virtual machines with Linux, and give them access to the host's file +system, for example in the /c directory. +Then execute the following commands, adapting the paths as needed: + + # Go to the work directory + BASEDIR=/c/Users/YOURNAME/Documents/SRC + mkdir $BASEDIR/MyTools + cd $BASEDIR/MyTools + # Get a bash script to build Linux versions using similar directory outputs + cp $BASEDIR/MsvcLibX/src/exe . + # Make sure the Linux C compiler finds MsvcLibX debug macros, but not other MsvcLibX include files. + # Important: Do not point C_INCLUDE_PATH at MsvcLibX/include, as this directory + # contains duplicates for standard include files (Ex: stdio.h), that will fail + # to compile in Linux. + mkdir ~/include + cp $BASEDIR/MsvcLibX/include/debugm.h ~/include + export C_INCLUDE_PATH=~/include + # Make sure that variable is defined in all future sessions + echo "export C_INCLUDE_PATH=~/include" >>~/.bashrc + # Compile your sample dirc.c program (which uses MsvcLibX debug macros) + ./exe dirc + # The output will be in subdirectories such as Linux.i686/ or Linux.x86_64/. + # (The exact name depends on `echo "$(uname -s).$(uname -m)"` output) + + +Adding new files to the library +------------------------------- + +All new files should have headers and comments similar to the existing ones. + +To add a new source file (let's call it newfile.c) into the library: + +- Put newfile.c in the %MSVCLIBX%\src directory. +- Add a +newfile.obj entry to the OBJECTS list in %MSVCLIBX%\src\Files.mak +- Also add a rule with newfile.c include files dependencies in src\Files.mak. +- Rebuild the library, and make sure there are no errors nor warnings. + +To add a new include file into the library: + +- All new include file names should be standard C library include files names! +- Put it in the include or include\sys subdirectory. + +To add an include file overriding an homonym one in the MSVC library: + +- The trick is to make it include MSVC's one, then define its own extensions. + As MSVC compilers do not support the #include_next directive, I've implemented + a mechanism for including MSVC include files using their full pathname. + As an example, see include/direct.h or include/sys/stat.h. + + +The make file system +-------------------- + +Microsoft Visual Studio tools contain a build tool called nmake, very similar +to, but slightly incompatible with, Unix make. +MsvcLibX's make.bat is designed to give a similar feel to Unix make. +It uses internally a number of make files: + +Make file | Description +----------- | ---------------------------------------------------------------- +NMakefile | Default make file to use, if none is specified. +DOS.mak | Generic rules for building MS-DOS programs into the DOS subdir. +WIN32.mak | Generic rules for building 32-bits Windows programs into WIN32. +WIN64.mak | Generic rules for building 64-bits Windows programs into WIN64. +WIN95.mak | Generic rules for building Windows 95 programs into WIN95. +All.mak | Generic rules for building one or more of the above. +Files.mak | Application-specific source file dependancy rules. Intended to be includable from both Windows' nmakefile and Linux' makefile. + +DOS.mak, WIN32.mak, WIN64.mak, and All.mak are pretty stable, and should not +be changed. The only likely case where a change is needed would be to add extra +libraries to link with _all_ programs. +To add a library for one particular program, it'd be better to add a specific +rule in its own make file, as described below. +In all cases, see the detailed notes in each make file header. + +Specific make files: + +To build a target called program.exe, the 5 make files with generic rules +(DOS.mak, WIN32.mak, WIN64.mak, WIN95.mak, and All.mak) first look for a +specific make file called program.mak. They include it if present. This allows +defining application-specific rules. +These rules should use macros defined in the 4 make files to specify the +build environment and parameters. Here's a list of the most useful ones: + +Macro | Description +--------- | ---------------------------------------------------------------- +T | Target OS. One of DOS, WIN32, WIN64, WIN95. +S | Path of the source files +O | Path where to put the object files +B | Path where to put the binary executable files +L | Path where to put the listings +CFLAGS | Flags for Microsoft C compiler +INCLUDE | List of C include file paths, serarated by ';' +LFLAGS | Flags for Microsoft linker +PROGRAM | The program base name, infered from the target name. +SOURCES | The list of sources for the program. Default: PROGRAM.c or .cpp +OBJECTS | The list of objects to link. Default: PROGRAM.obj + +Scripts: + +Script | Description +--------------------- | -------------------------------------------------------- +make.bat | The main build tool. Invokes nmake. +config.%HOSTNAME%.bat | Defines paths to all tools used by make. Do not edit. +configure.bat | Analyses your system, and generates a config.%HOSTNAME%.bat file. +configure.*.bat | Define user or task-specific extensions to configure.bat. +exe.bat | Front end to make.bat, generating multiple goals. +exe | Linux shell script, invoking cc with multiple goals. +src2objs.bat | Internal script used by make files to convert SOURCES to OBJECTS + +configure.bat with search for configure.*.bat scripts in %windir%, then in %HOME%, +then in the current directory. +Put configuration scripts with your global preferences in %windir% for example. +Within each directory, the files are called in the alphabetic order, allowing +to manage predictable dependancies. + +Example 1: The 2clip program has no MS-DOS version. To prevent the make system +from attempting to build a DOS version (Only necessary if you DO have MSVC 1.52 +installed), create a 2clip.mak file with this content: + + !IF "$(T)"=="DOS" + complain: + @echo>con There's no DOS version of this program. + + dirs $(O)\2clip.obj $(B)\2clip.exe: complain + @rem Do nothing + !ENDIF + +Example 2: Porting to Windows a resize.c program manipulating jpeg images, +and using the libjpeg library. Create a resize.mak file with lines like these: + + INCLUDE=$(INCLUDE);C:\JFL\SRC\Libs\libjpeg;C:\JFL\SRC\Libs\libjpeg\jpeg-8d + LFLAGS=$(LFLAGS) C:\JFL\SRC\Libs\libjpeg\$(B)\libjpeg.lib + +Example 3: Some Windows programs need to include additional resources, defined +in a .rc file. Ex: The update program uses a manifest to control its rights. +Create an update.mak file with directives like this: + + !IF "$(T)"=="WIN32" || "$(T)"=="WIN64" + SOURCES=update.c update.rc + LFLAGS=$(LFLAGS) /MANIFEST + !ENDIF + + +The debug system +---------------- + +The MsvcLibX library makes it easy to build two versions of each program: + +- A release version, small lean and fast. +- A debug version, with additional code to help developers debug the program. + +It follows Microsoft's convention of defining the macro _DEBUG when compiling +a C/C++ source for a debug build. +But it goes much further, by providing in debugm.h a set of macros to assist +debugging. + +The general principle is that by default, the debug version operates exactly +like the release version. (Except possibly for performance) +Then, if the "debug mode" is enabled, it outputs debug messages on stdout. +A major property of the MsvcLibX debugging output is that is is intended by +function call depth. This makes it considerably easier to read the debug output. + +The MsvcLibX library itself is built in debug and release versions. +The make.bat system will link the release version of your program with the +release version of the MsvcLibX library, and likewise for the debug versions. +To use it, include debugm.h in your main module, and add to your main() routine +a command-line option (-d or --debug maybe?) that calls DEBUG_ON(). +There's also an "extra debug mode", displaying even more details than the +debug mode. It is enabled by calling DEBUG_ON() twice. ==> Invoke with -d -d. + +Debug macros: + +Macro | Description +--------------------------- | ------------------------------------------------ +DEBUG_ON() | Enable the debug mode. +DEBUG_CODE(...) | The code within parentheses is only compiled in the debug version +DEBUG_PRINTF((format, ...)) | Generates a printf instruction in the debug version only, that prints only if debug mode is enabled, with the output indented by call depth. +DEBUG_ENTER((format, ...)) | Like DEBUG_PRINTF, but for use at the beginning of a function. Increases the indent level. +DEBUG_LEAVE((format, ...)) | Like DEBUG_PRINTF, but for use before returning from a function. Decreases the indent level. + +Note that every use of DEBUG_ENTER must be matched by one DEBUG_LEAVE. So if a +function has several return instructions, every return must be preceded by a +DEBUG_LEAVE. + +DEBUG_LEAVE alternatives: +To further simplify the source, a pair DEBUG_LEAVE()/return can be replaced by +one of the following macros: + +Macro | Simplified description +----------------------------- | ------------------------------------------------ +RETURN_INT(i) | DEBUG_LEAVE(("return %d\n", i)); return i; +RETURN_INT_COMMENT(i, (args)) | Idem, plus prints a comment behind the return +RETURN_BOOL(b) | DEBUG_LEAVE(("return %s\n", b?"TRUE":"FALSE")); return b; +RETURN_BOOL_COMMENT(b, (...)) | Idem, plus prints a comment behind the return +RETURN_CHAR(c) | DEBUG_LEAVE(("return %c\n", c)); return c; +RETURN_STRING(s) | DEBUG_LEAVE(("return %s\n", s)); return s; + +For all the above, the release version just does return retValue; + +Example for a recursive function factorial: + + int fact(int n) { + DEBUG_ENTER((__FUNCTION__ "(%d);\n", n)); + if (n) n *= fact(n-1); else n = 1; + RETURN_INT(n); + } + +The debug version, in debug mode, invoked with argument 4, prints: + + fact(4); + fact(3); + fact(2); + fact(1); + fact(0); + return 1; + return 1; + return 2; + return 6; + return 24; + + +Support for UTF-8 sources +------------------------- + +The MsvcLibX library supports writing C programs using 8-bit characters, +with strings encoded as UTF-8, and that will work for any cmd.exe code page. +This makes the sources much more simple and readable that using full-fledged +Unicode, with 16-bits wchar_t or WCHAR and L"strings" or _T("strings"). + +Note: The cmd.exe code page can be read and changed with the CHCP command. +The most common code pages are: + +CP | Description +----- | ---------------------------------------------------------------------------- +437 | MS-DOS OEM code page, still used by cmd.exe in US and west-European systems. +1252 | Windows "ANSI" code page, used by most GUI programs, like notepad.exe. +65001 | UTF-8 code page. Allows display any Unicode character. + +Important: Changing the code page will only work correctly if cmd.exe is using +a TrueType font. The default "Raster" font supports code page 437 only. + +To enable that UTF-8 support: + +1. Set the C or C++ source encoding to UTF-8 with BOM. (BOM = Byte-Order Mark) +Having a BOM is important, as without it some Windows editors will incorrectly +detect the encoding, and then sometimes corrupt the source. +2. Define one of the following constants in the .c source, _before_ including +any .h include files: + + #define _BSD_SOURCE 1 /* Defined by many standard BSD-Unix programs */ + #define _GNU_SOURCE 1 /* Defined by many standard GNU-Unix/Linux programs */ + #define _UTF8_SOURCE 1 /* MsvcLibX-specific */ + +Note that most modern Linux compilers do expect C sources encoded as UTF-8, +and will silently ignore the UTF-8 BOM if present. + +Internally, MsvcLibX extends Microsoft's convention of having two ANSI and Wide +versions of each routine, respectively with an 'A' and a 'W' suffix. Ex: +FindFirstFile() being an alias to either FindFirstFileA() or FindFirstFileW(). +MsvcLibX uses two additional suffixes: 'U' for the UTF-8 version, and 'M' for +the common MultiByte subroutine used by both the 'A' and 'U' versions. Ex: + +Function | Description +---------- | --------------------------------------------------------------- +readlinkW | Posix routine readlink - Wide char version +readlinkM | MultiByte char sub-routine, used by the next two routines. +readlinkA | Posix routine readlink - ANSI version +readlinkU | Posix routine readlink - UTF-8 version +readlink | Posix routine readlink - Alias to either readlinkA or readlinkU + +Note that the M version has one additional argument: The code page to use for +converting strings to and from Unicode. In that sense, it's not Posix-compliant. + +Gotcha: As of 2014-03-25, most file I/O and enumeration routines have been +restructured this way, but a few have not yet been: +scandir() and lstat() only support UTF-8 file names, not ANSI names. + +Gotcha: As of 2014-03-25, there's a potential issue with the C main() routine: +Supporting UTF-8 file names is not just supporting UTF-8 strings in library +functions. It's also necessary to process the command line, so that command line +arguments are passed in to the main() routine as UTF-8 strings. +Currently this is implemented as a macro that redefines the main token, so +that it generates a main() routine just calling a _mainU0() routine from +MsvcLibX.lib, followed by another local _mainU() routine with the body intended +for your main routine. Ex: + + int main(int argc, char *argv[]) { /* your main body */ } + +Becomes: + + int main(int argc, char *argv[]) {return _mainU0()} + int _mainU(int argc, char *argv[]) { /* your main body */ } + +The _mainU0() routine from MsvcLibX.lib reprocesses the Win32 command line as +UTF-8 argv[] arguments, then calls _mainU(argc, argv[]). +This works well and transparently, except in one case: +If one of your sources or include files contain a prototype for the main() +routine, then MsvcLibX' main macro will break that prototype, and cause +compilation and/or link errors. +If this happens, simply remove the main() prototype, which is useless anyway. + + +Support for NTFS symlinks and junctions +--------------------------------------- + +Posix defines only a single kind of symbolic links, usable for any kind of +targets, whether they're files, directories, or further symbolic links. +The standard C library defines functions for managing symbolic links: + +Function | Description +---------- | ---------------------------------------------------------------- +readlink() | Read a link target +symlink() | Create a link, or change its target +lstat() | Read the metadata (timestamp, access rights) for the link itself +lchmod() | Change the link access rights +lchown() | Change the link owner +realpath() | Generate an absolute path, with all links resolved + +Windows defines three types of links: + +Type | Description +--------- | --------------------------------------------------------------- +SYMLINK | Symbolic link to a file +SYMLINKD | Symbolic link to a directory +JUNCTION | Mount point, often used as a symbolic link to another directory + +All three types can be created in Vista and later by the mklink command. +JUNCTIONS can also be created in 2000 and later by Microsoft's SysInternal's +junction command. +One important difference is that JUNCTIONs can be created with normal user +rights, whereas SYMLINKs and SYMLINKDs require administrator rights in an +elevated command window. +A second important difference is that on networks, SYMLINKs and SYMLINKDs are +interpreted on the client side, whereas JUNCTIONs are interpreted on the server +side (despite having their target readable from the client side). + +The MsvcLibcX library tries to hide that complexity, and implements the standard +functions as if there were only one kind of link. +It also provides non-standard functions symlinkd() and junction() to +specifically create SYMLINKDs and JUNCTIONs respectively. + +Notes about readlink(): +For SYMLINKs and SYMLINKDs, the case is straightforward. +For JUNCTIONs, there are two problems: + +- The target is stored as an absolute path, even when the JUNCTION was created + with a relative path. readlink() tries to convert the absolute path to a + relative path, so that file copying utilities can clone trees with internal + JUNCTIONs. +- When the JUNCTION is on a network drive, the target refers to the absolute + path on the server. This may not be accessible from the client through the + existing mounted shares. Even when this is accessible, it's not always easy + to map the server path to a valid client path. + readlink() uses heuristics which always work for drives shared at the drive + level. Ex: a C: drive shared as C$, a D: drive shared as D$, etc. + The heuristic also very likely works for drives shared at the root or first + directory level. Ex: C:\ shared as CROOT, or C:\Public shared as PUBLIC. + As of 2014-03-25, it'll fail in any other case. Ex: + C:\Users\YOURNAME shared as YOURHOME, + or a C:\Public share mounted through its subdirectory C:\Public\Temp + +Notes about symlink(): +symlink() will attempt to create a SYMLINK or a SYMLINKD, depending on the type +of the target. This works well when the target exists. But when it does not +(which is legal), it will create a SYMLINK by default, or a SYMLINKD if the +target ends with a '/' or a '\'. Posix allows, but does not require, providing +a trailing '/', so the link type may possibly be incorrect. +junction() will have the same issues as readlink() above. + +Notes about junction(): +The problem for junction() is to convert a client-side target pathname provided +by the program running on the client, to a server-side pathname, necessary for +junctions to work. +For full-drive shares (i.e. any share named like D$), this is easy. +For non-full-drive shares (i.e. anything else), it will assume this is a +first level shared directory on the C: drive. Ex: A link on share PUBLIC +will be targeted at C:\PUBLIC. +Problem: The junction will not work if the share actually resides anywhere else +on the server. But, surprisingly, there's an easy workaround: +Simply create manually on the server itself, a junction called C:\PUBLIC, +pointing at the actual directory shared as PUBLIC. +This way the junctions created from the client side will work correctly, both +on the client and on the server side, after being resolved on the server side +through that second junction. + + +Support for Windows 95/98 +------------------------- + +The configure.bat script searches for old versions of the Visual C++ compiler, +which can build WIN32 programs that can run in Windows 95/98/ME/NT4. +The most recent of these is Visual C++ 8, from Visual Studio 2005. +The make.bat script can then use rules in win95.mak to builds WIN32 programs +that will run in any version of Windows from Windown 95 to Windows 10. + +Note however that Windows 95/98/ME only have a very limited support for Unicode +built in. The rest of this section mentions 95, but applies to 98 & ME as well. +The MsvcLibX library uses a number of Unicode functions not available in default +installations of Windows 95. This includes all file management functions. +Thus most of our WIN95 executables will not work by default in Windows 95. +To allow them to work, it is necessary to download from Microsoft a "Microsoft +Layer for Unicode on Windows 95/98/ME Systems" (MSLU for short), and install it +on the Windows 95 system. See the following links for details: +https://en.wikipedia.org/wiki/Microsoft_Layer_for_Unicode +https://msdn.microsoft.com/en-us/goglobal/bb688166.aspx +MSLU installation procedure: + +- Download the MSLU redistributable setup (unicows.exe) from: + http://go.microsoft.com/fwlink/?LinkId=14851 +- Extract unicows.dll from the unicows.exe archive. +- Copy that unicows.dll to the Windows 95 system, into %windir%\System. + +Testing WIN95 executables in a Windows 95 VM +VMWare Player does not have Windows 95 drivers for the HGFS file system. +This prevents accessing the host's files directly as network files, as is +usually done for Windows XP and later versions of Windows. +It is not possible to use network shares either, as Windows 95 only supports +the SMB 1 protocol, which is actively blocked by Windows Vista and later hosts. +It is possible, but inconvenient, to transit through a web server, and download +the files in the Windows 95 VM using Internet Explorer 4. +The best solution probably is to transit through a floppy or CD image, and +mount that image in the VM Player. Many tools, including our own HpMkIso.exe +can create CD images. A very convenient shareware called WinImage allows to +create floppy images. +Another solution is to install a Web server on the host PC, and use Internet +Explorer 4 in Windows 95 to download the executable files into the VM. + + +Support for DOS, and bound DOS+Windows programs +----------------------------------------------- + +- If Visual C++ 1.52 is installed, configure.bat will setup the make system +for building the MS-DOS version of your programs. (Output in the DOS directory) +- If Visual C++ 8 is installed, configure.bat will setup the make system +for building 32-bits versions of your programs compatible with Windows 95 +and all later versions, including 64-bits ones. (Output in the WIN95 directory) + +Both are available as part of the Visual Studio 2005 CD, still available for +download for MSDN subscribers from the MSDN web site. + +Win32 programs have an "MS-DOS stub", that runs when the Windows program is +executed under MS-DOS. +The default stub used by the Win32 linker if a tiny DOS program that displays +an error message such as: "This program can only run in Windows" + +When it builds the WIN95 or WIN32 version of a program, and when it has built +the DOS version already, the MsvcLibX make system uses that DOS version as the +stub for the Windows version. +This allows building executables that work in *all* versions of DOS and Windows! + +- When run in MS-DOS, it's the DOS stub of the exe that runs. +- When run in Windows (even 64-bits versions), it's the Win32 part that runs. + +Note that the make system will build such bound executables for any WIN32 +build made with more recent compilers. But these recent compilers generate +executables that cannot run in old versions of Windows. For example, the +Visual C++ 14 compiler can only target Windows Vista and later systems. +Having an executable that can run in DOS and Windows 7, but not in Windows XP, +is not very useful. Make sure to install the Visual C++ 8 compiler in parallel +with Visual C++ 1.52, and the latest compiler (Visual C++ 14 at the time of +this writing), to generate truly universal WIN95 builds, that run in +DOS/95/98/ME/2000/XP/Vista/7/8/10. + + +History +------- + +**1986** + +I (Jean-François Larvoire) started writing command-line tools for MS-DOS. +Some were enumerating files, using inline assembly language to make MS-DOS +interrupt 21h system calls: update, dirsize, redo, backnum, which, dirc... +To make it simple I factored these out in subroutines srch1st and srchnext, +that I manually copied from one program to the next. +Things got a bit tricky to support recursion, which was not straightforward +in MS-DOS. + + +**1992** + +We got an OS/2 server, and I started porting the above programs to OS/2. +MS-DOS was still important, so I used conditional compilation to support +both operating systems with the same source. +I wrote a second version of srch1st and srchnext for OS/2, and had to +include a new routine srchdone due to OS/2 API constraints. +dirc was the first program I ported, then I slowly duplicated the code into +the other programs. Synchronizing bug fixes became more difficult. +A nice trick was the OS/2 supported dual-mode EXEs, with both the DOS and +OS/2 version bound in the same .exe file. + + +**1995** + +We ditched the OS/2 server, and got a new one running Windows NT. +Again, I created a third conditionally compiled version of srch1st/srchnext/ +srchdone for WIN32, for use in dirc. +Manually back porting the updates and bug fixes to all programs became +really painful, and took several years. +Like OS/2, Windows supported dual-mode EXEs, and I updated my make files +to include both the DOS and Windows version in the same file. + + +**2005** + +I started working on Linux projects. Despite the bonanza of command-line +tools available, I couldn't find one equivalent to dirc. +So, yet another time, I created a fourth conditionally compiled version of +srch1st/srchnext/srchdone for Linux, and obtained a Linux version of dirc. +I also ported it and a couple of other programs to Tru64, which was the +first 64-bits OS I worked with. This exposed a few unsuspected bugs. +The thing became so complex than porting the changes and updates to the +other programs was a nightmare. I did it for a few of them, but never +got the time to port them all. + + +**2010** + +Building WIN64 versions was relatively easier due to the Tru64 precedent, +but added yet another set of conditional compilations. +The porting nightmare worsened. + + +**2012** + +I tried porting some unrelated Linux programs to Windows, and hit a wall: +Many include files and standard C library routines were missing in MSVC. +I then tried using MinGW, but it too was missing many required features! +I considered contributing updates to MinGW, but that project was too +complex and ill-documented at that time, and I eventually gave up. +Instead, I started writing my own "libc-ext" library of include files and +routines to supplement MSVC. +Ex: stdint.h, inttypes.h, fnmatch.h/fnmatch.c, ... +Also it became obvious that multiplying conditional compilations and +duplicating directory access code everywhere was wrong. Instead I had to +write standard dirent.h/dirent.c routines for DOS/OS2/Windows, and +rewrite all my programs around these standard routines. +I did it for DOS and Windows versions, and left stubs of the OS/2 versions, +for the unlikely case where somebody wants to revive them. + +**2013** + +The restructuration was over for dirc, dirsize, which, backnum, update. +The library got its final name, "MsvcLibX", to better match it purpose: +An extension of the Microsoft Visual C library, not of the standard libc. +As the library grew, debugging it became more difficult, and I decided to +use my debugm.h within the library: This file contains a set of debugging +macros I had developed for other programs. +I started thinking about sorely needed improvements: + +- There was no support for Windows symlinks and junctions. +- The Windows versions of the programs output ANSI file names into a + cmd.exe window using the OEM character set. This caused all files with + French names to be shown as garbage. +- Worse still, I had a few files and directories with non-ANSI names + (In Russian and Chinese), that caused the programs to fail! + +The Linux version of the program did not have these issues, as all recent +versions of Linux use the UTF-8 encoding, and this works transparently +even for old programs using 8-bits characters like mine. + + +**2014** + +I got a bit more time, and started working on a redesign of MsvcLibX's +dirent.c/dirent.h, and added lstat.c, symlink.c, readlink.c, etc, to +support symlinks, junctions, and UTF-8 file names. +This proved to be much more work than I initially thought, but the result +was worth the effort: dirc, update got easily adapted, with remarkably +few changes to their source. Adding recursion to update was easy. +I'm now able to use update to backup all files on my system, including +symbolic links, and junctions used as poor man's links. And the programs +now display names correctly in any code page with the right font. +A seventh program, truename, joined the collection using dirent.h routines. +Later in the year, I made significant other changes: + +- Split make.bat into a generic make.bat/configure.bat pair of scripts. + configure.bat needs to be run once, plus everytime the environment + changes. (Such as if a new MSVC version is installed.) + Project-specific definitions are moved to new files, such as our + configure.MsvcLibX.bat. +- Added a general mechanism for defining extensions to existing MSVC + include files. This allowed defining our own homonym include files, + containing just the missing definitions. Which in turn allowed to move + many such definitions, that were initially stored in unistd.h for lack + of an alternative, to their standard location. +- Updated all file functions to support WIN32 pathnames > 260 characters. + (The basic WIN32 functions that I used until then had that limitation; + I'm now using extended functions supporting path lengths up to 64K.) + +All tools like dirc, dirsize, which, backnum, update, truename, redo +benefit from that last change. + +**2015** + +A major improvement was the addition of support for new operating systems +and processor targets. This required redesigning several things: +The OS-specific definition macros have been renamed to more generic names. +The DosWin.mak file has been replaced by a more generic All.mak, +supporting the old dos.mak, win32.mak, and win64.mak, plus the new... + +- bios.mak Allows building 16-bits programs that can run in BIOS option + ROMs. These programs are based on the BiosLib library, + documented separately. +- win95.mak Allows building win32 programs that run in Windows 95. +- ia64.mak Allows building 64-bits programs that run in IA64 versions + of Windows. Not tested. +- arm.mak Allows building win32 programs for Windows RT. + Tests failed so far, due to a missing "ARM Desktop SDK". + +All.mak also skips building versions for which no tools are available; +This prevents problems in the normal case when people only have the latest +version of MSVC. In this case, it just builds the WIN32 and WIN64 versions. +The support for Windows 95 required fixing numerous issues with old +Microsoft tools and Windows SDKs. +Conversely, the support for Visual Studio 15 also required fixing lots of +issues, as the MSVC library has been completely redesigned, and split into +two parts: + +- A compiler-specific part, part of the compiler tree as before. +- A generic part, called Universal C runtime (UCRT) that's now part of + the windows SDK. + +And of course there were also issues with MsvcLibX recent improvements, +like Unicode support and symlink support, which had never been tested, +and of course did not work, in Windows 95 and XP. + + +**2016** + +Many significant changes and improvements this year: + +- Changed the UTF-8 C source support to require a UTF-8 BOM. + This is to prevent problems with Windows tools that tend to corrupt files + without a UTF-8 BOM, but with other UTF-8 characters. + This required changing all C/C++ compilation rules to first remove the + UTF-8 BOM, as MS compilers do not react correctly when they find one. +- Added a windows.h extension. + Just like Standard C library APIs, windows 8-bit APIs can be overriden to + refer to custom routines that support UTF-8 strings. + The MsvcLibX library was beginning to use a significant number of these + custom routines internally. They're now accessible directly to outside + UTF-8 programs targeting only Windows. +- Finished implementing support for the OUTDIR variable. (Started in 2015.) + All make files now optionally create output files in an %OUTDIR% directory. + This is intended for testing builds in VMs, with shared sources on the + host, but the output locally in the VM, avoiding to overwrite the main + version on the host. IF %OUTDIR% is not defined, the default output + still goes below the source directory as before. diff --git a/deps/MsvcLibX/config.DESKTOP-U79TD6T.bat b/deps/MsvcLibX/config.DESKTOP-U79TD6T.bat new file mode 100644 index 0000000000000000000000000000000000000000..b1b68e1540ff11bfd8fd1eee985bb28d0f439044 --- /dev/null +++ b/deps/MsvcLibX/config.DESKTOP-U79TD6T.bat @@ -0,0 +1,146 @@ +:# config.DESKTOP-U79TD6T.bat generated by configure.bat on 2020/05/19 Öܶþ 7:49:05.47 +:# +:# If changes are needeed, do not edit this file, but instead create a new script +:# called configure.YOURCHOICE.bat. This new script will be invoked automatically +:# by configure.bat while creating this file. Then your script can write extra +:# definitions, or change some of the variables before configure.bat writes them. +:# +:# Invoke configure.bat manually if anything changes in the tools config, such as +:# installing a Visual Studio update, or updating a configure.XXX.bat script. + +set "HAS_STINCLUDE=1" &:# Found the System Tools global C includes +set "STINCLUDE=C:\Users\admin\Desktop\temp\MyGitHub\C\include" &:# System Tools global C includes +set "HAS_SDK_FLAGS=/DHAS_STINCLUDE=1" &:# SDK detection flags for the C compiler + +SET "PF32=C:\Program Files (x86)" &:# 32-bits Program Files +SET "PF64=C:\Program Files" &:# 64-bits Program Files +SET "ARCH=AMD64" &:# PROCESSOR_ARCHITECTURE + +SET "MASM=" &:# Microsoft 16-bits Assembler base path +SET "MSVC=" &:# Microsoft 16-bits Visual C++ base path +SET "MAPSYM=" &:# 16-bits debugging symbols generator + +SET "VSTUDIOLONG=C:\Program Files (x86)\Microsoft Visual Studio 14.0" &:# Microsoft Visual Studio (Long path) +SET "VSTUDIO=C:\PROGRA~2\MICROS~2.0" &:# Microsoft Visual Studio (Short path) +SET "VSCOMMONLONG=C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7" &:# Microsoft Visual Studio Common Files (Long path) +SET "VSCOMMON=C:\PROGRA~2\MICROS~2.0\Common7" &:# Microsoft Visual Studio Common Files (Short path) +SET "VSIDELONG=C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE" &:# Microsoft Visual Studio IDE Files (Long path) +SET "VSIDE=C:\PROGRA~2\MICROS~2.0\Common7\IDE" &:# Microsoft Visual Studio IDE Files (Short path) +SET "VSTOOLSLONG=C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools" &:# Microsoft Visual Studio Tools (Long paths) +SET "VSTOOLS=C:\PROGRA~2\MICROS~2.0\Common7\Tools" &:# Microsoft Visual Studio Tools (Short paths) +SET "MSVC32LONG=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC" &:# Microsoft Visual C++ 32/64 bits (Long path) +SET "MSVC32=C:\PROGRA~2\MICROS~2.0\VC" &:# Microsoft Visual C++ 32/64 bits (Short path) + +SET "WIN_CP=936" &:# Windows Code Page +SET "WIN_CS=gb2312" &:# Windows Character Set +SET "DOS_CP=936" &:# DOS Code Page +SET "DOS_CS=gb2312" &:# DOS Character Set + +SET "AS=" &:# Assembler +SET "CC=" &:# C compiler +SET "INCLUDE=C:\Users\admin\Desktop\temp\MyGitHub\C\include" &:# Include paths. Define USER_INCLUDE if needed. +SET "LK=" &:# Linker +SET "LIB=" &:# Libraries paths. Define USER_LIBS if needed. +SET "LB=" &:# Library manager +SET "RC=" &:# Resource compiler +SET "MT=" &:# Manifest tool + +SET "DOS_CC=" &:# Microsoft Visual C++ 16-bits compiler +SET "DOS_AS=" &:# Microsoft 16-bits assembler +SET "DOS_LK=" &:# Microsoft 16-bits linker +SET "DOS_LB=" &:# Microsoft 16-bits librarian +SET "DOS_RC=" &:# Microsoft 16-bits resource compiler +SET "DOS_MT=" &:# Microsoft 16-bits manifest tool +SET "DOS_PATH=;C:\Windows\System32;C:\Windows" &:# All tools paths for 16-bits compilation +SET "DOS_VCINC=" &:# Visual C++ 16-bits compiler include dir for MsvcLibX include_next +SET "DOS_CRTINC=" &:# Visual C++ 16-bits CRT library include dir for MsvcLibX include_next +SET "DOS_INCPATH=" &:# Include paths for 16-bits compilation +SET "DOS_LIBPATH=" &:# Libraries paths for 16-bits linking +SET "DOS_WINSDK=" &:# Microsoft Windows 16-bits SDK +SET "DOS_WINSDKINC=" &:# Microsoft Windows 16-bits SDK Include directory + +SET "WIN95_CC=" &:# Microsoft Visual C++ 32-bits compiler +SET "WIN95_AS=" &:# Microsoft 32-bits assembler +SET "WIN95_LK=" &:# Microsoft 32-bits linker +SET "WIN95_LB=" &:# Microsoft 32-bits librarian +SET "WIN95_RC=" &:# Microsoft 32-bits resource compiler +SET "WIN95_MT=" &:# Microsoft 32-bits manifest tool +SET "WIN95_PATH=;C:\Windows\System32;C:\Windows" &:# All tools paths for 32-bits compilation +SET "WIN95_VCINC=" &:# Visual C++ 32-bits compiler include dir for MsvcLibX include_next +SET "WIN95_CRTINC=" &:# Visual C++ 32-bits CRT library include dir for MsvcLibX include_next +SET "WIN95_INCPATH=" &:# Include paths for 32-bits compilation +SET "WIN95_LIBPATH=" &:# Libraries paths for 32-bits linking +SET "WIN95_WINSDK=" &:# Microsoft Windows 32-bits SDK +SET "WIN95_WINSDKINC=" &:# Microsoft Windows 32-bits SDK Include directory + +SET "WIN32_CC="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\CL.EXE"" &:# Microsoft Visual C++ 32-bits compiler +SET "WIN32_AS="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\ML.EXE"" &:# Microsoft 32-bits assembler +SET "WIN32_LK="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\LINK.EXE"" &:# Microsoft 32-bits linker +SET "WIN32_LB="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\LIB.EXE"" &:# Microsoft 32-bits librarian +SET "WIN32_RC=" &:# Microsoft 32-bits resource compiler +SET "WIN32_MT=" &:# Microsoft 32-bits manifest tool +SET "WIN32_PATH=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools;C:\Windows\System32;C:\Windows" &:# All tools paths for 32-bits compilation +SET "WIN32_VCINC=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include" &:# Visual C++ 32-bits compiler include dir for MsvcLibX include_next +SET "WIN32_CRTINC=C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt" &:# Visual C++ 32-bits CRT library include dir for MsvcLibX include_next +SET "WIN32_INCPATH=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include;:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\shared;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\winrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\shared;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\winrt" &:# Include paths for 32-bits compilation +SET "WIN32_LIBPATH=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\um\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86" &:# Libraries paths for 32-bits linking +SET "WIN32_WINSDK=C:\Program Files (x86)\Windows Kits\10" &:# Microsoft Windows 32-bits SDK +SET "WIN32_WINSDKINC=C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0" &:# Microsoft Windows 32-bits SDK Include directory + +SET "IA64_CC=" &:# Microsoft Visual C++ IA64 compiler +SET "IA64_AS=" &:# Microsoft IA64 assembler +SET "IA64_LK=" &:# Microsoft IA64 linker +SET "IA64_LB=" &:# Microsoft IA64 librarian +SET "IA64_RC=" &:# Microsoft IA64 resource compiler +SET "IA64_MT=" &:# Microsoft IA64 manifest tool +SET "IA64_PATH=;C:\Windows\System32;C:\Windows" &:# All tools paths for IA64 compilation +SET "IA64_VCINC=" &:# Visual C++ IA64 compiler include dir for MsvcLibX include_next +SET "IA64_CRTINC=" &:# Visual C++ IA64 CRT library include dir for MsvcLibX include_next +SET "IA64_INCPATH=" &:# Include paths for IA64 compilation +SET "IA64_LIBPATH=" &:# Libraries paths for IA64 linking +SET "IA64_WINSDK=" &:# Microsoft Windows IA64 SDK +SET "IA64_WINSDKINC=" &:# Microsoft Windows IA64 SDK Include directory + +SET "WIN64_CC="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\CL.EXE"" &:# Microsoft Visual C++ 64-bits compiler +SET "WIN64_AS="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\ML64.EXE"" &:# Microsoft 64-bits assembler +SET "WIN64_LK="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\LINK.EXE"" &:# Microsoft 64-bits linker +SET "WIN64_LB="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\LIB.EXE"" &:# Microsoft 64-bits librarian +SET "WIN64_RC=" &:# Microsoft 64-bits resource compiler +SET "WIN64_MT=" &:# Microsoft 64-bits manifest tool +SET "WIN64_PATH=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools;C:\Windows\System32;C:\Windows" &:# All tools paths for 64-bits compilation +SET "WIN64_VCINC=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include" &:# Visual C++ 64-bits compiler include dir for MsvcLibX include_next +SET "WIN64_CRTINC=C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt" &:# Visual C++ 64-bits CRT library include dir for MsvcLibX include_next +SET "WIN64_INCPATH=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include;:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\shared;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\winrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\shared;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\winrt" &:# Include paths for 64-bits compilation +SET "WIN64_LIBPATH=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib\amd64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\um\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64" &:# Libraries paths for 64-bits linking +SET "WIN64_WINSDK=C:\Program Files (x86)\Windows Kits\10" &:# Microsoft Windows 64-bits SDK +SET "WIN64_WINSDKINC=C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0" &:# Microsoft Windows 64-bits SDK Include directory + +SET "ARM_CC="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64_arm\CL.EXE"" &:# Microsoft Visual C++ ARM compiler +SET "ARM_AS="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64_arm\ARMASM.EXE"" &:# Microsoft ARM assembler +SET "ARM_LK="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64_arm\LINK.EXE"" &:# Microsoft ARM linker +SET "ARM_LB="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64_arm\LIB.EXE"" &:# Microsoft ARM librarian +SET "ARM_RC=" &:# Microsoft ARM resource compiler +SET "ARM_MT=" &:# Microsoft ARM manifest tool +SET "ARM_PATH=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64_arm;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools;C:\Windows\System32;C:\Windows" &:# All tools paths for ARM compilation +SET "ARM_VCINC=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include" &:# Visual C++ ARM compiler include dir for MsvcLibX include_next +SET "ARM_CRTINC=C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt" &:# Visual C++ ARM CRT library include dir for MsvcLibX include_next +SET "ARM_INCPATH=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include;:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\shared;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\winrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\shared;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\winrt" &:# Include paths for ARM compilation +SET "ARM_LIBPATH=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\um\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm" &:# Libraries paths for ARM linking +SET "ARM_WINSDK=C:\Program Files (x86)\Windows Kits\10" &:# Microsoft Windows ARM SDK +SET "ARM_WINSDKINC=C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0" &:# Microsoft Windows ARM SDK Include directory + +SET "ARM64_CC=" &:# Microsoft Visual C++ ARM64 compiler +SET "ARM64_AS=" &:# Microsoft ARM64 assembler +SET "ARM64_LK=" &:# Microsoft ARM64 linker +SET "ARM64_LB=" &:# Microsoft ARM64 librarian +SET "ARM64_RC=" &:# Microsoft ARM64 resource compiler +SET "ARM64_MT=" &:# Microsoft ARM64 manifest tool +SET "ARM64_PATH=;C:\Windows\System32;C:\Windows" &:# All tools paths for ARM64 compilation +SET "ARM64_VCINC=" &:# Visual C++ ARM64 compiler include dir for MsvcLibX include_next +SET "ARM64_CRTINC=" &:# Visual C++ ARM64 CRT library include dir for MsvcLibX include_next +SET "ARM64_INCPATH=" &:# Include paths for ARM64 compilation +SET "ARM64_LIBPATH=" &:# Libraries paths for ARM64 linking +SET "ARM64_WINSDK=" &:# Microsoft Windows ARM64 SDK +SET "ARM64_WINSDKINC=" &:# Microsoft Windows ARM64 SDK Include directory + +exit /b 0 &:# Configuration done successfully diff --git a/deps/MsvcLibX/configure.bat b/deps/MsvcLibX/configure.bat new file mode 100644 index 0000000000000000000000000000000000000000..7037eb92afccbfe2e0d6872a108799d56538c490 --- /dev/null +++ b/deps/MsvcLibX/configure.bat @@ -0,0 +1,35 @@ +@echo off +:#***************************************************************************** +:# * +:# Filename: configure.bat * +:# * +:# Description: Detect system-specific settings and create config.*.bat * +:# * +:# Notes: Proxy script for %STINCLUDE%\configure.bat. * +:# * +:# Make any change needed in %STINCLUDE%\configure.bat. * +:# * +:# History: * +:# 2016-10-10 JFL jf.larvoire@hpe.com created this file. * +:# 2016-12-15 JFL Search for the real make.bat in [.|..|../..]\include. * +:# * +:# © Copyright 2016 Hewlett Packard Enterprise Development LP * +:# Licensed under the Apache 2.0 license www.apache.org/licenses/LICENSE-2.0 * +:#***************************************************************************** + +:# Get the full pathname of the STINCLUDE library directory +if defined STINCLUDE if not exist "%STINCLUDE%\make.bat" set "STINCLUDE=" &:# Allow overriding with another alias name, but ignore invalid overrides +for %%p in (. .. ..\..) do if not defined STINCLUDE if exist %%p\include\make.bat ( :# Default: Search it the current directory, and 2 levels above. + for /f "delims=" %%d in ('"pushd %%p\include & cd & popd"') do SET "STINCLUDE=%%d" +) +if not defined STINCLUDE ( :# Try getting the copy in the master environment + for /f "tokens=3" %%v in ('reg query "HKCU\Environment" /v STINCLUDE 2^>NUL') do set "STINCLUDE=%%v" +) + +if not exist %STINCLUDE%\make.bat ( + >&2 echo %0 Error: Cannot find SysToolsLib's global C include directory. Please define variable STINCLUDE. + exit /b 1 +) + +if [%1]==[-d] echo "%STINCLUDE%\configure.bat" %* +"%STINCLUDE%\configure.bat" %* diff --git a/deps/MsvcLibX/include/debugm.h b/deps/MsvcLibX/include/debugm.h new file mode 100644 index 0000000000000000000000000000000000000000..b20a7035c696864324e9a496cfaf5e777f5d0cd1 --- /dev/null +++ b/deps/MsvcLibX/include/debugm.h @@ -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 /* 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) */ + diff --git a/deps/MsvcLibX/include/direct.h b/deps/MsvcLibX/include/direct.h new file mode 100644 index 0000000000000000000000000000000000000000..7cedc1cf7dbc5db620efb1d8e41d2ab8afca3ab7 --- /dev/null +++ b/deps/MsvcLibX/include/direct.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 UCRT_INCLUDE_FILE(direct.h) /* Include MSVC's own file */ + +#undef mkdir /* This MSVC macro is incompatible with mkdir() function in unistd.h */ + +#endif /* defined(_MSVCLIBX_DIRECT_H) */ + diff --git a/deps/MsvcLibX/include/dirent.h b/deps/MsvcLibX/include/dirent.h new file mode 100644 index 0000000000000000000000000000000000000000..ac702e01dd62d897405bb94e455bd950e832c640 --- /dev/null +++ b/deps/MsvcLibX/include/dirent.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 +#include +#include +#include +#include + +#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 + +#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 +#include + +/* 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 + +#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) */ + diff --git a/deps/MsvcLibX/include/error.h b/deps/MsvcLibX/include/error.h new file mode 100644 index 0000000000000000000000000000000000000000..e8edad7c678524ada087e0c69eb35c647416ad10 --- /dev/null +++ b/deps/MsvcLibX/include/error.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 diff --git a/deps/MsvcLibX/include/fadvise.h b/deps/MsvcLibX/include/fadvise.h new file mode 100644 index 0000000000000000000000000000000000000000..37d4c310f053cf61e25343db6f65dfdad048343b --- /dev/null +++ b/deps/MsvcLibX/include/fadvise.h @@ -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) diff --git a/deps/MsvcLibX/include/fcntl.h b/deps/MsvcLibX/include/fcntl.h new file mode 100644 index 0000000000000000000000000000000000000000..735287c0d4b9973de79c649541371f98dd42cddb --- /dev/null +++ b/deps/MsvcLibX/include/fcntl.h @@ -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 UCRT_INCLUDE_FILE(fcntl.h) /* Include MSVC's own file */ + +/* Microsoft defines _open() in io.h */ +#include + +#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) */ diff --git a/deps/MsvcLibX/include/fnmatch.h b/deps/MsvcLibX/include/fnmatch.h new file mode 100644 index 0000000000000000000000000000000000000000..b41a2b5305112835996fc0e0aba66b37f1147554 --- /dev/null +++ b/deps/MsvcLibX/include/fnmatch.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) */ + diff --git a/deps/MsvcLibX/include/getopt.h b/deps/MsvcLibX/include/getopt.h new file mode 100644 index 0000000000000000000000000000000000000000..ad4b2f2baac299c5f0b252d4eb0f1dde26929a58 --- /dev/null +++ b/deps/MsvcLibX/include/getopt.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_ */ + diff --git a/deps/MsvcLibX/include/iconv.h b/deps/MsvcLibX/include/iconv.h new file mode 100644 index 0000000000000000000000000000000000000000..396296fb53be88713f390309cb10d5d3b58dd1c9 --- /dev/null +++ b/deps/MsvcLibX/include/iconv.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 + +#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 + +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) */ + diff --git a/deps/MsvcLibX/include/inttypes.h b/deps/MsvcLibX/include/inttypes.h new file mode 100644 index 0000000000000000000000000000000000000000..51740fade3119b1a5ff1bba5d2f2050130e2fe1f --- /dev/null +++ b/deps/MsvcLibX/include/inttypes.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 + +/* 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_ */ diff --git a/deps/MsvcLibX/include/libgen.h b/deps/MsvcLibX/include/libgen.h new file mode 100644 index 0000000000000000000000000000000000000000..f7ce9feff4144884d203cd5bd4d23eedcc589cc2 --- /dev/null +++ b/deps/MsvcLibX/include/libgen.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) */ diff --git a/deps/MsvcLibX/include/limits.h b/deps/MsvcLibX/include/limits.h new file mode 100644 index 0000000000000000000000000000000000000000..d4a9e09d5e76241ea985ad88a5e0fa7434e234f9 --- /dev/null +++ b/deps/MsvcLibX/include/limits.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 MSVC_INCLUDE_FILE(limits.h) /* Include MSVC's own 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) */ + diff --git a/deps/MsvcLibX/include/msvclibx.h b/deps/MsvcLibX/include/msvclibx.h new file mode 100644 index 0000000000000000000000000000000000000000..6395737f4baed2f9e963b1a0304bfed12d38d445 --- /dev/null +++ b/deps/MsvcLibX/include/msvclibx.h @@ -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 . See MsvcLibX' "sys/time.h" for explanations. */ +#define _WINSOCKAPI_ /* Prevent the inclusion of winsock.h in windows.h */ + +#endif /* _MSVCLIBX_H_ */ + diff --git a/deps/MsvcLibX/include/netdb.h b/deps/MsvcLibX/include/netdb.h new file mode 100644 index 0000000000000000000000000000000000000000..417150afc8c3df16594bff21f8de9fd45d86b9e2 --- /dev/null +++ b/deps/MsvcLibX/include/netdb.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 */ + diff --git a/deps/MsvcLibX/include/process.h b/deps/MsvcLibX/include/process.h new file mode 100644 index 0000000000000000000000000000000000000000..105b71669b1d885dd1c5e9c6a45d267ec60eb33c --- /dev/null +++ b/deps/MsvcLibX/include/process.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 UCRT_INCLUDE_FILE(process.h) /* Include MSVC's own 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) */ + diff --git a/deps/MsvcLibX/include/regex.h b/deps/MsvcLibX/include/regex.h new file mode 100644 index 0000000000000000000000000000000000000000..82158c7b2e0d22039928279e4dfa6e6c0a420f70 --- /dev/null +++ b/deps/MsvcLibX/include/regex.h @@ -0,0 +1,89 @@ +#ifndef _HSREGEX_H_ +#define _HSREGEX_H_ +#ifndef _HSREGEX_H +#define _HSREGEX_H /* never again */ + +#include /* 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 diff --git a/deps/MsvcLibX/include/reparsept.h b/deps/MsvcLibX/include/reparsept.h new file mode 100644 index 0000000000000000000000000000000000000000..1f2f7bea0c97db5f1c805d21d716ab348ada6c00 --- /dev/null +++ b/deps/MsvcLibX/include/reparsept.h @@ -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 + +/* 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() + + diff --git a/deps/MsvcLibX/include/stdbool.h b/deps/MsvcLibX/include/stdbool.h new file mode 100644 index 0000000000000000000000000000000000000000..4697fd52556c739768095a15d5df1b39663b0ded --- /dev/null +++ b/deps/MsvcLibX/include/stdbool.h @@ -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 diff --git a/deps/MsvcLibX/include/stdint.h b/deps/MsvcLibX/include/stdint.h new file mode 100644 index 0000000000000000000000000000000000000000..db321df86a6f130afae8cdf4b4ca7c23c00413f0 --- /dev/null +++ b/deps/MsvcLibX/include/stdint.h @@ -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 + +/* +// For Visual Studio 6 in C++ mode wrap 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 +# 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 */ +#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_ */ diff --git a/deps/MsvcLibX/include/stdio--.h b/deps/MsvcLibX/include/stdio--.h new file mode 100644 index 0000000000000000000000000000000000000000..66b7e6e326c14cdfa74e06ff80cf71de9a765a75 --- /dev/null +++ b/deps/MsvcLibX/include/stdio--.h @@ -0,0 +1,17 @@ +/*****************************************************************************\ +* * +* Filename: stdio--.h * +* * +* Description: front-end to stdio.h that redefines some unsafe functions * +* * +* Notes: This header is part of the GNU CoreUtils library. * +* msvclibx: Pass through to the standard stdio.h. * +* * +* 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 * +\*****************************************************************************/ + +#include diff --git a/deps/MsvcLibX/include/stdio.h b/deps/MsvcLibX/include/stdio.h new file mode 100644 index 0000000000000000000000000000000000000000..e819d131898e94c6587f701676efaa4b533e1578 --- /dev/null +++ b/deps/MsvcLibX/include/stdio.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 UCRT_INCLUDE_FILE(stdio.h) /* Include MSVC's own file */ + +#include + +#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) */ + diff --git a/deps/MsvcLibX/include/stdlib.h b/deps/MsvcLibX/include/stdlib.h new file mode 100644 index 0000000000000000000000000000000000000000..110641d4273e18ab310b1fe794754824467c54ba --- /dev/null +++ b/deps/MsvcLibX/include/stdlib.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 UCRT_INCLUDE_FILE(stdlib.h) /* Include MSVC's own 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) */ + diff --git a/deps/MsvcLibX/include/sys/param.h b/deps/MsvcLibX/include/sys/param.h new file mode 100644 index 0000000000000000000000000000000000000000..ebb0430fc98893503d0baee11af57e9f8736bb6c --- /dev/null +++ b/deps/MsvcLibX/include/sys/param.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 file */ + +#define _POSIX_ARG_MAX 8191 + +#endif /* defined(_WIN32) */ + +#endif /* !defined(_SYS_PARAM_H) */ + diff --git a/deps/MsvcLibX/include/sys/stat.h b/deps/MsvcLibX/include/sys/stat.h new file mode 100644 index 0000000000000000000000000000000000000000..2cbe7151481a408b008cc9485672c9507289b050 --- /dev/null +++ b/deps/MsvcLibX/include/sys/stat.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 +#include UCRT_INCLUDE_FILE(sys\stat.h) /* Include MSVC's own file */ +#include /* For dirent2stat() arguments definitions */ +#include /* for time_t definition */ +#include /* for timespec definition */ +/* Include MsvcLibX's override, to avoid conflict with the standard mkdir defined here, + should be manually included later on in the C source */ +#include + +#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 "debugm.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) */ + diff --git a/deps/MsvcLibX/include/sys/time.h b/deps/MsvcLibX/include/sys/time.h new file mode 100644 index 0000000000000000000000000000000000000000..2dd8f4a5e439147d91f3ee1af28ce9f55de7d3d0 --- /dev/null +++ b/deps/MsvcLibX/include/sys/time.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 , as this sys/time.h file has a definition * +* of struct timeval conflicting with that in , * +* and as a workaround it defines _WINSOCKAPI_ to prevent * +* from loading . * +* * +* The same conflict exists with , 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 . * +* 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 /* 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 /* 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) */ + diff --git a/deps/MsvcLibX/include/sys/types.h b/deps/MsvcLibX/include/sys/types.h new file mode 100644 index 0000000000000000000000000000000000000000..5b0f4133229721c9eb1cd86e0723a5f8f4238120 --- /dev/null +++ b/deps/MsvcLibX/include/sys/types.h @@ -0,0 +1,98 @@ +/*****************************************************************************\ +* * +* 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 UCRT_INCLUDE_FILE(sys\types.h) /* Include MSVC's own 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 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 +#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; + +/* 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) */ + diff --git a/deps/MsvcLibX/include/sys/utsname.h b/deps/MsvcLibX/include/sys/utsname.h new file mode 100644 index 0000000000000000000000000000000000000000..4b2a85527ffdaf8c2c3cede3350b70e37996d77b --- /dev/null +++ b/deps/MsvcLibX/include/sys/utsname.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 */ diff --git a/deps/MsvcLibX/include/system.h b/deps/MsvcLibX/include/system.h new file mode 100644 index 0000000000000000000000000000000000000000..56f102c33d4d0185fc0ba3bf22bf60d1a168a8a4 --- /dev/null +++ b/deps/MsvcLibX/include/system.h @@ -0,0 +1,2 @@ +/* CoreUtils global system configuration definitions */ + diff --git a/deps/MsvcLibX/include/time.h b/deps/MsvcLibX/include/time.h new file mode 100644 index 0000000000000000000000000000000000000000..f95ec6ddfa5905e822fe20c7d466624a4ad4ea74 --- /dev/null +++ b/deps/MsvcLibX/include/time.h @@ -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 WINSDK_INCLUDE_FILE(winsock2.h) +#include UCRT_INCLUDE_FILE(time.h) /* Include MSVC's own 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\time.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) */ + diff --git a/deps/MsvcLibX/include/unistd.h b/deps/MsvcLibX/include/unistd.h new file mode 100644 index 0000000000000000000000000000000000000000..748de62d2425fca989637d53a5e16a19d739b5a8 --- /dev/null +++ b/deps/MsvcLibX/include/unistd.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/types.h" /* Define pid_t and getppid(). */ +#include "dirent.h" /* Define pid_t and getppid(). */ +#include /* For functions like _chdir() and _getcwd() */ +#include /* 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 /* 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 +#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 */ + diff --git a/deps/MsvcLibX/include/utime.h b/deps/MsvcLibX/include/utime.h new file mode 100644 index 0000000000000000000000000000000000000000..e6771fa7a88d25b0a4312a4630108e63507aedf2 --- /dev/null +++ b/deps/MsvcLibX/include/utime.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 + +#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 from defining structures and functions without _ */ + +#include + +#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 */ + diff --git a/deps/MsvcLibX/include/windows.h b/deps/MsvcLibX/include/windows.h new file mode 100644 index 0000000000000000000000000000000000000000..03404d7653490866dc7ea34c7b4442bcc57b42df --- /dev/null +++ b/deps/MsvcLibX/include/windows.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 WINSDK_INCLUDE_FILE(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) */ diff --git a/deps/MsvcLibX/include/xfreopen.h b/deps/MsvcLibX/include/xfreopen.h new file mode 100644 index 0000000000000000000000000000000000000000..9ec6e493e9eb7df361fff0b425623d08ca00f018 --- /dev/null +++ b/deps/MsvcLibX/include/xfreopen.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); + diff --git a/deps/MsvcLibX/make.bat b/deps/MsvcLibX/make.bat new file mode 100644 index 0000000000000000000000000000000000000000..7a272561228129410dcba670dee0ddb723553647 --- /dev/null +++ b/deps/MsvcLibX/make.bat @@ -0,0 +1,35 @@ +@echo off +:#***************************************************************************** +:# * +:# Filename: make.bat * +:# * +:# Description: Build DOS and Windows targets * +:# * +:# Notes: Proxy script for %STINCLUDE%\make.bat. * +:# * +:# If any change is needed, put it in %STINCLUDE%\make.bat. * +:# * +:# History: * +:# 2016-10-10 JFL jf.larvoire@hpe.com created this file. * +:# 2016-12-15 JFL Search for the real make.bat in [.|..|../..]\include. * +:# * +:# © Copyright 2016 Hewlett Packard Enterprise Development LP * +:# Licensed under the Apache 2.0 license www.apache.org/licenses/LICENSE-2.0 * +:#***************************************************************************** + +:# Get the full pathname of the STINCLUDE library directory +if defined STINCLUDE if not exist "%STINCLUDE%\make.bat" set "STINCLUDE=" &:# Allow overriding with another alias name, but ignore invalid overrides +for %%p in (. .. ..\..) do if not defined STINCLUDE if exist %%p\include\make.bat ( :# Default: Search it the current directory, and 2 levels above. + for /f "delims=" %%d in ('"pushd %%p\include & cd & popd"') do SET "STINCLUDE=%%d" +) +if not defined STINCLUDE ( :# Try getting the copy in the master environment + for /f "tokens=3" %%v in ('reg query "HKCU\Environment" /v STINCLUDE 2^>NUL') do set "STINCLUDE=%%v" +) + +if not exist %STINCLUDE%\make.bat ( + >&2 echo %0 Error: Cannot find SysToolsLib's global C include directory. Please define variable STINCLUDE. + exit /b 1 +) + +if [%1]==[-d] echo "%STINCLUDE%\make.bat" %* +"%STINCLUDE%\make.bat" %* diff --git a/deps/MsvcLibX/src/Files.mak b/deps/MsvcLibX/src/Files.mak new file mode 100644 index 0000000000000000000000000000000000000000..0b9ad8ee8c8c7476d02c089f4eb9c8157df4b518 --- /dev/null +++ b/deps/MsvcLibX/src/Files.mak @@ -0,0 +1,261 @@ +############################################################################### +# # +# File name Files.mak # +# # +# Description MsvcLibX Specific file dependancies # +# # +# Notes # +# # +# History # +# 2012-10-21 JFL Initial version # +# 2013-03-27 JFL Added debugv.obj and getppid.obj. # +# 2014-02-03 JFL Added readlink.obj. # +# 2014-02-05 JFL Added symlink.obj. # +# 2014-02-06 JFL Added lstat*.obj. # +# 2014-02-10 JFL Added realpath.obj. # +# 2014-02-17 JFL Added err2errno.obj. # +# 2014-02-26 JFL Added filetime.obj. # +# 2014-02-27 JFL Added iconv.obj. # +# 2014-02-28 JFL Added chdir.obj and getcwd.obj. # +# 2014-03-04 JFL Added fopen.obj. # +# 2014-03-06 JFL Added strerror.obj. # +# 2014-03-24 JFL Added access.obj. # +# 2014-03-27 JFL Added spawn.obj. # +# 2014-05-30 JFL Moved here the OBJECTS macro definition from NMakeFile. # +# Added uname.obj and utimes.obj. # +# 2014-06-04 JFL Added clock_gettime.obj and gettimeofday.obj. # +# 2014-06-24 JFL Added fstat64.obj and fstat64i32.obj. # +# 2014-07-01 JFL Added mb2wpath.obj. # +# 2016-09-08 JFL Added basename.obj and dirname.obj. # +# 2016-09-12 JFL Added WIN32_OBJECTS, and several WIN32 UTF-8 routines. # +# 2016-10-11 JFL moved debugm.h to SysToolsLib global C include dir. # +# 2017-02-16 JFL Added open.obj. # +# # +# © Copyright 2016 Hewlett Packard Enterprise Development LP # +# Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 # +############################################################################### + +# List of object files to build and include in the MsvcLibX library +# IMPORTANT NOTE: Every time you add an object file in the list here, also +# store its specific source file dependancies below. +OBJECTS = \ + +access.obj \ + +basename.obj \ + +chdir.obj \ + +clock_gettime.obj \ + +debugv.obj \ + +dirent.obj \ + +dirname.obj \ + +err2errno.obj \ + +filetime.obj \ + +fnmatch.obj \ + +fopen.obj \ + +fstat64i32.obj \ + +fstat64.obj \ + +getcwd.obj \ + +getopt.obj \ + +getppid.obj \ + +gettimeofday.obj \ + +iconv.obj \ + +lstat64i32.obj \ + +lstat64.obj \ + +main.obj \ + +mb2wpath.obj \ + +mkdir.obj \ + +mkdtemp.obj \ + +mkstemp.obj \ + +open.obj \ + +readlink.obj \ + +realpath.obj \ + +spawn.obj \ + +strerror.obj \ + +strndup.obj \ + +strptime.obj \ + +symlink.obj \ + +uname.obj \ + +utime.obj \ + +utimes.obj \ + +xfreopen.obj \ +# +lstat32.obj \ +# +lstat32i64.obj \ + +# WIN32 UTF-8 extension routines, used for implementing UTF-8 support for WIN32 libc. +WIN32_OBJECTS = \ + +GetFileAttributes.obj \ + +GetFileAttributesEx.obj \ + +GetFullPathName.obj \ + +GetLongPathName.obj \ + +fullpath.obj \ + +# GnuLib routines that I mistakenly defined here +REMOVED_OBJECTS = \ + +error.obj \ + +initmain.obj \ + +xnmalloc.obj \ + +############################################################################### +# Include files dependancies # +############################################################################### + +I=..\include +CI=$(STINCLUDE) + +$(I)\chdir.h: $(I)\unistd.h $(I)\iconv.h $(CI)\debugm.h + +$(I)\config.h: $(I)\msvclibx.h $(I)\stdbool.h $(I)\unistd.h + +$(I)\direct.h: $(I)\msvclibx.h + +$(I)\dirent.h: $(I)\inttypes.h $(I)\sys\stat.h + +$(I)\error.h: $(I)\msvclibx.h + +# $(I)\fadvise.h: + +$(I)\fcntl.h: $(I)\msvclibx.h + +$(I)\fnmatch.h: $(I)\msvclibx.h + +$(I)\getcwd.h: $(I)\unistd.h $(CI)\debugm.h + +# $(I)\getopt.h: + +$(I)\grp.h: $(I)\msvclibx.h + +# $(I)\inttypes.h: + +# $(I)\msvclibx.h: + +# $(I)\netdb.h: + +$(I)\process.h: $(I)\msvclibx.h + +$(I)\pwd.h: $(I)\msvclibx.h + +# $(I)\regex.h: + +$(I)\sys\stat.h: $(I)\msvclibx.h $(I)\sys\types.h + +# $(I)\stdbool.h: + +# $(I)\stdint.h: + +$(I)\stdio.h: $(I)\msvclibx.h + +# $(I)\stdio--.h: + +$(I)\stdlib.h: $(I)\msvclibx.h + +# $(I)\system.h: + +$(I)\unistd.h: $(I)\msvclibx.h $(I)\dirent.h + +# $(I)\utime.h: + +$(I)\windowsU.h: $(I)\msvclibx.h + +$(I)\xfreopen.h: $(I)\msvclibx.h + +$(I)\sys\types.h: $(I)\msvclibx.h + + +############################################################################### +# Source files dependancies # +############################################################################### + +access.c: $(I)\MsvcLibX.h $(CI)\debugm.h + +basename.c: $(I)\libgen.h + +chdir.c: $(CI)\debugm.h $(I)\iconv.h $(I)\unistd.h + +clock_gettime.c: $(I)\MsvcLibX.h $(I)\time.h $(I)\sys\stat.h + +debugv.c: $(CI)\debugm.h + +dirent.c: $(CI)\debugm.h $(I)\dirent.h $(I)\sys\stat.h $(I)\unistd.h + +dirname.c: $(I)\libgen.h + +err2errno.c: $(I)\MsvcLibX.h $(CI)\debugm.h + +error.c: $(I)\config.h $(I)\error.h + +filetime.c: $(I)\sys\stat.h + +fnmatch.c: $(CI)\debugm.h $(I)\fnmatch.h + +fopen.c: $(I)\MsvcLibX.h + +fstat64.c: fstat.c $(CI)\debugm.h $(I)\dirent.h $(I)\MsvcLibX.h $(I)\sys\stat.h $(I)\stdint.h + +fstat64i32.c: fstat.c $(CI)\debugm.h $(I)\dirent.h $(I)\MsvcLibX.h $(I)\sys\stat.h $(I)\stdint.h + +fullpath.c: $(I)\stdlib.h $(I)\limits.h + +getcwd.c: $(CI)\debugm.h $(I)\unistd.h + +GetFileAttributesU.c: $(I)\windowsU.h $(I)\limits.h + +GetFileAttributesExU.c: $(I)\windowsU.h $(I)\limits.h + +GetFullPathNameU.c: $(I)\windowsU.h $(I)\limits.h + +GetLongPathNameU.c: $(I)\windowsU.h $(I)\limits.h + +getopt.c: $(I)\getopt.h + +# getppid.c: + +gettimeofday.c: $(I)\MsvcLibX.h $(I)\time.h $(I)\sys\time.h + +grp.c: $(I)\grp.h + +iconv.c: $(I)\iconv.h + +initmain.c: $(I)\config.h + +lstat32.c: lstat.c $(CI)\debugm.h $(I)\dirent.h $(I)\MsvcLibX.h $(I)\sys\stat.h $(I)\stdint.h $(I)\unistd.h + +lstat32i64.c: lstat.c $(CI)\debugm.h $(I)\dirent.h $(I)\MsvcLibX.h $(I)\sys\stat.h $(I)\stdint.h $(I)\unistd.h + +lstat64.c: lstat.c $(CI)\debugm.h $(I)\dirent.h $(I)\MsvcLibX.h $(I)\sys\stat.h $(I)\stdint.h $(I)\unistd.h + +lstat64i32.c: lstat.c $(CI)\debugm.h $(I)\dirent.h $(I)\MsvcLibX.h $(I)\sys\stat.h $(I)\stdint.h $(I)\unistd.h + +main.c: $(I)\MsvcLibX.h + +mb2wpath.c: $(I)\MsvcLibX.h $(CI)\debugm.h + +mkdir.c: $(I)\MsvcLibX.h $(I)\sys\stat.h + +mkdtemp.c: $(I)\unistd.h + +mkstemp.c: $(I)\unistd.h + +open.c: $(I)\MsvcLibX.h $(I)\fcntl.h $(CI)\debugm.h + +pwd.c: $(I)\pwd.h + +readlink.c: $(CI)\debugm.h $(I)\unistd.h $(I)\reparsept.h + +realpath.c: $(CI)\debugm.h $(I)\unistd.h + +spawm.c: $(CI)\debugm.h $(I)\MsvcLibX.h $(I)\process.h + +strerror.c: $(I)\MsvcLibX.h + +# strndup.c: + +# strptime.c: + +symlink.c: $(CI)\debugm.h $(I)\reparsept.h $(I)\unistd.h + +uname.c: $(I)\MsvcLibX.h $(I)\sys\utsname.h + +utime.c: $(CI)\debugm.h $(I)\unistd.h $(I)\utime.h $(I)\sys\time.h + +xfreopen.c: $(I)\xfreopen.h + +xnmalloc.c: $(I)\config.h + diff --git a/deps/MsvcLibX/src/GetFileAttributes.c b/deps/MsvcLibX/src/GetFileAttributes.c new file mode 100644 index 0000000000000000000000000000000000000000..8bf3a53e8699b76e24c0ca0f6804c237d37fc5ad --- /dev/null +++ b/deps/MsvcLibX/src/GetFileAttributes.c @@ -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 /* Also includes MsvcLibX' WIN32 UTF-8 extensions */ +#include + +/*---------------------------------------------------------------------------*\ +* * +| 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) */ + diff --git a/deps/MsvcLibX/src/GetFileAttributesEx.c b/deps/MsvcLibX/src/GetFileAttributesEx.c new file mode 100644 index 0000000000000000000000000000000000000000..c24664e8fa89f8be324e7d5ab2bb66aa8bc1b714 --- /dev/null +++ b/deps/MsvcLibX/src/GetFileAttributesEx.c @@ -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 /* Also includes MsvcLibX' WIN32 UTF-8 extensions */ +#include + +/*---------------------------------------------------------------------------*\ +* * +| 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) */ + diff --git a/deps/MsvcLibX/src/GetFullPathName.c b/deps/MsvcLibX/src/GetFullPathName.c new file mode 100644 index 0000000000000000000000000000000000000000..2f87f36fdf17b21b2e1ebb084c3ca469622a9f87 --- /dev/null +++ b/deps/MsvcLibX/src/GetFullPathName.c @@ -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 /* Also includes MsvcLibX' WIN32 UTF-8 extensions */ +#include +#include "debugm.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) */ + diff --git a/deps/MsvcLibX/src/GetLongPathName.c b/deps/MsvcLibX/src/GetLongPathName.c new file mode 100644 index 0000000000000000000000000000000000000000..58a10b616e5a661fa5a8064ca89dc97e0bcd3a20 --- /dev/null +++ b/deps/MsvcLibX/src/GetLongPathName.c @@ -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 /* Also includes MsvcLibX' WIN32 UTF-8 extensions */ +#include +#include "debugm.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) */ + diff --git a/deps/MsvcLibX/src/NMakefile b/deps/MsvcLibX/src/NMakefile new file mode 100644 index 0000000000000000000000000000000000000000..398576c9156516db9f85b677b4ac6a39b8f7c177 --- /dev/null +++ b/deps/MsvcLibX/src/NMakefile @@ -0,0 +1,239 @@ +############################################################################### +# # +# File name NMakefile # +# # +# Description An NMake file for making all MsvcLibX library versions # +# # +# Notes make.bat looks for a default nmake file called nmakefile. # +# # +# History # +# 2012-10-21 JFL Initial version # +# 2014-03-05 JFL Generate the DOS version only if DOS tools are present. # +# 2014-04-22 JFL Fixed the clean target to work even without 16-bits tools.# +# 2014-05-30 JFL Moved the OBJECTS macro definition to Files.mak. # +# 2014-12-03 JFL Fixed the zip target creation. # +# 2015-11-06 JFL Added support for a Win95 version. # +# 2016-01-11 JFL Added a rule to create the common ..\lib directory. # +# 2016-07-05 JFL Fixed a typo preventing the build of DOS S Debug version. # +# 2016-09-26 JFL Added macro LIBDIR, depending on OUTDIR. # +# Copy the include files to $(OUTDIR). # +# 2016-10-04 JFL Make sure nothing is displayed when doing a make clean. # +# 2016-10-06 JFL Added targets mostlyclean & distclean. # +# 2016-10-11 JFL Adapted for use with make files in the global include dir.# +# 2016-10-13 JFL Added target cleanenv. # +# 2016-11-03 JFL Added target config. # +# Updated the cleanenv: script to display the reg command # +# it uses to delete the global environment variable. # +# 2016-11-07 JFL Place LIBDIR in the parent directory even if OUTDIR defnd.# +# Do not copy include files to OUTDIR anymore. # +# 2016-11-16 JFL Removed the rule for copying INCDIR, not used anymore. # +# 2017-02-16 JFL Default goals now depend on the existence of their # +# corresponding make file. # +# # +# © Copyright 2016 Hewlett Packard Enterprise Development LP # +# Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 # +############################################################################### + +!IF DEFINED(MESSAGES) +!MESSAGE Started MsvcLibX/src/NMakefile in $(MAKEDIR) # Display this make file name +!ENDIF + +!IF DEFINED(OUTDIR) +OD=$(OUTDIR)^\ +!IF "$(OUTDIR:\=)"=="$(OUTDIR)" +LIBDIR=..\$(OUTDIR)\lib # If OUTDIR is relative, put it in MsvcLibX top directory +!ELSE +LIBDIR=$(OUTDIR)\lib # If OUTDIR is absolute, use it as is +!ENDIF +!ELSE +OD= +LIBDIR=..\lib +!ENDIF + +MSG=>con echo # Command for writing a progress message on the console +HEADLINE=$(MSG).&$(MSG) # Output a blank line, then a message + +# Default goal: Generate all versions +all: headline \ +!IF DEFINED(DOS_CC) && EXIST("$(STINCLUDE)\DOS.mak") + $(OD)DOS\MsvcLibX.lib \ +!ENDIF +!IF DEFINED(WIN95_CC) && EXIST("$(STINCLUDE)\WIN95.mak") + $(OD)WIN95\MsvcLibX.lib \ +!ENDIF +!IF DEFINED(WIN32_CC) && EXIST("$(STINCLUDE)\WIN32.mak") + $(OD)WIN32\MsvcLibX.lib \ +!ENDIF +!IF DEFINED(WIN64_CC) && EXIST("$(STINCLUDE)\WIN64.mak") + $(OD)WIN64\MsvcLibX.lib \ +!ENDIF +!IF DEFINED(DOS_CC) && EXIST("$(STINCLUDE)\DOS.mak") + $(OD)DOS\DEBUG\MsvcLibX.lib \ +!ENDIF +!IF DEFINED(WIN95_CC) && EXIST("$(STINCLUDE)\WIN95.mak") + $(OD)WIN95\DEBUG\MsvcLibX.lib \ +!ENDIF +!IF DEFINED(WIN32_CC) && EXIST("$(STINCLUDE)\WIN32.mak") + $(OD)WIN32\DEBUG\MsvcLibX.lib \ +!ENDIF +!IF DEFINED(WIN64_CC) && EXIST("$(STINCLUDE)\WIN64.mak") + $(OD)WIN64\DEBUG\MsvcLibX.lib \ +!ENDIF + +headline: + $(HEADLINE) Building all MsvcLibX library versions + +# Define the OBJECTS macro = the list of object files to include in the library +!INCLUDE "Files.mak" + +# Create the common libs directory +$(LIBDIR): + $(HEADLINE) Creating directory $(LIBDIR:..=MsvcLibX) + md $(LIBDIR) + +# Rules for building specific versions of the MsvcLibX library +$(OD)DOS\MsvcLibX.lib: $(OD)DOS\BIN\T\MsvcLibX.lib $(OD)DOS\BIN\S\MsvcLibX.lib $(OD)DOS\BIN\L\MsvcLibX.lib + @echo Done building all DOS release libraries + +$(OD)DOS\DEBUG\MsvcLibX.lib: $(OD)DOS\DEBUG\BIN\T\MsvcLibX.lib $(OD)DOS\DEBUG\BIN\S\MsvcLibX.lib $(OD)DOS\DEBUG\BIN\L\MsvcLibX.lib + @echo Done building all DOS debug libraries + +$(OD)DOS\BIN\T\MsvcLibX.lib: $(LIBDIR) NUL + $(HEADLINE) Building MsvcLibX library DOS tiny release version + set OBJECTS=$(OBJECTS) + $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\DOS.mak "DEBUG=0" "PROGRAM=MsvcLibX" "OBJECTS=%OBJECTS:+=+$(OD)DOS\OBJ\T\%" "MEM=T" dirs $@ + if exist $@ copy $@ $(LIBDIR)\MsvcLibXdt.lib + +$(OD)DOS\BIN\S\MsvcLibX.lib: $(LIBDIR) NUL + $(HEADLINE) Building MsvcLibX library DOS small release version + set OBJECTS=$(OBJECTS) + $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\DOS.mak "DEBUG=0" "PROGRAM=MsvcLibX" "OBJECTS=%OBJECTS:+=+$(OD)DOS\OBJ\S\%" "MEM=S" dirs $@ + if exist $@ copy $@ $(LIBDIR)\MsvcLibXds.lib + +$(OD)DOS\BIN\L\MsvcLibX.lib: $(LIBDIR) NUL + $(HEADLINE) Building MsvcLibX library DOS large release version + set OBJECTS=$(OBJECTS) + $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\DOS.mak "DEBUG=0" "PROGRAM=MsvcLibX" "OBJECTS=%OBJECTS:+=+$(OD)DOS\OBJ\L\%" "MEM=L" dirs $@ + if exist $@ copy $@ $(LIBDIR)\MsvcLibXdl.lib + +$(OD)WIN95\MsvcLibX.lib: $(LIBDIR) NUL + $(HEADLINE) Building MsvcLibX library WIN95 release version + set OBJECTS=$(OBJECTS) $(WIN32_OBJECTS) + $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\WIN95.mak "DEBUG=0" "PROGRAM=MsvcLibX" "OBJECTS=%OBJECTS:+=+$(OD)WIN95\OBJ\%" dirs $@ + if exist $@ copy $@ $(LIBDIR)\MsvcLibXw95.lib + +$(OD)WIN32\MsvcLibX.lib: $(LIBDIR) NUL + $(HEADLINE) Building MsvcLibX library WIN32 release version + set OBJECTS=$(OBJECTS) $(WIN32_OBJECTS) + set OD=$(OD) + $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\WIN32.mak "DEBUG=0" "PROGRAM=MsvcLibX" "OBJECTS=%OBJECTS:+=+$(OD)WIN32\OBJ\%" dirs $@ + if exist $@ copy $@ $(LIBDIR)\MsvcLibXw32.lib + +$(OD)WIN64\MsvcLibX.lib: $(LIBDIR) NUL + $(HEADLINE) Building MsvcLibX library WIN64 release version + set OBJECTS=$(OBJECTS) $(WIN32_OBJECTS) + $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\WIN64.mak "DEBUG=0" "PROGRAM=MsvcLibX" "OBJECTS=%OBJECTS:+=+$(OD)WIN64\OBJ\%" dirs $@ + if exist $@ copy $@ $(LIBDIR)\MsvcLibXw64.lib + +$(OD)DOS\DEBUG\BIN\T\MsvcLibX.lib: $(LIBDIR) NUL + $(HEADLINE) Building MsvcLibX library DOS tiny debug version + set OBJECTS=$(OBJECTS) + $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\DOS.mak "DEBUG=1" "PROGRAM=MsvcLibX" "OBJECTS=%OBJECTS:+=+$(OD)DOS\DEBUG\OBJ\T\%" "MEM=T" dirs $@ + if exist $@ copy $@ $(LIBDIR)\MsvcLibXdtd.lib + +$(OD)DOS\DEBUG\BIN\S\MsvcLibX.lib: $(LIBDIR) NUL + $(HEADLINE) Building MsvcLibX library DOS small debug version + set OBJECTS=$(OBJECTS) + $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\DOS.mak "DEBUG=1" "PROGRAM=MsvcLibX" "OBJECTS=%OBJECTS:+=+$(OD)DOS\DEBUG\OBJ\S\%" "MEM=S" dirs $@ + if exist $@ copy $@ $(LIBDIR)\MsvcLibXdsd.lib + +$(OD)DOS\DEBUG\BIN\L\MsvcLibX.lib: $(LIBDIR) NUL + $(HEADLINE) Building MsvcLibX library DOS large debug version + set OBJECTS=$(OBJECTS) + $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\DOS.mak "DEBUG=1" "PROGRAM=MsvcLibX" "OBJECTS=%OBJECTS:+=+$(OD)DOS\DEBUG\OBJ\L\%" "MEM=L" dirs $@ + if exist $@ copy $@ $(LIBDIR)\MsvcLibXdld.lib + +$(OD)WIN95\DEBUG\MsvcLibX.lib: $(LIBDIR) NUL + $(HEADLINE) Building MsvcLibX library WIN95 debug version + set OBJECTS=$(OBJECTS) $(WIN32_OBJECTS) + $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\WIN95.mak "DEBUG=1" "PROGRAM=MsvcLibX" "OBJECTS=%OBJECTS:+=+$(OD)WIN95\DEBUG\OBJ\%" dirs $@ + if exist $@ copy $@ $(LIBDIR)\MsvcLibXw95d.lib + +$(OD)WIN32\DEBUG\MsvcLibX.lib: $(LIBDIR) NUL + $(HEADLINE) Building MsvcLibX library WIN32 debug version + set OBJECTS=$(OBJECTS) $(WIN32_OBJECTS) + $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\WIN32.mak "DEBUG=1" "PROGRAM=MsvcLibX" "OBJECTS=%OBJECTS:+=+$(OD)WIN32\DEBUG\OBJ\%" dirs $@ + if exist $@ copy $@ $(LIBDIR)\MsvcLibXw32d.lib + +$(OD)WIN64\DEBUG\MsvcLibX.lib: $(LIBDIR) NUL + $(HEADLINE) Building MsvcLibX library WIN64 debug version + set OBJECTS=$(OBJECTS) $(WIN32_OBJECTS) + $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\WIN64.mak "DEBUG=1" "PROGRAM=MsvcLibX" "OBJECTS=%OBJECTS:+=+$(OD)WIN64\DEBUG\OBJ\%" dirs $@ + if exist $@ copy $@ $(LIBDIR)\MsvcLibXw64d.lib + +# Erase all global environment variables created by this build +VARS=MSVCLIBX # Global environment variables generated here +cleanenv: + call <<"$(TMP)\cleanenv-$(PID).bat" &:# Delete variables created here + @echo off + setlocal EnableExtensions EnableDelayedExpansion + set "KEY=HKCU\Environment" + if not "$(VARS)"=="" for %%v in ($(VARS)) do @( + >>"$(TMP)\cleanenv-$(PID).lst" (echo %%v) &:# Pass the name back to make.bat, for deleting it in the current shell environment + set "VALUE=" + for /f "tokens=1,3" %%a in ('reg query "%KEY%" ^| findstr /i /b /r /c:" *%%v "') do set VALUE="%%b" + if defined VALUE ( :# The global environment variable exists. Delete it, using its actual name with the correct case. + set CMD=reg delete "%KEY%" /v %%v /f + echo !CMD! + !CMD! >NUL + ) + ) +<< + +# Dummy target, to delete all files built by these make files +clean mostlyclean distclean: + rem # Delete temporary files + -for /f "delims=" %f in ('dir /b /s *~ *.bak #*# 2^>NUL') do @del "%f" + rem # Delete files built by this nmakefile + -for /f "delims=" %f in ('dir /b /s ..\*.zip *.log 2^>NUL') do @del "%f" + rem # Delete files built by the DOS.mak, WIN32.mak, WIN64.mak make files + rem # But make DOS.mak will fail if 16-bit tools are missing. Workaround: + -if exist $(STINCLUDE)\DOS.mak $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\DOS.mak clean + if exist $(OD)DOS rd /s /q $(OD)DOS + rem # No such problem with the others, but just in case, do the same. + -if exist $(STINCLUDE)\WIN95.mak $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\WIN95.mak clean + if exist $(OD)WIN95 rd /s /q $(OD)WIN95 + -if exist $(STINCLUDE)\WIN32.mak $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\WIN32.mak clean + if exist $(OD)WIN32 rd /s /q $(OD)WIN32 + -if exist $(STINCLUDE)\WIN64.mak $(MAKE) /$(MAKEFLAGS) /f $(STINCLUDE)\WIN64.mak clean + if exist $(OD)WIN64 rd /s /q $(OD)WIN64 +!IF DEFINED(OUTDIR) + -rd /S /Q $(OUTDIR) >NUL 2>&1 +!ENDIF + -if "$@"=="distclean" del /Q config.*.bat >NUL 2>&1 + +# Dummy target, to build a source archive +dist zip: + $(MSG) Building ..\MsvcLibX.zip + cd .. + if exist MsvcLibX.zip del MsvcLibX.zip + set PATH=$(PATH);C:\Program Files\7-zip + 7z.exe a MsvcLibX.zip *.txt src\*.bat src\*.mak src\*makefile src\exe src\*.c -r include\*.h lib\ + rem # Delete files that got dragged in by wild cards, but that we don't want in the source zip. + 7z.exe d MsvcLibX.zip src\config.*.bat lib\*.lib + cd src + +# Run the configure.bat script in every subdirectory +config: + rem Nothing to do in $(MAKEDIR) as there is no further child level + +# Dummy target, to display a help screen +help: + type << +Targets: + all Rebuild all library versions (Default) + clean Delete all files built here, and all backup files + distclean Do a clean, then delete config.*.bat files + zip Build a source archive in ..\MsvcLibX.zip. Requires 7-zip. +<= 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 +#include +#include +#include "msvclibx.h" +#include "debugm.h" + +#ifdef _WIN32 + +#include + +/*---------------------------------------------------------------------------*\ +* * +| 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) */ + diff --git a/deps/MsvcLibX/src/basename.c b/deps/MsvcLibX/src/basename.c new file mode 100644 index 0000000000000000000000000000000000000000..f89aa22e1f2d8def34c9f770eb6519b9bfbd103f --- /dev/null +++ b/deps/MsvcLibX/src/basename.c @@ -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 +#include +#include +#include +#include + +#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; +} diff --git a/deps/MsvcLibX/src/chdir.c b/deps/MsvcLibX/src/chdir.c new file mode 100644 index 0000000000000000000000000000000000000000..48ab62fe06f4a461e6100fb7778c375907937c2a --- /dev/null +++ b/deps/MsvcLibX/src/chdir.c @@ -0,0 +1,147 @@ +/*****************************************************************************\ +* * +* 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 +#include +#include +/* MsvcLibX library extensions */ +#include +#include +#include "debugm.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 + +/*---------------------------------------------------------------------------*\ +* * +| 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) */ + diff --git a/deps/MsvcLibX/src/clock_gettime.c b/deps/MsvcLibX/src/clock_gettime.c new file mode 100644 index 0000000000000000000000000000000000000000..02202e5d2e44e56d73848875e9fd007289749268 --- /dev/null +++ b/deps/MsvcLibX/src/clock_gettime.c @@ -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 +#include + + +#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 + +#include /* 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) */ diff --git a/deps/MsvcLibX/src/config.DESKTOP-U79TD6T.bat b/deps/MsvcLibX/src/config.DESKTOP-U79TD6T.bat new file mode 100644 index 0000000000000000000000000000000000000000..6d57a1358a82104a40218466707cd066352f159d --- /dev/null +++ b/deps/MsvcLibX/src/config.DESKTOP-U79TD6T.bat @@ -0,0 +1,151 @@ +:# config.DESKTOP-U79TD6T.bat generated by configure.bat on 2020/05/19 Öܶþ 7:50:15.02 +:# +:# If changes are needeed, do not edit this file, but instead create a new script +:# called configure.YOURCHOICE.bat. This new script will be invoked automatically +:# by configure.bat while creating this file. Then your script can write extra +:# definitions, or change some of the variables before configure.bat writes them. +:# +:# Invoke configure.bat manually if anything changes in the tools config, such as +:# installing a Visual Studio update, or updating a configure.XXX.bat script. + +set "HAS_STINCLUDE=1" &:# Found the System Tools global C includes +set "STINCLUDE=C:\Users\admin\Desktop\temp\MyGitHub\C\include" &:# System Tools global C includes +set "HAS_MSVCLIBX=1" &:# Found the MSVC Library eXtensions library +set "MSVCLIBX=C:\Users\admin\Desktop\temp\MyGitHub\C\MsvcLibX" &:# MSVC Library eXtensions library +set "HAS_SDK_FLAGS=/DHAS_STINCLUDE=1 /DHAS_MSVCLIBX=1" &:# SDK detection flags for the C compiler + +SET "PF32=C:\Program Files (x86)" &:# 32-bits Program Files +SET "PF64=C:\Program Files" &:# 64-bits Program Files +SET "ARCH=AMD64" &:# PROCESSOR_ARCHITECTURE + +SET "MASM=" &:# Microsoft 16-bits Assembler base path +SET "MSVC=" &:# Microsoft 16-bits Visual C++ base path +SET "MAPSYM=" &:# 16-bits debugging symbols generator + +SET "VSTUDIOLONG=C:\Program Files (x86)\Microsoft Visual Studio 14.0" &:# Microsoft Visual Studio (Long path) +SET "VSTUDIO=C:\PROGRA~2\MICROS~2.0" &:# Microsoft Visual Studio (Short path) +SET "VSCOMMONLONG=C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7" &:# Microsoft Visual Studio Common Files (Long path) +SET "VSCOMMON=C:\PROGRA~2\MICROS~2.0\Common7" &:# Microsoft Visual Studio Common Files (Short path) +SET "VSIDELONG=C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE" &:# Microsoft Visual Studio IDE Files (Long path) +SET "VSIDE=C:\PROGRA~2\MICROS~2.0\Common7\IDE" &:# Microsoft Visual Studio IDE Files (Short path) +SET "VSTOOLSLONG=C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools" &:# Microsoft Visual Studio Tools (Long paths) +SET "VSTOOLS=C:\PROGRA~2\MICROS~2.0\Common7\Tools" &:# Microsoft Visual Studio Tools (Short paths) +SET "MSVC32LONG=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC" &:# Microsoft Visual C++ 32/64 bits (Long path) +SET "MSVC32=C:\PROGRA~2\MICROS~2.0\VC" &:# Microsoft Visual C++ 32/64 bits (Short path) + +SET "WIN_CP=936" &:# Windows Code Page +SET "WIN_CS=gb2312" &:# Windows Character Set +SET "DOS_CP=936" &:# DOS Code Page +SET "DOS_CS=gb2312" &:# DOS Character Set + +SET "AS=" &:# Assembler +SET "CC=" &:# C compiler +SET "INCLUDE=C:\Users\admin\Desktop\temp\MyGitHub\C\include" &:# Include paths. Define USER_INCLUDE if needed. +SET "LK=" &:# Linker +SET "LIB=" &:# Libraries paths. Define USER_LIBS if needed. +SET "LB=" &:# Library manager +SET "RC=" &:# Resource compiler +SET "MT=" &:# Manifest tool + +SET "DOS_CC=" &:# Microsoft Visual C++ 16-bits compiler +SET "DOS_AS=" &:# Microsoft 16-bits assembler +SET "DOS_LK=" &:# Microsoft 16-bits linker +SET "DOS_LB=" &:# Microsoft 16-bits librarian +SET "DOS_RC=" &:# Microsoft 16-bits resource compiler +SET "DOS_MT=" &:# Microsoft 16-bits manifest tool +SET "DOS_PATH=;C:\Windows\System32;C:\Windows" &:# All tools paths for 16-bits compilation +SET "DOS_VCINC=" &:# Visual C++ 16-bits compiler include dir for MsvcLibX include_next +SET "DOS_CRTINC=" &:# Visual C++ 16-bits CRT library include dir for MsvcLibX include_next +SET "DOS_INCPATH=" &:# Include paths for 16-bits compilation +SET "DOS_LIBPATH=" &:# Libraries paths for 16-bits linking +SET "DOS_WINSDK=" &:# Microsoft Windows 16-bits SDK +SET "DOS_WINSDKINC=" &:# Microsoft Windows 16-bits SDK Include directory + +SET "WIN95_CC=" &:# Microsoft Visual C++ 32-bits compiler +SET "WIN95_AS=" &:# Microsoft 32-bits assembler +SET "WIN95_LK=" &:# Microsoft 32-bits linker +SET "WIN95_LB=" &:# Microsoft 32-bits librarian +SET "WIN95_RC=" &:# Microsoft 32-bits resource compiler +SET "WIN95_MT=" &:# Microsoft 32-bits manifest tool +SET "WIN95_PATH=;C:\Windows\System32;C:\Windows" &:# All tools paths for 32-bits compilation +SET "WIN95_VCINC=" &:# Visual C++ 32-bits compiler include dir for MsvcLibX include_next +SET "WIN95_CRTINC=" &:# Visual C++ 32-bits CRT library include dir for MsvcLibX include_next +SET "WIN95_INCPATH=" &:# Include paths for 32-bits compilation +SET "WIN95_LIBPATH=" &:# Libraries paths for 32-bits linking +SET "WIN95_WINSDK=" &:# Microsoft Windows 32-bits SDK +SET "WIN95_WINSDKINC=" &:# Microsoft Windows 32-bits SDK Include directory + +SET "WIN32_CC="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\CL.EXE"" &:# Microsoft Visual C++ 32-bits compiler +SET "WIN32_AS="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\ML.EXE"" &:# Microsoft 32-bits assembler +SET "WIN32_LK="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\LINK.EXE"" &:# Microsoft 32-bits linker +SET "WIN32_LB="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\LIB.EXE"" &:# Microsoft 32-bits librarian +SET "WIN32_RC=" &:# Microsoft 32-bits resource compiler +SET "WIN32_MT=" &:# Microsoft 32-bits manifest tool +SET "WIN32_PATH=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools;C:\Windows\System32;C:\Windows" &:# All tools paths for 32-bits compilation +SET "WIN32_VCINC=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include" &:# Visual C++ 32-bits compiler include dir for MsvcLibX include_next +SET "WIN32_CRTINC=C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt" &:# Visual C++ 32-bits CRT library include dir for MsvcLibX include_next +SET "WIN32_INCPATH=C:\Users\admin\Desktop\temp\MyGitHub\C\MsvcLibX\include;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include;:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\shared;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\winrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\shared;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\winrt" &:# Include paths for 32-bits compilation +SET "WIN32_LIBPATH=C:\Users\admin\Desktop\temp\MyGitHub\C\MsvcLibX\lib;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\um\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x86;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x86" &:# Libraries paths for 32-bits linking +SET "WIN32_WINSDK=C:\Program Files (x86)\Windows Kits\10" &:# Microsoft Windows 32-bits SDK +SET "WIN32_WINSDKINC=C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0" &:# Microsoft Windows 32-bits SDK Include directory + +SET "IA64_CC=" &:# Microsoft Visual C++ IA64 compiler +SET "IA64_AS=" &:# Microsoft IA64 assembler +SET "IA64_LK=" &:# Microsoft IA64 linker +SET "IA64_LB=" &:# Microsoft IA64 librarian +SET "IA64_RC=" &:# Microsoft IA64 resource compiler +SET "IA64_MT=" &:# Microsoft IA64 manifest tool +SET "IA64_PATH=;C:\Windows\System32;C:\Windows" &:# All tools paths for IA64 compilation +SET "IA64_VCINC=" &:# Visual C++ IA64 compiler include dir for MsvcLibX include_next +SET "IA64_CRTINC=" &:# Visual C++ IA64 CRT library include dir for MsvcLibX include_next +SET "IA64_INCPATH=" &:# Include paths for IA64 compilation +SET "IA64_LIBPATH=" &:# Libraries paths for IA64 linking +SET "IA64_WINSDK=" &:# Microsoft Windows IA64 SDK +SET "IA64_WINSDKINC=" &:# Microsoft Windows IA64 SDK Include directory + +SET "WIN64_CC="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\CL.EXE"" &:# Microsoft Visual C++ 64-bits compiler +SET "WIN64_AS="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\ML64.EXE"" &:# Microsoft 64-bits assembler +SET "WIN64_LK="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\LINK.EXE"" &:# Microsoft 64-bits linker +SET "WIN64_LB="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64\LIB.EXE"" &:# Microsoft 64-bits librarian +SET "WIN64_RC=" &:# Microsoft 64-bits resource compiler +SET "WIN64_MT=" &:# Microsoft 64-bits manifest tool +SET "WIN64_PATH=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools;C:\Windows\System32;C:\Windows" &:# All tools paths for 64-bits compilation +SET "WIN64_VCINC=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include" &:# Visual C++ 64-bits compiler include dir for MsvcLibX include_next +SET "WIN64_CRTINC=C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt" &:# Visual C++ 64-bits CRT library include dir for MsvcLibX include_next +SET "WIN64_INCPATH=C:\Users\admin\Desktop\temp\MyGitHub\C\MsvcLibX\include;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include;:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\shared;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\winrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\shared;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\winrt" &:# Include paths for 64-bits compilation +SET "WIN64_LIBPATH=C:\Users\admin\Desktop\temp\MyGitHub\C\MsvcLibX\lib;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib\amd64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\um\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\x64;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\x64" &:# Libraries paths for 64-bits linking +SET "WIN64_WINSDK=C:\Program Files (x86)\Windows Kits\10" &:# Microsoft Windows 64-bits SDK +SET "WIN64_WINSDKINC=C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0" &:# Microsoft Windows 64-bits SDK Include directory + +SET "ARM_CC="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64_arm\CL.EXE"" &:# Microsoft Visual C++ ARM compiler +SET "ARM_AS="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64_arm\ARMASM.EXE"" &:# Microsoft ARM assembler +SET "ARM_LK="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64_arm\LINK.EXE"" &:# Microsoft ARM linker +SET "ARM_LB="C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64_arm\LIB.EXE"" &:# Microsoft ARM librarian +SET "ARM_RC=" &:# Microsoft ARM resource compiler +SET "ARM_MT=" &:# Microsoft ARM manifest tool +SET "ARM_PATH=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64_arm;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\bin\amd64;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\Tools;C:\Windows\System32;C:\Windows" &:# All tools paths for ARM compilation +SET "ARM_VCINC=C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include" &:# Visual C++ ARM compiler include dir for MsvcLibX include_next +SET "ARM_CRTINC=C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt" &:# Visual C++ ARM CRT library include dir for MsvcLibX include_next +SET "ARM_INCPATH=C:\Users\admin\Desktop\temp\MyGitHub\C\MsvcLibX\include;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include;:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\shared;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.17763.0\winrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\shared;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\um;C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\winrt" &:# Include paths for ARM compilation +SET "ARM_LIBPATH=C:\Users\admin\Desktop\temp\MyGitHub\C\MsvcLibX\lib;C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\lib\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\um\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.10240.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.17763.0\ucrt\arm;C:\Program Files (x86)\Windows Kits\10\Lib\10.0.18362.0\ucrt\arm" &:# Libraries paths for ARM linking +SET "ARM_WINSDK=C:\Program Files (x86)\Windows Kits\10" &:# Microsoft Windows ARM SDK +SET "ARM_WINSDKINC=C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0" &:# Microsoft Windows ARM SDK Include directory + +SET "ARM64_CC=" &:# Microsoft Visual C++ ARM64 compiler +SET "ARM64_AS=" &:# Microsoft ARM64 assembler +SET "ARM64_LK=" &:# Microsoft ARM64 linker +SET "ARM64_LB=" &:# Microsoft ARM64 librarian +SET "ARM64_RC=" &:# Microsoft ARM64 resource compiler +SET "ARM64_MT=" &:# Microsoft ARM64 manifest tool +SET "ARM64_PATH=;C:\Windows\System32;C:\Windows" &:# All tools paths for ARM64 compilation +SET "ARM64_VCINC=" &:# Visual C++ ARM64 compiler include dir for MsvcLibX include_next +SET "ARM64_CRTINC=" &:# Visual C++ ARM64 CRT library include dir for MsvcLibX include_next +SET "ARM64_INCPATH=" &:# Include paths for ARM64 compilation +SET "ARM64_LIBPATH=" &:# Libraries paths for ARM64 linking +SET "ARM64_WINSDK=" &:# Microsoft Windows ARM64 SDK +SET "ARM64_WINSDKINC=" &:# Microsoft Windows ARM64 SDK Include directory + +:# List of commands to run when make.bat exits +SET "POST_MAKE_ACTIONS=set "MSVCLIBX=C:\Users\admin\Desktop\temp\MyGitHub\C\MsvcLibX"" + +exit /b 0 &:# Configuration done successfully diff --git a/deps/MsvcLibX/src/configure.MsvcLibX.bat b/deps/MsvcLibX/src/configure.MsvcLibX.bat new file mode 100644 index 0000000000000000000000000000000000000000..767225480ace29ec7306d771560d9a416f3174bf --- /dev/null +++ b/deps/MsvcLibX/src/configure.MsvcLibX.bat @@ -0,0 +1,36 @@ +@echo off +:#***************************************************************************** +:# * +:# Filename: configure.MsvcLibX.bat * +:# * +:# Description: Special make actions for rebuilding the MsvcLibX library * +:# * +:# Notes: * +:# * +:# History: * +:# 2015-11-06 JFL Created this script. * +:# 2016-09-27 JFL Correct the final MSVCLIBX if there's a different OUTDIR. * +:# 2016-11-03 JFL Removed the side effect creating %OUTDIR%. * +:# 2016-11-07 JFL Removed the dependency on OUTDIR. * +:# Immediately set the system environment. * +:# 2016-11-16 JFL Allow using a predefined alias for this lib base path. * +:# 2016-12-16 JFL Only use setx if requested by user, with PERSISTENT_VARS. * +:# * +:# © Copyright 2016 Hewlett Packard Enterprise Development LP * +:# Licensed under the Apache 2.0 license www.apache.org/licenses/LICENSE-2.0 * +:#***************************************************************************** + +:# Get the full pathname of the MsvcLibX library base directory +if defined MSVCLIBX if not exist "%MSVCLIBX%\include\msvclibx.h" set "MSVCLIBX=" &:# Allow overriding with another alias name, but ignore invalid overrides +if not defined MSVCLIBX for /f "delims=" %%d in ('"pushd .. & cd & popd"') do SET "MSVCLIBX=%%d" &:# Default: Use the current directory + +:# Declare the SDKs and libraries we need +%BEGIN_SDK_DEFS% +%USE_SDK% MSVCLIBX &:# Triggers the emission of a %CONFIG% record for MSVCLIBX +%END_SDK_DEFS% + +:# Set the local environment variable just before make exits, so that future commands in this CMD window have it. +%ADD_POST_MAKE_ACTION% set "MSVCLIBX=%MSVCLIBX%" + +:# Set the system environment variable, so that other CMD windows opened later on inherit it +if defined PERSISTENT_VARS setx MSVCLIBX "%MSVCLIBX%" >NUL diff --git a/deps/MsvcLibX/src/configure.bat b/deps/MsvcLibX/src/configure.bat new file mode 100644 index 0000000000000000000000000000000000000000..7037eb92afccbfe2e0d6872a108799d56538c490 --- /dev/null +++ b/deps/MsvcLibX/src/configure.bat @@ -0,0 +1,35 @@ +@echo off +:#***************************************************************************** +:# * +:# Filename: configure.bat * +:# * +:# Description: Detect system-specific settings and create config.*.bat * +:# * +:# Notes: Proxy script for %STINCLUDE%\configure.bat. * +:# * +:# Make any change needed in %STINCLUDE%\configure.bat. * +:# * +:# History: * +:# 2016-10-10 JFL jf.larvoire@hpe.com created this file. * +:# 2016-12-15 JFL Search for the real make.bat in [.|..|../..]\include. * +:# * +:# © Copyright 2016 Hewlett Packard Enterprise Development LP * +:# Licensed under the Apache 2.0 license www.apache.org/licenses/LICENSE-2.0 * +:#***************************************************************************** + +:# Get the full pathname of the STINCLUDE library directory +if defined STINCLUDE if not exist "%STINCLUDE%\make.bat" set "STINCLUDE=" &:# Allow overriding with another alias name, but ignore invalid overrides +for %%p in (. .. ..\..) do if not defined STINCLUDE if exist %%p\include\make.bat ( :# Default: Search it the current directory, and 2 levels above. + for /f "delims=" %%d in ('"pushd %%p\include & cd & popd"') do SET "STINCLUDE=%%d" +) +if not defined STINCLUDE ( :# Try getting the copy in the master environment + for /f "tokens=3" %%v in ('reg query "HKCU\Environment" /v STINCLUDE 2^>NUL') do set "STINCLUDE=%%v" +) + +if not exist %STINCLUDE%\make.bat ( + >&2 echo %0 Error: Cannot find SysToolsLib's global C include directory. Please define variable STINCLUDE. + exit /b 1 +) + +if [%1]==[-d] echo "%STINCLUDE%\configure.bat" %* +"%STINCLUDE%\configure.bat" %* diff --git a/deps/MsvcLibX/src/debugv.c b/deps/MsvcLibX/src/debugv.c new file mode 100644 index 0000000000000000000000000000000000000000..a0a757032ca51429f33b5685ad5f6bb0be67b1a7 --- /dev/null +++ b/deps/MsvcLibX/src/debugv.c @@ -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 "debugm.h" + +#if defined(_DEBUG) + +DEBUG_GLOBALS + +#endif /* !defined(_DEBUG) */ + diff --git a/deps/MsvcLibX/src/dirent.c b/deps/MsvcLibX/src/dirent.c new file mode 100644 index 0000000000000000000000000000000000000000..5fbf3be6cabb38bf2dd75836aa27a4a4964661da --- /dev/null +++ b/deps/MsvcLibX/src/dirent.c @@ -0,0 +1,708 @@ +/*****************************************************************************\ +* * +* 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 . * +* 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 "dirent.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 +#include +#include +#include +#include +/* MsvcLibX library extensions */ +#include /* For readlink() */ +#include /* For Filetime2String() */ +#include "debugm.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 + +/* 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; +} + diff --git a/deps/MsvcLibX/src/dirname.c b/deps/MsvcLibX/src/dirname.c new file mode 100644 index 0000000000000000000000000000000000000000..97fffcfe8c98ee111800bf3f790d2138313b3a5b --- /dev/null +++ b/deps/MsvcLibX/src/dirname.c @@ -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 +#include +#include +#include +#include + +#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; +} diff --git a/deps/MsvcLibX/src/err2errno.c b/deps/MsvcLibX/src/err2errno.c new file mode 100644 index 0000000000000000000000000000000000000000..ec4260df0b1e59422e3802d770c4805cab910499 --- /dev/null +++ b/deps/MsvcLibX/src/err2errno.c @@ -0,0 +1,121 @@ +/*****************************************************************************\ +* * +* 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 +#include +/* MsvcLibX library extensions */ +#include "debugm.h" + + +#ifdef _WIN32 + +#include + +/*---------------------------------------------------------------------------*\ +* * +| 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 +#pragma message("Using the default " MSVCLIBX_STRINGIZE(_get_errno_from_oserr) "()") +/* 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 */ + diff --git a/deps/MsvcLibX/src/exe b/deps/MsvcLibX/src/exe new file mode 100644 index 0000000000000000000000000000000000000000..0afeaf5d6bc239ffe1178b6dad8efead29490228 --- /dev/null +++ b/deps/MsvcLibX/src/exe @@ -0,0 +1,99 @@ +#!/bin/bash +#*****************************************************************************# +# # +# Filename: exe # +# # +# Description: Build simple C/C++ programs for Unix/Linux # +# # +# Notes: Usage: ./exe PROGRAM # +# # +# Stores the executables in $OS.$PROC/[Debug/] for # +# consistency with the Windows build tools. # +# This allows sharing sources in a host system, and # +# using VMs for building the various Windows and Linux # +# versions in a set of OS-specific subdirectories. # +# # +# History: # +# 2013-12-16 JFL Added support for MinGW64. # +# 2015-12-12 JFL Help now displays the output directory name. # +# 2016-01-07 JFL Added compilation option -Wall. # +# # +# © Copyright 2016 Hewlett Packard Enterprise Development LP # +# Licensed under the Apache 2.0 license - www.apache.org/licenses/LICENSE-2.0 # +#*****************************************************************************# + +FileNoCase() # Case-independant search for a file. +{ + find . -type f | grep -i -E "./$1$" | sed s=./== +} + +# Identify the OS +OS=`uname -s` +PROC=`uname -p` +if [[ "$OS" == "OSF1" && "`uname -m`" == "alpha" ]] ; then + OS=Tru64 +fi +if [[ "$OS" == "WindowsNT" ]] ; then + OS=WIN32 +fi +OUTDIR=$OS.$PROC +if [[ "${OS:0:7}" == "MINGW32" ]] ; then # Ex: "MINGW32_NT-6.1" + OUTDIR=MINGW32 # MigGW shell if NOT case sensitive + # 2013-12-16 Actually, the 64-bits tool chain also reports MINGW32_NT-6.1 + # So distinguish the two by whether /mingw is mounted on C:\MinGW or C:\MinGW64 + if mount | grep /mingw | grep 64 > /dev/null ; then + OUTDIR=MINGW64 # MigGW shell if NOT case sensitive + fi +fi +if [[ "${OS:0:7}" == "MINGW64" ]] ; then # Ex: ? + OUTDIR=MINGW64 +fi +if [[ "${OS:0:6}" == "CYGWIN" ]] ; then # Ex: "CYGWIN_NT-6.1-WOW64" + OUTDIR=cygwin # Cygwin shell if case sensitive, so use lower case +fi + +# Command line analysis. +case "$1" in + "" | "-h" | "-?" | --help) + echo "Build simple C/C++ programs, storing the executables in $OUTDIR/" + echo "Usage: ./exe PROGRAM" + exit 0 + ;; +esac + +# Identify the source file and program to build. +PROGRAM=$1 +shift +SOURCES=`FileNoCase ${PROGRAM}.c` +CFLAGS="-std=c99 -Wall" # Force compilation in C, even if there are // comments. +if [[ "${SOURCES}" == "" ]] ; then + SOURCES=`FileNoCase ${PROGRAM}.cpp` + CFLAGS="-std=gnu++98 -lstdc++" # Force compilation in C++, even if plain C. + # -lstdc++ prevents error "undefined reference to '__gxx_personality_v0'" +fi +if [[ "${SOURCES}" == "" ]] ; then + echo "Failed to find ${PROGRAM} source." + exit 1 +fi + +# Make sure our include directories are accessible +if [[ -d "/u/JFL/SRC/Include" ]] ; then + if [[ ":$C_INCLUDE_PATH:" != *:/u/JFL/SRC/Include:* ]] ; then + if [[ "$C_INCLUDE_PATH" == "" ]] ; then + export C_INCLUDE_PATH="/u/JFL/SRC/Include" + else + export C_INCLUDE_PATH="$C_INCLUDE_PATH:/u/JFL/SRC/Include" + fi + fi +fi +echo "# C_INCLUDE_PATH=\"$C_INCLUDE_PATH\"" + +# Build it. +# gmake CC=gcc CFLAGS="$CFLAGS" SOURCES="$SOURCES" PROGRAM="$PROGRAM" OS="$OS" $* +mkdir -p $OUTDIR +echo "gcc $CFLAGS -U_DEBUG $SOURCES -o $OUTDIR/$PROGRAM" +gcc $CFLAGS -U_DEBUG $SOURCES -o $OUTDIR/$PROGRAM +mkdir -p $OUTDIR/debug +echo "gcc $CFLAGS -D_DEBUG $SOURCES -o $OUTDIR/debug/$PROGRAM" +gcc $CFLAGS -D_DEBUG $SOURCES -o $OUTDIR/debug/$PROGRAM + diff --git a/deps/MsvcLibX/src/exe.bat b/deps/MsvcLibX/src/exe.bat new file mode 100644 index 0000000000000000000000000000000000000000..f93d6ba3993fbf425ae8c778b60df6abd4589cb1 --- /dev/null +++ b/deps/MsvcLibX/src/exe.bat @@ -0,0 +1,82 @@ +@echo off +:#***************************************************************************** +:# * +:# Filename: exe.bat * +:# * +:# Description: Front end to make.bat, to simply build multiple targets * +:# * +:# Arguments: Use option -? to display a help screen * +:# * +:# Notes: Builds the 16-bits MS-DOS version if Visual C++ 1.52 is * +:# installed in its default location in C:\MSVC. * +:# * +:# History: * +:# 2003-03-31 JFL Adapted from previous projects * +:# 2014-03-21 JFL Builds the 16-bits MS-DOS version if Visual C++ 1.52 is * +:# installed in its default location in C:\MSVC. * +:# 2014-03-27 JFL Changed option -f to use nmake option /A. * +:# Added option -r for completeness. * +:# 2015-11-13 JFL Adapted to the new multitarget make system. * +:# * +:# © Copyright 2016 Hewlett Packard Enterprise Development LP * +:# Licensed under the Apache 2.0 license www.apache.org/licenses/LICENSE-2.0 * +:#***************************************************************************** + +setlocal enableextensions enabledelayedexpansion +goto main + +:main +set "FORCE=0" +set "ACTION=default" +set "EXEC=" +set "MAKEOPTS=" + +goto get_arg +:next_arg +shift +:get_arg +if .%1.==.-?. goto help +if .%1.==./?. goto help +if .%1.==.-a. set "ACTION=all" & goto next_arg +if .%1.==.-d. set "ACTION=debug" & goto next_arg +if .%1.==.-f. set "FORCE=1" & goto next_arg +if .%1.==.-r. set "ACTION=release" & goto next_arg +if .%1.==.-X. set "EXEC=echo" & goto next_arg +set MAKEOPTS=%2 %3 %4 %5 %6 %7 %8 %9 +if "%FORCE%"=="1" set "MAKEOPTS=%MAKEOPTS% /A" +goto %ACTION% + +:help +echo. +echo..exe program builder from a C or C++ source +echo. +echo.Usage: exe [options] program [nmake_options] +echo. +echo.Options: +echo. +echo. -? Display this help page +echo. -a Builds all release ^& debug versions (default) +echo. -d Builds all debug versions only +echo. -f Force building all program targets, irrespective of file dates +echo. -r Builds all release versions only +echo. -X Display the make command generated and exit +echo. +echo.Notes: +echo.* exe myprog ^<==^> make myprog.exe debug\myprog.exe +echo.* This builds all possible OS targets +echo.* To force rebuilding all targets, irrespective of their date, +echo. use nmake option /A. So: exe -f myprog ^<==^> exe myprog /A +goto :eof + +:release +%EXEC% make %MAKEOPTS% %1.exe +goto :eof + +:debug +%EXEC% make %MAKEOPTS% debug\%1.exe +goto :eof + +:default +:all +%EXEC% make %MAKEOPTS% %1.exe debug\%1.exe +goto :eof diff --git a/deps/MsvcLibX/src/filetime.c b/deps/MsvcLibX/src/filetime.c new file mode 100644 index 0000000000000000000000000000000000000000..7531ba3daa9aee9c2653559dd1b5d2da3bc1cf84 --- /dev/null +++ b/deps/MsvcLibX/src/filetime.c @@ -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 . * +* 2014-07-03 JFL Filetime2String: Output time with µ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 /* Define time_t */ +#include + +#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 + +/*---------------------------------------------------------------------------*\ +* * +| 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 µ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) */ + diff --git a/deps/MsvcLibX/src/fnmatch.c b/deps/MsvcLibX/src/fnmatch.c new file mode 100644 index 0000000000000000000000000000000000000000..20c22560089ea0383dbc9f72690585fc5a663e3d --- /dev/null +++ b/deps/MsvcLibX/src/fnmatch.c @@ -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 +#include +#include + +#include "fnmatch.h" /* Include our associated .h, in the same dir as this .c. Do not use <>. */ +#include "debugm.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) + diff --git a/deps/MsvcLibX/src/fstat.c b/deps/MsvcLibX/src/fstat.c new file mode 100644 index 0000000000000000000000000000000000000000..ba6a635bb0939fd9d7d187dba3accf3b9b329766 --- /dev/null +++ b/deps/MsvcLibX/src/fstat.c @@ -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 +#include +#include +/* MsvcLibX library extensions */ +#include +#include "debugm.h" +#include + + +#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 + +/*---------------------------------------------------------------------------*\ +* * +| 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 */ + diff --git a/deps/MsvcLibX/src/fstat64.c b/deps/MsvcLibX/src/fstat64.c new file mode 100644 index 0000000000000000000000000000000000000000..de6a2c6dcd6cc817224baf414bd4bb978d87c092 --- /dev/null +++ b/deps/MsvcLibX/src/fstat64.c @@ -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" diff --git a/deps/MsvcLibX/src/fstat64i32.c b/deps/MsvcLibX/src/fstat64i32.c new file mode 100644 index 0000000000000000000000000000000000000000..6275260720a63d13d39c28dda82627851684866e --- /dev/null +++ b/deps/MsvcLibX/src/fstat64i32.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" diff --git a/deps/MsvcLibX/src/fullpath.c b/deps/MsvcLibX/src/fullpath.c new file mode 100644 index 0000000000000000000000000000000000000000..8d94d159db4857c0c8a7176d94ff70080f8435af --- /dev/null +++ b/deps/MsvcLibX/src/fullpath.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 +#include +#include + +#ifdef _WIN32 /* Automatically defined when targeting a Win32 application */ + +#include /* 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) */ + diff --git a/deps/MsvcLibX/src/getcwd.c b/deps/MsvcLibX/src/getcwd.c new file mode 100644 index 0000000000000000000000000000000000000000..b04127c211a7acd4bab0fb4c841a48b9aed180c3 --- /dev/null +++ b/deps/MsvcLibX/src/getcwd.c @@ -0,0 +1,152 @@ +/*****************************************************************************\ +* * +* 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 +#include +/* MsvcLibX library extensions */ +#include +#include "debugm.h" + +#if defined(_MSDOS) + +/* DOS own getcwd() is OK. */ + +#endif /* defined(_MSDOS) */ + + +#ifdef _WIN32 + +#include + +/*---------------------------------------------------------------------------*\ +* * +| 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 */ + diff --git a/deps/MsvcLibX/src/getopt.c b/deps/MsvcLibX/src/getopt.c new file mode 100644 index 0000000000000000000000000000000000000000..81976204ccd3cd5eba6d62536dbae9abaf90f3f6 --- /dev/null +++ b/deps/MsvcLibX/src/getopt.c @@ -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 +#include +#include +#include +#include +#include +#include "getopt.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 +} diff --git a/deps/MsvcLibX/src/getppid.c b/deps/MsvcLibX/src/getppid.c new file mode 100644 index 0000000000000000000000000000000000000000..73f66e51443339e2e3768a96e7166f661a18e5ac --- /dev/null +++ b/deps/MsvcLibX/src/getppid.c @@ -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 + +#ifdef _WIN32 + +#include +#pragma pack(push,8) /* Work around a bug in tlhelp32.h in WIN64, which generates the wrong structure if packing has been changed */ +#include +#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 + + diff --git a/deps/MsvcLibX/src/gettimeofday.c b/deps/MsvcLibX/src/gettimeofday.c new file mode 100644 index 0000000000000000000000000000000000000000..9cc548366b3602b662570889060f7e2ed976859f --- /dev/null +++ b/deps/MsvcLibX/src/gettimeofday.c @@ -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 +#include + +#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) */ diff --git a/deps/MsvcLibX/src/iconv.c b/deps/MsvcLibX/src/iconv.c new file mode 100644 index 0000000000000000000000000000000000000000..b60ed61029559ec87e8ba12990c216fc6c97165a --- /dev/null +++ b/deps/MsvcLibX/src/iconv.c @@ -0,0 +1,228 @@ +/*****************************************************************************\ +* * +* 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 +#include +#include +/* MsvcLibX library extensions */ +#include "iconv.h" +#include "debugm.h" + +#if defined(_MSDOS) + +/* TO DO: Add support for DOS code pages! */ + +#endif /* defined(_MSDOS) */ + + +#ifdef _WIN32 + +#include + +/*---------------------------------------------------------------------------*\ +* * +| 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 */ + diff --git a/deps/MsvcLibX/src/lstat.c b/deps/MsvcLibX/src/lstat.c new file mode 100644 index 0000000000000000000000000000000000000000..bd688c13b9166f0f716d7e27fecfa1dc69ed3796 --- /dev/null +++ b/deps/MsvcLibX/src/lstat.c @@ -0,0 +1,431 @@ +/*****************************************************************************\ +* * +* 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 . * +* 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 +#include +#include +/* MsvcLibX library extensions */ +#include "msvclibx.h" +#include +#include +#include /* For ResolveLinks() definition */ +#include "debugm.h" +#include + +#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 + +/*---------------------------------------------------------------------------*\ +* * +| 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 */ + diff --git a/deps/MsvcLibX/src/lstat32.c b/deps/MsvcLibX/src/lstat32.c new file mode 100644 index 0000000000000000000000000000000000000000..5486f45b8eb1e2698a9c33e26f938e4e30f21cef --- /dev/null +++ b/deps/MsvcLibX/src/lstat32.c @@ -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 diff --git a/deps/MsvcLibX/src/lstat32i64.c b/deps/MsvcLibX/src/lstat32i64.c new file mode 100644 index 0000000000000000000000000000000000000000..8eafed1d3eb5ec83cb6189ab8cc9146fe0be4762 --- /dev/null +++ b/deps/MsvcLibX/src/lstat32i64.c @@ -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 diff --git a/deps/MsvcLibX/src/lstat64.c b/deps/MsvcLibX/src/lstat64.c new file mode 100644 index 0000000000000000000000000000000000000000..b84b3271e34eb6f2bdc64f0901d006baf551524a --- /dev/null +++ b/deps/MsvcLibX/src/lstat64.c @@ -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" diff --git a/deps/MsvcLibX/src/lstat64i32.c b/deps/MsvcLibX/src/lstat64i32.c new file mode 100644 index 0000000000000000000000000000000000000000..f5325d18327d18d9a3673fdaaf52742944cc7453 --- /dev/null +++ b/deps/MsvcLibX/src/lstat64i32.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" diff --git a/deps/MsvcLibX/src/main.c b/deps/MsvcLibX/src/main.c new file mode 100644 index 0000000000000000000000000000000000000000..7c87c7fb7edf7d961110e32efeb4d076781cad75 --- /dev/null +++ b/deps/MsvcLibX/src/main.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 +#include "msvclibx.h" + +#ifdef _WIN32 + +#include +#include /* 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) */ + diff --git a/deps/MsvcLibX/src/make.bat b/deps/MsvcLibX/src/make.bat new file mode 100644 index 0000000000000000000000000000000000000000..7a272561228129410dcba670dee0ddb723553647 --- /dev/null +++ b/deps/MsvcLibX/src/make.bat @@ -0,0 +1,35 @@ +@echo off +:#***************************************************************************** +:# * +:# Filename: make.bat * +:# * +:# Description: Build DOS and Windows targets * +:# * +:# Notes: Proxy script for %STINCLUDE%\make.bat. * +:# * +:# If any change is needed, put it in %STINCLUDE%\make.bat. * +:# * +:# History: * +:# 2016-10-10 JFL jf.larvoire@hpe.com created this file. * +:# 2016-12-15 JFL Search for the real make.bat in [.|..|../..]\include. * +:# * +:# © Copyright 2016 Hewlett Packard Enterprise Development LP * +:# Licensed under the Apache 2.0 license www.apache.org/licenses/LICENSE-2.0 * +:#***************************************************************************** + +:# Get the full pathname of the STINCLUDE library directory +if defined STINCLUDE if not exist "%STINCLUDE%\make.bat" set "STINCLUDE=" &:# Allow overriding with another alias name, but ignore invalid overrides +for %%p in (. .. ..\..) do if not defined STINCLUDE if exist %%p\include\make.bat ( :# Default: Search it the current directory, and 2 levels above. + for /f "delims=" %%d in ('"pushd %%p\include & cd & popd"') do SET "STINCLUDE=%%d" +) +if not defined STINCLUDE ( :# Try getting the copy in the master environment + for /f "tokens=3" %%v in ('reg query "HKCU\Environment" /v STINCLUDE 2^>NUL') do set "STINCLUDE=%%v" +) + +if not exist %STINCLUDE%\make.bat ( + >&2 echo %0 Error: Cannot find SysToolsLib's global C include directory. Please define variable STINCLUDE. + exit /b 1 +) + +if [%1]==[-d] echo "%STINCLUDE%\make.bat" %* +"%STINCLUDE%\make.bat" %* diff --git a/deps/MsvcLibX/src/mb2wpath.c b/deps/MsvcLibX/src/mb2wpath.c new file mode 100644 index 0000000000000000000000000000000000000000..a41ff75d94f578dc9eff8e3fdb94c638268dfff3 --- /dev/null +++ b/deps/MsvcLibX/src/mb2wpath.c @@ -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 "debugm.h" + +#if defined(_WIN32) + +#include +#include /* 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) */ + diff --git a/deps/MsvcLibX/src/mkdir.c b/deps/MsvcLibX/src/mkdir.c new file mode 100644 index 0000000000000000000000000000000000000000..e83f4c1773cff3134f6852501f2864ba61f152dc --- /dev/null +++ b/deps/MsvcLibX/src/mkdir.c @@ -0,0 +1,102 @@ +/*****************************************************************************\ +* * +* 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 . * +* 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 +#include /* For _mkdir() */ +#include +/* MsvcLibX library extensions */ +#include +#include "msvclibx.h" + +#ifdef _WIN32 + +#include + +/*---------------------------------------------------------------------------*\ +* * +| 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) */ + diff --git a/deps/MsvcLibX/src/mkdtemp.c b/deps/MsvcLibX/src/mkdtemp.c new file mode 100644 index 0000000000000000000000000000000000000000..602cdd4b5524d03fe28846a8cb8cfa22bd808b46 --- /dev/null +++ b/deps/MsvcLibX/src/mkdtemp.c @@ -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 +#include +#include +#include +#include + +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; +} + diff --git a/deps/MsvcLibX/src/mkstemp.c b/deps/MsvcLibX/src/mkstemp.c new file mode 100644 index 0000000000000000000000000000000000000000..ab576b65421b18a24deb6eafe89de24e870dbdd5 --- /dev/null +++ b/deps/MsvcLibX/src/mkstemp.c @@ -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 +#include +#include +#include +#include +#include +#include +#include + +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; +} + diff --git a/deps/MsvcLibX/src/open.c b/deps/MsvcLibX/src/open.c new file mode 100644 index 0000000000000000000000000000000000000000..8876ff43eb2f248e7f4c3e551ba1d1e609308f62 --- /dev/null +++ b/deps/MsvcLibX/src/open.c @@ -0,0 +1,83 @@ +/*****************************************************************************\ +* * +* 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 +#include "msvclibx.h" +#include "fcntl.h" +#include "debugm.h" + +#ifdef _WIN32 + +#include + +/*---------------------------------------------------------------------------*\ +* * +| 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) */ diff --git a/deps/MsvcLibX/src/readlink.c b/deps/MsvcLibX/src/readlink.c new file mode 100644 index 0000000000000000000000000000000000000000..d7c728c9fc6bfcba32b77e68cd997ba325e5635c --- /dev/null +++ b/deps/MsvcLibX/src/readlink.c @@ -0,0 +1,508 @@ +/*****************************************************************************\ +* * +* 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 +#pragma comment(lib, "Mpr.lib") + +#include +#include "debugm.h" + +#ifdef _WIN32 + +#include +#include "reparsept.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 + + diff --git a/deps/MsvcLibX/src/realpath.c b/deps/MsvcLibX/src/realpath.c new file mode 100644 index 0000000000000000000000000000000000000000..8d60c9f554367ad79aa7d778471d06c030378197 --- /dev/null +++ b/deps/MsvcLibX/src/realpath.c @@ -0,0 +1,598 @@ +/*****************************************************************************\ +* * +* 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 +#include +#include +#include +#include /* For _getdcwd() */ +#include /* For toupper() */ +#include "debugm.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 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 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 /* 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) */ + diff --git a/deps/MsvcLibX/src/spawn.c b/deps/MsvcLibX/src/spawn.c new file mode 100644 index 0000000000000000000000000000000000000000..ab70172b3e0e3212c990c013bfee6e94a3ac3125 --- /dev/null +++ b/deps/MsvcLibX/src/spawn.c @@ -0,0 +1,117 @@ +/*****************************************************************************\ +* * +* 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 +/* MsvcLibX library extensions */ +#include "debugm.h" +#include "msvclibx.h" + +#ifdef _WIN32 + +#include +#include + +/*---------------------------------------------------------------------------*\ +* * +| 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) */ + diff --git a/deps/MsvcLibX/src/src2objs.bat b/deps/MsvcLibX/src/src2objs.bat new file mode 100644 index 0000000000000000000000000000000000000000..b840e308c4f6a6c824bda023eb3907665f95f0d2 --- /dev/null +++ b/deps/MsvcLibX/src/src2objs.bat @@ -0,0 +1,125 @@ +@echo off +:****************************************************************************** +:* * +:* Filename: src2objs.bat * +:* * +:* Description: Generate object files names from source files names * +:* * +:* Notes: * +:* * +:* History: * +:* 2010-04-07 JFL Created this batch. * +:* * +:# © Copyright 2016 Hewlett Packard Enterprise Development LP * +:# Licensed under the Apache 2.0 license www.apache.org/licenses/LICENSE-2.0 * +:****************************************************************************** + +setlocal 2>NUL +set ARG0=%0 + +:# Mechanism for calling subroutines. Done by {call %0 _call_ label [arguments]}. +if .%1.==._call_. shift /2 & goto %2 +set CALL=call %0 _call_ +set RETURN=goto end +:# Silent return. Used for routines silently called via call :label. +set _RETURN=goto _end +set PUTVARS=call :putvars + +:# Set global defaults +setlocal +set OUTFILE=obj\objects.mak +set OUTPATH=obj +set NO_EXEC=0 +goto get_args + +:help +echo Generate object files names from source files names +echo. +echo Usage: %ARG0% [options] source ... +echo. +echo Options: +echo -?^|-h This help +echo -o {pathname} Output file pathname. Default: %OUTFILE% +echo -X Display object files names, but do not create the output file +goto end + +:get_args +if .%1.==.. goto help +if .%1.==.-?. goto help +if .%1.==./?. goto help +if %1==-o shift & goto set_out +if %1==-X shift & goto no_exec +goto go + +:set_out +set OUTFILE=%1 +:# Split the path. Uses a fake drive @ to prevent prepending the current path on an existing drive. +for %%F in (@:"%OUTFILE%") do ( + set "OUTPATH=%%~dpF" +) +:# Remove the head "@:\ and tail \ to the path +set "OUTPATH=%OUTPATH:~4,-1%" +shift +goto get_args + +:no_exec +set NO_EXEC=1 +goto get_args + +:# Check prerequisites +:check +verify other 2>nul +setlocal enableextensions +if errorlevel 1 ( + echo>&2 Error: Unable to enable command extensions. + exit /b 1 +) +set VAR=before +if "%VAR%" == "before" ( + set VAR=after + if not "!VAR!" == "after" ( + echo>&2 Error: Delayed environment variable expansion must be enabled. + echo>&2 Please restart your cmd.exe shell with the /V option, + echo>&2 or set HKLM\Software\Microsoft\Command Processor\DelayedExpansion=1 + exit /b 1 + ) +) +%_RETURN% + +:go +%CALL% check +if errorlevel 1 exit /b 1 +set OBJECTS= +:next +if .%1.==.. goto done +for %%s in (%1) do ( + set EXT=%%~xs + set OBJ= + if .!EXT!.==..c. set OBJ=obj + if .!EXT!.==..C. set OBJ=obj + if .!EXT!.==..cpp. set OBJ=obj + if .!EXT!.==..CPP. set OBJ=obj + if .!EXT!.==..asm. set OBJ=obj + if .!EXT!.==..ASM. set OBJ=obj + if .!EXT!.==..rc. set OBJ=res + if .!EXT!.==..RC. set OBJ=res + if .!OBJ!.==.. ( + echo>&2 Error: Unsupported source type: !EXT! + echo>&2 Please add a conversion rule in %ARG0% + ) else ( + if .!OBJECTS!.==.. ( + set OBJECTS=%OUTPATH%\%%~ns.!OBJ! + ) else ( + set OBJECTS=!OBJECTS! %OUTPATH%\%%~ns.!OBJ! + ) + ) +) +shift +goto next +:done +echo OBJECTS=%OBJECTS% +if %NO_EXEC%==0 echo>%OUTFILE% OBJECTS=%OBJECTS% + +:end +:_end + diff --git a/deps/MsvcLibX/src/strerror.c b/deps/MsvcLibX/src/strerror.c new file mode 100644 index 0000000000000000000000000000000000000000..2f8f3248290738c7c0819aa33308101e23209d48 --- /dev/null +++ b/deps/MsvcLibX/src/strerror.c @@ -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 +#include +#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) */ + diff --git a/deps/MsvcLibX/src/strndup.c b/deps/MsvcLibX/src/strndup.c new file mode 100644 index 0000000000000000000000000000000000000000..5f68b8e5fcbace69990d0e0dd1a20fe7ade46162 --- /dev/null +++ b/deps/MsvcLibX/src/strndup.c @@ -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 +#include + +/* 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; +} + diff --git a/deps/MsvcLibX/src/strptime.c b/deps/MsvcLibX/src/strptime.c new file mode 100644 index 0000000000000000000000000000000000000000..142a2408ddd94521dd33d23d24f20b9695be4fca --- /dev/null +++ b/deps/MsvcLibX/src/strptime.c @@ -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 +#include +#include + +/* + * 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); +} diff --git a/deps/MsvcLibX/src/symlink.c b/deps/MsvcLibX/src/symlink.c new file mode 100644 index 0000000000000000000000000000000000000000..e791cea35aa15725e7e94125fe300e4bce1b6a32 --- /dev/null +++ b/deps/MsvcLibX/src/symlink.c @@ -0,0 +1,454 @@ +/*****************************************************************************\ +* * +* 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 +#pragma comment(lib, "Mpr.lib") + +#include +#include "debugm.h" + +#ifdef _WIN32 + +#include + +#include "reparsept.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 + + diff --git a/deps/MsvcLibX/src/uname.c b/deps/MsvcLibX/src/uname.c new file mode 100644 index 0000000000000000000000000000000000000000..10baef0fe62de87498d3c11788ee679dc8ccaf13 --- /dev/null +++ b/deps/MsvcLibX/src/uname.c @@ -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/utsname.h" +#include /* For itoa() */ + +static char major[4] = {0}; +static char minor[4] = {0}; + +#ifdef _MSDOS + +#include + +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 + +#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) */ diff --git a/deps/MsvcLibX/src/utime.c b/deps/MsvcLibX/src/utime.c new file mode 100644 index 0000000000000000000000000000000000000000..c365ae9f60f1713f455648336958e8c32eedeb42 --- /dev/null +++ b/deps/MsvcLibX/src/utime.c @@ -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 +#include /* Must be included before any direct or indirect inclusion */ +#include + +#include "debugm.h" + +#if defined(_DEBUG) +#include +#endif /* defined(_DEBUG) */ + +#ifdef _WIN32 + +#include +#include /* For MSVC's _get_osfhandle() */ +#include /* 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) */ + diff --git a/deps/MsvcLibX/src/utimes.c b/deps/MsvcLibX/src/utimes.c new file mode 100644 index 0000000000000000000000000000000000000000..482883b87b9fbebab6cad7b0cd1a1391746aaae6 --- /dev/null +++ b/deps/MsvcLibX/src/utimes.c @@ -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 . * +* 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 +#include /* Must be included before any direct or indirect inclusion */ +#include + +#include "debugm.h" + +#if defined(_DEBUG) +#include +#endif /* defined(_DEBUG) */ + +#ifdef _WIN32 + +#include +#include /* For MSVC's _get_osfhandle() */ +#include /* 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 = 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) */ + diff --git a/deps/MsvcLibX/src/xfreopen.c b/deps/MsvcLibX/src/xfreopen.c new file mode 100644 index 0000000000000000000000000000000000000000..724fb8e13b4e09119e23cb37692e8c2ca9eb6d3a --- /dev/null +++ b/deps/MsvcLibX/src/xfreopen.c @@ -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 +#include +#include +#include +#include "xfreopen.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; +} + diff --git a/deps/pthread/config.h b/deps/pthread/config.h index 7331e0775f094fe45add4ba7363c36ec936ad51c..057ecfa04a44dc1dc40d79c3da88e6222228964d 100644 --- a/deps/pthread/config.h +++ b/deps/pthread/config.h @@ -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? */ diff --git a/deps/wepoll/CMakeLists.txt b/deps/wepoll/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..a81fd782bbc4b05a1158273a7fcc6701bc4d980d --- /dev/null +++ b/deps/wepoll/CMakeLists.txt @@ -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 () diff --git a/deps/wepoll/inc/wepoll.h b/deps/wepoll/inc/wepoll.h new file mode 100644 index 0000000000000000000000000000000000000000..afe2e14a6d17696548d91dd4c1e0fbd633314347 --- /dev/null +++ b/deps/wepoll/inc/wepoll.h @@ -0,0 +1,111 @@ +/* + * wepoll - epoll for Windows + * https://github.com/piscisaureus/wepoll + * + * Copyright 2012-2020, Bert Belder + * 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 + +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_ */ diff --git a/deps/wepoll/src/wepoll.c b/deps/wepoll/src/wepoll.c new file mode 100644 index 0000000000000000000000000000000000000000..efe68624e2ef30fa5bb15124f6f877d1ba162d17 --- /dev/null +++ b/deps/wepoll/src/wepoll.c @@ -0,0 +1,2258 @@ +/* + * wepoll - epoll for Windows + * https://github.com/piscisaureus/wepoll + * + * Copyright 2012-2020, Bert Belder + * 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. + */ + +#define WEPOLL_EXPORT + +#include + +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 + +#include + +#include + +#define WEPOLL_INTERNAL static +#define WEPOLL_INTERNAL_VAR static + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#ifdef __clang__ +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wreserved-id-macro" +#endif + +#ifdef _WIN32_WINNT +#undef _WIN32_WINNT +#endif + +#define _WIN32_WINNT 0x0600 + +#ifdef __clang__ +#pragma clang diagnostic pop +#endif + +#ifndef __GNUC__ +#pragma warning(push, 1) +#endif + +#include +#include +#include + +#ifndef __GNUC__ +#pragma warning(pop) +#endif + +WEPOLL_INTERNAL int nt_global_init(void); + +typedef LONG NTSTATUS; +typedef NTSTATUS* PNTSTATUS; + +#ifndef NT_SUCCESS +#define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0) +#endif + +#ifndef STATUS_SUCCESS +#define STATUS_SUCCESS ((NTSTATUS) 0x00000000L) +#endif + +#ifndef STATUS_PENDING +#define STATUS_PENDING ((NTSTATUS) 0x00000103L) +#endif + +#ifndef STATUS_CANCELLED +#define STATUS_CANCELLED ((NTSTATUS) 0xC0000120L) +#endif + +#ifndef STATUS_NOT_FOUND +#define STATUS_NOT_FOUND ((NTSTATUS) 0xC0000225L) +#endif + +typedef struct _IO_STATUS_BLOCK { + NTSTATUS Status; + ULONG_PTR Information; +} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK; + +typedef VOID(NTAPI* PIO_APC_ROUTINE)(PVOID ApcContext, + PIO_STATUS_BLOCK IoStatusBlock, + ULONG Reserved); + +typedef struct _UNICODE_STRING { + USHORT Length; + USHORT MaximumLength; + PWSTR Buffer; +} UNICODE_STRING, *PUNICODE_STRING; + +#define RTL_CONSTANT_STRING(s) \ + { sizeof(s) - sizeof((s)[0]), sizeof(s), s } + +typedef struct _OBJECT_ATTRIBUTES { + ULONG Length; + HANDLE RootDirectory; + PUNICODE_STRING ObjectName; + ULONG Attributes; + PVOID SecurityDescriptor; + PVOID SecurityQualityOfService; +} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES; + +#define RTL_CONSTANT_OBJECT_ATTRIBUTES(ObjectName, Attributes) \ + { sizeof(OBJECT_ATTRIBUTES), NULL, ObjectName, Attributes, NULL, NULL } + +#ifndef FILE_OPEN +#define FILE_OPEN 0x00000001UL +#endif + +#define KEYEDEVENT_WAIT 0x00000001UL +#define KEYEDEVENT_WAKE 0x00000002UL +#define KEYEDEVENT_ALL_ACCESS \ + (STANDARD_RIGHTS_REQUIRED | KEYEDEVENT_WAIT | KEYEDEVENT_WAKE) + +#define NT_NTDLL_IMPORT_LIST(X) \ + X(NTSTATUS, \ + NTAPI, \ + NtCancelIoFileEx, \ + (HANDLE FileHandle, \ + PIO_STATUS_BLOCK IoRequestToCancel, \ + PIO_STATUS_BLOCK IoStatusBlock)) \ + \ + X(NTSTATUS, \ + NTAPI, \ + NtCreateFile, \ + (PHANDLE FileHandle, \ + ACCESS_MASK DesiredAccess, \ + POBJECT_ATTRIBUTES ObjectAttributes, \ + PIO_STATUS_BLOCK IoStatusBlock, \ + PLARGE_INTEGER AllocationSize, \ + ULONG FileAttributes, \ + ULONG ShareAccess, \ + ULONG CreateDisposition, \ + ULONG CreateOptions, \ + PVOID EaBuffer, \ + ULONG EaLength)) \ + \ + X(NTSTATUS, \ + NTAPI, \ + NtCreateKeyedEvent, \ + (PHANDLE KeyedEventHandle, \ + ACCESS_MASK DesiredAccess, \ + POBJECT_ATTRIBUTES ObjectAttributes, \ + ULONG Flags)) \ + \ + X(NTSTATUS, \ + NTAPI, \ + NtDeviceIoControlFile, \ + (HANDLE FileHandle, \ + HANDLE Event, \ + PIO_APC_ROUTINE ApcRoutine, \ + PVOID ApcContext, \ + PIO_STATUS_BLOCK IoStatusBlock, \ + ULONG IoControlCode, \ + PVOID InputBuffer, \ + ULONG InputBufferLength, \ + PVOID OutputBuffer, \ + ULONG OutputBufferLength)) \ + \ + X(NTSTATUS, \ + NTAPI, \ + NtReleaseKeyedEvent, \ + (HANDLE KeyedEventHandle, \ + PVOID KeyValue, \ + BOOLEAN Alertable, \ + PLARGE_INTEGER Timeout)) \ + \ + X(NTSTATUS, \ + NTAPI, \ + NtWaitForKeyedEvent, \ + (HANDLE KeyedEventHandle, \ + PVOID KeyValue, \ + BOOLEAN Alertable, \ + PLARGE_INTEGER Timeout)) \ + \ + X(ULONG, WINAPI, RtlNtStatusToDosError, (NTSTATUS Status)) + +#define X(return_type, attributes, name, parameters) \ + WEPOLL_INTERNAL_VAR return_type(attributes* name) parameters; +NT_NTDLL_IMPORT_LIST(X) +#undef X + +#define AFD_POLL_RECEIVE 0x0001 +#define AFD_POLL_RECEIVE_EXPEDITED 0x0002 +#define AFD_POLL_SEND 0x0004 +#define AFD_POLL_DISCONNECT 0x0008 +#define AFD_POLL_ABORT 0x0010 +#define AFD_POLL_LOCAL_CLOSE 0x0020 +#define AFD_POLL_ACCEPT 0x0080 +#define AFD_POLL_CONNECT_FAIL 0x0100 + +typedef struct _AFD_POLL_HANDLE_INFO { + HANDLE Handle; + ULONG Events; + NTSTATUS Status; +} AFD_POLL_HANDLE_INFO, *PAFD_POLL_HANDLE_INFO; + +typedef struct _AFD_POLL_INFO { + LARGE_INTEGER Timeout; + ULONG NumberOfHandles; + ULONG Exclusive; + AFD_POLL_HANDLE_INFO Handles[1]; +} AFD_POLL_INFO, *PAFD_POLL_INFO; + +WEPOLL_INTERNAL int afd_create_helper_handle(HANDLE iocp_handle, + HANDLE* afd_helper_handle_out); + +WEPOLL_INTERNAL int afd_poll(HANDLE afd_helper_handle, + AFD_POLL_INFO* poll_info, + IO_STATUS_BLOCK* io_status_block); +WEPOLL_INTERNAL int afd_cancel_poll(HANDLE afd_helper_handle, + IO_STATUS_BLOCK* io_status_block); + +#define return_map_error(value) \ + do { \ + err_map_win_error(); \ + return (value); \ + } while (0) + +#define return_set_error(value, error) \ + do { \ + err_set_win_error(error); \ + return (value); \ + } while (0) + +WEPOLL_INTERNAL void err_map_win_error(void); +WEPOLL_INTERNAL void err_set_win_error(DWORD error); +WEPOLL_INTERNAL int err_check_handle(HANDLE handle); + +#define IOCTL_AFD_POLL 0x00012024 + +static UNICODE_STRING afd__helper_name = + RTL_CONSTANT_STRING(L"\\Device\\Afd\\Wepoll"); + +static OBJECT_ATTRIBUTES afd__helper_attributes = + RTL_CONSTANT_OBJECT_ATTRIBUTES(&afd__helper_name, 0); + +int afd_create_helper_handle(HANDLE iocp_handle, + HANDLE* afd_helper_handle_out) { + HANDLE afd_helper_handle; + IO_STATUS_BLOCK iosb; + NTSTATUS status; + + /* By opening \Device\Afd without specifying any extended attributes, we'll + * get a handle that lets us talk to the AFD driver, but that doesn't have an + * associated endpoint (so it's not a socket). */ + status = NtCreateFile(&afd_helper_handle, + SYNCHRONIZE, + &afd__helper_attributes, + &iosb, + NULL, + 0, + FILE_SHARE_READ | FILE_SHARE_WRITE, + FILE_OPEN, + 0, + NULL, + 0); + if (status != STATUS_SUCCESS) + return_set_error(-1, RtlNtStatusToDosError(status)); + + if (CreateIoCompletionPort(afd_helper_handle, iocp_handle, 0, 0) == NULL) + goto error; + + if (!SetFileCompletionNotificationModes(afd_helper_handle, + FILE_SKIP_SET_EVENT_ON_HANDLE)) + goto error; + + *afd_helper_handle_out = afd_helper_handle; + return 0; + +error: + CloseHandle(afd_helper_handle); + return_map_error(-1); +} + +int afd_poll(HANDLE afd_helper_handle, + AFD_POLL_INFO* poll_info, + IO_STATUS_BLOCK* io_status_block) { + NTSTATUS status; + + /* Blocking operation is not supported. */ + assert(io_status_block != NULL); + + io_status_block->Status = STATUS_PENDING; + status = NtDeviceIoControlFile(afd_helper_handle, + NULL, + NULL, + io_status_block, + io_status_block, + IOCTL_AFD_POLL, + poll_info, + sizeof *poll_info, + poll_info, + sizeof *poll_info); + + if (status == STATUS_SUCCESS) + return 0; + else if (status == STATUS_PENDING) + return_set_error(-1, ERROR_IO_PENDING); + else + return_set_error(-1, RtlNtStatusToDosError(status)); +} + +int afd_cancel_poll(HANDLE afd_helper_handle, + IO_STATUS_BLOCK* io_status_block) { + NTSTATUS cancel_status; + IO_STATUS_BLOCK cancel_iosb; + + /* If the poll operation has already completed or has been cancelled earlier, + * there's nothing left for us to do. */ + if (io_status_block->Status != STATUS_PENDING) + return 0; + + cancel_status = + NtCancelIoFileEx(afd_helper_handle, io_status_block, &cancel_iosb); + + /* NtCancelIoFileEx() may return STATUS_NOT_FOUND if the operation completed + * just before calling NtCancelIoFileEx(). This is not an error. */ + if (cancel_status == STATUS_SUCCESS || cancel_status == STATUS_NOT_FOUND) + return 0; + else + return_set_error(-1, RtlNtStatusToDosError(cancel_status)); +} + +WEPOLL_INTERNAL int epoll_global_init(void); + +WEPOLL_INTERNAL int init(void); + +typedef struct port_state port_state_t; +typedef struct queue queue_t; +typedef struct sock_state sock_state_t; +typedef struct ts_tree_node ts_tree_node_t; + +WEPOLL_INTERNAL port_state_t* port_new(HANDLE* iocp_handle_out); +WEPOLL_INTERNAL int port_close(port_state_t* port_state); +WEPOLL_INTERNAL int port_delete(port_state_t* port_state); + +WEPOLL_INTERNAL int port_wait(port_state_t* port_state, + struct epoll_event* events, + int maxevents, + int timeout); + +WEPOLL_INTERNAL int port_ctl(port_state_t* port_state, + int op, + SOCKET sock, + struct epoll_event* ev); + +WEPOLL_INTERNAL int port_register_socket(port_state_t* port_state, + sock_state_t* sock_state, + SOCKET socket); +WEPOLL_INTERNAL void port_unregister_socket(port_state_t* port_state, + sock_state_t* sock_state); +WEPOLL_INTERNAL sock_state_t* port_find_socket(port_state_t* port_state, + SOCKET socket); + +WEPOLL_INTERNAL void port_request_socket_update(port_state_t* port_state, + sock_state_t* sock_state); +WEPOLL_INTERNAL void port_cancel_socket_update(port_state_t* port_state, + sock_state_t* sock_state); + +WEPOLL_INTERNAL void port_add_deleted_socket(port_state_t* port_state, + sock_state_t* sock_state); +WEPOLL_INTERNAL void port_remove_deleted_socket(port_state_t* port_state, + sock_state_t* sock_state); + +WEPOLL_INTERNAL HANDLE port_get_iocp_handle(port_state_t* port_state); +WEPOLL_INTERNAL queue_t* port_get_poll_group_queue(port_state_t* port_state); + +WEPOLL_INTERNAL port_state_t* port_state_from_handle_tree_node( + ts_tree_node_t* tree_node); +WEPOLL_INTERNAL ts_tree_node_t* port_state_to_handle_tree_node( + port_state_t* port_state); + +/* The reflock is a special kind of lock that normally prevents a chunk of + * memory from being freed, but does allow the chunk of memory to eventually be + * released in a coordinated fashion. + * + * Under normal operation, threads increase and decrease the reference count, + * which are wait-free operations. + * + * Exactly once during the reflock's lifecycle, a thread holding a reference to + * the lock may "destroy" the lock; this operation blocks until all other + * threads holding a reference to the lock have dereferenced it. After + * "destroy" returns, the calling thread may assume that no other threads have + * a reference to the lock. + * + * Attemmpting to lock or destroy a lock after reflock_unref_and_destroy() has + * been called is invalid and results in undefined behavior. Therefore the user + * should use another lock to guarantee that this can't happen. + */ + +typedef struct reflock { + volatile long state; /* 32-bit Interlocked APIs operate on `long` values. */ +} reflock_t; + +WEPOLL_INTERNAL int reflock_global_init(void); + +WEPOLL_INTERNAL void reflock_init(reflock_t* reflock); +WEPOLL_INTERNAL void reflock_ref(reflock_t* reflock); +WEPOLL_INTERNAL void reflock_unref(reflock_t* reflock); +WEPOLL_INTERNAL void reflock_unref_and_destroy(reflock_t* reflock); + +#include + +/* N.b.: the tree functions do not set errno or LastError when they fail. Each + * of the API functions has at most one failure mode. It is up to the caller to + * set an appropriate error code when necessary. */ + +typedef struct tree tree_t; +typedef struct tree_node tree_node_t; + +typedef struct tree { + tree_node_t* root; +} tree_t; + +typedef struct tree_node { + tree_node_t* left; + tree_node_t* right; + tree_node_t* parent; + uintptr_t key; + bool red; +} tree_node_t; + +WEPOLL_INTERNAL void tree_init(tree_t* tree); +WEPOLL_INTERNAL void tree_node_init(tree_node_t* node); + +WEPOLL_INTERNAL int tree_add(tree_t* tree, tree_node_t* node, uintptr_t key); +WEPOLL_INTERNAL void tree_del(tree_t* tree, tree_node_t* node); + +WEPOLL_INTERNAL tree_node_t* tree_find(const tree_t* tree, uintptr_t key); +WEPOLL_INTERNAL tree_node_t* tree_root(const tree_t* tree); + +typedef struct ts_tree { + tree_t tree; + SRWLOCK lock; +} ts_tree_t; + +typedef struct ts_tree_node { + tree_node_t tree_node; + reflock_t reflock; +} ts_tree_node_t; + +WEPOLL_INTERNAL void ts_tree_init(ts_tree_t* rtl); +WEPOLL_INTERNAL void ts_tree_node_init(ts_tree_node_t* node); + +WEPOLL_INTERNAL int ts_tree_add(ts_tree_t* ts_tree, + ts_tree_node_t* node, + uintptr_t key); + +WEPOLL_INTERNAL ts_tree_node_t* ts_tree_del_and_ref(ts_tree_t* ts_tree, + uintptr_t key); +WEPOLL_INTERNAL ts_tree_node_t* ts_tree_find_and_ref(ts_tree_t* ts_tree, + uintptr_t key); + +WEPOLL_INTERNAL void ts_tree_node_unref(ts_tree_node_t* node); +WEPOLL_INTERNAL void ts_tree_node_unref_and_destroy(ts_tree_node_t* node); + +static ts_tree_t epoll__handle_tree; + +int epoll_global_init(void) { + ts_tree_init(&epoll__handle_tree); + return 0; +} + +static HANDLE epoll__create(void) { + port_state_t* port_state; + HANDLE ephnd; + ts_tree_node_t* tree_node; + + if (init() < 0) + return NULL; + + port_state = port_new(&ephnd); + if (port_state == NULL) + return NULL; + + tree_node = port_state_to_handle_tree_node(port_state); + if (ts_tree_add(&epoll__handle_tree, tree_node, (uintptr_t) ephnd) < 0) { + /* This should never happen. */ + port_delete(port_state); + return_set_error(NULL, ERROR_ALREADY_EXISTS); + } + + return ephnd; +} + +HANDLE epoll_create(int size) { + if (size <= 0) + return_set_error(NULL, ERROR_INVALID_PARAMETER); + + return epoll__create(); +} + +HANDLE epoll_create1(int flags) { + if (flags != 0) + return_set_error(NULL, ERROR_INVALID_PARAMETER); + + return epoll__create(); +} + +int epoll_close(SOCKET ephnd) { + ts_tree_node_t* tree_node; + port_state_t* port_state; + + if (init() < 0) + return -1; + + tree_node = ts_tree_del_and_ref(&epoll__handle_tree, (uintptr_t) ephnd); + if (tree_node == NULL) { + err_set_win_error(ERROR_INVALID_PARAMETER); + goto err; + } + + port_state = port_state_from_handle_tree_node(tree_node); + port_close(port_state); + + ts_tree_node_unref_and_destroy(tree_node); + + return port_delete(port_state); + +err: + err_check_handle((HANDLE)ephnd); + return -1; +} + +int epoll_ctl(SOCKET ephnd, int op, SOCKET sock, struct epoll_event* ev) { + ts_tree_node_t* tree_node; + port_state_t* port_state; + int r; + + if (init() < 0) + return -1; + + tree_node = ts_tree_find_and_ref(&epoll__handle_tree, (uintptr_t) ephnd); + if (tree_node == NULL) { + err_set_win_error(ERROR_INVALID_PARAMETER); + goto err; + } + + port_state = port_state_from_handle_tree_node(tree_node); + r = port_ctl(port_state, op, sock, ev); + + ts_tree_node_unref(tree_node); + + if (r < 0) + goto err; + + return 0; + +err: + /* On Linux, in the case of epoll_ctl(), EBADF takes priority over other + * errors. Wepoll mimics this behavior. */ + err_check_handle((HANDLE) ephnd); + err_check_handle((HANDLE) sock); + return -1; +} + +int epoll_wait(SOCKET ephnd, + struct epoll_event* events, + int maxevents, + int timeout) { + ts_tree_node_t* tree_node; + port_state_t* port_state; + int num_events; + + if (maxevents <= 0) + return_set_error(-1, ERROR_INVALID_PARAMETER); + + if (init() < 0) + return -1; + + tree_node = ts_tree_find_and_ref(&epoll__handle_tree, (uintptr_t) ephnd); + if (tree_node == NULL) { + err_set_win_error(ERROR_INVALID_PARAMETER); + goto err; + } + + port_state = port_state_from_handle_tree_node(tree_node); + num_events = port_wait(port_state, events, maxevents, timeout); + + ts_tree_node_unref(tree_node); + + if (num_events < 0) + goto err; + + return num_events; + +err: + err_check_handle((HANDLE) ephnd); + return -1; +} + +#include + +#define ERR__ERRNO_MAPPINGS(X) \ + X(ERROR_ACCESS_DENIED, EACCES) \ + X(ERROR_ALREADY_EXISTS, EEXIST) \ + X(ERROR_BAD_COMMAND, EACCES) \ + X(ERROR_BAD_EXE_FORMAT, ENOEXEC) \ + X(ERROR_BAD_LENGTH, EACCES) \ + X(ERROR_BAD_NETPATH, ENOENT) \ + X(ERROR_BAD_NET_NAME, ENOENT) \ + X(ERROR_BAD_NET_RESP, ENETDOWN) \ + X(ERROR_BAD_PATHNAME, ENOENT) \ + X(ERROR_BROKEN_PIPE, EPIPE) \ + X(ERROR_CANNOT_MAKE, EACCES) \ + X(ERROR_COMMITMENT_LIMIT, ENOMEM) \ + X(ERROR_CONNECTION_ABORTED, ECONNABORTED) \ + X(ERROR_CONNECTION_ACTIVE, EISCONN) \ + X(ERROR_CONNECTION_REFUSED, ECONNREFUSED) \ + X(ERROR_CRC, EACCES) \ + X(ERROR_DIR_NOT_EMPTY, ENOTEMPTY) \ + X(ERROR_DISK_FULL, ENOSPC) \ + X(ERROR_DUP_NAME, EADDRINUSE) \ + X(ERROR_FILENAME_EXCED_RANGE, ENOENT) \ + X(ERROR_FILE_NOT_FOUND, ENOENT) \ + X(ERROR_GEN_FAILURE, EACCES) \ + X(ERROR_GRACEFUL_DISCONNECT, EPIPE) \ + X(ERROR_HOST_DOWN, EHOSTUNREACH) \ + X(ERROR_HOST_UNREACHABLE, EHOSTUNREACH) \ + X(ERROR_INSUFFICIENT_BUFFER, EFAULT) \ + X(ERROR_INVALID_ADDRESS, EADDRNOTAVAIL) \ + X(ERROR_INVALID_FUNCTION, EINVAL) \ + X(ERROR_INVALID_HANDLE, EBADF) \ + X(ERROR_INVALID_NETNAME, EADDRNOTAVAIL) \ + X(ERROR_INVALID_PARAMETER, EINVAL) \ + X(ERROR_INVALID_USER_BUFFER, EMSGSIZE) \ + X(ERROR_IO_PENDING, EINPROGRESS) \ + X(ERROR_LOCK_VIOLATION, EACCES) \ + X(ERROR_MORE_DATA, EMSGSIZE) \ + X(ERROR_NETNAME_DELETED, ECONNABORTED) \ + X(ERROR_NETWORK_ACCESS_DENIED, EACCES) \ + X(ERROR_NETWORK_BUSY, ENETDOWN) \ + X(ERROR_NETWORK_UNREACHABLE, ENETUNREACH) \ + X(ERROR_NOACCESS, EFAULT) \ + X(ERROR_NONPAGED_SYSTEM_RESOURCES, ENOMEM) \ + X(ERROR_NOT_ENOUGH_MEMORY, ENOMEM) \ + X(ERROR_NOT_ENOUGH_QUOTA, ENOMEM) \ + X(ERROR_NOT_FOUND, ENOENT) \ + X(ERROR_NOT_LOCKED, EACCES) \ + X(ERROR_NOT_READY, EACCES) \ + X(ERROR_NOT_SAME_DEVICE, EXDEV) \ + X(ERROR_NOT_SUPPORTED, ENOTSUP) \ + X(ERROR_NO_MORE_FILES, ENOENT) \ + X(ERROR_NO_SYSTEM_RESOURCES, ENOMEM) \ + X(ERROR_OPERATION_ABORTED, EINTR) \ + X(ERROR_OUT_OF_PAPER, EACCES) \ + X(ERROR_PAGED_SYSTEM_RESOURCES, ENOMEM) \ + X(ERROR_PAGEFILE_QUOTA, ENOMEM) \ + X(ERROR_PATH_NOT_FOUND, ENOENT) \ + X(ERROR_PIPE_NOT_CONNECTED, EPIPE) \ + X(ERROR_PORT_UNREACHABLE, ECONNRESET) \ + X(ERROR_PROTOCOL_UNREACHABLE, ENETUNREACH) \ + X(ERROR_REM_NOT_LIST, ECONNREFUSED) \ + X(ERROR_REQUEST_ABORTED, EINTR) \ + X(ERROR_REQ_NOT_ACCEP, EWOULDBLOCK) \ + X(ERROR_SECTOR_NOT_FOUND, EACCES) \ + X(ERROR_SEM_TIMEOUT, ETIMEDOUT) \ + X(ERROR_SHARING_VIOLATION, EACCES) \ + X(ERROR_TOO_MANY_NAMES, ENOMEM) \ + X(ERROR_TOO_MANY_OPEN_FILES, EMFILE) \ + X(ERROR_UNEXP_NET_ERR, ECONNABORTED) \ + X(ERROR_WAIT_NO_CHILDREN, ECHILD) \ + X(ERROR_WORKING_SET_QUOTA, ENOMEM) \ + X(ERROR_WRITE_PROTECT, EACCES) \ + X(ERROR_WRONG_DISK, EACCES) \ + X(WSAEACCES, EACCES) \ + X(WSAEADDRINUSE, EADDRINUSE) \ + X(WSAEADDRNOTAVAIL, EADDRNOTAVAIL) \ + X(WSAEAFNOSUPPORT, EAFNOSUPPORT) \ + X(WSAECONNABORTED, ECONNABORTED) \ + X(WSAECONNREFUSED, ECONNREFUSED) \ + X(WSAECONNRESET, ECONNRESET) \ + X(WSAEDISCON, EPIPE) \ + X(WSAEFAULT, EFAULT) \ + X(WSAEHOSTDOWN, EHOSTUNREACH) \ + X(WSAEHOSTUNREACH, EHOSTUNREACH) \ + X(WSAEINPROGRESS, EBUSY) \ + X(WSAEINTR, EINTR) \ + X(WSAEINVAL, EINVAL) \ + X(WSAEISCONN, EISCONN) \ + X(WSAEMSGSIZE, EMSGSIZE) \ + X(WSAENETDOWN, ENETDOWN) \ + X(WSAENETRESET, EHOSTUNREACH) \ + X(WSAENETUNREACH, ENETUNREACH) \ + X(WSAENOBUFS, ENOMEM) \ + X(WSAENOTCONN, ENOTCONN) \ + X(WSAENOTSOCK, ENOTSOCK) \ + X(WSAEOPNOTSUPP, EOPNOTSUPP) \ + X(WSAEPROCLIM, ENOMEM) \ + X(WSAESHUTDOWN, EPIPE) \ + X(WSAETIMEDOUT, ETIMEDOUT) \ + X(WSAEWOULDBLOCK, EWOULDBLOCK) \ + X(WSANOTINITIALISED, ENETDOWN) \ + X(WSASYSNOTREADY, ENETDOWN) \ + X(WSAVERNOTSUPPORTED, ENOSYS) + +static errno_t err__map_win_error_to_errno(DWORD error) { + switch (error) { +#define X(error_sym, errno_sym) \ + case error_sym: \ + return errno_sym; + ERR__ERRNO_MAPPINGS(X) +#undef X + } + return EINVAL; +} + +void err_map_win_error(void) { + errno = err__map_win_error_to_errno(GetLastError()); +} + +void err_set_win_error(DWORD error) { + SetLastError(error); + errno = err__map_win_error_to_errno(error); +} + +int err_check_handle(HANDLE handle) { + DWORD flags; + + /* GetHandleInformation() succeeds when passed INVALID_HANDLE_VALUE, so check + * for this condition explicitly. */ + if (handle == INVALID_HANDLE_VALUE) + return_set_error(-1, ERROR_INVALID_HANDLE); + + if (!GetHandleInformation(handle, &flags)) + return_map_error(-1); + + return 0; +} + +#include + +#define array_count(a) (sizeof(a) / (sizeof((a)[0]))) + +#define container_of(ptr, type, member) \ + ((type*) ((uintptr_t) (ptr) - offsetof(type, member))) + +#define unused_var(v) ((void) (v)) + +/* Polyfill `inline` for older versions of msvc (up to Visual Studio 2013) */ +#if defined(_MSC_VER) && _MSC_VER < 1900 +#define inline __inline +#endif + +WEPOLL_INTERNAL int ws_global_init(void); +WEPOLL_INTERNAL SOCKET ws_get_base_socket(SOCKET socket); + +static bool init__done = false; +static INIT_ONCE init__once = INIT_ONCE_STATIC_INIT; + +static BOOL CALLBACK init__once_callback(INIT_ONCE* once, + void* parameter, + void** context) { + unused_var(once); + unused_var(parameter); + unused_var(context); + + /* N.b. that initialization order matters here. */ + if (ws_global_init() < 0 || nt_global_init() < 0 || + reflock_global_init() < 0 || epoll_global_init() < 0) + return FALSE; + + init__done = true; + return TRUE; +} + +int init(void) { + if (!init__done && + !InitOnceExecuteOnce(&init__once, init__once_callback, NULL, NULL)) + /* `InitOnceExecuteOnce()` itself is infallible, and it doesn't set any + * error code when the once-callback returns FALSE. We return -1 here to + * indicate that global initialization failed; the failing init function is + * resposible for setting `errno` and calling `SetLastError()`. */ + return -1; + + return 0; +} + +/* Set up a workaround for the following problem: + * FARPROC addr = GetProcAddress(...); + * MY_FUNC func = (MY_FUNC) addr; <-- GCC 8 warning/error. + * MY_FUNC func = (MY_FUNC) (void*) addr; <-- MSVC warning/error. + * To compile cleanly with either compiler, do casts with this "bridge" type: + * MY_FUNC func = (MY_FUNC) (nt__fn_ptr_cast_t) addr; */ +#ifdef __GNUC__ +typedef void* nt__fn_ptr_cast_t; +#else +typedef FARPROC nt__fn_ptr_cast_t; +#endif + +#define X(return_type, attributes, name, parameters) \ + WEPOLL_INTERNAL return_type(attributes* name) parameters = NULL; +NT_NTDLL_IMPORT_LIST(X) +#undef X + +int nt_global_init(void) { + HMODULE ntdll; + FARPROC fn_ptr; + + ntdll = GetModuleHandleW(L"ntdll.dll"); + if (ntdll == NULL) + return -1; + +#define X(return_type, attributes, name, parameters) \ + fn_ptr = GetProcAddress(ntdll, #name); \ + if (fn_ptr == NULL) \ + return -1; \ + name = (return_type(attributes*) parameters)(nt__fn_ptr_cast_t) fn_ptr; + NT_NTDLL_IMPORT_LIST(X) +#undef X + + return 0; +} + +#include + +typedef struct poll_group poll_group_t; + +typedef struct queue_node queue_node_t; + +WEPOLL_INTERNAL poll_group_t* poll_group_acquire(port_state_t* port); +WEPOLL_INTERNAL void poll_group_release(poll_group_t* poll_group); + +WEPOLL_INTERNAL void poll_group_delete(poll_group_t* poll_group); + +WEPOLL_INTERNAL poll_group_t* poll_group_from_queue_node( + queue_node_t* queue_node); +WEPOLL_INTERNAL HANDLE + poll_group_get_afd_helper_handle(poll_group_t* poll_group); + +typedef struct queue_node { + queue_node_t* prev; + queue_node_t* next; +} queue_node_t; + +typedef struct queue { + queue_node_t head; +} queue_t; + +WEPOLL_INTERNAL void queue_init(queue_t* queue); +WEPOLL_INTERNAL void queue_node_init(queue_node_t* node); + +WEPOLL_INTERNAL queue_node_t* queue_first(const queue_t* queue); +WEPOLL_INTERNAL queue_node_t* queue_last(const queue_t* queue); + +WEPOLL_INTERNAL void queue_prepend(queue_t* queue, queue_node_t* node); +WEPOLL_INTERNAL void queue_append(queue_t* queue, queue_node_t* node); +WEPOLL_INTERNAL void queue_move_to_start(queue_t* queue, queue_node_t* node); +WEPOLL_INTERNAL void queue_move_to_end(queue_t* queue, queue_node_t* node); +WEPOLL_INTERNAL void queue_remove(queue_node_t* node); + +WEPOLL_INTERNAL bool queue_is_empty(const queue_t* queue); +WEPOLL_INTERNAL bool queue_is_enqueued(const queue_node_t* node); + +static const size_t POLL_GROUP__MAX_GROUP_SIZE = 32; + +typedef struct poll_group { + port_state_t* port_state; + queue_node_t queue_node; + HANDLE afd_helper_handle; + size_t group_size; +} poll_group_t; + +static poll_group_t* poll_group__new(port_state_t* port_state) { + HANDLE iocp_handle = port_get_iocp_handle(port_state); + queue_t* poll_group_queue = port_get_poll_group_queue(port_state); + + poll_group_t* poll_group = malloc(sizeof *poll_group); + if (poll_group == NULL) + return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); + + memset(poll_group, 0, sizeof *poll_group); + + queue_node_init(&poll_group->queue_node); + poll_group->port_state = port_state; + + if (afd_create_helper_handle(iocp_handle, &poll_group->afd_helper_handle) < + 0) { + free(poll_group); + return NULL; + } + + queue_append(poll_group_queue, &poll_group->queue_node); + + return poll_group; +} + +void poll_group_delete(poll_group_t* poll_group) { + assert(poll_group->group_size == 0); + CloseHandle(poll_group->afd_helper_handle); + queue_remove(&poll_group->queue_node); + free(poll_group); +} + +poll_group_t* poll_group_from_queue_node(queue_node_t* queue_node) { + return container_of(queue_node, poll_group_t, queue_node); +} + +HANDLE poll_group_get_afd_helper_handle(poll_group_t* poll_group) { + return poll_group->afd_helper_handle; +} + +poll_group_t* poll_group_acquire(port_state_t* port_state) { + queue_t* poll_group_queue = port_get_poll_group_queue(port_state); + poll_group_t* poll_group = + !queue_is_empty(poll_group_queue) + ? container_of( + queue_last(poll_group_queue), poll_group_t, queue_node) + : NULL; + + if (poll_group == NULL || + poll_group->group_size >= POLL_GROUP__MAX_GROUP_SIZE) + poll_group = poll_group__new(port_state); + if (poll_group == NULL) + return NULL; + + if (++poll_group->group_size == POLL_GROUP__MAX_GROUP_SIZE) + queue_move_to_start(poll_group_queue, &poll_group->queue_node); + + return poll_group; +} + +void poll_group_release(poll_group_t* poll_group) { + port_state_t* port_state = poll_group->port_state; + queue_t* poll_group_queue = port_get_poll_group_queue(port_state); + + poll_group->group_size--; + assert(poll_group->group_size < POLL_GROUP__MAX_GROUP_SIZE); + + queue_move_to_end(poll_group_queue, &poll_group->queue_node); + + /* Poll groups are currently only freed when the epoll port is closed. */ +} + +WEPOLL_INTERNAL sock_state_t* sock_new(port_state_t* port_state, + SOCKET socket); +WEPOLL_INTERNAL void sock_delete(port_state_t* port_state, + sock_state_t* sock_state); +WEPOLL_INTERNAL void sock_force_delete(port_state_t* port_state, + sock_state_t* sock_state); + +WEPOLL_INTERNAL int sock_set_event(port_state_t* port_state, + sock_state_t* sock_state, + const struct epoll_event* ev); + +WEPOLL_INTERNAL int sock_update(port_state_t* port_state, + sock_state_t* sock_state); +WEPOLL_INTERNAL int sock_feed_event(port_state_t* port_state, + IO_STATUS_BLOCK* io_status_block, + struct epoll_event* ev); + +WEPOLL_INTERNAL sock_state_t* sock_state_from_queue_node( + queue_node_t* queue_node); +WEPOLL_INTERNAL queue_node_t* sock_state_to_queue_node( + sock_state_t* sock_state); +WEPOLL_INTERNAL sock_state_t* sock_state_from_tree_node( + tree_node_t* tree_node); +WEPOLL_INTERNAL tree_node_t* sock_state_to_tree_node(sock_state_t* sock_state); + +#define PORT__MAX_ON_STACK_COMPLETIONS 256 + +typedef struct port_state { + HANDLE iocp_handle; + tree_t sock_tree; + queue_t sock_update_queue; + queue_t sock_deleted_queue; + queue_t poll_group_queue; + ts_tree_node_t handle_tree_node; + CRITICAL_SECTION lock; + size_t active_poll_count; +} port_state_t; + +static port_state_t* port__alloc(void) { + port_state_t* port_state = malloc(sizeof *port_state); + if (port_state == NULL) + return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); + + return port_state; +} + +static void port__free(port_state_t* port) { + assert(port != NULL); + free(port); +} + +static HANDLE port__create_iocp(void) { + HANDLE iocp_handle = + CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); + if (iocp_handle == NULL) + return_map_error(NULL); + + return iocp_handle; +} + +port_state_t* port_new(HANDLE* iocp_handle_out) { + port_state_t* port_state; + HANDLE iocp_handle; + + port_state = port__alloc(); + if (port_state == NULL) + goto err1; + + iocp_handle = port__create_iocp(); + if (iocp_handle == NULL) + goto err2; + + memset(port_state, 0, sizeof *port_state); + + port_state->iocp_handle = iocp_handle; + tree_init(&port_state->sock_tree); + queue_init(&port_state->sock_update_queue); + queue_init(&port_state->sock_deleted_queue); + queue_init(&port_state->poll_group_queue); + ts_tree_node_init(&port_state->handle_tree_node); + InitializeCriticalSection(&port_state->lock); + + *iocp_handle_out = iocp_handle; + return port_state; + +err2: + port__free(port_state); +err1: + return NULL; +} + +static int port__close_iocp(port_state_t* port_state) { + HANDLE iocp_handle = port_state->iocp_handle; + port_state->iocp_handle = NULL; + + if (!CloseHandle(iocp_handle)) + return_map_error(-1); + + return 0; +} + +int port_close(port_state_t* port_state) { + int result; + + EnterCriticalSection(&port_state->lock); + result = port__close_iocp(port_state); + LeaveCriticalSection(&port_state->lock); + + return result; +} + +int port_delete(port_state_t* port_state) { + tree_node_t* tree_node; + queue_node_t* queue_node; + + /* At this point the IOCP port should have been closed. */ + assert(port_state->iocp_handle == NULL); + + while ((tree_node = tree_root(&port_state->sock_tree)) != NULL) { + sock_state_t* sock_state = sock_state_from_tree_node(tree_node); + sock_force_delete(port_state, sock_state); + } + + while ((queue_node = queue_first(&port_state->sock_deleted_queue)) != NULL) { + sock_state_t* sock_state = sock_state_from_queue_node(queue_node); + sock_force_delete(port_state, sock_state); + } + + while ((queue_node = queue_first(&port_state->poll_group_queue)) != NULL) { + poll_group_t* poll_group = poll_group_from_queue_node(queue_node); + poll_group_delete(poll_group); + } + + assert(queue_is_empty(&port_state->sock_update_queue)); + + DeleteCriticalSection(&port_state->lock); + + port__free(port_state); + + return 0; +} + +static int port__update_events(port_state_t* port_state) { + queue_t* sock_update_queue = &port_state->sock_update_queue; + + /* Walk the queue, submitting new poll requests for every socket that needs + * it. */ + while (!queue_is_empty(sock_update_queue)) { + queue_node_t* queue_node = queue_first(sock_update_queue); + sock_state_t* sock_state = sock_state_from_queue_node(queue_node); + + if (sock_update(port_state, sock_state) < 0) + return -1; + + /* sock_update() removes the socket from the update queue. */ + } + + return 0; +} + +static void port__update_events_if_polling(port_state_t* port_state) { + if (port_state->active_poll_count > 0) + port__update_events(port_state); +} + +static int port__feed_events(port_state_t* port_state, + struct epoll_event* epoll_events, + OVERLAPPED_ENTRY* iocp_events, + DWORD iocp_event_count) { + int epoll_event_count = 0; + DWORD i; + + for (i = 0; i < iocp_event_count; i++) { + IO_STATUS_BLOCK* io_status_block = + (IO_STATUS_BLOCK*) iocp_events[i].lpOverlapped; + struct epoll_event* ev = &epoll_events[epoll_event_count]; + + epoll_event_count += sock_feed_event(port_state, io_status_block, ev); + } + + return epoll_event_count; +} + +static int port__poll(port_state_t* port_state, + struct epoll_event* epoll_events, + OVERLAPPED_ENTRY* iocp_events, + DWORD maxevents, + DWORD timeout) { + DWORD completion_count; + + if (port__update_events(port_state) < 0) + return -1; + + port_state->active_poll_count++; + + LeaveCriticalSection(&port_state->lock); + + BOOL r = GetQueuedCompletionStatusEx(port_state->iocp_handle, + iocp_events, + maxevents, + &completion_count, + timeout, + FALSE); + + EnterCriticalSection(&port_state->lock); + + port_state->active_poll_count--; + + if (!r) + return_map_error(-1); + + return port__feed_events( + port_state, epoll_events, iocp_events, completion_count); +} + +int port_wait(port_state_t* port_state, + struct epoll_event* events, + int maxevents, + int timeout) { + OVERLAPPED_ENTRY stack_iocp_events[PORT__MAX_ON_STACK_COMPLETIONS]; + OVERLAPPED_ENTRY* iocp_events; + uint64_t due = 0; + DWORD gqcs_timeout; + int result; + + /* Check whether `maxevents` is in range. */ + if (maxevents <= 0) + return_set_error(-1, ERROR_INVALID_PARAMETER); + + /* Decide whether the IOCP completion list can live on the stack, or allocate + * memory for it on the heap. */ + if ((size_t) maxevents <= array_count(stack_iocp_events)) { + iocp_events = stack_iocp_events; + } else if ((iocp_events = + malloc((size_t) maxevents * sizeof *iocp_events)) == NULL) { + iocp_events = stack_iocp_events; + maxevents = array_count(stack_iocp_events); + } + + /* Compute the timeout for GetQueuedCompletionStatus, and the wait end + * time, if the user specified a timeout other than zero or infinite. */ + if (timeout > 0) { + due = GetTickCount64() + (uint64_t) timeout; + gqcs_timeout = (DWORD) timeout; + } else if (timeout == 0) { + gqcs_timeout = 0; + } else { + gqcs_timeout = INFINITE; + } + + EnterCriticalSection(&port_state->lock); + + /* Dequeue completion packets until either at least one interesting event + * has been discovered, or the timeout is reached. */ + for (;;) { + uint64_t now; + + result = port__poll( + port_state, events, iocp_events, (DWORD) maxevents, gqcs_timeout); + if (result < 0 || result > 0) + break; /* Result, error, or time-out. */ + + if (timeout < 0) + continue; /* When timeout is negative, never time out. */ + + /* Update time. */ + now = GetTickCount64(); + + /* Do not allow the due time to be in the past. */ + if (now >= due) { + SetLastError(WAIT_TIMEOUT); + break; + } + + /* Recompute time-out argument for GetQueuedCompletionStatus. */ + gqcs_timeout = (DWORD)(due - now); + } + + port__update_events_if_polling(port_state); + + LeaveCriticalSection(&port_state->lock); + + if (iocp_events != stack_iocp_events) + free(iocp_events); + + if (result >= 0) + return result; + else if (GetLastError() == WAIT_TIMEOUT) + return 0; + else + return -1; +} + +static int port__ctl_add(port_state_t* port_state, + SOCKET sock, + struct epoll_event* ev) { + sock_state_t* sock_state = sock_new(port_state, sock); + if (sock_state == NULL) + return -1; + + if (sock_set_event(port_state, sock_state, ev) < 0) { + sock_delete(port_state, sock_state); + return -1; + } + + port__update_events_if_polling(port_state); + + return 0; +} + +static int port__ctl_mod(port_state_t* port_state, + SOCKET sock, + struct epoll_event* ev) { + sock_state_t* sock_state = port_find_socket(port_state, sock); + if (sock_state == NULL) + return -1; + + if (sock_set_event(port_state, sock_state, ev) < 0) + return -1; + + port__update_events_if_polling(port_state); + + return 0; +} + +static int port__ctl_del(port_state_t* port_state, SOCKET sock) { + sock_state_t* sock_state = port_find_socket(port_state, sock); + if (sock_state == NULL) + return -1; + + sock_delete(port_state, sock_state); + + return 0; +} + +static int port__ctl_op(port_state_t* port_state, + int op, + SOCKET sock, + struct epoll_event* ev) { + switch (op) { + case EPOLL_CTL_ADD: + return port__ctl_add(port_state, sock, ev); + case EPOLL_CTL_MOD: + return port__ctl_mod(port_state, sock, ev); + case EPOLL_CTL_DEL: + return port__ctl_del(port_state, sock); + default: + return_set_error(-1, ERROR_INVALID_PARAMETER); + } +} + +int port_ctl(port_state_t* port_state, + int op, + SOCKET sock, + struct epoll_event* ev) { + int result; + + EnterCriticalSection(&port_state->lock); + result = port__ctl_op(port_state, op, sock, ev); + LeaveCriticalSection(&port_state->lock); + + return result; +} + +int port_register_socket(port_state_t* port_state, + sock_state_t* sock_state, + SOCKET socket) { + if (tree_add(&port_state->sock_tree, + sock_state_to_tree_node(sock_state), + socket) < 0) + return_set_error(-1, ERROR_ALREADY_EXISTS); + return 0; +} + +void port_unregister_socket(port_state_t* port_state, + sock_state_t* sock_state) { + tree_del(&port_state->sock_tree, sock_state_to_tree_node(sock_state)); +} + +sock_state_t* port_find_socket(port_state_t* port_state, SOCKET socket) { + tree_node_t* tree_node = tree_find(&port_state->sock_tree, socket); + if (tree_node == NULL) + return_set_error(NULL, ERROR_NOT_FOUND); + return sock_state_from_tree_node(tree_node); +} + +void port_request_socket_update(port_state_t* port_state, + sock_state_t* sock_state) { + if (queue_is_enqueued(sock_state_to_queue_node(sock_state))) + return; + queue_append(&port_state->sock_update_queue, + sock_state_to_queue_node(sock_state)); +} + +void port_cancel_socket_update(port_state_t* port_state, + sock_state_t* sock_state) { + unused_var(port_state); + if (!queue_is_enqueued(sock_state_to_queue_node(sock_state))) + return; + queue_remove(sock_state_to_queue_node(sock_state)); +} + +void port_add_deleted_socket(port_state_t* port_state, + sock_state_t* sock_state) { + if (queue_is_enqueued(sock_state_to_queue_node(sock_state))) + return; + queue_append(&port_state->sock_deleted_queue, + sock_state_to_queue_node(sock_state)); +} + +void port_remove_deleted_socket(port_state_t* port_state, + sock_state_t* sock_state) { + unused_var(port_state); + if (!queue_is_enqueued(sock_state_to_queue_node(sock_state))) + return; + queue_remove(sock_state_to_queue_node(sock_state)); +} + +HANDLE port_get_iocp_handle(port_state_t* port_state) { + assert(port_state->iocp_handle != NULL); + return port_state->iocp_handle; +} + +queue_t* port_get_poll_group_queue(port_state_t* port_state) { + return &port_state->poll_group_queue; +} + +port_state_t* port_state_from_handle_tree_node(ts_tree_node_t* tree_node) { + return container_of(tree_node, port_state_t, handle_tree_node); +} + +ts_tree_node_t* port_state_to_handle_tree_node(port_state_t* port_state) { + return &port_state->handle_tree_node; +} + +void queue_init(queue_t* queue) { + queue_node_init(&queue->head); +} + +void queue_node_init(queue_node_t* node) { + node->prev = node; + node->next = node; +} + +static inline void queue__detach_node(queue_node_t* node) { + node->prev->next = node->next; + node->next->prev = node->prev; +} + +queue_node_t* queue_first(const queue_t* queue) { + return !queue_is_empty(queue) ? queue->head.next : NULL; +} + +queue_node_t* queue_last(const queue_t* queue) { + return !queue_is_empty(queue) ? queue->head.prev : NULL; +} + +void queue_prepend(queue_t* queue, queue_node_t* node) { + node->next = queue->head.next; + node->prev = &queue->head; + node->next->prev = node; + queue->head.next = node; +} + +void queue_append(queue_t* queue, queue_node_t* node) { + node->next = &queue->head; + node->prev = queue->head.prev; + node->prev->next = node; + queue->head.prev = node; +} + +void queue_move_to_start(queue_t* queue, queue_node_t* node) { + queue__detach_node(node); + queue_prepend(queue, node); +} + +void queue_move_to_end(queue_t* queue, queue_node_t* node) { + queue__detach_node(node); + queue_append(queue, node); +} + +void queue_remove(queue_node_t* node) { + queue__detach_node(node); + queue_node_init(node); +} + +bool queue_is_empty(const queue_t* queue) { + return !queue_is_enqueued(&queue->head); +} + +bool queue_is_enqueued(const queue_node_t* node) { + return node->prev != node; +} + +static const long REFLOCK__REF = (long) 0x00000001; +static const long REFLOCK__REF_MASK = (long) 0x0fffffff; +static const long REFLOCK__DESTROY = (long) 0x10000000; +static const long REFLOCK__DESTROY_MASK = (long) 0xf0000000; +static const long REFLOCK__POISON = (long) 0x300dead0; + +static HANDLE reflock__keyed_event = NULL; + +int reflock_global_init(void) { + NTSTATUS status = NtCreateKeyedEvent( + &reflock__keyed_event, KEYEDEVENT_ALL_ACCESS, NULL, 0); + if (status != STATUS_SUCCESS) + return_set_error(-1, RtlNtStatusToDosError(status)); + return 0; +} + +void reflock_init(reflock_t* reflock) { + reflock->state = 0; +} + +static void reflock__signal_event(void* address) { + NTSTATUS status = + NtReleaseKeyedEvent(reflock__keyed_event, address, FALSE, NULL); + if (status != STATUS_SUCCESS) + abort(); +} + +static void reflock__await_event(void* address) { + NTSTATUS status = + NtWaitForKeyedEvent(reflock__keyed_event, address, FALSE, NULL); + if (status != STATUS_SUCCESS) + abort(); +} + +void reflock_ref(reflock_t* reflock) { + long state = InterlockedAdd(&reflock->state, REFLOCK__REF); + + /* Verify that the counter didn't overflow and the lock isn't destroyed. */ + assert((state & REFLOCK__DESTROY_MASK) == 0); + unused_var(state); +} + +void reflock_unref(reflock_t* reflock) { + long state = InterlockedAdd(&reflock->state, -REFLOCK__REF); + + /* Verify that the lock was referenced and not already destroyed. */ + assert((state & REFLOCK__DESTROY_MASK & ~REFLOCK__DESTROY) == 0); + + if (state == REFLOCK__DESTROY) + reflock__signal_event(reflock); +} + +void reflock_unref_and_destroy(reflock_t* reflock) { + long state = + InterlockedAdd(&reflock->state, REFLOCK__DESTROY - REFLOCK__REF); + long ref_count = state & REFLOCK__REF_MASK; + + /* Verify that the lock was referenced and not already destroyed. */ + assert((state & REFLOCK__DESTROY_MASK) == REFLOCK__DESTROY); + + if (ref_count != 0) + reflock__await_event(reflock); + + state = InterlockedExchange(&reflock->state, REFLOCK__POISON); + assert(state == REFLOCK__DESTROY); +} + +static const uint32_t SOCK__KNOWN_EPOLL_EVENTS = + EPOLLIN | EPOLLPRI | EPOLLOUT | EPOLLERR | EPOLLHUP | EPOLLRDNORM | + EPOLLRDBAND | EPOLLWRNORM | EPOLLWRBAND | EPOLLMSG | EPOLLRDHUP; + +typedef enum sock__poll_status { + SOCK__POLL_IDLE = 0, + SOCK__POLL_PENDING, + SOCK__POLL_CANCELLED +} sock__poll_status_t; + +typedef struct sock_state { + IO_STATUS_BLOCK io_status_block; + AFD_POLL_INFO poll_info; + queue_node_t queue_node; + tree_node_t tree_node; + poll_group_t* poll_group; + SOCKET base_socket; + epoll_data_t user_data; + uint32_t user_events; + uint32_t pending_events; + sock__poll_status_t poll_status; + bool delete_pending; +} sock_state_t; + +static inline sock_state_t* sock__alloc(void) { + sock_state_t* sock_state = malloc(sizeof *sock_state); + if (sock_state == NULL) + return_set_error(NULL, ERROR_NOT_ENOUGH_MEMORY); + return sock_state; +} + +static inline void sock__free(sock_state_t* sock_state) { + free(sock_state); +} + +static int sock__cancel_poll(sock_state_t* sock_state) { + assert(sock_state->poll_status == SOCK__POLL_PENDING); + + if (afd_cancel_poll(poll_group_get_afd_helper_handle(sock_state->poll_group), + &sock_state->io_status_block) < 0) + return -1; + + sock_state->poll_status = SOCK__POLL_CANCELLED; + sock_state->pending_events = 0; + return 0; +} + +sock_state_t* sock_new(port_state_t* port_state, SOCKET socket) { + SOCKET base_socket; + poll_group_t* poll_group; + sock_state_t* sock_state; + + if (socket == 0 || socket == INVALID_SOCKET) + return_set_error(NULL, ERROR_INVALID_HANDLE); + + base_socket = ws_get_base_socket(socket); + if (base_socket == INVALID_SOCKET) + return NULL; + + poll_group = poll_group_acquire(port_state); + if (poll_group == NULL) + return NULL; + + sock_state = sock__alloc(); + if (sock_state == NULL) + goto err1; + + memset(sock_state, 0, sizeof *sock_state); + + sock_state->base_socket = base_socket; + sock_state->poll_group = poll_group; + + tree_node_init(&sock_state->tree_node); + queue_node_init(&sock_state->queue_node); + + if (port_register_socket(port_state, sock_state, socket) < 0) + goto err2; + + return sock_state; + +err2: + sock__free(sock_state); +err1: + poll_group_release(poll_group); + + return NULL; +} + +static int sock__delete(port_state_t* port_state, + sock_state_t* sock_state, + bool force) { + if (!sock_state->delete_pending) { + if (sock_state->poll_status == SOCK__POLL_PENDING) + sock__cancel_poll(sock_state); + + port_cancel_socket_update(port_state, sock_state); + port_unregister_socket(port_state, sock_state); + + sock_state->delete_pending = true; + } + + /* If the poll request still needs to complete, the sock_state object can't + * be free()d yet. `sock_feed_event()` or `port_close()` will take care + * of this later. */ + if (force || sock_state->poll_status == SOCK__POLL_IDLE) { + /* Free the sock_state now. */ + port_remove_deleted_socket(port_state, sock_state); + poll_group_release(sock_state->poll_group); + sock__free(sock_state); + } else { + /* Free the socket later. */ + port_add_deleted_socket(port_state, sock_state); + } + + return 0; +} + +void sock_delete(port_state_t* port_state, sock_state_t* sock_state) { + sock__delete(port_state, sock_state, false); +} + +void sock_force_delete(port_state_t* port_state, sock_state_t* sock_state) { + sock__delete(port_state, sock_state, true); +} + +int sock_set_event(port_state_t* port_state, + sock_state_t* sock_state, + const struct epoll_event* ev) { + /* EPOLLERR and EPOLLHUP are always reported, even when not requested by the + * caller. However they are disabled after a event has been reported for a + * socket for which the EPOLLONESHOT flag as set. */ + uint32_t events = ev->events | EPOLLERR | EPOLLHUP; + + sock_state->user_events = events; + sock_state->user_data = ev->data; + + if ((events & SOCK__KNOWN_EPOLL_EVENTS & ~sock_state->pending_events) != 0) + port_request_socket_update(port_state, sock_state); + + return 0; +} + +static inline DWORD sock__epoll_events_to_afd_events(uint32_t epoll_events) { + /* Always monitor for AFD_POLL_LOCAL_CLOSE, which is triggered when the + * socket is closed with closesocket() or CloseHandle(). */ + DWORD afd_events = AFD_POLL_LOCAL_CLOSE; + + if (epoll_events & (EPOLLIN | EPOLLRDNORM)) + afd_events |= AFD_POLL_RECEIVE | AFD_POLL_ACCEPT; + if (epoll_events & (EPOLLPRI | EPOLLRDBAND)) + afd_events |= AFD_POLL_RECEIVE_EXPEDITED; + if (epoll_events & (EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND)) + afd_events |= AFD_POLL_SEND; + if (epoll_events & (EPOLLIN | EPOLLRDNORM | EPOLLRDHUP)) + afd_events |= AFD_POLL_DISCONNECT; + if (epoll_events & EPOLLHUP) + afd_events |= AFD_POLL_ABORT; + if (epoll_events & EPOLLERR) + afd_events |= AFD_POLL_CONNECT_FAIL; + + return afd_events; +} + +static inline uint32_t sock__afd_events_to_epoll_events(DWORD afd_events) { + uint32_t epoll_events = 0; + + if (afd_events & (AFD_POLL_RECEIVE | AFD_POLL_ACCEPT)) + epoll_events |= EPOLLIN | EPOLLRDNORM; + if (afd_events & AFD_POLL_RECEIVE_EXPEDITED) + epoll_events |= EPOLLPRI | EPOLLRDBAND; + if (afd_events & AFD_POLL_SEND) + epoll_events |= EPOLLOUT | EPOLLWRNORM | EPOLLWRBAND; + if (afd_events & AFD_POLL_DISCONNECT) + epoll_events |= EPOLLIN | EPOLLRDNORM | EPOLLRDHUP; + if (afd_events & AFD_POLL_ABORT) + epoll_events |= EPOLLHUP; + if (afd_events & AFD_POLL_CONNECT_FAIL) + /* Linux reports all these events after connect() has failed. */ + epoll_events |= + EPOLLIN | EPOLLOUT | EPOLLERR | EPOLLRDNORM | EPOLLWRNORM | EPOLLRDHUP; + + return epoll_events; +} + +int sock_update(port_state_t* port_state, sock_state_t* sock_state) { + assert(!sock_state->delete_pending); + + if ((sock_state->poll_status == SOCK__POLL_PENDING) && + (sock_state->user_events & SOCK__KNOWN_EPOLL_EVENTS & + ~sock_state->pending_events) == 0) { + /* All the events the user is interested in are already being monitored by + * the pending poll operation. It might spuriously complete because of an + * event that we're no longer interested in; when that happens we'll submit + * a new poll operation with the updated event mask. */ + + } else if (sock_state->poll_status == SOCK__POLL_PENDING) { + /* A poll operation is already pending, but it's not monitoring for all the + * events that the user is interested in. Therefore, cancel the pending + * poll operation; when we receive it's completion package, a new poll + * operation will be submitted with the correct event mask. */ + if (sock__cancel_poll(sock_state) < 0) + return -1; + + } else if (sock_state->poll_status == SOCK__POLL_CANCELLED) { + /* The poll operation has already been cancelled, we're still waiting for + * it to return. For now, there's nothing that needs to be done. */ + + } else if (sock_state->poll_status == SOCK__POLL_IDLE) { + /* No poll operation is pending; start one. */ + sock_state->poll_info.Exclusive = FALSE; + sock_state->poll_info.NumberOfHandles = 1; + sock_state->poll_info.Timeout.QuadPart = INT64_MAX; + sock_state->poll_info.Handles[0].Handle = (HANDLE) sock_state->base_socket; + sock_state->poll_info.Handles[0].Status = 0; + sock_state->poll_info.Handles[0].Events = + sock__epoll_events_to_afd_events(sock_state->user_events); + + if (afd_poll(poll_group_get_afd_helper_handle(sock_state->poll_group), + &sock_state->poll_info, + &sock_state->io_status_block) < 0) { + switch (GetLastError()) { + case ERROR_IO_PENDING: + /* Overlapped poll operation in progress; this is expected. */ + break; + case ERROR_INVALID_HANDLE: + /* Socket closed; it'll be dropped from the epoll set. */ + return sock__delete(port_state, sock_state, false); + default: + /* Other errors are propagated to the caller. */ + return_map_error(-1); + } + } + + /* The poll request was successfully submitted. */ + sock_state->poll_status = SOCK__POLL_PENDING; + sock_state->pending_events = sock_state->user_events; + + } else { + /* Unreachable. */ + assert(false); + } + + port_cancel_socket_update(port_state, sock_state); + return 0; +} + +int sock_feed_event(port_state_t* port_state, + IO_STATUS_BLOCK* io_status_block, + struct epoll_event* ev) { + sock_state_t* sock_state = + container_of(io_status_block, sock_state_t, io_status_block); + AFD_POLL_INFO* poll_info = &sock_state->poll_info; + uint32_t epoll_events = 0; + + sock_state->poll_status = SOCK__POLL_IDLE; + sock_state->pending_events = 0; + + if (sock_state->delete_pending) { + /* Socket has been deleted earlier and can now be freed. */ + return sock__delete(port_state, sock_state, false); + + } else if (io_status_block->Status == STATUS_CANCELLED) { + /* The poll request was cancelled by CancelIoEx. */ + + } else if (!NT_SUCCESS(io_status_block->Status)) { + /* The overlapped request itself failed in an unexpected way. */ + epoll_events = EPOLLERR; + + } else if (poll_info->NumberOfHandles < 1) { + /* This poll operation succeeded but didn't report any socket events. */ + + } else if (poll_info->Handles[0].Events & AFD_POLL_LOCAL_CLOSE) { + /* The poll operation reported that the socket was closed. */ + return sock__delete(port_state, sock_state, false); + + } else { + /* Events related to our socket were reported. */ + epoll_events = + sock__afd_events_to_epoll_events(poll_info->Handles[0].Events); + } + + /* Requeue the socket so a new poll request will be submitted. */ + port_request_socket_update(port_state, sock_state); + + /* Filter out events that the user didn't ask for. */ + epoll_events &= sock_state->user_events; + + /* Return if there are no epoll events to report. */ + if (epoll_events == 0) + return 0; + + /* If the the socket has the EPOLLONESHOT flag set, unmonitor all events, + * even EPOLLERR and EPOLLHUP. But always keep looking for closed sockets. */ + if (sock_state->user_events & EPOLLONESHOT) + sock_state->user_events = 0; + + ev->data = sock_state->user_data; + ev->events = epoll_events; + return 1; +} + +sock_state_t* sock_state_from_queue_node(queue_node_t* queue_node) { + return container_of(queue_node, sock_state_t, queue_node); +} + +queue_node_t* sock_state_to_queue_node(sock_state_t* sock_state) { + return &sock_state->queue_node; +} + +sock_state_t* sock_state_from_tree_node(tree_node_t* tree_node) { + return container_of(tree_node, sock_state_t, tree_node); +} + +tree_node_t* sock_state_to_tree_node(sock_state_t* sock_state) { + return &sock_state->tree_node; +} + +void ts_tree_init(ts_tree_t* ts_tree) { + tree_init(&ts_tree->tree); + InitializeSRWLock(&ts_tree->lock); +} + +void ts_tree_node_init(ts_tree_node_t* node) { + tree_node_init(&node->tree_node); + reflock_init(&node->reflock); +} + +int ts_tree_add(ts_tree_t* ts_tree, ts_tree_node_t* node, uintptr_t key) { + int r; + + AcquireSRWLockExclusive(&ts_tree->lock); + r = tree_add(&ts_tree->tree, &node->tree_node, key); + ReleaseSRWLockExclusive(&ts_tree->lock); + + return r; +} + +static inline ts_tree_node_t* ts_tree__find_node(ts_tree_t* ts_tree, + uintptr_t key) { + tree_node_t* tree_node = tree_find(&ts_tree->tree, key); + if (tree_node == NULL) + return NULL; + + return container_of(tree_node, ts_tree_node_t, tree_node); +} + +ts_tree_node_t* ts_tree_del_and_ref(ts_tree_t* ts_tree, uintptr_t key) { + ts_tree_node_t* ts_tree_node; + + AcquireSRWLockExclusive(&ts_tree->lock); + + ts_tree_node = ts_tree__find_node(ts_tree, key); + if (ts_tree_node != NULL) { + tree_del(&ts_tree->tree, &ts_tree_node->tree_node); + reflock_ref(&ts_tree_node->reflock); + } + + ReleaseSRWLockExclusive(&ts_tree->lock); + + return ts_tree_node; +} + +ts_tree_node_t* ts_tree_find_and_ref(ts_tree_t* ts_tree, uintptr_t key) { + ts_tree_node_t* ts_tree_node; + + AcquireSRWLockShared(&ts_tree->lock); + + ts_tree_node = ts_tree__find_node(ts_tree, key); + if (ts_tree_node != NULL) + reflock_ref(&ts_tree_node->reflock); + + ReleaseSRWLockShared(&ts_tree->lock); + + return ts_tree_node; +} + +void ts_tree_node_unref(ts_tree_node_t* node) { + reflock_unref(&node->reflock); +} + +void ts_tree_node_unref_and_destroy(ts_tree_node_t* node) { + reflock_unref_and_destroy(&node->reflock); +} + +void tree_init(tree_t* tree) { + memset(tree, 0, sizeof *tree); +} + +void tree_node_init(tree_node_t* node) { + memset(node, 0, sizeof *node); +} + +#define TREE__ROTATE(cis, trans) \ + tree_node_t* p = node; \ + tree_node_t* q = node->trans; \ + tree_node_t* parent = p->parent; \ + \ + if (parent) { \ + if (parent->left == p) \ + parent->left = q; \ + else \ + parent->right = q; \ + } else { \ + tree->root = q; \ + } \ + \ + q->parent = parent; \ + p->parent = q; \ + p->trans = q->cis; \ + if (p->trans) \ + p->trans->parent = p; \ + q->cis = p; + +static inline void tree__rotate_left(tree_t* tree, tree_node_t* node) { + TREE__ROTATE(left, right) +} + +static inline void tree__rotate_right(tree_t* tree, tree_node_t* node) { + TREE__ROTATE(right, left) +} + +#define TREE__INSERT_OR_DESCEND(side) \ + if (parent->side) { \ + parent = parent->side; \ + } else { \ + parent->side = node; \ + break; \ + } + +#define TREE__REBALANCE_AFTER_INSERT(cis, trans) \ + tree_node_t* grandparent = parent->parent; \ + tree_node_t* uncle = grandparent->trans; \ + \ + if (uncle && uncle->red) { \ + parent->red = uncle->red = false; \ + grandparent->red = true; \ + node = grandparent; \ + } else { \ + if (node == parent->trans) { \ + tree__rotate_##cis(tree, parent); \ + node = parent; \ + parent = node->parent; \ + } \ + parent->red = false; \ + grandparent->red = true; \ + tree__rotate_##trans(tree, grandparent); \ + } + +int tree_add(tree_t* tree, tree_node_t* node, uintptr_t key) { + tree_node_t* parent; + + parent = tree->root; + if (parent) { + for (;;) { + if (key < parent->key) { + TREE__INSERT_OR_DESCEND(left) + } else if (key > parent->key) { + TREE__INSERT_OR_DESCEND(right) + } else { + return -1; + } + } + } else { + tree->root = node; + } + + node->key = key; + node->left = node->right = NULL; + node->parent = parent; + node->red = true; + + for (; parent && parent->red; parent = node->parent) { + if (parent == parent->parent->left) { + TREE__REBALANCE_AFTER_INSERT(left, right) + } else { + TREE__REBALANCE_AFTER_INSERT(right, left) + } + } + tree->root->red = false; + + return 0; +} + +#define TREE__REBALANCE_AFTER_REMOVE(cis, trans) \ + tree_node_t* sibling = parent->trans; \ + \ + if (sibling->red) { \ + sibling->red = false; \ + parent->red = true; \ + tree__rotate_##cis(tree, parent); \ + sibling = parent->trans; \ + } \ + if ((sibling->left && sibling->left->red) || \ + (sibling->right && sibling->right->red)) { \ + if (!sibling->trans || !sibling->trans->red) { \ + sibling->cis->red = false; \ + sibling->red = true; \ + tree__rotate_##trans(tree, sibling); \ + sibling = parent->trans; \ + } \ + sibling->red = parent->red; \ + parent->red = sibling->trans->red = false; \ + tree__rotate_##cis(tree, parent); \ + node = tree->root; \ + break; \ + } \ + sibling->red = true; + +void tree_del(tree_t* tree, tree_node_t* node) { + tree_node_t* parent = node->parent; + tree_node_t* left = node->left; + tree_node_t* right = node->right; + tree_node_t* next; + bool red; + + if (!left) { + next = right; + } else if (!right) { + next = left; + } else { + next = right; + while (next->left) + next = next->left; + } + + if (parent) { + if (parent->left == node) + parent->left = next; + else + parent->right = next; + } else { + tree->root = next; + } + + if (left && right) { + red = next->red; + next->red = node->red; + next->left = left; + left->parent = next; + if (next != right) { + parent = next->parent; + next->parent = node->parent; + node = next->right; + parent->left = node; + next->right = right; + right->parent = next; + } else { + next->parent = parent; + parent = next; + node = next->right; + } + } else { + red = node->red; + node = next; + } + + if (node) + node->parent = parent; + if (red) + return; + if (node && node->red) { + node->red = false; + return; + } + + do { + if (node == tree->root) + break; + if (node == parent->left) { + TREE__REBALANCE_AFTER_REMOVE(left, right) + } else { + TREE__REBALANCE_AFTER_REMOVE(right, left) + } + node = parent; + parent = parent->parent; + } while (!node->red); + + if (node) + node->red = false; +} + +tree_node_t* tree_find(const tree_t* tree, uintptr_t key) { + tree_node_t* node = tree->root; + while (node) { + if (key < node->key) + node = node->left; + else if (key > node->key) + node = node->right; + else + return node; + } + return NULL; +} + +tree_node_t* tree_root(const tree_t* tree) { + return tree->root; +} + +#ifndef SIO_BSP_HANDLE_POLL +#define SIO_BSP_HANDLE_POLL 0x4800001D +#endif + +#ifndef SIO_BASE_HANDLE +#define SIO_BASE_HANDLE 0x48000022 +#endif + +int ws_global_init(void) { + int r; + WSADATA wsa_data; + + r = WSAStartup(MAKEWORD(2, 2), &wsa_data); + if (r != 0) + return_set_error(-1, (DWORD) r); + + return 0; +} + +static inline SOCKET ws__ioctl_get_bsp_socket(SOCKET socket, DWORD ioctl) { + SOCKET bsp_socket; + DWORD bytes; + + if (WSAIoctl(socket, + ioctl, + NULL, + 0, + &bsp_socket, + sizeof bsp_socket, + &bytes, + NULL, + NULL) != SOCKET_ERROR) + return bsp_socket; + else + return INVALID_SOCKET; +} + +SOCKET ws_get_base_socket(SOCKET socket) { + SOCKET base_socket; + DWORD error; + + for (;;) { + base_socket = ws__ioctl_get_bsp_socket(socket, SIO_BASE_HANDLE); + if (base_socket != INVALID_SOCKET) + return base_socket; + + error = GetLastError(); + if (error == WSAENOTSOCK) + return_set_error(INVALID_SOCKET, error); + + /* Even though Microsoft documentation clearly states that LSPs should + * never intercept the `SIO_BASE_HANDLE` ioctl [1], Komodia based LSPs do + * so anyway, breaking it, with the apparent intention of preventing LSP + * bypass [2]. Fortunately they don't handle `SIO_BSP_HANDLE_POLL`, which + * we can use to obtain the socket associated with the next protocol chain + * entry. If this succeeds, loop around and call `SIO_BASE_HANDLE` again + * with the retrieved BSP socket to be sure that we actually got all the + * way to the base. + * [1] https://docs.microsoft.com/en-us/windows/win32/winsock/winsock-ioctls + * [2] https://www.komodia.com/newwiki/index.php?title=Komodia%27s_Redirector_bug_fixes#Version_2.2.2.6 + */ + + base_socket = ws__ioctl_get_bsp_socket(socket, SIO_BSP_HANDLE_POLL); + if (base_socket != INVALID_SOCKET && base_socket != socket) + socket = base_socket; + else + return_set_error(INVALID_SOCKET, error); + } +} diff --git a/deps/zlib-1.2.11/CMakeLists.txt b/deps/zlib-1.2.11/CMakeLists.txt index 686e6fcff5c2c20815c97d6b976804b3c491527b..5502070819894480a0d7a7320d0f113cc545a0ce 100644 --- a/deps/zlib-1.2.11/CMakeLists.txt +++ b/deps/zlib-1.2.11/CMakeLists.txt @@ -1,8 +1,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF (TD_LINUX_64 OR TD_WINDOWS_64) +IF (TD_LINUX) INCLUDE_DIRECTORIES(inc) AUX_SOURCE_DIRECTORY(src SRC) ADD_LIBRARY(z ${SRC}) -ENDIF () +ENDIF () \ No newline at end of file diff --git a/src/balance/CMakeLists.txt b/src/balance/CMakeLists.txt index 45b7c4ed57c678d28bfd5d9e2734b2e5ff724fe3..d5d9ba1d9c6193f406d9b13b0ce9c76d6c08582d 100644 --- a/src/balance/CMakeLists.txt +++ b/src/balance/CMakeLists.txt @@ -1,16 +1,13 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - 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) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/mnode/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/dnode/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/sdb/inc) - INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/mnode/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/dnode/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/sdb/inc) +INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(src SRC) + +IF (TD_LINUX) ADD_LIBRARY(balance ${SRC}) -ENDIF () +ENDIF () \ No newline at end of file diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt index 987c309add49401923899123e613d14b1ebd644c..d5cbf3cab6d408914303e3c06230930bb59f734d 100644 --- a/src/client/CMakeLists.txt +++ b/src/client/CMakeLists.txt @@ -3,15 +3,10 @@ PROJECT(TDengine) INCLUDE_DIRECTORIES(inc) INCLUDE_DIRECTORIES(jni) -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/query/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) -INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) AUX_SOURCE_DIRECTORY(src SRC) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) +IF (TD_LINUX) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/jni/linux) # set the static lib name @@ -40,19 +35,18 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) ELSEIF (TD_WINDOWS) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/jni/windows) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/jni/windows/win32) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) ADD_LIBRARY(taos_static STATIC ${SRC}) - TARGET_LINK_LIBRARIES(taos_static trpc tutil) + TARGET_LINK_LIBRARIES(taos_static trpc tutil query) # generate dynamic library (*.dll) ADD_LIBRARY(taos SHARED ${SRC}) IF (NOT TD_GODLL) SET_TARGET_PROPERTIES(taos PROPERTIES LINK_FLAGS /DEF:${TD_COMMUNITY_DIR}/src/client/src/taos.def) ENDIF () - TARGET_LINK_LIBRARIES(taos trpc tutil) + TARGET_LINK_LIBRARIES(taos trpc tutil query) -ELSEIF (TD_DARWIN_64) +ELSEIF (TD_DARWIN) SET(CMAKE_MACOSX_RPATH 1) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/jni/linux) diff --git a/src/client/src/TSDBJNIConnector.c b/src/client/src/TSDBJNIConnector.c index eee255f55ba184652141dc1faf07e8b314ba0a8a..5036983424184c799f42169e2ec1dcf39bfc109f 100644 --- a/src/client/src/TSDBJNIConnector.c +++ b/src/client/src/TSDBJNIConnector.c @@ -224,7 +224,7 @@ JNIEXPORT jlong JNICALL Java_com_taosdata_jdbc_TSDBJNIConnector_connectImp(JNIEn */ tsNumOfThreadsPerCore = 0.0; - ret = (jlong)taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, jport); + ret = (jlong)taos_connect((char *)host, (char *)user, (char *)pass, (char *)dbname, (uint16_t)jport); if (ret == 0) { jniError("jobj:%p, conn:%p, connect to database failed, host=%s, user=%s, dbname=%s, port=%d", jobj, (void *)ret, (char *)host, (char *)user, (char *)dbname, jport); diff --git a/src/client/src/taos.def b/src/client/src/taos.def index 39906c7486dc242513f31028c367607fa0197dc9..df84ac657e73fe2a643d8c185e62b02a1a3cf4ad 100644 --- a/src/client/src/taos.def +++ b/src/client/src/taos.def @@ -1,11 +1,19 @@ EXPORTS taos_init +taos_cleanup taos_options taos_connect taos_close +taos_stmt_init +taos_stmt_prepare +taos_stmt_bind_param +taos_stmt_add_batch +taos_stmt_execute +taos_stmt_use_result +taos_stmt_close taos_query -taos_use_result taos_fetch_row +taos_result_precision taos_free_result taos_field_count taos_num_fields @@ -14,6 +22,9 @@ taos_fetch_fields taos_select_db taos_print_row taos_stop_query +taos_fetch_block +taos_validate_sql +taos_fetch_lengths taos_get_server_info taos_get_client_info taos_errstr @@ -27,5 +38,5 @@ taos_unsubscribe taos_open_stream taos_close_stream taos_fetch_block -taos_result_precision +taos_load_table_info diff --git a/src/client/src/tscAsync.c b/src/client/src/tscAsync.c index 85cff4ba17859fe0ca48ce1e5b9a280765e0c79a..759c6e5e1ea463cffe31d8fc007cf905b0638ef3 100644 --- a/src/client/src/tscAsync.c +++ b/src/client/src/tscAsync.c @@ -54,7 +54,7 @@ void doAsyncQuery(STscObj* pObj, SSqlObj* pSql, void (*fp)(), void* param, const return; } - strntolower(pSql->sqlstr, sqlstr, sqlLen); + strntolower(pSql->sqlstr, sqlstr, (int32_t)sqlLen); tscDebugL("%p SQL: %s", pSql, pSql->sqlstr); pSql->cmd.curSql = pSql->sqlstr; @@ -81,7 +81,7 @@ void taos_query_a(TAOS *taos, const char *sqlstr, __async_cb_func_t fp, void *pa return; } - int32_t sqlLen = strlen(sqlstr); + int32_t sqlLen = (int32_t)strlen(sqlstr); if (sqlLen > tsMaxSQLStringLen) { tscError("sql string exceeds max length:%d", tsMaxSQLStringLen); terrno = TSDB_CODE_TSC_INVALID_SQL; diff --git a/src/client/src/tscFunctionImpl.c b/src/client/src/tscFunctionImpl.c index e47d9b91e073603c1795484d14fd36e2aa2e6cac..d1f5b510a4917e7de83191e0dd3d8f8802a5cf0c 100644 --- a/src/client/src/tscFunctionImpl.c +++ b/src/client/src/tscFunctionImpl.c @@ -169,7 +169,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI // (uid, tid) + VGID + TAGSIZE + VARSTR_HEADER_SIZE if (functionId == TSDB_FUNC_TID_TAG) { // todo use struct *type = TSDB_DATA_TYPE_BINARY; - *bytes = dataBytes + sizeof(int64_t) + sizeof(int32_t) + sizeof(int32_t) + VARSTR_HEADER_SIZE; + *bytes = (int16_t)(dataBytes + sizeof(int64_t) + sizeof(int32_t) + sizeof(int32_t) + VARSTR_HEADER_SIZE); *interBytes = *bytes; return TSDB_CODE_SUCCESS; } @@ -198,7 +198,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI if (isSuperTable) { if (functionId == TSDB_FUNC_MIN || functionId == TSDB_FUNC_MAX) { *type = TSDB_DATA_TYPE_BINARY; - *bytes = dataBytes + DATA_SET_FLAG_SIZE; + *bytes = (int16_t)(dataBytes + DATA_SET_FLAG_SIZE); *interBytes = *bytes; return TSDB_CODE_SUCCESS; @@ -221,7 +221,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI return TSDB_CODE_SUCCESS; } else if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) { *type = TSDB_DATA_TYPE_BINARY; - *bytes = sizeof(STopBotInfo) + (sizeof(tValuePair) + POINTER_BYTES + extLength) * param; + *bytes = (int16_t)(sizeof(STopBotInfo) + (sizeof(tValuePair) + POINTER_BYTES + extLength) * param); *interBytes = *bytes; return TSDB_CODE_SUCCESS; @@ -239,7 +239,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI return TSDB_CODE_SUCCESS; } else if (functionId == TSDB_FUNC_LAST_ROW) { *type = TSDB_DATA_TYPE_BINARY; - *bytes = sizeof(SLastrowInfo) + dataBytes; + *bytes = (int16_t)(sizeof(SLastrowInfo) + dataBytes); *interBytes = *bytes; return TSDB_CODE_SUCCESS; @@ -308,7 +308,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI *interBytes = *bytes + sizeof(SResultInfo); } else if (functionId == TSDB_FUNC_FIRST_DST || functionId == TSDB_FUNC_LAST_DST) { *type = TSDB_DATA_TYPE_BINARY; - *bytes = dataBytes + sizeof(SFirstLastInfo); + *bytes = (int16_t)(dataBytes + sizeof(SFirstLastInfo)); *interBytes = *bytes; } else if (functionId == TSDB_FUNC_TOP || functionId == TSDB_FUNC_BOTTOM) { *type = (int16_t)dataType; @@ -317,7 +317,7 @@ int32_t getResultDataInfo(int32_t dataType, int32_t dataBytes, int32_t functionI size_t size = sizeof(STopBotInfo) + (sizeof(tValuePair) + POINTER_BYTES + extLength) * param; // the output column may be larger than sizeof(STopBotInfo) - *interBytes = size; + *interBytes = (int32_t)size; } else if (functionId == TSDB_FUNC_LAST_ROW) { *type = (int16_t)dataType; *bytes = (int16_t)dataBytes; @@ -947,11 +947,11 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin, if (pCtx->inputType == TSDB_DATA_TYPE_TINYINT) { int8_t *data = (int8_t *)pOutput; - UPDATE_DATA(pCtx, *data, val, notNullElems, isMin, key); + UPDATE_DATA(pCtx, *data, (int8_t)val, notNullElems, isMin, key); } else if (pCtx->inputType == TSDB_DATA_TYPE_SMALLINT) { int16_t *data = (int16_t *)pOutput; - UPDATE_DATA(pCtx, *data, val, notNullElems, isMin, key); + UPDATE_DATA(pCtx, *data, (int16_t)val, notNullElems, isMin, key); } else if (pCtx->inputType == TSDB_DATA_TYPE_INT) { int32_t *data = (int32_t *)pOutput; #if defined(_DEBUG_VIEW) @@ -959,7 +959,7 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin, #endif if ((*data < val) ^ isMin) { - *data = val; + *data = (int32_t)val; for (int32_t i = 0; i < (pCtx)->tagInfo.numOfTagCols; ++i) { SQLFunctionCtx *__ctx = pCtx->tagInfo.pTagCtxList[i]; if (__ctx->functionId == TSDB_FUNC_TS_DUMMY) { @@ -982,7 +982,7 @@ static void minMax_function(SQLFunctionCtx *pCtx, char *pOutput, int32_t isMin, float *data = (float *)pOutput; double val = GET_DOUBLE_VAL(tval); - UPDATE_DATA(pCtx, *data, val, notNullElems, isMin, key); + UPDATE_DATA(pCtx, *data, (float)val, notNullElems, isMin, key); } return; @@ -2040,7 +2040,7 @@ static void copyTopBotRes(SQLFunctionCtx *pCtx, int32_t type) { case TSDB_DATA_TYPE_INT: { int32_t *output = (int32_t *)pCtx->aOutputBuf; for (int32_t i = 0; i < len; ++i, output += step) { - *output = tvp[i]->v.i64Key; + *output = (int32_t)tvp[i]->v.i64Key; } break; } @@ -2061,21 +2061,21 @@ static void copyTopBotRes(SQLFunctionCtx *pCtx, int32_t type) { case TSDB_DATA_TYPE_FLOAT: { float *output = (float *)pCtx->aOutputBuf; for (int32_t i = 0; i < len; ++i, output += step) { - *output = tvp[i]->v.dKey; + *output = (float)tvp[i]->v.dKey; } break; } case TSDB_DATA_TYPE_SMALLINT: { int16_t *output = (int16_t *)pCtx->aOutputBuf; for (int32_t i = 0; i < len; ++i, output += step) { - *output = tvp[i]->v.i64Key; + *output = (int16_t)tvp[i]->v.i64Key; } break; } case TSDB_DATA_TYPE_TINYINT: { int8_t *output = (int8_t *)pCtx->aOutputBuf; for (int32_t i = 0; i < len; ++i, output += step) { - *output = tvp[i]->v.i64Key; + *output = (int8_t)tvp[i]->v.i64Key; } break; } @@ -2225,7 +2225,7 @@ static void top_function(SQLFunctionCtx *pCtx) { } notNullElems++; - do_top_function_add(pRes, pCtx->param[0].i64Key, data, pCtx->ptsList[i], pCtx->inputType, &pCtx->tagInfo, NULL, 0); + do_top_function_add(pRes, (int32_t)pCtx->param[0].i64Key, data, pCtx->ptsList[i], pCtx->inputType, &pCtx->tagInfo, NULL, 0); } if (!pCtx->hasNull) { @@ -2251,7 +2251,7 @@ static void top_function_f(SQLFunctionCtx *pCtx, int32_t index) { assert(pRes->num >= 0); SET_VAL(pCtx, 1, 1); - do_top_function_add(pRes, pCtx->param[0].i64Key, pData, pCtx->ptsList[index], pCtx->inputType, &pCtx->tagInfo, NULL, + do_top_function_add(pRes, (int32_t)pCtx->param[0].i64Key, pData, pCtx->ptsList[index], pCtx->inputType, &pCtx->tagInfo, NULL, 0); SResultInfo *pResInfo = GET_RES_INFO(pCtx); @@ -2275,7 +2275,7 @@ static void top_func_merge(SQLFunctionCtx *pCtx) { STopBotInfo *pOutput = getTopBotOutputInfo(pCtx); for (int32_t i = 0; i < pInput->num; ++i) { - do_top_function_add(pOutput, pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, + do_top_function_add(pOutput, (int32_t)pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, pCtx->inputType, &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); } } @@ -2291,7 +2291,7 @@ static void top_func_second_merge(SQLFunctionCtx *pCtx) { // the intermediate result is binary, we only use the output data type for (int32_t i = 0; i < pInput->num; ++i) { int16_t type = (pCtx->outputType == TSDB_DATA_TYPE_FLOAT)? TSDB_DATA_TYPE_DOUBLE:pCtx->outputType; - do_top_function_add(pOutput, pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, + do_top_function_add(pOutput, (int32_t)pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, type, &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); } @@ -2315,7 +2315,7 @@ static void bottom_function(SQLFunctionCtx *pCtx) { } notNullElems++; - do_bottom_function_add(pRes, pCtx->param[0].i64Key, data, pCtx->ptsList[i], pCtx->inputType, &pCtx->tagInfo, NULL, + do_bottom_function_add(pRes, (int32_t)pCtx->param[0].i64Key, data, pCtx->ptsList[i], pCtx->inputType, &pCtx->tagInfo, NULL, 0); } @@ -2340,7 +2340,7 @@ static void bottom_function_f(SQLFunctionCtx *pCtx, int32_t index) { STopBotInfo *pRes = getTopBotOutputInfo(pCtx); SET_VAL(pCtx, 1, 1); - do_bottom_function_add(pRes, pCtx->param[0].i64Key, pData, pCtx->ptsList[index], pCtx->inputType, &pCtx->tagInfo, + do_bottom_function_add(pRes, (int32_t)pCtx->param[0].i64Key, pData, pCtx->ptsList[index], pCtx->inputType, &pCtx->tagInfo, NULL, 0); SResultInfo *pResInfo = GET_RES_INFO(pCtx); @@ -2364,7 +2364,7 @@ static void bottom_func_merge(SQLFunctionCtx *pCtx) { STopBotInfo *pOutput = getTopBotOutputInfo(pCtx); for (int32_t i = 0; i < pInput->num; ++i) { - do_bottom_function_add(pOutput, pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, + do_bottom_function_add(pOutput, (int32_t)pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, pCtx->inputType, &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); } } @@ -2380,7 +2380,7 @@ static void bottom_func_second_merge(SQLFunctionCtx *pCtx) { // the intermediate result is binary, we only use the output data type for (int32_t i = 0; i < pInput->num; ++i) { int16_t type = (pCtx->outputType == TSDB_DATA_TYPE_FLOAT) ? TSDB_DATA_TYPE_DOUBLE : pCtx->outputType; - do_bottom_function_add(pOutput, pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, type, + do_bottom_function_add(pOutput, (int32_t)pCtx->param[0].i64Key, &pInput->res[i]->v.i64Key, pInput->res[i]->timestamp, type, &pCtx->tagInfo, pInput->res[i]->pTags, pCtx->currentStage); } @@ -2430,7 +2430,7 @@ static bool percentile_function_setup(SQLFunctionCtx *pCtx) { } SResultInfo *pResInfo = GET_RES_INFO(pCtx); - SSchema field[1] = {{pCtx->inputType, "dummyCol", 0, pCtx->inputBytes}}; + SSchema field[1] = { { (uint8_t)pCtx->inputType, "dummyCol", 0, pCtx->inputBytes } }; SColumnModel *pModel = createColumnModel(field, 1, 1000); int32_t orderIdx = 0; @@ -2543,7 +2543,7 @@ static void apercentile_function(SQLFunctionCtx *pCtx) { v = GET_INT16_VAL(data); break; case TSDB_DATA_TYPE_BIGINT: - v = GET_INT64_VAL(data); + v = (double)(GET_INT64_VAL(data)); break; case TSDB_DATA_TYPE_FLOAT: v = GET_FLOAT_VAL(data); @@ -2588,7 +2588,7 @@ static void apercentile_function_f(SQLFunctionCtx *pCtx, int32_t index) { v = GET_INT16_VAL(pData); break; case TSDB_DATA_TYPE_BIGINT: - v = GET_INT64_VAL(pData); + v = (double)(GET_INT64_VAL(pData)); break; case TSDB_DATA_TYPE_FLOAT: v = GET_FLOAT_VAL(pData); @@ -2875,7 +2875,7 @@ static void leastsquares_finalizer(SQLFunctionCtx *pCtx) { double(*param)[3] = pInfo->mat; - param[1][1] = pInfo->num; + param[1][1] = (double)pInfo->num; param[1][0] = param[0][1]; param[0][0] -= param[1][0] * (param[0][1] / param[1][1]); @@ -3027,13 +3027,13 @@ static void diff_function(SQLFunctionCtx *pCtx) { pCtx->param[1].i64Key = pData[i]; pCtx->param[1].nType = pCtx->inputType; } else if ((i == 0 && pCtx->order == TSDB_ORDER_ASC) || (i == pCtx->size - 1 && pCtx->order == TSDB_ORDER_DESC)) { - *pOutput = pData[i] - pCtx->param[1].i64Key; + *pOutput = (int32_t)(pData[i] - pCtx->param[1].i64Key); *pTimestamp = pCtx->ptsList[i]; pOutput += 1; pTimestamp += 1; } else { - *pOutput = pData[i] - pCtx->param[1].i64Key; // direct previous may be null + *pOutput = (int32_t)(pData[i] - pCtx->param[1].i64Key); // direct previous may be null *pTimestamp = pCtx->ptsList[i]; pOutput += 1; @@ -3121,13 +3121,13 @@ static void diff_function(SQLFunctionCtx *pCtx) { pCtx->param[1].dKey = pData[i]; pCtx->param[1].nType = pCtx->inputType; } else if ((i == 0 && pCtx->order == TSDB_ORDER_ASC) || (i == pCtx->size - 1 && pCtx->order == TSDB_ORDER_DESC)) { - *pOutput = pData[i] - pCtx->param[1].dKey; + *pOutput = (float)(pData[i] - pCtx->param[1].dKey); *pTimestamp = pCtx->ptsList[i]; pOutput += 1; pTimestamp += 1; } else { - *pOutput = pData[i] - pCtx->param[1].dKey; + *pOutput = (float)(pData[i] - pCtx->param[1].dKey); *pTimestamp = pCtx->ptsList[i]; pOutput += 1; @@ -3154,12 +3154,12 @@ static void diff_function(SQLFunctionCtx *pCtx) { pCtx->param[1].i64Key = pData[i]; pCtx->param[1].nType = pCtx->inputType; } else if ((i == 0 && pCtx->order == TSDB_ORDER_ASC) || (i == pCtx->size - 1 && pCtx->order == TSDB_ORDER_DESC)) { - *pOutput = pData[i] - pCtx->param[1].i64Key; + *pOutput = (int16_t)(pData[i] - pCtx->param[1].i64Key); *pTimestamp = pCtx->ptsList[i]; pOutput += 1; pTimestamp += 1; } else { - *pOutput = pData[i] - pCtx->param[1].i64Key; + *pOutput = (int16_t)(pData[i] - pCtx->param[1].i64Key); *pTimestamp = pCtx->ptsList[i]; pOutput += 1; @@ -3185,13 +3185,13 @@ static void diff_function(SQLFunctionCtx *pCtx) { pCtx->param[1].i64Key = pData[i]; pCtx->param[1].nType = pCtx->inputType; } else if ((i == 0 && pCtx->order == TSDB_ORDER_ASC) || (i == pCtx->size - 1 && pCtx->order == TSDB_ORDER_DESC)) { - *pOutput = pData[i] - pCtx->param[1].i64Key; + *pOutput = (int8_t)(pData[i] - pCtx->param[1].i64Key); *pTimestamp = pCtx->ptsList[i]; pOutput += 1; pTimestamp += 1; } else { - *pOutput = pData[i] - pCtx->param[1].i64Key; + *pOutput = (int8_t)(pData[i] - pCtx->param[1].i64Key); *pTimestamp = pCtx->ptsList[i]; pOutput += 1; @@ -3256,7 +3256,7 @@ static void diff_function_f(SQLFunctionCtx *pCtx, int32_t index) { pCtx->param[1].nType = pCtx->inputType; pCtx->param[1].i64Key = *(int32_t *)pData; } else { - *(int32_t *)pCtx->aOutputBuf = *(int32_t *)pData - pCtx->param[1].i64Key; + *(int32_t *)pCtx->aOutputBuf = *(int32_t *)pData - (int32_t)pCtx->param[1].i64Key; pCtx->param[1].i64Key = *(int32_t *)pData; *(int64_t *)pCtx->ptsOutputBuf = pCtx->ptsList[index]; } @@ -3335,10 +3335,10 @@ static void arithmetic_function_f(SQLFunctionCtx *pCtx, int32_t index) { continue; \ } \ if (inputData[i] < minOutput) { \ - minOutput = inputData[i]; \ + minOutput = (double)inputData[i]; \ } \ if (inputData[i] > maxOutput) { \ - maxOutput = inputData[i]; \ + maxOutput = (double)inputData[i]; \ } \ numOfNotNullElem++; \ } \ @@ -3383,11 +3383,11 @@ static void spread_function(SQLFunctionCtx *pCtx) { if ((pCtx->inputType >= TSDB_DATA_TYPE_TINYINT && pCtx->inputType <= TSDB_DATA_TYPE_BIGINT) || (pCtx->inputType == TSDB_DATA_TYPE_TIMESTAMP)) { if (pInfo->min > pCtx->preAggVals.statis.min) { - pInfo->min = pCtx->preAggVals.statis.min; + pInfo->min = (double)pCtx->preAggVals.statis.min; } if (pInfo->max < pCtx->preAggVals.statis.max) { - pInfo->max = pCtx->preAggVals.statis.max; + pInfo->max = (double)pCtx->preAggVals.statis.max; } } else if (pCtx->inputType == TSDB_DATA_TYPE_DOUBLE || pCtx->inputType == TSDB_DATA_TYPE_FLOAT) { if (pInfo->min > GET_DOUBLE_VAL(&(pCtx->preAggVals.statis.min))) { @@ -3456,7 +3456,7 @@ static void spread_function_f(SQLFunctionCtx *pCtx, int32_t index) { } else if (pCtx->inputType == TSDB_DATA_TYPE_INT) { val = GET_INT32_VAL(pData); } else if (pCtx->inputType == TSDB_DATA_TYPE_BIGINT || pCtx->inputType == TSDB_DATA_TYPE_TIMESTAMP) { - val = GET_INT64_VAL(pData); + val = (double)(GET_INT64_VAL(pData)); } else if (pCtx->inputType == TSDB_DATA_TYPE_DOUBLE) { val = GET_DOUBLE_VAL(pData); } else if (pCtx->inputType == TSDB_DATA_TYPE_FLOAT) { diff --git a/src/client/src/tscLocal.c b/src/client/src/tscLocal.c index a8f287d499b8ffa4f7ef72e5f8a89b738c01769a..a56a01ba02a2206c632aa5d2fd11cf6c877f4769 100644 --- a/src/client/src/tscLocal.c +++ b/src/client/src/tscLocal.c @@ -223,12 +223,12 @@ static int32_t tscBuildTableSchemaResultFields(SSqlObj *pSql, int32_t numOfCols, rowLen += ((TSDB_COL_NAME_LEN - 1) + VARSTR_HEADER_SIZE); - f.bytes = typeColLength + VARSTR_HEADER_SIZE; + f.bytes = (int16_t)(typeColLength + VARSTR_HEADER_SIZE); f.type = TSDB_DATA_TYPE_BINARY; tstrncpy(f.name, "Type", sizeof(f.name)); pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f); - pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, typeColLength + VARSTR_HEADER_SIZE, + pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, (int16_t)(typeColLength + VARSTR_HEADER_SIZE), typeColLength, false); rowLen += typeColLength + VARSTR_HEADER_SIZE; @@ -243,12 +243,12 @@ static int32_t tscBuildTableSchemaResultFields(SSqlObj *pSql, int32_t numOfCols, rowLen += sizeof(int32_t); - f.bytes = noteColLength + VARSTR_HEADER_SIZE; + f.bytes = (int16_t)(noteColLength + VARSTR_HEADER_SIZE); f.type = TSDB_DATA_TYPE_BINARY; tstrncpy(f.name, "Note", sizeof(f.name)); pInfo = tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f); - pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, noteColLength + VARSTR_HEADER_SIZE, + pInfo->pSqlExpr = tscSqlExprAppend(pQueryInfo, TSDB_FUNC_TS_DUMMY, &index, TSDB_DATA_TYPE_BINARY, (int16_t)(noteColLength + VARSTR_HEADER_SIZE), noteColLength, false); rowLen += noteColLength + VARSTR_HEADER_SIZE; @@ -305,7 +305,7 @@ static void tscProcessCurrentDB(SSqlObj *pSql) { if (t == 0) { setVardataNull(vx, TSDB_DATA_TYPE_BINARY); } else { - STR_WITH_SIZE_TO_VARSTR(vx, db, t); + STR_WITH_SIZE_TO_VARSTR(vx, db, (VarDataLenT)t); } tscSetLocalQueryResult(pSql, vx, pExpr->aliasName, pExpr->resType, pExpr->resBytes); @@ -320,10 +320,10 @@ static void tscProcessServerVer(SSqlObj *pSql) { pExpr->resType = TSDB_DATA_TYPE_BINARY; size_t t = strlen(v); - pExpr->resBytes = t + VARSTR_HEADER_SIZE; + pExpr->resBytes = (int16_t)(t + VARSTR_HEADER_SIZE); char* vx = calloc(1, pExpr->resBytes); - STR_WITH_SIZE_TO_VARSTR(vx, v, t); + STR_WITH_SIZE_TO_VARSTR(vx, v, (VarDataLenT)t); tscSetLocalQueryResult(pSql, vx, pExpr->aliasName, pExpr->resType, pExpr->resBytes); taosTFree(vx); @@ -336,10 +336,10 @@ static void tscProcessClientVer(SSqlObj *pSql) { pExpr->resType = TSDB_DATA_TYPE_BINARY; size_t t = strlen(version); - pExpr->resBytes = t + VARSTR_HEADER_SIZE; + pExpr->resBytes = (int16_t)(t + VARSTR_HEADER_SIZE); char* v = calloc(1, pExpr->resBytes); - STR_WITH_SIZE_TO_VARSTR(v, version, t); + STR_WITH_SIZE_TO_VARSTR(v, version, (VarDataLenT)t); tscSetLocalQueryResult(pSql, v, pExpr->aliasName, pExpr->resType, pExpr->resBytes); taosTFree(v); @@ -379,10 +379,10 @@ void tscSetLocalQueryResult(SSqlObj *pSql, const char *val, const char *columnNa pQueryInfo->fieldsInfo.pFields = taosArrayInit(1, sizeof(TAOS_FIELD)); pQueryInfo->fieldsInfo.pSupportInfo = taosArrayInit(1, sizeof(SFieldSupInfo)); - TAOS_FIELD f = tscCreateField(type, columnName, valueLength); + TAOS_FIELD f = tscCreateField((int8_t)type, columnName, (int16_t)valueLength); tscFieldInfoAppend(&pQueryInfo->fieldsInfo, &f); - tscInitResObjForLocalQuery(pSql, 1, valueLength); + tscInitResObjForLocalQuery(pSql, 1, (int32_t)valueLength); TAOS_FIELD *pField = tscFieldInfoGetField(&pQueryInfo->fieldsInfo, 0); SFieldSupInfo* pInfo = tscFieldInfoGetSupp(&pQueryInfo->fieldsInfo, 0); diff --git a/src/client/src/tscLocalMerge.c b/src/client/src/tscLocalMerge.c index 394b7257810bf3b6446ce60c4c26166dbfeab342..b7d8a0b7b26fb66ecb1f14f7f63c7b0f10bc2d98 100644 --- a/src/client/src/tscLocalMerge.c +++ b/src/client/src/tscLocalMerge.c @@ -133,7 +133,7 @@ static void tscInitSqlContext(SSqlCmd *pCmd, SLocalReducer *pReducer, tOrderDesc } static SFillColInfo* createFillColInfo(SQueryInfo* pQueryInfo) { - int32_t numOfCols = tscSqlExprNumOfExprs(pQueryInfo); + int32_t numOfCols = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); int32_t offset = 0; SFillColInfo* pFillCol = calloc(numOfCols, sizeof(SFillColInfo)); @@ -141,7 +141,7 @@ static SFillColInfo* createFillColInfo(SQueryInfo* pQueryInfo) { SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i); pFillCol[i].col.bytes = pExpr->resBytes; - pFillCol[i].col.type = pExpr->resType; + pFillCol[i].col.type = (int8_t)pExpr->resType; pFillCol[i].flag = pExpr->colInfo.flag; pFillCol[i].col.offset = offset; pFillCol[i].functionId = pExpr->functionId; @@ -361,7 +361,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd pQueryInfo->limit.offset = pQueryInfo->prjOffset; } - pReducer->offset = pQueryInfo->limit.offset; + pReducer->offset = (int32_t)pQueryInfo->limit.offset; pRes->pLocalReducer = pReducer; pRes->numOfGroups = 0; @@ -376,7 +376,7 @@ void tscCreateLocalReducer(tExtMemBuffer **pMemBuffer, int32_t numOfBuffer, tOrd if (pQueryInfo->fillType != TSDB_FILL_NONE) { SFillColInfo* pFillCol = createFillColInfo(pQueryInfo); pReducer->pFillInfo = taosInitFillInfo(pQueryInfo->order.order, revisedSTime, pQueryInfo->groupbyExpr.numOfGroupCols, - 4096, numOfCols, pQueryInfo->slidingTime, pQueryInfo->slidingTimeUnit, + 4096, (int32_t)numOfCols, pQueryInfo->slidingTime, pQueryInfo->slidingTimeUnit, tinfo.precision, pQueryInfo->fillType, pFillCol); } @@ -405,7 +405,7 @@ static int32_t tscFlushTmpBufferImpl(tExtMemBuffer *pMemoryBuf, tOrderDescriptor // sort before flush to disk, the data must be consecutively put on tFilePage. if (pDesc->orderInfo.numOfCols > 0) { - tColDataQSort(pDesc, pPage->num, 0, pPage->num - 1, pPage->data, orderType); + tColDataQSort(pDesc, (int32_t)pPage->num, 0, (int32_t)pPage->num - 1, pPage->data, orderType); } #ifdef _DEBUG_VIEW @@ -414,7 +414,7 @@ static int32_t tscFlushTmpBufferImpl(tExtMemBuffer *pMemoryBuf, tOrderDescriptor #endif // write to cache after being sorted - if (tExtMemBufferPut(pMemoryBuf, pPage->data, pPage->num) < 0) { + if (tExtMemBufferPut(pMemoryBuf, pPage->data, (int32_t)pPage->num) < 0) { tscError("failed to save data in temporary buffer"); return -1; } @@ -446,7 +446,7 @@ int32_t saveToBuffer(tExtMemBuffer *pMemoryBuf, tOrderDescriptor *pDesc, tFilePa } // current buffer is overflow, flush data to extensive buffer - int32_t numOfRemainEntries = pModel->capacity - pPage->num; + int32_t numOfRemainEntries = pModel->capacity - (int32_t)pPage->num; tColModelAppend(pModel, pPage, data, 0, numOfRemainEntries, numOfRows); // current buffer is full, need to flushed to disk @@ -679,7 +679,7 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr SSqlExpr *pExpr = tscSqlExprGet(pQueryInfo, i); pSchema[i].bytes = pExpr->resBytes; - pSchema[i].type = pExpr->resType; + pSchema[i].type = (int8_t)pExpr->resType; rlen += pExpr->resBytes; } @@ -689,7 +689,7 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr capacity = nBufferSizes / rlen; } - pModel = createColumnModel(pSchema, size, capacity); + pModel = createColumnModel(pSchema, (int32_t)size, capacity); int32_t pg = DEFAULT_PAGE_SIZE; int32_t overhead = sizeof(tFilePage); @@ -740,12 +740,12 @@ int32_t tscLocalReducerEnvCreate(SSqlObj *pSql, tExtMemBuffer ***pMemBuffer, tOr getResultDataInfo(p1->type, p1->bytes, functionId, 0, &type, &bytes, &inter, 0, false); } - pSchema[i].type = type; + pSchema[i].type = (uint8_t)type; pSchema[i].bytes = bytes; strcpy(pSchema[i].name, pModel->pFields[i].field.name); } - *pFinalModel = createColumnModel(pSchema, size, capacity); + *pFinalModel = createColumnModel(pSchema, (int32_t)size, capacity); taosTFree(pSchema); return TSDB_CODE_SUCCESS; @@ -780,7 +780,7 @@ int32_t loadNewDataFromDiskFor(SLocalReducer *pLocalReducer, SLocalDataSource *p pOneInterDataSrc->rowIdx = 0; pOneInterDataSrc->pageId += 1; - if (pOneInterDataSrc->pageId < + if ((uint32_t)pOneInterDataSrc->pageId < pOneInterDataSrc->pMemBuffer->fileMeta.flushoutData.pFlushoutInfo[pOneInterDataSrc->flushoutIdx].numOfPages) { tExtMemBufferLoadData(pOneInterDataSrc->pMemBuffer, &(pOneInterDataSrc->filePage), pOneInterDataSrc->flushoutIdx, pOneInterDataSrc->pageId); @@ -924,8 +924,8 @@ static void doFillResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool doneO if (pQueryInfo->limit.offset > 0) { if (pQueryInfo->limit.offset < pRes->numOfRows) { - int32_t prevSize = pFinalDataPage->num; - tColModelErase(pLocalReducer->resColModel, pFinalDataPage, prevSize, 0, pQueryInfo->limit.offset - 1); + int32_t prevSize = (int32_t)pFinalDataPage->num; + tColModelErase(pLocalReducer->resColModel, pFinalDataPage, prevSize, 0, (int32_t)pQueryInfo->limit.offset - 1); /* remove the hole in column model */ tColModelCompact(pLocalReducer->resColModel, pFinalDataPage, prevSize); @@ -942,8 +942,8 @@ static void doFillResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool doneO if (pQueryInfo->limit.limit >= 0 && pRes->numOfClauseTotal > pQueryInfo->limit.limit) { /* impose the limitation of output rows on the final result */ - int32_t prevSize = pFinalDataPage->num; - int32_t overflow = pRes->numOfClauseTotal - pQueryInfo->limit.limit; + int32_t prevSize = (int32_t)pFinalDataPage->num; + int32_t overflow = (int32_t)(pRes->numOfClauseTotal - pQueryInfo->limit.limit); assert(overflow < pRes->numOfRows); pRes->numOfClauseTotal = pQueryInfo->limit.limit; @@ -1001,7 +1001,7 @@ static void doFillResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool doneO } /* all output for current group are completed */ - int32_t totalRemainRows = getFilledNumOfRes(pFillInfo, actualETime, pLocalReducer->resColModel->capacity); + int32_t totalRemainRows = (int32_t)getFilledNumOfRes(pFillInfo, actualETime, pLocalReducer->resColModel->capacity); if (totalRemainRows <= 0) { break; } @@ -1011,7 +1011,7 @@ static void doFillResult(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool doneO if (pRes->numOfRows > 0) { if (pQueryInfo->limit.limit >= 0 && pRes->numOfClauseTotal > pQueryInfo->limit.limit) { - int32_t overflow = pRes->numOfClauseTotal - pQueryInfo->limit.limit; + int32_t overflow = (int32_t)(pRes->numOfClauseTotal - pQueryInfo->limit.limit); pRes->numOfRows -= overflow; assert(pRes->numOfRows >= 0); @@ -1279,7 +1279,7 @@ bool doGenerateFinalResults(SSqlObj *pSql, SLocalReducer *pLocalReducer, bool no SFillInfo* pFillInfo = pLocalReducer->pFillInfo; if (pFillInfo != NULL) { - taosFillSetStartInfo(pFillInfo, pResBuf->num, pQueryInfo->window.ekey); + taosFillSetStartInfo(pFillInfo, (int32_t)pResBuf->num, pQueryInfo->window.ekey); taosFillCopyInputDataFromOneFilePage(pFillInfo, pResBuf); } @@ -1338,7 +1338,7 @@ static bool doBuildFilledResultForGroup(SSqlObj *pSql) { int64_t etime = *(int64_t *)(pFinalDataBuf->data + TSDB_KEYSIZE * (pFillInfo->numOfRows - 1)); // the first column must be the timestamp column - int32_t rows = getFilledNumOfRes(pFillInfo, etime, pLocalReducer->resColModel->capacity); + int32_t rows = (int32_t)getFilledNumOfRes(pFillInfo, etime, pLocalReducer->resColModel->capacity); if (rows > 0) { // do fill gap doFillResult(pSql, pLocalReducer, false); } @@ -1367,7 +1367,7 @@ static bool doHandleLastRemainData(SSqlObj *pSql) { int64_t etime = (pQueryInfo->window.skey < pQueryInfo->window.ekey) ? pQueryInfo->window.ekey : pQueryInfo->window.skey; assert(pFillInfo->numOfRows == 0); - int32_t rows = getFilledNumOfRes(pFillInfo, etime, pLocalReducer->resColModel->capacity); + int32_t rows = (int32_t)getFilledNumOfRes(pFillInfo, etime, pLocalReducer->resColModel->capacity); if (rows > 0) { // do interpo doFillResult(pSql, pLocalReducer, true); } diff --git a/src/client/src/tscParseInsert.c b/src/client/src/tscParseInsert.c index 2f245ee513cf1b28abc989f83ec327512ef898ff..33c87996245ece6d5483845b96f1c2ce4d484806 100644 --- a/src/client/src/tscParseInsert.c +++ b/src/client/src/tscParseInsert.c @@ -61,7 +61,7 @@ static int32_t tscToInteger(SSQLToken *pToken, int64_t *value, char **endPtr) { if (v > INT64_MAX || v <= INT64_MIN) { errno = ERANGE; } else { - *value = v; + *value = (int64_t)v; } } @@ -426,7 +426,7 @@ int tsParseOneRowData(char **str, STableDataBlocks *pDataBlocks, SSchema schema[ *str += index; if (sToken.type == TK_QUESTION) { - uint32_t offset = start - pDataBlocks->pData; + uint32_t offset = (uint32_t)(start - pDataBlocks->pData); if (tscAddParamToDataBlock(pDataBlocks, pSchema->type, (uint8_t)timePrec, pSchema->bytes, offset) != NULL) { continue; } @@ -450,7 +450,7 @@ int tsParseOneRowData(char **str, STableDataBlocks *pDataBlocks, SSchema schema[ char delim = sToken.z[0]; int32_t cnt = 0; int32_t j = 0; - for (int32_t k = 1; k < sToken.n - 1; ++k) { + for (uint32_t k = 1; k < sToken.n - 1; ++k) { if (sToken.z[k] == delim || sToken.z[k] == '\\') { if (sToken.z[k + 1] == delim) { cnt++; @@ -504,7 +504,7 @@ int tsParseOneRowData(char **str, STableDataBlocks *pDataBlocks, SSchema schema[ ptr += schema[i].bytes; } - rowSize = ptr - payload; + rowSize = (int32_t)(ptr - payload); } return rowSize; @@ -846,7 +846,7 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql) { if (TK_STRING == sToken.type) { strdequote(sToken.z); - sToken.n = strtrim(sToken.z); + sToken.n = (uint32_t)strtrim(sToken.z); } if (sToken.type == TK_RP) { @@ -972,7 +972,7 @@ static int32_t tscCheckIfCreateTable(char **sqlstr, SSqlObj *pSql) { } } - int32_t len = cend - cstart + 1; + int32_t len = (int32_t)(cend - cstart + 1); if (cstart != NULL && createTable == true) { /* move the column list to start position of the next accessed points */ memmove(sql - len, cstart, len); @@ -1188,7 +1188,7 @@ int tsParseInsertSql(SSqlObj *pSql) { if (TK_STRING == sToken.type) { strdequote(sToken.z); - sToken.n = strtrim(sToken.z); + sToken.n = (uint32_t)strtrim(sToken.z); } if (sToken.type == TK_RP) { @@ -1426,7 +1426,7 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int code) { char *tokenBuf = calloc(1, 4096); - while ((readLen = getline(&line, &n, fp)) != -1) { + while ((readLen = taosGetline(&line, &n, fp)) != -1) { if (('\r' == line[readLen - 1]) || ('\n' == line[readLen - 1])) { line[--readLen] = 0; } @@ -1471,7 +1471,7 @@ static void parseFileSendDataBlock(void *param, TAOS_RES *tres, int code) { pParentSql->fp = pParentSql->fetchFp; // all data has been sent to vnode, call user function - int32_t v = (pParentSql->res.code != TSDB_CODE_SUCCESS) ? pParentSql->res.code : pParentSql->res.numOfRows; + int32_t v = (pParentSql->res.code != TSDB_CODE_SUCCESS) ? pParentSql->res.code : (int32_t)pParentSql->res.numOfRows; (*pParentSql->fp)(pParentSql->param, pParentSql, v); } } diff --git a/src/client/src/tscProfile.c b/src/client/src/tscProfile.c index 363243b1d7a427fa1d1b4b0dc8a5a0273ba51396..f48e7b7691536cb8f9a5b8561e95b8a5a0f0fefc 100644 --- a/src/client/src/tscProfile.c +++ b/src/client/src/tscProfile.c @@ -96,7 +96,7 @@ void tscSaveSlowQuery(SSqlObj *pSql) { } tscDebug("%p query time:%" PRId64 " sql:%s", pSql, pSql->res.useconds, pSql->sqlstr); - int32_t sqlSize = TSDB_SLOW_QUERY_SQL_LEN + size; + int32_t sqlSize = (int32_t)(TSDB_SLOW_QUERY_SQL_LEN + size); char *sql = malloc(sqlSize); if (sql == NULL) { diff --git a/src/client/src/tscSQLParser.c b/src/client/src/tscSQLParser.c index 4e0c238ac07f7d0a666f0be3cd1ba238f4abb0e1..bc33aac174efba65b6ca3ec26db3286b1b6ab51b 100644 --- a/src/client/src/tscSQLParser.c +++ b/src/client/src/tscSQLParser.c @@ -161,7 +161,7 @@ static int32_t handlePassword(SSqlCmd* pCmd, SSQLToken* pPwd) { } strdequote(pPwd->z); - pPwd->n = strtrim(pPwd->z); // trim space before and after passwords + pPwd->n = (uint32_t)strtrim(pPwd->z); // trim space before and after passwords if (pPwd->n <= 0) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg1); @@ -1029,12 +1029,12 @@ static char* getAccountId(SSqlObj* pSql) { return pSql->pTscObj->acctId; } static void getCurrentDBName(SSqlObj* pSql, SSQLToken* pDBToken) { pDBToken->z = pSql->pTscObj->db; - pDBToken->n = strlen(pSql->pTscObj->db); + pDBToken->n = (uint32_t)strlen(pSql->pTscObj->db); } /* length limitation, strstr cannot be applied */ static bool hasSpecifyDB(SSQLToken* pTableName) { - for (int32_t i = 0; i < pTableName->n; ++i) { + for (uint32_t i = 0; i < pTableName->n; ++i) { if (pTableName->z[i] == TS_PATH_DELIMITER[0]) { return true; } @@ -1047,7 +1047,7 @@ int32_t setObjFullName(char* fullName, const char* account, SSQLToken* pDB, SSQL int32_t totalLen = 0; if (account != NULL) { - int32_t len = strlen(account); + int32_t len = (int32_t)strlen(account); strcpy(fullName, account); fullName[len] = TS_PATH_DELIMITER[0]; totalLen += (len + 1); @@ -1122,7 +1122,7 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel } for (int32_t i = 0; i < pSelection->nExpr; ++i) { - int32_t outputIndex = tscSqlExprNumOfExprs(pQueryInfo); + int32_t outputIndex = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); tSQLExprItem* pItem = &pSelection->a[i]; // project on all fields @@ -1205,7 +1205,7 @@ int32_t parseSelectClause(SSqlCmd* pCmd, int32_t clauseIndex, tSQLExprList* pSel char* c = tbufGetData(&bw, true); // set the serialized binary string as the parameter of arithmetic expression - addExprParams(pExpr, c, TSDB_DATA_TYPE_BINARY, len, index.tableIndex); + addExprParams(pExpr, c, TSDB_DATA_TYPE_BINARY, (int32_t)len, index.tableIndex); insertResultField(pQueryInfo, i, &columnList, sizeof(double), TSDB_DATA_TYPE_DOUBLE, pExpr->aliasName, pExpr); @@ -1332,7 +1332,7 @@ static void addProjectQueryCol(SQueryInfo* pQueryInfo, int32_t startPos, SColumn ids.num = 0; } - insertResultField(pQueryInfo, startPos, &ids, pExpr->resBytes, pExpr->resType, pExpr->aliasName, pExpr); + insertResultField(pQueryInfo, startPos, &ids, pExpr->resBytes, (int8_t)pExpr->resType, pExpr->aliasName, pExpr); } void tscAddSpecialColumnForSelect(SQueryInfo* pQueryInfo, int32_t outputColIndex, int16_t functionId, @@ -1395,7 +1395,7 @@ int32_t addProjectionExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, t const char* msg0 = "invalid column name"; const char* msg1 = "tag for normal table query is not allowed"; - int32_t startPos = tscSqlExprNumOfExprs(pQueryInfo); + int32_t startPos = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); if (pItem->pNode->nSQLOptr == TK_ALL) { // project on all fields SColumnIndex index = COLUMN_INDEX_INITIALIZER; @@ -1486,7 +1486,7 @@ static int32_t setExprInfoForFunctions(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SS tscColumnListInsert(pQueryInfo->colList, &index); SColumnList ids = getColumnList(1, pColIndex->tableIndex, pColIndex->columnIndex); - insertResultField(pQueryInfo, resColIdx, &ids, bytes, type, columnName, pExpr); + insertResultField(pQueryInfo, resColIdx, &ids, bytes, (int8_t)type, columnName, pExpr); return TSDB_CODE_SUCCESS; } @@ -1684,7 +1684,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col if (finalResult) { int32_t numOfOutput = tscNumOfFields(pQueryInfo); - insertResultField(pQueryInfo, numOfOutput, &ids, pExpr->resBytes, pExpr->resType, pExpr->aliasName, pExpr); + insertResultField(pQueryInfo, numOfOutput, &ids, pExpr->resBytes, (int32_t)pExpr->resType, pExpr->aliasName, pExpr); } else { for (int32_t i = 0; i < ids.num; ++i) { tscColumnListInsert(pQueryInfo->colList, &(ids.ids[i])); @@ -1981,7 +1981,7 @@ int32_t addExprAndResultField(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, int32_t col int32_t ret = getResultDataInfo(s.type, s.bytes, TSDB_FUNC_TID_TAG, 0, &type, &bytes, &inter, 0, 0); assert(ret == TSDB_CODE_SUCCESS); - s.type = type; + s.type = (uint8_t)type; s.bytes = bytes; TSDB_QUERY_SET_TYPE(pQueryInfo->type, TSDB_QUERY_TYPE_TAG_FILTER_QUERY); @@ -2014,7 +2014,7 @@ void getColumnName(tSQLExprItem* pItem, char* resultFieldName, int32_t nameLengt if (pItem->aliasName != NULL) { strncpy(resultFieldName, pItem->aliasName, nameLength); } else { - int32_t len = (pItem->pNode->operand.n < nameLength) ? pItem->pNode->operand.n : nameLength; + int32_t len = ((int32_t)pItem->pNode->operand.n < nameLength) ? (int32_t)pItem->pNode->operand.n : nameLength; strncpy(resultFieldName, pItem->pNode->operand.z, len); } } @@ -2383,7 +2383,7 @@ int32_t tscTansformSQLFuncForSTableQuery(SQueryInfo* pQueryInfo) { if ((functionId >= TSDB_FUNC_SUM && functionId <= TSDB_FUNC_TWA) || (functionId >= TSDB_FUNC_FIRST_DST && functionId <= TSDB_FUNC_LAST_DST) || (functionId >= TSDB_FUNC_RATE && functionId <= TSDB_FUNC_AVG_IRATE)) { - if (getResultDataInfo(pSrcSchema->type, pSrcSchema->bytes, functionId, pExpr->param[0].i64Key, &type, &bytes, + if (getResultDataInfo(pSrcSchema->type, pSrcSchema->bytes, functionId, (int32_t)pExpr->param[0].i64Key, &type, &bytes, &interBytes, 0, true) != TSDB_CODE_SUCCESS) { return TSDB_CODE_TSC_INVALID_SQL; } @@ -3144,7 +3144,7 @@ static int32_t validateSQLExpr(SSqlCmd* pCmd, tSQLExpr* pExpr, SQueryInfo* pQuer return TSDB_CODE_TSC_INVALID_SQL; } - int32_t outputIndex = tscSqlExprNumOfExprs(pQueryInfo); + int32_t outputIndex = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); tSQLExprItem item = {.pNode = pExpr, .aliasName = NULL}; @@ -3633,7 +3633,7 @@ static int32_t setTableCondForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, num = j; char* name = extractDBName(pTableMetaInfo->name, db); - SSQLToken dbToken = {.type = TK_STRING, .z = name, .n = strlen(name)}; + SSQLToken dbToken = { .type = TK_STRING, .z = name, .n = (uint32_t)strlen(name) }; for (int32_t i = 0; i < num; ++i) { if (i >= 1) { @@ -3641,7 +3641,7 @@ static int32_t setTableCondForSTableQuery(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, } char idBuf[TSDB_TABLE_ID_LEN] = {0}; - int32_t xlen = strlen(segments[i]); + int32_t xlen = (int32_t)strlen(segments[i]); SSQLToken t = {.z = segments[i], .n = xlen, .type = TK_STRING}; int32_t ret = setObjFullName(idBuf, account, &dbToken, &t, &xlen); @@ -4110,10 +4110,10 @@ int32_t parseFillClause(SSqlCmd* pCmd, SQueryInfo* pQueryInfo, SQuerySQL* pQuery startPos = 0; if (numOfFillVal > size) { - numOfFillVal = size; + numOfFillVal = (int32_t)size; } } else { - numOfFillVal = (pFillToken->nExpr > size) ? size : pFillToken->nExpr; + numOfFillVal = (pFillToken->nExpr > (int32_t)size) ? (int32_t)size : pFillToken->nExpr; } int32_t j = 1; @@ -4776,7 +4776,7 @@ int32_t validateLocalConfig(tDCLSQL* pOptions) { } int32_t validateColumnName(char* name) { - bool ret = isKeyWord(name, strlen(name)); + bool ret = isKeyWord(name, (int32_t)strlen(name)); if (ret) { return TSDB_CODE_TSC_INVALID_SQL; } @@ -4790,7 +4790,7 @@ int32_t validateColumnName(char* name) { if (token.type == TK_STRING) { strdequote(token.z); - token.n = strtrim(token.z); + token.n = (uint32_t)strtrim(token.z); int32_t k = tSQLGetToken(token.z, &token.type); if (k != token.n) { @@ -4935,17 +4935,17 @@ static int32_t setKeepOption(SSqlCmd* pCmd, SCMCreateDbMsg* pMsg, SCreateDBInfo* if (pKeep != NULL) { switch (pKeep->nExpr) { case 1: - pMsg->daysToKeep = htonl(pKeep->a[0].pVar.i64Key); + pMsg->daysToKeep = htonl((int32_t)pKeep->a[0].pVar.i64Key); break; case 2: { - pMsg->daysToKeep = htonl(pKeep->a[0].pVar.i64Key); - pMsg->daysToKeep1 = htonl(pKeep->a[1].pVar.i64Key); + pMsg->daysToKeep = htonl((int32_t)pKeep->a[0].pVar.i64Key); + pMsg->daysToKeep1 = htonl((int32_t)pKeep->a[1].pVar.i64Key); break; } case 3: { - pMsg->daysToKeep = htonl(pKeep->a[0].pVar.i64Key); - pMsg->daysToKeep1 = htonl(pKeep->a[1].pVar.i64Key); - pMsg->daysToKeep2 = htonl(pKeep->a[2].pVar.i64Key); + pMsg->daysToKeep = htonl((int32_t)pKeep->a[0].pVar.i64Key); + pMsg->daysToKeep1 = htonl((int32_t)pKeep->a[1].pVar.i64Key); + pMsg->daysToKeep2 = htonl((int32_t)pKeep->a[2].pVar.i64Key); break; } default: { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg); } @@ -4984,7 +4984,7 @@ static void setCreateDBOption(SCMCreateDbMsg* pMsg, SCreateDBInfo* pCreateDb) { pMsg->cacheBlockSize = htonl(pCreateDb->cacheBlockSize); pMsg->totalBlocks = htonl(pCreateDb->numOfBlocks); pMsg->daysPerFile = htonl(pCreateDb->daysPerFile); - pMsg->commitTime = htonl(pCreateDb->commitTime); + pMsg->commitTime = htonl((int32_t)pCreateDb->commitTime); pMsg->minRowsPerFileBlock = htonl(pCreateDb->minRowsPerBlock); pMsg->maxRowsPerFileBlock = htonl(pCreateDb->maxRowsPerBlock); pMsg->fsyncPeriod = htonl(pCreateDb->fsyncPeriod); @@ -5041,7 +5041,7 @@ void addGroupInfoForSubquery(SSqlObj* pParentObj, SSqlObj* pSql, int32_t subClau SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, subClauseIndex); size_t size = taosArrayGetSize(pQueryInfo->exprList); - SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, size - 1); + SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, (int32_t)size - 1); if (pExpr->functionId != TSDB_FUNC_TAG) { STableMetaInfo* pTableMetaInfo = tscGetMetaInfo(pQueryInfo, tableIndex); @@ -5058,7 +5058,7 @@ void addGroupInfoForSubquery(SSqlObj* pParentObj, SSqlObj* pSql, int32_t subClau // NOTE: tag column does not add to source column list SColumnList ids = {0}; - insertResultField(pQueryInfo, size, &ids, bytes, type, name, pExpr); + insertResultField(pQueryInfo, (int32_t)size, &ids, bytes, (int8_t)type, name, pExpr); int32_t relIndex = index.columnIndex; @@ -5088,9 +5088,9 @@ void doAddGroupColumnForSubquery(SQueryInfo* pQueryInfo, int32_t tagIndex) { SSchema* pSchema = tscGetTableColumnSchema(pTableMetaInfo->pTableMeta, pColIndex->colIndex); SColumnIndex colIndex = {.tableIndex = 0, .columnIndex = pColIndex->colIndex}; - tscAddSpecialColumnForSelect(pQueryInfo, size, TSDB_FUNC_PRJ, &colIndex, pSchema, TSDB_COL_NORMAL); + tscAddSpecialColumnForSelect(pQueryInfo, (int32_t)size, TSDB_FUNC_PRJ, &colIndex, pSchema, TSDB_COL_NORMAL); - SFieldSupInfo* pInfo = tscFieldInfoGetSupp(&pQueryInfo->fieldsInfo, size); + SFieldSupInfo* pInfo = tscFieldInfoGetSupp(&pQueryInfo->fieldsInfo, (int32_t)size); doLimitOutputNormalColOfGroupby(pInfo->pSqlExpr); pInfo->visible = false; } @@ -5118,7 +5118,7 @@ static void doUpdateSqlFunctionForTagPrj(SQueryInfo* pQueryInfo) { SSqlExpr* pExpr = tscSqlExprGet(pQueryInfo, i); if (pExpr->functionId != TSDB_FUNC_TAG_DUMMY && pExpr->functionId != TSDB_FUNC_TS_DUMMY) { SSchema* pColSchema = &pSchema[pExpr->colInfo.colIndex]; - getResultDataInfo(pColSchema->type, pColSchema->bytes, pExpr->functionId, pExpr->param[0].i64Key, &pExpr->resType, + getResultDataInfo(pColSchema->type, pColSchema->bytes, pExpr->functionId, (int32_t)pExpr->param[0].i64Key, &pExpr->resType, &pExpr->resBytes, &pExpr->interBytes, tagLength, true); } } @@ -5343,7 +5343,7 @@ static int32_t doAddGroupbyColumnsOnDemand(SSqlCmd* pCmd, SQueryInfo* pQueryInfo // NOTE: tag column does not add to source column list SColumnList ids = getColumnList(1, 0, pColIndex->colIndex); - insertResultField(pQueryInfo, size, &ids, bytes, type, name, pExpr); + insertResultField(pQueryInfo, (int32_t)size, &ids, bytes, (int8_t)type, name, pExpr); } else { // if this query is "group by" normal column, interval is not allowed if (pQueryInfo->intervalTime > 0) { @@ -5584,7 +5584,7 @@ int32_t tscCheckCreateDbParams(SSqlCmd* pCmd, SCMCreateDbMsg* pCreate) { void tscPrintSelectClause(SSqlObj* pSql, int32_t subClauseIndex) { SQueryInfo* pQueryInfo = tscGetQueryInfoDetail(&pSql->cmd, subClauseIndex); - int32_t size = tscSqlExprNumOfExprs(pQueryInfo); + int32_t size = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); if (size == 0) { return; } @@ -6028,7 +6028,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) { // in case of join query, time range is required. if (QUERY_IS_JOIN_QUERY(pQueryInfo->type)) { - int64_t timeRange = labs(pQueryInfo->window.skey - pQueryInfo->window.ekey); + int64_t timeRange = ABS(pQueryInfo->window.skey - pQueryInfo->window.ekey); if (timeRange == 0 && pQueryInfo->window.skey == 0) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6); @@ -6055,7 +6055,7 @@ int32_t doCheckForQuery(SSqlObj* pSql, SQuerySQL* pQuerySql, int32_t index) { } if (pQueryInfo->intervalTime > 0) { - int64_t timeRange = labs(pQueryInfo->window.skey - pQueryInfo->window.ekey); + int64_t timeRange = ABS(pQueryInfo->window.skey - pQueryInfo->window.ekey); // number of result is not greater than 10,000,000 if ((timeRange == 0) || (timeRange / pQueryInfo->intervalTime) > MAX_RETRIEVE_ROWS_IN_INTERVAL_QUERY) { return invalidSqlErrMsg(tscGetErrorMsgPayload(pCmd), msg6); @@ -6111,7 +6111,7 @@ int32_t exprTreeFromSqlExpr(SSqlCmd* pCmd, tExprNode **pExpr, const tSQLExpr* pS SSqlExpr* p1 = taosArrayGetP(pExprInfo, i); if (strcmp((*pExpr)->pSchema->name, p1->aliasName) == 0) { - (*pExpr)->pSchema->type = p1->resType; + (*pExpr)->pSchema->type = (uint8_t)p1->resType; (*pExpr)->pSchema->bytes = p1->resBytes; break; } diff --git a/src/client/src/tscSchemaUtil.c b/src/client/src/tscSchemaUtil.c index 63607b7a86e0cce38c9a2f07f41b7055b538cb96..244bb8116452fac495f2d140b8b3d8b3e8d96eeb 100644 --- a/src/client/src/tscSchemaUtil.c +++ b/src/client/src/tscSchemaUtil.c @@ -208,7 +208,7 @@ char* tsGetTagsValue(STableMeta* pTableMeta) { } // todo refactor -__attribute__ ((unused))static FORCE_INLINE char* skipSegments(char* input, char delim, int32_t num) { +UNUSED_FUNC static FORCE_INLINE char* skipSegments(char* input, char delim, int32_t num) { for (int32_t i = 0; i < num; ++i) { while (*input != 0 && *input++ != delim) { }; @@ -216,7 +216,7 @@ __attribute__ ((unused))static FORCE_INLINE char* skipSegments(char* input, char return input; } -__attribute__ ((unused)) static FORCE_INLINE size_t copy(char* dst, const char* src, char delimiter) { +UNUSED_FUNC static FORCE_INLINE size_t copy(char* dst, const char* src, char delimiter) { size_t len = 0; while (*src != delimiter && *src != 0) { *dst++ = *src++; diff --git a/src/client/src/tscServer.c b/src/client/src/tscServer.c index 3fd0aa79a647788e58c4b92cc5af1c7938a5f1b1..4d4254fa46b83af5cb2ab28c822964a650f952e5 100644 --- a/src/client/src/tscServer.c +++ b/src/client/src/tscServer.c @@ -377,7 +377,7 @@ void tscProcessMsgFromServer(SRpcMsg *rpcMsg, SRpcEpSet *pEpSet) { } if (rpcMsg->code != TSDB_CODE_TSC_ACTION_IN_PROGRESS) { - rpcMsg->code = (pRes->code == TSDB_CODE_SUCCESS)? pRes->numOfRows: pRes->code; + rpcMsg->code = (pRes->code == TSDB_CODE_SUCCESS) ? (int32_t)pRes->numOfRows : pRes->code; bool shouldFree = tscShouldBeFreed(pSql); (*pSql->fp)(pSql->param, pSql, rpcMsg->code); @@ -569,10 +569,10 @@ static int32_t tscEstimateQueryMsgSize(SSqlCmd *pCmd, int32_t clauseIndex) { const static int32_t MIN_QUERY_MSG_PKT_SIZE = TSDB_MAX_BYTES_PER_ROW * 5; SQueryInfo * pQueryInfo = tscGetQueryInfoDetail(pCmd, clauseIndex); - int32_t srcColListSize = taosArrayGetSize(pQueryInfo->colList) * sizeof(SColumnInfo); + int32_t srcColListSize = (int32_t)(taosArrayGetSize(pQueryInfo->colList) * sizeof(SColumnInfo)); size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo); - int32_t exprSize = sizeof(SSqlFuncMsg) * numOfExprs; + int32_t exprSize = (int32_t)(sizeof(SSqlFuncMsg) * numOfExprs); return MIN_QUERY_MSG_PKT_SIZE + minMsgSize() + sizeof(SQueryTableMsg) + srcColListSize + exprSize + 4096; } @@ -612,7 +612,7 @@ static char *doSerializeTableInfo(SQueryTableMsg* pQueryMsg, SSqlObj *pSql, char pMsg += sizeof(STableIdInfo); } else { // it is a subquery of the super table query, this EP info is acquired from vgroupInfo int32_t index = pTableMetaInfo->vgroupIndex; - int32_t numOfVgroups = taosArrayGetSize(pTableMetaInfo->pVgroupTables); + int32_t numOfVgroups = (int32_t)taosArrayGetSize(pTableMetaInfo->pVgroupTables); assert(index >= 0 && index < numOfVgroups); tscDebug("%p query on stable, vgIndex:%d, numOfVgroups:%d", pSql, index, numOfVgroups); @@ -623,7 +623,7 @@ static char *doSerializeTableInfo(SQueryTableMsg* pQueryMsg, SSqlObj *pSql, char tscSetDnodeEpSet(pSql, &pTableIdList->vgInfo); pQueryMsg->head.vgId = htonl(pTableIdList->vgInfo.vgId); - int32_t numOfTables = taosArrayGetSize(pTableIdList->itemList); + int32_t numOfTables = (int32_t)taosArrayGetSize(pTableIdList->itemList); pQueryMsg->numOfTables = htonl(numOfTables); // set the number of tables // serialize each table id info @@ -675,7 +675,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { SQueryTableMsg *pQueryMsg = (SQueryTableMsg *)pCmd->payload; - int32_t numOfTags = taosArrayGetSize(pTableMetaInfo->tagColList); + int32_t numOfTags = (int32_t)taosArrayGetSize(pTableMetaInfo->tagColList); if (pQueryInfo->order.order == TSDB_ORDER_ASC) { pQueryMsg->window.skey = htobe64(pQueryInfo->window.skey); @@ -690,7 +690,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { pQueryMsg->fillType = htons(pQueryInfo->fillType); pQueryMsg->limit = htobe64(pQueryInfo->limit.limit); pQueryMsg->offset = htobe64(pQueryInfo->limit.offset); - pQueryMsg->numOfCols = htons(taosArrayGetSize(pQueryInfo->colList)); + pQueryMsg->numOfCols = htons((int16_t)taosArrayGetSize(pQueryInfo->colList)); pQueryMsg->intervalTime = htobe64(pQueryInfo->intervalTime); pQueryMsg->slidingTime = htobe64(pQueryInfo->slidingTime); pQueryMsg->slidingTimeUnit = pQueryInfo->slidingTimeUnit; @@ -700,7 +700,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { pQueryMsg->queryType = htonl(pQueryInfo->type); size_t numOfOutput = tscSqlExprNumOfExprs(pQueryInfo); - pQueryMsg->numOfOutput = htons(numOfOutput); + pQueryMsg->numOfOutput = htons((int16_t)numOfOutput); // set column list ids size_t numOfCols = taosArrayGetSize(pQueryInfo->colList); @@ -872,7 +872,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { } // compressed ts block - pQueryMsg->tsOffset = htonl(pMsg - pCmd->payload); + pQueryMsg->tsOffset = htonl((int32_t)(pMsg - pCmd->payload)); int32_t tsLen = 0; int32_t numOfBlocks = 0; @@ -905,7 +905,7 @@ int tscBuildQueryMsg(SSqlObj *pSql, SSqlInfo *pInfo) { pQueryMsg->tsOrder = htonl(pQueryInfo->tsBuf->tsOrder); } - int32_t msgLen = pMsg - pCmd->payload; + int32_t msgLen = (int32_t)(pMsg - pCmd->payload); tscDebug("%p msg built success,len:%d bytes", pSql, msgLen); pCmd->payloadLen = msgLen; @@ -1005,7 +1005,7 @@ int32_t tscBuildUserMsg(SSqlObj *pSql, SSqlInfo *pInfo) { SUserInfo *pUser = &pInfo->pDCLInfo->user; strncpy(pAlterMsg->user, pUser->user.z, pUser->user.n); - pAlterMsg->flag = pUser->type; + pAlterMsg->flag = (int8_t)pUser->type; if (pUser->type == TSDB_ALTER_USER_PRIVILEGES) { pAlterMsg->privilege = (char)pCmd->count; @@ -1280,7 +1280,7 @@ int tscBuildCreateTableMsg(SSqlObj *pSql, SSqlInfo *pInfo) { tscFieldInfoClear(&pQueryInfo->fieldsInfo); - msgLen = pMsg - (char*)pCreateTableMsg; + msgLen = (int32_t)(pMsg - (char*)pCreateTableMsg); pCreateTableMsg->contLen = htonl(msgLen); pCmd->payloadLen = msgLen; pCmd->msgType = TSDB_MSG_TYPE_CM_CREATE_TABLE; @@ -1333,7 +1333,7 @@ int tscBuildAlterTableMsg(SSqlObj *pSql, SSqlInfo *pInfo) { memcpy(pMsg, pAlterInfo->tagData.data, pAlterInfo->tagData.dataLen); pMsg += pAlterInfo->tagData.dataLen; - msgLen = pMsg - (char*)pAlterTableMsg; + msgLen = (int32_t)(pMsg - (char*)pAlterTableMsg); pCmd->payloadLen = msgLen; pCmd->msgType = TSDB_MSG_TYPE_CM_ALTER_TABLE; @@ -1534,12 +1534,12 @@ int tscBuildTableMetaMsg(SSqlObj *pSql, SSqlInfo *pInfo) { pMsg += len; } - pCmd->payloadLen = pMsg - (char*)pInfoMsg; + pCmd->payloadLen = (int32_t)(pMsg - (char*)pInfoMsg); pCmd->msgType = TSDB_MSG_TYPE_CM_TABLE_META; taosTFree(tmpData); - assert(msgLen + minMsgSize() <= pCmd->allocSize); + assert(msgLen + minMsgSize() <= (int32_t)pCmd->allocSize); return TSDB_CODE_SUCCESS; } @@ -1631,7 +1631,7 @@ int tscBuildSTableVgroupMsg(SSqlObj *pSql, SSqlInfo *pInfo) { } pCmd->msgType = TSDB_MSG_TYPE_CM_STABLE_VGROUP; - pCmd->payloadLen = (pMsg - pCmd->payload); + pCmd->payloadLen = (int32_t)(pMsg - pCmd->payload); return TSDB_CODE_SUCCESS; } diff --git a/src/client/src/tscSql.c b/src/client/src/tscSql.c index 10720874e29dbb4836c294f2ab757ebb1cd39443..3e5280401fbd3e62fbd56c28fa9d981aa691a40b 100644 --- a/src/client/src/tscSql.c +++ b/src/client/src/tscSql.c @@ -85,7 +85,7 @@ SSqlObj *taosConnectImpl(const char *ip, const char *user, const char *pass, con taosEncryptPass((uint8_t *)pass, strlen(pass), pObj->pass); if (db) { - int32_t len = strlen(db); + int32_t len = (int32_t)strlen(db); /* db name is too long */ if (len >= TSDB_DB_NAME_LEN) { terrno = TSDB_CODE_TSC_INVALID_DB_LENGTH; @@ -240,7 +240,7 @@ TAOS_RES* taos_query(TAOS *taos, const char *sqlstr) { return NULL; } - int32_t sqlLen = strlen(sqlstr); + int32_t sqlLen = (int32_t)strlen(sqlstr); if (sqlLen > tsMaxSQLStringLen) { tscError("sql string exceeds max length:%d", tsMaxSQLStringLen); terrno = TSDB_CODE_TSC_INVALID_SQL; @@ -269,7 +269,7 @@ TAOS_RES* taos_query_c(TAOS *taos, const char *sqlstr, uint32_t sqlLen) { return NULL; } - if (sqlLen > tsMaxSQLStringLen) { + if (sqlLen > (uint32_t)tsMaxSQLStringLen) { tscError("sql string exceeds max length:%d", tsMaxSQLStringLen); terrno = TSDB_CODE_TSC_INVALID_SQL; return NULL; @@ -328,7 +328,7 @@ int taos_affected_rows(TAOS_RES *tres) { SSqlObj* pSql = (SSqlObj*) tres; if (pSql == NULL || pSql->signature != pSql) return 0; - return (pSql->res.numOfRows); + return (int)(pSql->res.numOfRows); } TAOS_FIELD *taos_fetch_fields(TAOS_RES *res) { @@ -363,7 +363,7 @@ int taos_retrieve(TAOS_RES *res) { } tscProcessSql(pSql); - return pRes->numOfRows; + return (int)pRes->numOfRows; } int taos_fetch_block_impl(TAOS_RES *res, TAOS_ROW *rows) { @@ -404,7 +404,7 @@ int taos_fetch_block_impl(TAOS_RES *res, TAOS_ROW *rows) { *rows = pRes->tsrow; - return (pQueryInfo->order.order == TSDB_ORDER_DESC) ? pRes->numOfRows : -pRes->numOfRows; + return (int)((pQueryInfo->order.order == TSDB_ORDER_DESC) ? pRes->numOfRows : -pRes->numOfRows); } TAOS_ROW taos_fetch_row(TAOS_RES *res) { @@ -749,7 +749,7 @@ int taos_validate_sql(TAOS *taos, const char *sql) { tscDebug("%p Valid SQL: %s pObj:%p", pSql, sql, pObj); - int32_t sqlLen = strlen(sql); + int32_t sqlLen = (int32_t)strlen(sql); if (sqlLen > tsMaxSQLStringLen) { tscError("%p sql too long", pSql); pRes->code = TSDB_CODE_TSC_INVALID_SQL; @@ -822,11 +822,11 @@ static int tscParseTblNameList(SSqlObj *pSql, const char *tblNameList, int32_t t } memcpy(tblName, str, nextStr - str); - int32_t len = nextStr - str; + int32_t len = (int32_t)(nextStr - str); tblName[len] = '\0'; str = nextStr + 1; - len = strtrim(tblName); + len = (int32_t)strtrim(tblName); SSQLToken sToken = {.n = len, .type = TK_ID, .z = tblName}; tSQLGetToken(tblName, &sToken.type); @@ -892,7 +892,7 @@ int taos_load_table_info(TAOS *taos, const char *tableNameList) { assert(pSql->fp == NULL); tscDebug("%p tableNameList: %s pObj:%p", pSql, tableNameList, pObj); - int32_t tblListLen = strlen(tableNameList); + int32_t tblListLen = (int32_t)strlen(tableNameList); if (tblListLen > MAX_TABLE_NAME_LENGTH) { tscError("%p tableNameList too long, length:%d, maximum allowed:%d", pSql, tblListLen, MAX_TABLE_NAME_LENGTH); pRes->code = TSDB_CODE_TSC_INVALID_SQL; diff --git a/src/client/src/tscStream.c b/src/client/src/tscStream.c index 6235e0aeba415627352bc3fd864eb6e35eb6086e..d0591de0114ab6b96be22140edfad5f90bb5b53b 100644 --- a/src/client/src/tscStream.c +++ b/src/client/src/tscStream.c @@ -47,14 +47,14 @@ static bool isProjectStream(SQueryInfo* pQueryInfo) { } static int64_t tscGetRetryDelayTime(int64_t slidingTime, int16_t prec) { - float retryRangeFactor = 0.3; + float retryRangeFactor = 0.3f; // change to ms if (prec == TSDB_TIME_PRECISION_MICRO) { slidingTime = slidingTime / 1000; } - int64_t retryDelta = (int64_t)tsStreamCompRetryDelay * retryRangeFactor; + int64_t retryDelta = (int64_t)(tsStreamCompRetryDelay * retryRangeFactor); retryDelta = ((rand() % retryDelta) + tsStreamCompRetryDelay) * 1000L; if (slidingTime < retryDelta) { @@ -299,7 +299,7 @@ static void tscSetRetryTimer(SSqlStream *pStream, SSqlObj *pSql, int64_t timer) pSql->cmd.command = TSDB_SQL_SELECT; // start timer for next computing - taosTmrReset(tscProcessStreamTimer, timer, pStream, tscTmr, &pStream->pTimer); + taosTmrReset(tscProcessStreamTimer, (int32_t)timer, pStream, tscTmr, &pStream->pTimer); } static int64_t getLaunchTimeDelay(const SSqlStream* pStream) { @@ -314,7 +314,7 @@ static int64_t getLaunchTimeDelay(const SSqlStream* pStream) { int64_t remainTimeWindow = pStream->slidingTime - delayDelta; if (maxDelay > remainTimeWindow) { - maxDelay = (remainTimeWindow / 1.5); + maxDelay = (int64_t)(remainTimeWindow / 1.5f); } int64_t currentDelay = (rand() % maxDelay); // a random number @@ -505,7 +505,7 @@ static void tscCreateStream(void *param, TAOS_RES *res, int code) { int64_t starttime = tscGetLaunchTimestamp(pStream); pCmd->command = TSDB_SQL_SELECT; - taosTmrReset(tscProcessStreamTimer, starttime, pStream, tscTmr, &pStream->pTimer); + taosTmrReset(tscProcessStreamTimer, (int32_t)starttime, pStream, tscTmr, &pStream->pTimer); tscDebug("%p stream:%p is opened, query on:%s, interval:%" PRId64 ", sliding:%" PRId64 ", first launched in:%" PRId64 ", sql:%s", pSql, pStream, pTableMetaInfo->name, pStream->interval, pStream->slidingTime, starttime, pSql->sqlstr); diff --git a/src/client/src/tscSubquery.c b/src/client/src/tscSubquery.c index fed790b9af5da4aa97abeb9e64ca97914cef0054..8a596d8893561684ef100bc0c128e254b37ce685 100644 --- a/src/client/src/tscSubquery.c +++ b/src/client/src/tscSubquery.c @@ -641,8 +641,8 @@ static void tidTagRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow pSupporter->pIdTagList = tmp; memcpy(pSupporter->pIdTagList + pSupporter->totalLen, pRes->data, validLen); - pSupporter->totalLen += validLen; - pSupporter->num += pRes->numOfRows; + pSupporter->totalLen += (int32_t)validLen; + pSupporter->num += (int32_t)pRes->numOfRows; // query not completed, continue to retrieve tid + tag tuples if (!pRes->completed) { @@ -775,7 +775,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow if (!pRes->completed) { taosGetTmpfilePath("ts-join", pSupporter->path); pSupporter->f = fopen(pSupporter->path, "w"); - pRes->row = pRes->numOfRows; + pRes->row = (int32_t)pRes->numOfRows; taos_fetch_rows_a(tres, tsCompRetrieveCallback, param); return; @@ -801,7 +801,7 @@ static void tsCompRetrieveCallback(void* param, TAOS_RES* tres, int32_t numOfRow // TODO check for failure pSupporter->f = fopen(pSupporter->path, "w"); - pRes->row = pRes->numOfRows; + pRes->row = (int32_t)pRes->numOfRows; // set the callback function pSql->fp = tscJoinQueryCallback; @@ -1214,7 +1214,7 @@ int32_t tscLaunchJoinSubquery(SSqlObj *pSql, int16_t tableIndex, SJoinSupporter getResultDataInfo(s->type, s->bytes, TSDB_FUNC_TID_TAG, 0, &type, &bytes, &inter, 0, 0); - SSchema s1 = {.colId = s->colId, .type = type, .bytes = bytes}; + SSchema s1 = {.colId = s->colId, .type = (uint8_t)type, .bytes = bytes}; pSupporter->tagSize = s1.bytes; assert(isValidDataType(s1.type) && s1.bytes > 0); @@ -1561,7 +1561,8 @@ void tscHandleSubqueryError(SRetrieveSupport *trsupport, SSqlObj *pSql, int numO tscDebug("%p sub:%p orderOfSub:%d freed, finished subqueries:%d", pParentSql, pSql, trsupport->subqueryIndex, pState->numOfTotal - remain); - return tscFreeSubSqlObj(trsupport, pSql); + tscFreeSubSqlObj(trsupport, pSql); + return; } // all subqueries are failed @@ -1598,7 +1599,7 @@ static void tscAllDataRetrievedFromDnode(SRetrieveSupport *trsupport, SSqlObj* p STableMetaInfo* pTableMetaInfo = pQueryInfo->pTableMetaInfo[0]; // data in from current vnode is stored in cache and disk - uint32_t numOfRowsFromSubquery = trsupport->pExtMemBuffer[idx]->numOfTotalElems + trsupport->localBuffer->num; + uint32_t numOfRowsFromSubquery = (uint32_t)(trsupport->pExtMemBuffer[idx]->numOfTotalElems + trsupport->localBuffer->num); tscDebug("%p sub:%p all data retrieved from ep:%s, vgId:%d, numOfRows:%d, orderOfSub:%d", pParentSql, pSql, pTableMetaInfo->vgroupList->vgroups[0].epAddr[0].fqdn, pTableMetaInfo->vgroupList->vgroups[0].vgId, numOfRowsFromSubquery, idx); @@ -1616,14 +1617,16 @@ static void tscAllDataRetrievedFromDnode(SRetrieveSupport *trsupport, SSqlObj* p if (tsTotalTmpDirGB != 0 && tsAvailTmpDirectorySpace < tsReservedTmpDirectorySpace) { tscError("%p sub:%p client disk space remain %.3f GB, need at least %.3f GB, stop query", pParentSql, pSql, tsAvailTmpDirectorySpace, tsReservedTmpDirectorySpace); - return tscAbortFurtherRetryRetrieval(trsupport, pSql, TSDB_CODE_TSC_NO_DISKSPACE); + tscAbortFurtherRetryRetrieval(trsupport, pSql, TSDB_CODE_TSC_NO_DISKSPACE); + return; } // each result for a vnode is ordered as an independant list, // then used as an input of loser tree for disk-based merge int32_t code = tscFlushTmpBuffer(trsupport->pExtMemBuffer[idx], pDesc, trsupport->localBuffer, pQueryInfo->groupbyExpr.orderType); if (code != 0) { // set no disk space error info, and abort retry - return tscAbortFurtherRetryRetrieval(trsupport, pSql, code); + tscAbortFurtherRetryRetrieval(trsupport, pSql, code); + return; } int32_t remain = -1; @@ -1631,7 +1634,8 @@ static void tscAllDataRetrievedFromDnode(SRetrieveSupport *trsupport, SSqlObj* p tscDebug("%p sub:%p orderOfSub:%d freed, finished subqueries:%d", pParentSql, pSql, trsupport->subqueryIndex, pState->numOfTotal - remain); - return tscFreeSubSqlObj(trsupport, pSql); + tscFreeSubSqlObj(trsupport, pSql); + return; } // all sub-queries are returned, start to local merge process @@ -1724,7 +1728,8 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR if (num > tsMaxNumOfOrderedResults && tscIsProjectionQueryOnSTable(pQueryInfo, 0)) { tscError("%p sub:%p num of OrderedRes is too many, max allowed:%" PRId32 " , current:%" PRId64, pParentSql, pSql, tsMaxNumOfOrderedResults, num); - return tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_SORTED_RES_TOO_MANY); + tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_SORTED_RES_TOO_MANY); + return; } #ifdef _DEBUG_VIEW @@ -1739,11 +1744,12 @@ static void tscRetrieveFromDnodeCallBack(void *param, TAOS_RES *tres, int numOfR if (tsTotalTmpDirGB != 0 && tsAvailTmpDirectorySpace < tsReservedTmpDirectorySpace) { tscError("%p sub:%p client disk space remain %.3f GB, need at least %.3f GB, stop query", pParentSql, pSql, tsAvailTmpDirectorySpace, tsReservedTmpDirectorySpace); - return tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_NO_DISKSPACE); + tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_NO_DISKSPACE); + return; } int32_t ret = saveToBuffer(trsupport->pExtMemBuffer[idx], pDesc, trsupport->localBuffer, pRes->data, - pRes->numOfRows, pQueryInfo->groupbyExpr.orderType); + (int32_t)pRes->numOfRows, pQueryInfo->groupbyExpr.orderType); if (ret != 0) { // set no disk space error info, and abort retry tscAbortFurtherRetryRetrieval(trsupport, tres, TSDB_CODE_TSC_NO_DISKSPACE); @@ -1871,7 +1877,7 @@ static void multiVnodeInsertFinalize(void* param, TAOS_RES* tres, int numOfRows) // todo remove this parameter in async callback function definition. // all data has been sent to vnode, call user function - int32_t v = (pParentObj->res.code != TSDB_CODE_SUCCESS)? pParentObj->res.code:pParentObj->res.numOfRows; + int32_t v = (pParentObj->res.code != TSDB_CODE_SUCCESS) ? pParentObj->res.code : (int32_t)pParentObj->res.numOfRows; (*pParentObj->fp)(pParentObj->param, pParentObj, v); } @@ -1907,7 +1913,7 @@ int32_t tscHandleMultivnodeInsert(SSqlObj *pSql) { assert(size > 0); pSql->pSubs = calloc(size, POINTER_BYTES); - pSql->numOfSubs = size; + pSql->numOfSubs = (uint16_t)size; tscDebug("%p submit data to %zu vnode(s)", pSql, size); @@ -1999,7 +2005,7 @@ static void doBuildResFromSubqueries(SSqlObj* pSql) { continue; } - numOfRes = MIN(numOfRes, pSql->pSubs[i]->res.numOfRows); + numOfRes = (int32_t)(MIN(numOfRes, pSql->pSubs[i]->res.numOfRows)); } int32_t totalSize = tscGetResRowLength(pQueryInfo->exprList); @@ -2172,7 +2178,7 @@ void **doSetResultRowData(SSqlObj *pSql, bool finalResult) { SArithmeticSupport *sas = (SArithmeticSupport *) calloc(1, sizeof(SArithmeticSupport)); sas->offset = 0; sas->pArithExpr = pSup->pArithExprInfo; - sas->numOfCols = tscSqlExprNumOfExprs(pQueryInfo); + sas->numOfCols = (int32_t)tscSqlExprNumOfExprs(pQueryInfo); sas->exprList = pQueryInfo->exprList; sas->data = calloc(sas->numOfCols, POINTER_BYTES); diff --git a/src/client/src/tscSystem.c b/src/client/src/tscSystem.c index a252beec33a3752782054cdba107747df0785d92..878fdd500f378ea9059e357868d20a81b7e65f6f 100644 --- a/src/client/src/tscSystem.c +++ b/src/client/src/tscSystem.c @@ -78,7 +78,7 @@ int32_t tscInitRpc(const char *user, const char *secret, void** pDnodeConn) { return 0; } -void taos_init_imp() { +void taos_init_imp(void) { char temp[128]; errno = TSDB_CODE_SUCCESS; @@ -124,9 +124,9 @@ void taos_init_imp() { int queueSize = tsMaxConnections*2; if (tscEmbedded == 0) { - tscNumOfThreads = tsNumOfCores * tsNumOfThreadsPerCore / 2.0; + tscNumOfThreads = (int)(tsNumOfCores * tsNumOfThreadsPerCore / 2.0); } else { - tscNumOfThreads = tsNumOfCores * tsNumOfThreadsPerCore / 4.0; + tscNumOfThreads = (int)(tsNumOfCores * tsNumOfThreadsPerCore / 4.0); } if (tscNumOfThreads < 2) tscNumOfThreads = 2; diff --git a/src/client/src/tscUtil.c b/src/client/src/tscUtil.c index 9e0ff8a9bfbc26434455f1da7cbc95c89401fd1e..c74cc82f85b2cc784a17ade8a53eca6286d41707 100644 --- a/src/client/src/tscUtil.c +++ b/src/client/src/tscUtil.c @@ -57,7 +57,7 @@ void tsSetSTableQueryCond(STagCond* pTagCond, uint64_t uid, SBufferWriter* bw) { SCond cond = { .uid = uid, - .len = tbufTell(bw), + .len = (int32_t)(tbufTell(bw)), .cond = NULL, }; @@ -481,7 +481,7 @@ int32_t tscCopyDataBlockToPayload(SSqlObj* pSql, STableDataBlocks* pDataBlock) { */ pCmd->payloadLen = pDataBlock->size; - assert(pCmd->allocSize >= pCmd->payloadLen + 100 && pCmd->payloadLen > 0); + assert(pCmd->allocSize >= (uint32_t)(pCmd->payloadLen + 100) && pCmd->payloadLen > 0); return TSDB_CODE_SUCCESS; } @@ -570,7 +570,7 @@ static int trimDataBlock(void* pDataBlock, STableDataBlocks* pTableDataBlock, bo SSubmitBlk* pBlock = pDataBlock; memcpy(pDataBlock, pTableDataBlock->pData, sizeof(SSubmitBlk)); - pDataBlock += sizeof(SSubmitBlk); + pDataBlock = (char*)pDataBlock + sizeof(SSubmitBlk); int32_t flen = 0; // original total length of row @@ -584,7 +584,7 @@ static int trimDataBlock(void* pDataBlock, STableDataBlocks* pTableDataBlock, bo pCol->bytes = htons(pSchema[j].bytes); pCol->offset = 0; - pDataBlock += sizeof(STColumn); + pDataBlock = (char*)pDataBlock + sizeof(STColumn); flen += TYPE_BYTES[pSchema[j].type]; } @@ -604,7 +604,7 @@ static int trimDataBlock(void* pDataBlock, STableDataBlocks* pTableDataBlock, bo for (int32_t i = 0; i < numOfRows; ++i) { SDataRow trow = (SDataRow) pDataBlock; - dataRowSetLen(trow, TD_DATA_ROW_HEAD_SIZE + flen); + dataRowSetLen(trow, (uint16_t)(TD_DATA_ROW_HEAD_SIZE + flen)); dataRowSetVersion(trow, pTableMeta->sversion); int toffset = 0; @@ -614,7 +614,7 @@ static int trimDataBlock(void* pDataBlock, STableDataBlocks* pTableDataBlock, bo p += pSchema[j].bytes; } - pDataBlock += dataRowLen(trow); + pDataBlock = (char*)pDataBlock + dataRowLen(trow); pBlock->dataLen += dataRowLen(trow); } @@ -667,7 +667,7 @@ int32_t tscMergeTableDataBlocks(SSqlObj* pSql, SArray* pTableDataBlockList) { if (dataBuf->nAllocSize < destSize) { while (dataBuf->nAllocSize < destSize) { - dataBuf->nAllocSize = dataBuf->nAllocSize * 1.5; + dataBuf->nAllocSize = (uint32_t)(dataBuf->nAllocSize * 1.5); } char* tmp = realloc(dataBuf->pData, dataBuf->nAllocSize); @@ -759,7 +759,7 @@ int tscAllocPayload(SSqlCmd* pCmd, int size) { if (pCmd->payload == NULL) return TSDB_CODE_TSC_OUT_OF_MEMORY; pCmd->allocSize = size; } else { - if (pCmd->allocSize < size) { + if (pCmd->allocSize < (uint32_t)size) { char* b = realloc(pCmd->payload, size); if (b == NULL) return TSDB_CODE_TSC_OUT_OF_MEMORY; pCmd->payload = b; @@ -769,7 +769,7 @@ int tscAllocPayload(SSqlCmd* pCmd, int size) { memset(pCmd->payload, 0, pCmd->allocSize); } - assert(pCmd->allocSize >= size); + assert(pCmd->allocSize >= (uint32_t)size); return TSDB_CODE_SUCCESS; } @@ -963,7 +963,7 @@ static SSqlExpr* doBuildSqlExpr(SQueryInfo* pQueryInfo, int16_t functionId, SCol SSqlExpr* tscSqlExprInsert(SQueryInfo* pQueryInfo, int32_t index, int16_t functionId, SColumnIndex* pColIndex, int16_t type, int16_t size, int16_t interSize, bool isTagCol) { - int32_t num = taosArrayGetSize(pQueryInfo->exprList); + int32_t num = (int32_t)taosArrayGetSize(pQueryInfo->exprList); if (index == num) { return tscSqlExprAppend(pQueryInfo, functionId, pColIndex, type, size, interSize, isTagCol); } @@ -1184,7 +1184,7 @@ void tscColumnListDestroy(SArray* pColumnList) { */ static int32_t validateQuoteToken(SSQLToken* pToken) { strdequote(pToken->z); - pToken->n = strtrim(pToken->z); + pToken->n = (uint32_t)strtrim(pToken->z); int32_t k = tSQLGetToken(pToken->z, &pToken->type); @@ -1207,7 +1207,7 @@ int32_t tscValidateName(SSQLToken* pToken) { if (sep == NULL) { // single part if (pToken->type == TK_STRING) { strdequote(pToken->z); - pToken->n = strtrim(pToken->z); + pToken->n = (uint32_t)strtrim(pToken->z); int len = tSQLGetToken(pToken->z, &pToken->type); @@ -1232,7 +1232,7 @@ int32_t tscValidateName(SSQLToken* pToken) { char* pStr = pToken->z; if (pToken->type == TK_SPACE) { - pToken->n = strtrim(pToken->z); + pToken->n = (uint32_t)strtrim(pToken->z); } pToken->n = tSQLGetToken(pToken->z, &pToken->type); @@ -1251,7 +1251,7 @@ int32_t tscValidateName(SSQLToken* pToken) { int32_t firstPartLen = pToken->n; pToken->z = sep + 1; - pToken->n = oldLen - (sep - pStr) - 1; + pToken->n = (uint32_t)(oldLen - (sep - pStr) - 1); int32_t len = tSQLGetToken(pToken->z, &pToken->type); if (len != pToken->n || (pToken->type != TK_STRING && pToken->type != TK_ID)) { return TSDB_CODE_TSC_INVALID_SQL; @@ -1763,7 +1763,7 @@ SSqlObj* createSubqueryObj(SSqlObj* pSql, int16_t tableIndex, void (*fp)(), void uint64_t uid = pTableMetaInfo->pTableMeta->id.uid; tscSqlExprCopy(pNewQueryInfo->exprList, pQueryInfo->exprList, uid, true); - int32_t numOfOutput = tscSqlExprNumOfExprs(pNewQueryInfo); + int32_t numOfOutput = (int32_t)tscSqlExprNumOfExprs(pNewQueryInfo); if (numOfOutput > 0) { // todo refactor to extract method size_t numOfExprs = tscSqlExprNumOfExprs(pQueryInfo); diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 05114cc3244cab876c7aec5af31ac23cc42b3d8f..0da7bda994db83882e36e9d52a7983635ad85330 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -1,17 +1,8 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF (TD_WINDOWS) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/iconv) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/regex) -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(inc) - AUX_SOURCE_DIRECTORY(src SRC) + ADD_LIBRARY(common ${SRC}) TARGET_LINK_LIBRARIES(common tutil) diff --git a/src/cq/CMakeLists.txt b/src/cq/CMakeLists.txt index 4ccdb765c32926efa35e131322df2c584bd4c2b2..4e63cd4953a9d71fac6070926cf7ecb8d2ccb3cb 100644 --- a/src/cq/CMakeLists.txt +++ b/src/cq/CMakeLists.txt @@ -1,16 +1,11 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -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) INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SRC) -ADD_LIBRARY(tcq ${SRC}) -TARGET_LINK_LIBRARIES(tcq tutil common taos) - -ADD_SUBDIRECTORY(test) - +IF (TD_LINUX) + ADD_LIBRARY(tcq ${SRC}) + TARGET_LINK_LIBRARIES(tcq tutil common taos) + ADD_SUBDIRECTORY(test) +ENDIF () diff --git a/src/cq/test/CMakeLists.txt b/src/cq/test/CMakeLists.txt index 82781f531a30ace6066b1dc65500e06608cc054e..59c0ac79cfffd35a40beb58a2a172a9bf27dca15 100644 --- a/src/cq/test/CMakeLists.txt +++ b/src/cq/test/CMakeLists.txt @@ -1,12 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -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) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/cq/inc) - LIST(APPEND CQTEST_SRC ./cqtest.c) ADD_EXECUTABLE(cqtest ${CQTEST_SRC}) TARGET_LINK_LIBRARIES(cqtest tcq) diff --git a/src/dnode/CMakeLists.txt b/src/dnode/CMakeLists.txt index 64d69e9f0103fe1756976a273d16f7ab9bddc729..032e12624fd9a5a44435155aa2d676cf9644bac2 100644 --- a/src/dnode/CMakeLists.txt +++ b/src/dnode/CMakeLists.txt @@ -1,22 +1,16 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - 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/query/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/mnode/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/tsdb/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc) - INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/mnode/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/tsdb/inc) +INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(src SRC) + +IF (TD_LINUX) ADD_EXECUTABLE(taosd ${SRC}) -# TARGET_LINK_LIBRARIES(taosd mnode taos_static monitor http mqtt tsdb twal vnode cJson lz4 balance sync) TARGET_LINK_LIBRARIES(taosd mnode taos monitor http mqtt tsdb twal vnode cJson lz4 balance sync) IF (TD_ACCOUNT) @@ -41,7 +35,4 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) COMMAND ${CMAKE_COMMAND} -E echo charset UTF-8 >> ${TD_TESTS_OUTPUT_DIR}/cfg/taos.cfg COMMENT "prepare taosd environment") ADD_CUSTOM_TARGET(${PREPARE_ENV_TARGET} ALL WORKING_DIRECTORY ${TD_EXECUTABLE_OUTPUT_PATH} DEPENDS ${PREPARE_ENV_CMD}) - -ENDIF () - - +ENDIF () \ No newline at end of file diff --git a/src/kit/CMakeLists.txt b/src/kit/CMakeLists.txt index 7095d797555091ac553ffa6e023ed47f75f9305d..3bacd426f3fc92b18d50e06033f3ad913375540f 100644 --- a/src/kit/CMakeLists.txt +++ b/src/kit/CMakeLists.txt @@ -3,7 +3,5 @@ PROJECT(TDengine) ADD_SUBDIRECTORY(shell) ADD_SUBDIRECTORY(taosdemo) -ADD_SUBDIRECTORY(taosdump) -ADD_SUBDIRECTORY(taosmigrate) #ADD_SUBDIRECTORY(taosClusterTest) ADD_SUBDIRECTORY(taosnetwork) diff --git a/src/kit/shell/CMakeLists.txt b/src/kit/shell/CMakeLists.txt index 445d4f6951af4cf97c1a919893838625281c6c44..76af19f4815a8cc9fda812bc1f8d9ccf1356f174 100644 --- a/src/kit/shell/CMakeLists.txt +++ b/src/kit/shell/CMakeLists.txt @@ -1,15 +1,11 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -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/client/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) INCLUDE_DIRECTORIES(inc) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) +IF (TD_LINUX) AUX_SOURCE_DIRECTORY(./src SRC) LIST(REMOVE_ITEM SRC ./src/shellWindows.c) LIST(REMOVE_ITEM SRC ./src/shellDarwin.c) @@ -23,15 +19,13 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) SET_TARGET_PROPERTIES(shell PROPERTIES OUTPUT_NAME taos) ELSEIF (TD_WINDOWS) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/regex) LIST(APPEND SRC ./src/shellEngine.c) LIST(APPEND SRC ./src/shellMain.c) LIST(APPEND SRC ./src/shellWindows.c) ADD_EXECUTABLE(shell ${SRC}) TARGET_LINK_LIBRARIES(shell taos_static) SET_TARGET_PROPERTIES(shell PROPERTIES OUTPUT_NAME taos) -ELSEIF (TD_DARWIN_64) +ELSEIF (TD_DARWIN) LIST(APPEND SRC ./src/shellEngine.c) LIST(APPEND SRC ./src/shellMain.c) LIST(APPEND SRC ./src/shellDarwin.c) diff --git a/src/kit/taosdemo/CMakeLists.txt b/src/kit/taosdemo/CMakeLists.txt index 5045e8cd3ffae75436950a2b8a102977d6f8a305..a13bb767fcf8f78bac4f79217992a4d30413d761 100644 --- a/src/kit/taosdemo/CMakeLists.txt +++ b/src/kit/taosdemo/CMakeLists.txt @@ -1,13 +1,10 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(inc) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) +IF (TD_LINUX) AUX_SOURCE_DIRECTORY(. SRC) ADD_EXECUTABLE(taosdemo ${SRC}) @@ -16,5 +13,5 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) # ELSE () # TARGET_LINK_LIBRARIES(taosdemo taos_static) # ENDIF () - + ENDIF () diff --git a/src/kit/taosdump/CMakeLists.txt b/src/kit/taosdump/CMakeLists.txt deleted file mode 100644 index 1c5dd3eda235dc56c490cf9027e8c31d3017431a..0000000000000000000000000000000000000000 --- a/src/kit/taosdump/CMakeLists.txt +++ /dev/null @@ -1,23 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -PROJECT(TDengine) - -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) -INCLUDE_DIRECTORIES(inc) - -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - AUX_SOURCE_DIRECTORY(. SRC) - ADD_EXECUTABLE(taosdump ${SRC}) - -# IF (TD_PAGMODE_LITE) - TARGET_LINK_LIBRARIES(taosdump taos) -# ELSE () -# TARGET_LINK_LIBRARIES(taosdump taos_static) -# ENDIF () - - -ENDIF () diff --git a/src/kit/taosdump/taosdump.c b/src/kit/taosdump/taosdump.c deleted file mode 100644 index 8a05c893e8f406bb37abf002161dcfbd87ac0ab6..0000000000000000000000000000000000000000 --- a/src/kit/taosdump/taosdump.c +++ /dev/null @@ -1,2235 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include -#include -#ifndef _ALPINE - #include -#endif -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "os.h" -#include "taos.h" -#include "taosdef.h" -#include "taosmsg.h" -#include "tglobal.h" -#include "tsclient.h" -#include "tsdb.h" -#include "tutil.h" - -#define COMMAND_SIZE 65536 -//#define DEFAULT_DUMP_FILE "taosdump.sql" - -int converStringToReadable(char *str, int size, char *buf, int bufsize); -int convertNCharToReadable(char *str, int size, char *buf, int bufsize); -void taosDumpCharset(FILE *fp); -void taosLoadFileCharset(FILE *fp, char *fcharset); - -typedef struct { - short bytes; - int8_t type; -} SOColInfo; - -// -------------------------- SHOW DATABASE INTERFACE----------------------- -enum _show_db_index { - TSDB_SHOW_DB_NAME_INDEX, - TSDB_SHOW_DB_CREATED_TIME_INDEX, - TSDB_SHOW_DB_VGROUPS_INDEX, - TSDB_SHOW_DB_NTABLES_INDEX, - TSDB_SHOW_DB_REPLICA_INDEX, - TSDB_SHOW_DB_DAYS_INDEX, - TSDB_SHOW_DB_KEEP_INDEX, - TSDB_SHOW_DB_TABLES_INDEX, - TSDB_SHOW_DB_ROWS_INDEX, - TSDB_SHOW_DB_CACHE_INDEX, - TSDB_SHOW_DB_ABLOCKS_INDEX, - TSDB_SHOW_DB_TBLOCKS_INDEX, - TSDB_SHOW_DB_CTIME_INDEX, - TSDB_SHOW_DB_CLOG_INDEX, - TSDB_SHOW_DB_COMP_INDEX, - TSDB_MAX_SHOW_DB -}; - -// -----------------------------------------SHOW TABLES CONFIGURE ------------------------------------- -enum _show_tables_index { - TSDB_SHOW_TABLES_NAME_INDEX, - TSDB_SHOW_TABLES_CREATED_TIME_INDEX, - TSDB_SHOW_TABLES_COLUMNS_INDEX, - TSDB_SHOW_TABLES_METRIC_INDEX, - TSDB_MAX_SHOW_TABLES -}; - -// ---------------------------------- DESCRIBE METRIC CONFIGURE ------------------------------ -enum _describe_table_index { - TSDB_DESCRIBE_METRIC_FIELD_INDEX, - TSDB_DESCRIBE_METRIC_TYPE_INDEX, - TSDB_DESCRIBE_METRIC_LENGTH_INDEX, - TSDB_DESCRIBE_METRIC_NOTE_INDEX, - TSDB_MAX_DESCRIBE_METRIC -}; - -typedef struct { - char field[TSDB_COL_NAME_LEN + 1]; - char type[16]; - int length; - char note[128]; -} SColDes; - -typedef struct { - char name[TSDB_COL_NAME_LEN + 1]; - SColDes cols[]; -} STableDef; - -extern char version[]; - -typedef struct { - char name[TSDB_DB_NAME_LEN + 1]; - int32_t replica; - int32_t days; - int32_t keep; - int32_t tables; - int32_t rows; - int32_t cache; - int32_t ablocks; - int32_t tblocks; - int32_t ctime; - int32_t clog; - int32_t comp; -} SDbInfo; - -typedef struct { - char name[TSDB_TABLE_NAME_LEN + 1]; - char metric[TSDB_TABLE_NAME_LEN + 1]; -} STableRecord; - -typedef struct { - bool isMetric; - STableRecord tableRecord; -} STableRecordInfo; - -typedef struct { - pthread_t threadID; - int32_t threadIndex; - int32_t totalThreads; - char dbName[TSDB_TABLE_NAME_LEN + 1]; - void *taosCon; -} SThreadParaObj; - -static int64_t totalDumpOutRows = 0; - -SDbInfo **dbInfos = NULL; - -const char *argp_program_version = version; -const char *argp_program_bug_address = ""; - -/* Program documentation. */ -static char doc[] = ""; -/* "Argp example #4 -- a program with somewhat more complicated\ */ -/* options\ */ -/* \vThis part of the documentation comes *after* the options;\ */ -/* note that the text is automatically filled, but it's possible\ */ -/* to force a line-break, e.g.\n<-- here."; */ - -/* A description of the arguments we accept. */ -static char args_doc[] = "dbname [tbname ...]\n--databases dbname ...\n--all-databases\n-i inpath\n-o outpath"; - -/* Keys for options without short-options. */ -#define OPT_ABORT 1 /* –abort */ - -/* The options we understand. */ -static struct argp_option options[] = { - // connection option - {"host", 'h', "HOST", 0, "Server host dumping data from. Default is localhost.", 0}, - {"user", 'u', "USER", 0, "User name used to connect to server. Default is root.", 0}, - {"password", 'p', "PASSWORD", 0, "User password to connect to server. Default is taosdata.", 0}, - {"port", 'P', "PORT", 0, "Port to connect", 0}, - {"cversion", 'v', "CVERION", 0, "client version", 0}, - {"mysqlFlag", 'q', "MYSQLFLAG", 0, "mysqlFlag, Default is 0", 0}, - // input/output file - {"outpath", 'o', "OUTPATH", 0, "Output file path.", 1}, - {"inpath", 'i', "INPATH", 0, "Input file path.", 1}, - {"config", 'c', "CONFIG_DIR", 0, "Configure directory. Default is /etc/taos/taos.cfg.", 1}, - {"encode", 'e', "ENCODE", 0, "Input file encoding.", 1}, - // dump unit options - {"all-databases", 'A', 0, 0, "Dump all databases.", 2}, - {"databases", 'B', 0, 0, "Dump assigned databases", 2}, - // dump format options - {"schemaonly", 's', 0, 0, "Only dump schema.", 3}, - {"with-property", 'M', 0, 0, "Dump schema with properties.", 3}, - {"start-time", 'S', "START_TIME", 0, "Start time to dump.", 3}, - {"end-time", 'E', "END_TIME", 0, "End time to dump.", 3}, - {"data-batch", 'N', "DATA_BATCH", 0, "Number of data point per insert statement. Default is 1.", 3}, - {"table-batch", 't', "TABLE_BATCH", 0, "Number of table dumpout into one output file. Default is 1.", 3}, - {"thread_num", 'T', "THREAD_NUM", 0, "Number of thread for dump in file. Default is 5.", 3}, - {"allow-sys", 'a', 0, 0, "Allow to dump sys database", 3}, - {0}}; - -/* Used by main to communicate with parse_opt. */ -struct arguments { - // connection option - char *host; - char *user; - char *password; - uint16_t port; - char cversion[12]; - uint16_t mysqlFlag; - // output file - char outpath[TSDB_FILENAME_LEN+1]; - char inpath[TSDB_FILENAME_LEN+1]; - char *encode; - // dump unit option - bool all_databases; - bool databases; - // dump format option - bool schemaonly; - bool with_property; - int64_t start_time; - int64_t end_time; - int32_t data_batch; - int32_t table_batch; // num of table which will be dump into one output file. - bool allow_sys; - // other options - int32_t thread_num; - int abort; - char **arg_list; - int arg_list_len; - bool isDumpIn; -}; - -/* Parse a single option. */ -static error_t parse_opt(int key, char *arg, struct argp_state *state) { - /* Get the input argument from argp_parse, which we - know is a pointer to our arguments structure. */ - struct arguments *arguments = state->input; - wordexp_t full_path; - - switch (key) { - // connection option - case 'a': - arguments->allow_sys = true; - break; - case 'h': - arguments->host = arg; - break; - case 'u': - arguments->user = arg; - break; - case 'p': - arguments->password = arg; - break; - case 'P': - arguments->port = atoi(arg); - break; - case 'q': - arguments->mysqlFlag = atoi(arg); - break; - case 'v': - if (wordexp(arg, &full_path, 0) != 0) { - fprintf(stderr, "Invalid client vesion %s\n", arg); - return -1; - } - tstrncpy(arguments->cversion, full_path.we_wordv[0], 11); - wordfree(&full_path); - break; - // output file path - case 'o': - if (wordexp(arg, &full_path, 0) != 0) { - fprintf(stderr, "Invalid path %s\n", arg); - return -1; - } - tstrncpy(arguments->outpath, full_path.we_wordv[0], TSDB_FILENAME_LEN); - wordfree(&full_path); - break; - case 'i': - arguments->isDumpIn = true; - if (wordexp(arg, &full_path, 0) != 0) { - fprintf(stderr, "Invalid path %s\n", arg); - return -1; - } - tstrncpy(arguments->inpath, full_path.we_wordv[0], TSDB_FILENAME_LEN); - wordfree(&full_path); - break; - case 'c': - if (wordexp(arg, &full_path, 0) != 0) { - fprintf(stderr, "Invalid path %s\n", arg); - return -1; - } - tstrncpy(configDir, full_path.we_wordv[0], TSDB_FILENAME_LEN); - wordfree(&full_path); - break; - case 'e': - arguments->encode = arg; - break; - // dump unit option - case 'A': - arguments->all_databases = true; - break; - case 'B': - arguments->databases = true; - break; - // dump format option - case 's': - arguments->schemaonly = true; - break; - case 'M': - arguments->with_property = true; - break; - case 'S': - // parse time here. - arguments->start_time = atol(arg); - break; - case 'E': - arguments->end_time = atol(arg); - break; - case 'N': - arguments->data_batch = atoi(arg); - break; - case 't': - arguments->table_batch = atoi(arg); - break; - case 'T': - arguments->thread_num = atoi(arg); - break; - case OPT_ABORT: - arguments->abort = 1; - break; - case ARGP_KEY_ARG: - arguments->arg_list = &state->argv[state->next - 1]; - arguments->arg_list_len = state->argc - state->next + 1; - state->next = state->argc; - break; - - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -/* Our argp parser. */ -static struct argp argp = {options, parse_opt, args_doc, doc}; - -int taosDumpOut(struct arguments *arguments); -int taosDumpIn(struct arguments *arguments); -void taosDumpCreateDbClause(SDbInfo *dbInfo, bool isDumpProperty, FILE *fp); -int taosDumpDb(SDbInfo *dbInfo, struct arguments *arguments, FILE *fp, TAOS *taosCon); -int32_t taosDumpStable(char *table, FILE *fp, TAOS* taosCon); -void taosDumpCreateTableClause(STableDef *tableDes, int numOfCols, FILE *fp); -void taosDumpCreateMTableClause(STableDef *tableDes, char *metric, int numOfCols, FILE *fp); -int32_t taosDumpTable(char *table, char *metric, struct arguments *arguments, FILE *fp, TAOS* taosCon); -int taosDumpTableData(FILE *fp, char *tbname, struct arguments *arguments, TAOS* taosCon); -int taosCheckParam(struct arguments *arguments); -void taosFreeDbInfos(); -static void taosStartDumpOutWorkThreads(struct arguments* args, int32_t numOfThread, char *dbName); - -struct arguments tsArguments = { - // connection option - NULL, - "root", - "taosdata", - 0, - "", - 0, - // outpath and inpath - "", - "", - NULL, - // dump unit option - false, - false, - // dump format option - false, - false, - 0, - INT64_MAX, - 1, - 1, - false, - // other options - 5, - 0, - NULL, - 0, - false -}; - -int queryDB(TAOS *taos, char *command) { - TAOS_RES *pSql = NULL; - int32_t code = -1; - - pSql = taos_query(taos, command); - code = taos_errno(pSql); - if (code) { - fprintf(stderr, "sql error: %s, reason:%s\n", command, taos_errstr(pSql)); - } - taos_free_result(pSql); - return code; -} - -int main(int argc, char *argv[]) { - - /* Parse our arguments; every option seen by parse_opt will be - reflected in arguments. */ - argp_parse(&argp, argc, argv, 0, 0, &tsArguments); - - if (tsArguments.abort) { - #ifndef _ALPINE - error(10, 0, "ABORTED"); - #else - abort(); - #endif - } - - printf("====== arguments config ======\n"); - { - printf("host: %s\n", tsArguments.host); - printf("user: %s\n", tsArguments.user); - printf("password: %s\n", tsArguments.password); - printf("port: %u\n", tsArguments.port); - printf("cversion: %s\n", tsArguments.cversion); - printf("mysqlFlag: %d\n", tsArguments.mysqlFlag); - printf("outpath: %s\n", tsArguments.outpath); - printf("inpath: %s\n", tsArguments.inpath); - printf("encode: %s\n", tsArguments.encode); - printf("all_databases: %d\n", tsArguments.all_databases); - printf("databases: %d\n", tsArguments.databases); - printf("schemaonly: %d\n", tsArguments.schemaonly); - printf("with_property: %d\n", tsArguments.with_property); - printf("start_time: %" PRId64 "\n", tsArguments.start_time); - printf("end_time: %" PRId64 "\n", tsArguments.end_time); - printf("data_batch: %d\n", tsArguments.data_batch); - printf("table_batch: %d\n", tsArguments.table_batch); - printf("allow_sys: %d\n", tsArguments.allow_sys); - printf("abort: %d\n", tsArguments.abort); - printf("isDumpIn: %d\n", tsArguments.isDumpIn); - printf("arg_list_len: %d\n", tsArguments.arg_list_len); - - for (int32_t i = 0; i < tsArguments.arg_list_len; i++) { - printf("arg_list[%d]: %s\n", i, tsArguments.arg_list[i]); - } - } - printf("==============================\n"); - - if (tsArguments.cversion[0] != 0){ - tstrncpy(version, tsArguments.cversion, 11); - } - - if (taosCheckParam(&tsArguments) < 0) { - exit(EXIT_FAILURE); - } - - if (tsArguments.isDumpIn) { - if (taosDumpIn(&tsArguments) < 0) return -1; - } else { - if (taosDumpOut(&tsArguments) < 0) return -1; - } - - return 0; -} - -void taosFreeDbInfos() { - if (dbInfos == NULL) return; - for (int i = 0; i < 128; i++) taosTFree(dbInfos[i]); - taosTFree(dbInfos); -} - -// check table is normal table or super table -int taosGetTableRecordInfo(char *table, STableRecordInfo *pTableRecordInfo, TAOS *taosCon) { - TAOS_ROW row = NULL; - bool isSet = false; - TAOS_RES *result = NULL; - - memset(pTableRecordInfo, 0, sizeof(STableRecordInfo)); - - char* tempCommand = (char *)malloc(COMMAND_SIZE); - if (tempCommand == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return -1; - } - - sprintf(tempCommand, "show tables like %s", table); - - result = taos_query(taosCon, tempCommand); - int32_t code = taos_errno(result); - - if (code != 0) { - fprintf(stderr, "failed to run command %s\n", tempCommand); - free(tempCommand); - taos_free_result(result); - return -1; - } - - TAOS_FIELD *fields = taos_fetch_fields(result); - - while ((row = taos_fetch_row(result)) != NULL) { - isSet = true; - pTableRecordInfo->isMetric = false; - strncpy(pTableRecordInfo->tableRecord.name, (char *)row[TSDB_SHOW_TABLES_NAME_INDEX], - fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes); - strncpy(pTableRecordInfo->tableRecord.metric, (char *)row[TSDB_SHOW_TABLES_METRIC_INDEX], - fields[TSDB_SHOW_TABLES_METRIC_INDEX].bytes); - break; - } - - taos_free_result(result); - result = NULL; - - if (isSet) { - free(tempCommand); - return 0; - } - - sprintf(tempCommand, "show stables like %s", table); - - result = taos_query(taosCon, tempCommand); - code = taos_errno(result); - - if (code != 0) { - fprintf(stderr, "failed to run command %s\n", tempCommand); - free(tempCommand); - taos_free_result(result); - return -1; - } - - while ((row = taos_fetch_row(result)) != NULL) { - isSet = true; - pTableRecordInfo->isMetric = true; - tstrncpy(pTableRecordInfo->tableRecord.metric, table, TSDB_TABLE_NAME_LEN); - break; - } - - taos_free_result(result); - result = NULL; - - if (isSet) { - free(tempCommand); - return 0; - } - fprintf(stderr, "invalid table/metric %s\n", table); - free(tempCommand); - return -1; -} - - -int32_t taosSaveAllNormalTableToTempFile(TAOS *taosCon, char*meter, char* metric, int* fd) { - STableRecord tableRecord; - - if (-1 == *fd) { - *fd = open(".tables.tmp.0", O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH); - if (*fd == -1) { - fprintf(stderr, "failed to open temp file: .tables.tmp.0\n"); - return -1; - } - } - - memset(&tableRecord, 0, sizeof(STableRecord)); - tstrncpy(tableRecord.name, meter, TSDB_TABLE_NAME_LEN); - tstrncpy(tableRecord.metric, metric, TSDB_TABLE_NAME_LEN); - - taosTWrite(*fd, &tableRecord, sizeof(STableRecord)); - return 0; -} - - -int32_t taosSaveTableOfMetricToTempFile(TAOS *taosCon, char* metric, struct arguments *arguments, int32_t* totalNumOfThread) { - TAOS_ROW row; - int fd = -1; - STableRecord tableRecord; - - char* tmpCommand = (char *)malloc(COMMAND_SIZE); - if (tmpCommand == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return -1; - } - - sprintf(tmpCommand, "select tbname from %s", metric); - - TAOS_RES *result = taos_query(taosCon, tmpCommand); - int32_t code = taos_errno(result); - if (code != 0) { - fprintf(stderr, "failed to run command %s\n", tmpCommand); - free(tmpCommand); - taos_free_result(result); - return -1; - } - - TAOS_FIELD *fields = taos_fetch_fields(result); - - int32_t numOfTable = 0; - int32_t numOfThread = *totalNumOfThread; - char tmpFileName[TSDB_FILENAME_LEN + 1]; - while ((row = taos_fetch_row(result)) != NULL) { - if (0 == numOfTable) { - memset(tmpFileName, 0, TSDB_FILENAME_LEN); - sprintf(tmpFileName, ".tables.tmp.%d", numOfThread); - fd = open(tmpFileName, O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH); - if (fd == -1) { - fprintf(stderr, "failed to open temp file: %s\n", tmpFileName); - taos_free_result(result); - for (int32_t loopCnt = 0; loopCnt < numOfThread; loopCnt++) { - sprintf(tmpFileName, ".tables.tmp.%d", loopCnt); - (void)remove(tmpFileName); - } - free(tmpCommand); - return -1; - } - - numOfThread++; - } - - memset(&tableRecord, 0, sizeof(STableRecord)); - tstrncpy(tableRecord.name, (char *)row[0], fields[0].bytes); - tstrncpy(tableRecord.metric, metric, TSDB_TABLE_NAME_LEN); - - taosTWrite(fd, &tableRecord, sizeof(STableRecord)); - - numOfTable++; - - if (numOfTable >= arguments->table_batch) { - numOfTable = 0; - close(fd); - fd = -1; - } - } - - if (fd >= 0) { - close(fd); - fd = -1; - } - - taos_free_result(result); - - *totalNumOfThread = numOfThread; - - free(tmpCommand); - - return 0; -} - -int taosDumpOut(struct arguments *arguments) { - TAOS *taos = NULL; - TAOS_RES *result = NULL; - char *command = NULL; - - TAOS_ROW row; - FILE *fp = NULL; - int32_t count = 0; - STableRecordInfo tableRecordInfo; - - char tmpBuf[TSDB_FILENAME_LEN+9] = {0}; - if (arguments->outpath[0] != 0) { - sprintf(tmpBuf, "%s/dbs.sql", arguments->outpath); - } else { - sprintf(tmpBuf, "dbs.sql"); - } - - fp = fopen(tmpBuf, "w"); - if (fp == NULL) { - fprintf(stderr, "failed to open file %s\n", tmpBuf); - return -1; - } - - dbInfos = (SDbInfo **)calloc(128, sizeof(SDbInfo *)); - if (dbInfos == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - goto _exit_failure; - } - - command = (char *)malloc(COMMAND_SIZE); - if (command == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - goto _exit_failure; - } - - /* Connect to server */ - taos = taos_connect(arguments->host, arguments->user, arguments->password, NULL, arguments->port); - if (taos == NULL) { - fprintf(stderr, "failed to connect to TDengine server\n"); - goto _exit_failure; - } - - /* --------------------------------- Main Code -------------------------------- */ - /* if (arguments->databases || arguments->all_databases) { // dump part of databases or all databases */ - /* */ - taosDumpCharset(fp); - - sprintf(command, "show databases"); - result = taos_query(taos, command); - int32_t code = taos_errno(result); - - if (code != 0) { - fprintf(stderr, "failed to run command: %s, reason: %s\n", command, taos_errstr(taos)); - goto _exit_failure; - } - - TAOS_FIELD *fields = taos_fetch_fields(result); - - while ((row = taos_fetch_row(result)) != NULL) { - // sys database name : 'monitor', but subsequent version changed to 'log' - if (strncasecmp(row[TSDB_SHOW_DB_NAME_INDEX], "monitor", fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0 && - (!arguments->allow_sys)) - continue; - - if (arguments->databases) { // input multi dbs - for (int i = 0; arguments->arg_list[i]; i++) { - if (strncasecmp(arguments->arg_list[i], (char *)row[TSDB_SHOW_DB_NAME_INDEX], - fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) - goto _dump_db_point; - } - continue; - } else if (!arguments->all_databases) { // only input one db - if (strncasecmp(arguments->arg_list[0], (char *)row[TSDB_SHOW_DB_NAME_INDEX], - fields[TSDB_SHOW_DB_NAME_INDEX].bytes) == 0) - goto _dump_db_point; - else - continue; - } - - _dump_db_point: - - dbInfos[count] = (SDbInfo *)calloc(1, sizeof(SDbInfo)); - if (dbInfos[count] == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - goto _exit_failure; - } - - strncpy(dbInfos[count]->name, (char *)row[TSDB_SHOW_DB_NAME_INDEX], fields[TSDB_SHOW_DB_NAME_INDEX].bytes); - #if 0 - dbInfos[count]->replica = (int)(*((int16_t *)row[TSDB_SHOW_DB_REPLICA_INDEX])); - dbInfos[count]->days = (int)(*((int16_t *)row[TSDB_SHOW_DB_DAYS_INDEX])); - dbInfos[count]->keep = *((int *)row[TSDB_SHOW_DB_KEEP_INDEX]); - dbInfos[count]->tables = *((int *)row[TSDB_SHOW_DB_TABLES_INDEX]); - dbInfos[count]->rows = *((int *)row[TSDB_SHOW_DB_ROWS_INDEX]); - dbInfos[count]->cache = *((int *)row[TSDB_SHOW_DB_CACHE_INDEX]); - dbInfos[count]->ablocks = *((int *)row[TSDB_SHOW_DB_ABLOCKS_INDEX]); - dbInfos[count]->tblocks = (int)(*((int16_t *)row[TSDB_SHOW_DB_TBLOCKS_INDEX])); - dbInfos[count]->ctime = *((int *)row[TSDB_SHOW_DB_CTIME_INDEX]); - dbInfos[count]->clog = (int)(*((int8_t *)row[TSDB_SHOW_DB_CLOG_INDEX])); - dbInfos[count]->comp = (int)(*((int8_t *)row[TSDB_SHOW_DB_COMP_INDEX])); -#endif - - count++; - - if (arguments->databases) { - if (count > arguments->arg_list_len) break; - - } else if (!arguments->all_databases) { - if (count >= 1) break; - } - } - - if (count == 0) { - fprintf(stderr, "No databases valid to dump\n"); - goto _exit_failure; - } - - if (arguments->databases || arguments->all_databases) { // case: taosdump --databases dbx dby ... OR taosdump --all-databases - for (int i = 0; i < count; i++) { - taosDumpDb(dbInfos[i], arguments, fp, taos); - } - } else { - if (arguments->arg_list_len == 1) { // case: taosdump - taosDumpDb(dbInfos[0], arguments, fp, taos); - } else { // case: taosdump tablex tabley ... - taosDumpCreateDbClause(dbInfos[0], arguments->with_property, fp); - - sprintf(command, "use %s", dbInfos[0]->name); - - result = taos_query(taos, command); - int32_t code = taos_errno(result); - if (code != 0) { - fprintf(stderr, "invalid database %s\n", dbInfos[0]->name); - goto _exit_failure; - } - - fprintf(fp, "USE %s;\n\n", dbInfos[0]->name); - - int32_t totalNumOfThread = 1; // 0: all normal talbe into .tables.tmp.0 - int normalTblFd = -1; - int32_t retCode; - for (int i = 1; arguments->arg_list[i]; i++) { - if (taosGetTableRecordInfo(arguments->arg_list[i], &tableRecordInfo, taos) < 0) { - fprintf(stderr, "input the invalide table %s\n", arguments->arg_list[i]); - continue; - } - - if (tableRecordInfo.isMetric) { // dump all table of this metric - (void)taosDumpStable(tableRecordInfo.tableRecord.metric, fp, taos); - retCode = taosSaveTableOfMetricToTempFile(taos, tableRecordInfo.tableRecord.metric, arguments, &totalNumOfThread); - } else { - if (tableRecordInfo.tableRecord.metric[0] != '\0') { // dump this sub table and it's metric - (void)taosDumpStable(tableRecordInfo.tableRecord.metric, fp, taos); - } - retCode = taosSaveAllNormalTableToTempFile(taos, tableRecordInfo.tableRecord.name, tableRecordInfo.tableRecord.metric, &normalTblFd); - } - - if (retCode < 0) { - if (-1 != normalTblFd){ - taosClose(normalTblFd); - } - goto _clean_tmp_file; - } - } - - if (-1 != normalTblFd){ - taosClose(normalTblFd); - } - - // start multi threads to dumpout - taosStartDumpOutWorkThreads(arguments, totalNumOfThread, dbInfos[0]->name); - - char tmpFileName[TSDB_FILENAME_LEN + 1]; - _clean_tmp_file: - for (int loopCnt = 0; loopCnt < totalNumOfThread; loopCnt++) { - sprintf(tmpFileName, ".tables.tmp.%d", loopCnt); - remove(tmpFileName); - } - } - } - - /* Close the handle and return */ - fclose(fp); - taos_close(taos); - taos_free_result(result); - taosTFree(command); - taosFreeDbInfos(); - fprintf(stderr, "dump out rows: %" PRId64 "\n", totalDumpOutRows); - return 0; - -_exit_failure: - fclose(fp); - taos_close(taos); - taos_free_result(result); - taosTFree(command); - taosFreeDbInfos(); - fprintf(stderr, "dump out rows: %" PRId64 "\n", totalDumpOutRows); - return -1; -} - -int taosGetTableDes(char *table, STableDef *tableDes, TAOS* taosCon, bool isSuperTable) { - TAOS_ROW row = NULL; - TAOS_RES *tmpResult = NULL; - int count = 0; - - char* tempCommand = (char *)malloc(COMMAND_SIZE); - if (tempCommand == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return -1; - } - - char* tbuf = (char *)malloc(COMMAND_SIZE); - if (tbuf == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - free(tempCommand); - return -1; - } - - sprintf(tempCommand, "describe %s", table); - - tmpResult = taos_query(taosCon, tempCommand); - int32_t code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "failed to run command %s\n", tempCommand); - free(tempCommand); - free(tbuf); - taos_free_result(tmpResult); - return -1; - } - - TAOS_FIELD *fields = taos_fetch_fields(tmpResult); - - tstrncpy(tableDes->name, table, TSDB_COL_NAME_LEN); - - while ((row = taos_fetch_row(tmpResult)) != NULL) { - strncpy(tableDes->cols[count].field, (char *)row[TSDB_DESCRIBE_METRIC_FIELD_INDEX], - fields[TSDB_DESCRIBE_METRIC_FIELD_INDEX].bytes); - strncpy(tableDes->cols[count].type, (char *)row[TSDB_DESCRIBE_METRIC_TYPE_INDEX], - fields[TSDB_DESCRIBE_METRIC_TYPE_INDEX].bytes); - tableDes->cols[count].length = *((int *)row[TSDB_DESCRIBE_METRIC_LENGTH_INDEX]); - strncpy(tableDes->cols[count].note, (char *)row[TSDB_DESCRIBE_METRIC_NOTE_INDEX], - fields[TSDB_DESCRIBE_METRIC_NOTE_INDEX].bytes); - - count++; - } - - taos_free_result(tmpResult); - tmpResult = NULL; - - if (isSuperTable) { - free(tempCommand); - free(tbuf); - return count; - } - - // if chidl-table have tag, using select tagName from table to get tagValue - for (int i = 0 ; i < count; i++) { - if (strcmp(tableDes->cols[i].note, "TAG") != 0) continue; - - - sprintf(tempCommand, "select %s from %s", tableDes->cols[i].field, table); - - tmpResult = taos_query(taosCon, tempCommand); - code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "failed to run command %s\n", tempCommand); - free(tempCommand); - free(tbuf); - taos_free_result(tmpResult); - return -1; - } - - fields = taos_fetch_fields(tmpResult); - - row = taos_fetch_row(tmpResult); - if (NULL == row) { - fprintf(stderr, " fetch failed to run command %s\n", tempCommand); - free(tempCommand); - free(tbuf); - taos_free_result(tmpResult); - return -1; - } - - switch (fields[0].type) { - case TSDB_DATA_TYPE_BOOL: - sprintf(tableDes->cols[i].note, "%d", ((((int)(*((char *)row[0]))) == 1) ? 1 : 0)); - break; - case TSDB_DATA_TYPE_TINYINT: - sprintf(tableDes->cols[i].note, "%d", (int)(*((char *)row[0]))); - break; - case TSDB_DATA_TYPE_SMALLINT: - sprintf(tableDes->cols[i].note, "%d", (int)(*((short *)row[0]))); - break; - case TSDB_DATA_TYPE_INT: - sprintf(tableDes->cols[i].note, "%d", *((int *)row[0])); - break; - case TSDB_DATA_TYPE_BIGINT: - sprintf(tableDes->cols[i].note, "%" PRId64 "", *((int64_t *)row[0])); - break; - case TSDB_DATA_TYPE_FLOAT: - sprintf(tableDes->cols[i].note, "%f", GET_FLOAT_VAL(row[0])); - break; - case TSDB_DATA_TYPE_DOUBLE: - sprintf(tableDes->cols[i].note, "%f", GET_DOUBLE_VAL(row[0])); - break; - case TSDB_DATA_TYPE_BINARY: - tableDes->cols[i].note[0] = '\''; - converStringToReadable((char *)row[0], fields[0].bytes, tbuf, COMMAND_SIZE); - char* pstr = stpcpy(&(tableDes->cols[i].note[1]), tbuf); - *(pstr++) = '\''; - break; - case TSDB_DATA_TYPE_NCHAR: - convertNCharToReadable((char *)row[0], fields[0].bytes, tbuf, COMMAND_SIZE); - sprintf(tableDes->cols[i].note, "\'%s\'", tbuf); - break; - case TSDB_DATA_TYPE_TIMESTAMP: - sprintf(tableDes->cols[i].note, "%" PRId64 "", *(int64_t *)row[0]); - #if 0 - if (!arguments->mysqlFlag) { - sprintf(tableDes->cols[i].note, "%" PRId64 "", *(int64_t *)row[0]); - } else { - char buf[64] = "\0"; - int64_t ts = *((int64_t *)row[0]); - time_t tt = (time_t)(ts / 1000); - struct tm *ptm = localtime(&tt); - strftime(buf, 64, "%y-%m-%d %H:%M:%S", ptm); - sprintf(tableDes->cols[i].note, "\'%s.%03d\'", buf, (int)(ts % 1000)); - } - #endif - break; - default: - break; - } - - taos_free_result(tmpResult); - tmpResult = NULL; - } - - free(tempCommand); - free(tbuf); - - return count; -} - -int32_t taosDumpTable(char *table, char *metric, struct arguments *arguments, FILE *fp, TAOS* taosCon) { - int count = 0; - - STableDef *tableDes = (STableDef *)calloc(1, sizeof(STableDef) + sizeof(SColDes) * TSDB_MAX_COLUMNS); - - if (metric != NULL && metric[0] != '\0') { // dump table schema which is created by using super table - /* - count = taosGetTableDes(metric, tableDes, taosCon); - - if (count < 0) { - free(tableDes); - return -1; - } - - taosDumpCreateTableClause(tableDes, count, fp); - - memset(tableDes, 0, sizeof(STableDef) + sizeof(SColDes) * TSDB_MAX_COLUMNS); - */ - - count = taosGetTableDes(table, tableDes, taosCon, false); - - if (count < 0) { - free(tableDes); - return -1; - } - - // create child-table using super-table - taosDumpCreateMTableClause(tableDes, metric, count, fp); - - } else { // dump table definition - count = taosGetTableDes(table, tableDes, taosCon, false); - - if (count < 0) { - free(tableDes); - return -1; - } - - // create normal-table or super-table - taosDumpCreateTableClause(tableDes, count, fp); - } - - free(tableDes); - - return taosDumpTableData(fp, table, arguments, taosCon); -} - -void taosDumpCreateDbClause(SDbInfo *dbInfo, bool isDumpProperty, FILE *fp) { - - char* tmpCommand = (char *)malloc(COMMAND_SIZE); - if (tmpCommand == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return; - } - - char *pstr = tmpCommand; - - pstr += sprintf(pstr, "CREATE DATABASE IF NOT EXISTS %s", dbInfo->name); - if (isDumpProperty) { - pstr += sprintf(pstr, - " REPLICA %d DAYS %d KEEP %d TABLES %d ROWS %d CACHE %d ABLOCKS %d TBLOCKS %d CTIME %d CLOG %d COMP %d", - dbInfo->replica, dbInfo->days, dbInfo->keep, dbInfo->tables, dbInfo->rows, dbInfo->cache, - dbInfo->ablocks, dbInfo->tblocks, dbInfo->ctime, dbInfo->clog, dbInfo->comp); - } - - pstr += sprintf(pstr, ";"); - - fprintf(fp, "%s\n\n", tmpCommand); - free(tmpCommand); -} - -void* taosDumpOutWorkThreadFp(void *arg) -{ - SThreadParaObj *pThread = (SThreadParaObj*)arg; - STableRecord tableRecord; - int fd; - - char tmpFileName[TSDB_FILENAME_LEN*4] = {0}; - sprintf(tmpFileName, ".tables.tmp.%d", pThread->threadIndex); - fd = open(tmpFileName, O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH); - if (fd == -1) { - fprintf(stderr, "taosDumpTableFp() failed to open temp file: %s\n", tmpFileName); - return NULL; - } - - FILE *fp = NULL; - memset(tmpFileName, 0, TSDB_FILENAME_LEN + 128); - - if (tsArguments.outpath[0] != 0) { - sprintf(tmpFileName, "%s/%s.tables.%d.sql", tsArguments.outpath, pThread->dbName, pThread->threadIndex); - } else { - sprintf(tmpFileName, "%s.tables.%d.sql", pThread->dbName, pThread->threadIndex); - } - - fp = fopen(tmpFileName, "w"); - if (fp == NULL) { - fprintf(stderr, "failed to open file %s\n", tmpFileName); - close(fd); - return NULL; - } - - memset(tmpFileName, 0, TSDB_FILENAME_LEN); - sprintf(tmpFileName, "use %s", pThread->dbName); - - TAOS_RES* tmpResult = taos_query(pThread->taosCon, tmpFileName); - int32_t code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "invalid database %s\n", pThread->dbName); - taos_free_result(tmpResult); - fclose(fp); - close(fd); - return NULL; - } - - fprintf(fp, "USE %s\n\n", pThread->dbName); - while (1) { - ssize_t readLen = read(fd, &tableRecord, sizeof(STableRecord)); - if (readLen <= 0) break; - taosDumpTable(tableRecord.name, tableRecord.metric, &tsArguments, fp, pThread->taosCon); - } - - taos_free_result(tmpResult); - close(fd); - fclose(fp); - - return NULL; -} - -static void taosStartDumpOutWorkThreads(struct arguments* args, int32_t numOfThread, char *dbName) -{ - pthread_attr_t thattr; - SThreadParaObj *threadObj = (SThreadParaObj *)calloc(numOfThread, sizeof(SThreadParaObj)); - for (int t = 0; t < numOfThread; ++t) { - SThreadParaObj *pThread = threadObj + t; - pThread->threadIndex = t; - pThread->totalThreads = numOfThread; - tstrncpy(pThread->dbName, dbName, TSDB_TABLE_NAME_LEN); - pThread->taosCon = taos_connect(args->host, args->user, args->password, NULL, args->port); - - if (pThread->taosCon == NULL) { - fprintf(stderr, "ERROR: thread:%d failed connect to TDengine, error:%s\n", pThread->threadIndex, taos_errstr(pThread->taosCon)); - exit(0); - } - - pthread_attr_init(&thattr); - pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); - - if (pthread_create(&(pThread->threadID), &thattr, taosDumpOutWorkThreadFp, (void*)pThread) != 0) { - fprintf(stderr, "ERROR: thread:%d failed to start\n", pThread->threadIndex); - exit(0); - } - } - - for (int32_t t = 0; t < numOfThread; ++t) { - pthread_join(threadObj[t].threadID, NULL); - } - - for (int32_t t = 0; t < numOfThread; ++t) { - taos_close(threadObj[t].taosCon); - } - free(threadObj); -} - - - -int32_t taosDumpStable(char *table, FILE *fp, TAOS* taosCon) { - int count = 0; - - STableDef *tableDes = (STableDef *)calloc(1, sizeof(STableDef) + sizeof(SColDes) * TSDB_MAX_COLUMNS); - if (NULL == tableDes) { - fprintf(stderr, "failed to allocate memory\n"); - exit(-1); - } - - count = taosGetTableDes(table, tableDes, taosCon, true); - - if (count < 0) { - free(tableDes); - fprintf(stderr, "failed to get stable schema\n"); - exit(-1); - } - - taosDumpCreateTableClause(tableDes, count, fp); - - free(tableDes); - return 0; -} - - -int32_t taosDumpCreateSuperTableClause(TAOS* taosCon, char* dbName, FILE *fp) -{ - TAOS_ROW row; - int fd = -1; - STableRecord tableRecord; - - char* tmpCommand = (char *)malloc(COMMAND_SIZE); - if (tmpCommand == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - exit(-1); - } - - sprintf(tmpCommand, "use %s", dbName); - - TAOS_RES* tmpResult = taos_query(taosCon, tmpCommand); - int32_t code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "invalid database %s, error: %s\n", dbName, taos_errstr(taosCon)); - free(tmpCommand); - taos_free_result(tmpResult); - exit(-1); - } - - taos_free_result(tmpResult); - - sprintf(tmpCommand, "show stables"); - - tmpResult = taos_query(taosCon, tmpCommand); - code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "failed to run command %s, error: %s\n", tmpCommand, taos_errstr(taosCon)); - free(tmpCommand); - taos_free_result(tmpResult); - exit(-1); - } - - TAOS_FIELD *fields = taos_fetch_fields(tmpResult); - - char tmpFileName[TSDB_FILENAME_LEN + 1]; - memset(tmpFileName, 0, TSDB_FILENAME_LEN); - sprintf(tmpFileName, ".stables.tmp"); - fd = open(tmpFileName, O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH); - if (fd == -1) { - fprintf(stderr, "failed to open temp file: %s\n", tmpFileName); - taos_free_result(tmpResult); - free(tmpCommand); - (void)remove(".stables.tmp"); - exit(-1); - } - - while ((row = taos_fetch_row(tmpResult)) != NULL) { - memset(&tableRecord, 0, sizeof(STableRecord)); - strncpy(tableRecord.name, (char *)row[TSDB_SHOW_TABLES_NAME_INDEX], fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes); - taosTWrite(fd, &tableRecord, sizeof(STableRecord)); - } - - taos_free_result(tmpResult); - (void)lseek(fd, 0, SEEK_SET); - - while (1) { - ssize_t readLen = read(fd, &tableRecord, sizeof(STableRecord)); - if (readLen <= 0) break; - - (void)taosDumpStable(tableRecord.name, fp, taosCon); - } - - close(fd); - (void)remove(".stables.tmp"); - - free(tmpCommand); - return 0; -} - - -int taosDumpDb(SDbInfo *dbInfo, struct arguments *arguments, FILE *fp, TAOS *taosCon) { - TAOS_ROW row; - int fd = -1; - STableRecord tableRecord; - - taosDumpCreateDbClause(dbInfo, arguments->with_property, fp); - - char* tmpCommand = (char *)malloc(COMMAND_SIZE); - if (tmpCommand == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return -1; - } - - sprintf(tmpCommand, "use %s", dbInfo->name); - - TAOS_RES* tmpResult = taos_query(taosCon, tmpCommand); - int32_t code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "invalid database %s\n", dbInfo->name); - free(tmpCommand); - taos_free_result(tmpResult); - return -1; - } - taos_free_result(tmpResult); - - fprintf(fp, "USE %s\n\n", dbInfo->name); - - (void)taosDumpCreateSuperTableClause(taosCon, dbInfo->name, fp); - - sprintf(tmpCommand, "show tables"); - - tmpResult = taos_query(taosCon, tmpCommand); - code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "failed to run command %s\n", tmpCommand); - free(tmpCommand); - taos_free_result(tmpResult); - return -1; - } - - TAOS_FIELD *fields = taos_fetch_fields(tmpResult); - - int32_t numOfTable = 0; - int32_t numOfThread = 0; - char tmpFileName[TSDB_FILENAME_LEN + 1]; - while ((row = taos_fetch_row(tmpResult)) != NULL) { - if (0 == numOfTable) { - memset(tmpFileName, 0, TSDB_FILENAME_LEN); - sprintf(tmpFileName, ".tables.tmp.%d", numOfThread); - fd = open(tmpFileName, O_RDWR | O_CREAT, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH); - if (fd == -1) { - fprintf(stderr, "failed to open temp file: %s\n", tmpFileName); - taos_free_result(tmpResult); - for (int32_t loopCnt = 0; loopCnt < numOfThread; loopCnt++) { - sprintf(tmpFileName, ".tables.tmp.%d", loopCnt); - (void)remove(tmpFileName); - } - free(tmpCommand); - return -1; - } - - numOfThread++; - } - - memset(&tableRecord, 0, sizeof(STableRecord)); - tstrncpy(tableRecord.name, (char *)row[TSDB_SHOW_TABLES_NAME_INDEX], fields[TSDB_SHOW_TABLES_NAME_INDEX].bytes); - tstrncpy(tableRecord.metric, (char *)row[TSDB_SHOW_TABLES_METRIC_INDEX], fields[TSDB_SHOW_TABLES_METRIC_INDEX].bytes); - - taosTWrite(fd, &tableRecord, sizeof(STableRecord)); - - numOfTable++; - - if (numOfTable >= arguments->table_batch) { - numOfTable = 0; - close(fd); - fd = -1; - } - } - - if (fd >= 0) { - close(fd); - fd = -1; - } - - taos_free_result(tmpResult); - - // start multi threads to dumpout - taosStartDumpOutWorkThreads(arguments, numOfThread, dbInfo->name); - for (int loopCnt = 0; loopCnt < numOfThread; loopCnt++) { - sprintf(tmpFileName, ".tables.tmp.%d", loopCnt); - (void)remove(tmpFileName); - } - - free(tmpCommand); - - return 0; -} - -void taosDumpCreateTableClause(STableDef *tableDes, int numOfCols, FILE *fp) { - int counter = 0; - int count_temp = 0; - - char* tmpBuf = (char *)malloc(COMMAND_SIZE); - if (tmpBuf == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return; - } - - char* pstr = tmpBuf; - - pstr += sprintf(tmpBuf, "CREATE TABLE IF NOT EXISTS %s", tableDes->name); - - for (; counter < numOfCols; counter++) { - if (tableDes->cols[counter].note[0] != '\0') break; - - if (counter == 0) { - pstr += sprintf(pstr, " (%s %s", tableDes->cols[counter].field, tableDes->cols[counter].type); - } else { - pstr += sprintf(pstr, ", %s %s", tableDes->cols[counter].field, tableDes->cols[counter].type); - } - - if (strcasecmp(tableDes->cols[counter].type, "binary") == 0 || - strcasecmp(tableDes->cols[counter].type, "nchar") == 0) { - pstr += sprintf(pstr, "(%d)", tableDes->cols[counter].length); - } - } - - count_temp = counter; - - for (; counter < numOfCols; counter++) { - if (counter == count_temp) { - pstr += sprintf(pstr, ") TAGS (%s %s", tableDes->cols[counter].field, tableDes->cols[counter].type); - } else { - pstr += sprintf(pstr, ", %s %s", tableDes->cols[counter].field, tableDes->cols[counter].type); - } - - if (strcasecmp(tableDes->cols[counter].type, "binary") == 0 || - strcasecmp(tableDes->cols[counter].type, "nchar") == 0) { - pstr += sprintf(pstr, "(%d)", tableDes->cols[counter].length); - } - } - - pstr += sprintf(pstr, ");"); - - fprintf(fp, "%s\n", tmpBuf); - - free(tmpBuf); -} - -void taosDumpCreateMTableClause(STableDef *tableDes, char *metric, int numOfCols, FILE *fp) { - int counter = 0; - int count_temp = 0; - - char* tmpBuf = (char *)malloc(COMMAND_SIZE); - if (tmpBuf == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return; - } - - char *pstr = NULL; - pstr = tmpBuf; - - pstr += sprintf(tmpBuf, "CREATE TABLE IF NOT EXISTS %s USING %s TAGS (", tableDes->name, metric); - - for (; counter < numOfCols; counter++) { - if (tableDes->cols[counter].note[0] != '\0') break; - } - - assert(counter < numOfCols); - count_temp = counter; - - for (; counter < numOfCols; counter++) { - if (counter != count_temp) { - if (strcasecmp(tableDes->cols[counter].type, "binary") == 0 || - strcasecmp(tableDes->cols[counter].type, "nchar") == 0) { - //pstr += sprintf(pstr, ", \'%s\'", tableDes->cols[counter].note); - pstr += sprintf(pstr, ", %s", tableDes->cols[counter].note); - } else { - pstr += sprintf(pstr, ", %s", tableDes->cols[counter].note); - } - } else { - if (strcasecmp(tableDes->cols[counter].type, "binary") == 0 || - strcasecmp(tableDes->cols[counter].type, "nchar") == 0) { - //pstr += sprintf(pstr, "\'%s\'", tableDes->cols[counter].note); - pstr += sprintf(pstr, "%s", tableDes->cols[counter].note); - } else { - pstr += sprintf(pstr, "%s", tableDes->cols[counter].note); - } - /* pstr += sprintf(pstr, "%s", tableDes->cols[counter].note); */ - } - - /* if (strcasecmp(tableDes->cols[counter].type, "binary") == 0 || strcasecmp(tableDes->cols[counter].type, "nchar") - * == 0) { */ - /* pstr += sprintf(pstr, "(%d)", tableDes->cols[counter].length); */ - /* } */ - } - - pstr += sprintf(pstr, ");"); - - fprintf(fp, "%s\n", tmpBuf); - free(tmpBuf); -} - -int taosDumpTableData(FILE *fp, char *tbname, struct arguments *arguments, TAOS* taosCon) { - /* char temp[MAX_COMMAND_SIZE] = "\0"; */ - int64_t totalRows = 0; - int count = 0; - char *pstr = NULL; - TAOS_ROW row = NULL; - int numFields = 0; - char *tbuf = NULL; - - char* tmpCommand = (char *)calloc(1, COMMAND_SIZE); - if (tmpCommand == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return -1; - } - - char* tmpBuffer = (char *)calloc(1, COMMAND_SIZE); - if (tmpBuffer == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - free(tmpCommand); - return -1; - } - - pstr = tmpBuffer; - - if (arguments->schemaonly) { - free(tmpCommand); - free(tmpBuffer); - return 0; - } - - sprintf(tmpCommand, - "select * from %s where _c0 >= %" PRId64 " and _c0 <= %" PRId64 " order by _c0 asc", - tbname, - arguments->start_time, - arguments->end_time); - - TAOS_RES* tmpResult = taos_query(taosCon, tmpCommand); - int32_t code = taos_errno(tmpResult); - if (code != 0) { - fprintf(stderr, "failed to run command %s, reason: %s\n", tmpCommand, taos_errstr(taosCon)); - free(tmpCommand); - free(tmpBuffer); - taos_free_result(tmpResult); - return -1; - } - - numFields = taos_field_count(tmpResult); - assert(numFields > 0); - TAOS_FIELD *fields = taos_fetch_fields(tmpResult); - tbuf = (char *)malloc(COMMAND_SIZE); - if (tbuf == NULL) { - fprintf(stderr, "No enough memory\n"); - free(tmpCommand); - free(tmpBuffer); - taos_free_result(tmpResult); - return -1; - } - - char sqlStr[8] = "\0"; - if (arguments->mysqlFlag) { - sprintf(sqlStr, "INSERT"); - } else { - sprintf(sqlStr, "IMPORT"); - } - - int rowFlag = 0; - count = 0; - while ((row = taos_fetch_row(tmpResult)) != NULL) { - pstr = tmpBuffer; - - if (count == 0) { - pstr += sprintf(pstr, "%s INTO %s VALUES (", sqlStr, tbname); - } else { - if (arguments->mysqlFlag) { - if (0 == rowFlag) { - pstr += sprintf(pstr, "("); - rowFlag++; - } else { - pstr += sprintf(pstr, ", ("); - } - } else { - pstr += sprintf(pstr, "("); - } - } - - for (int col = 0; col < numFields; col++) { - if (col != 0) pstr += sprintf(pstr, ", "); - - if (row[col] == NULL) { - pstr += sprintf(pstr, "NULL"); - continue; - } - - switch (fields[col].type) { - case TSDB_DATA_TYPE_BOOL: - pstr += sprintf(pstr, "%d", ((((int)(*((char *)row[col]))) == 1) ? 1 : 0)); - break; - case TSDB_DATA_TYPE_TINYINT: - pstr += sprintf(pstr, "%d", (int)(*((char *)row[col]))); - break; - case TSDB_DATA_TYPE_SMALLINT: - pstr += sprintf(pstr, "%d", (int)(*((short *)row[col]))); - break; - case TSDB_DATA_TYPE_INT: - pstr += sprintf(pstr, "%d", *((int *)row[col])); - break; - case TSDB_DATA_TYPE_BIGINT: - pstr += sprintf(pstr, "%" PRId64 "", *((int64_t *)row[col])); - break; - case TSDB_DATA_TYPE_FLOAT: - pstr += sprintf(pstr, "%f", GET_FLOAT_VAL(row[col])); - break; - case TSDB_DATA_TYPE_DOUBLE: - pstr += sprintf(pstr, "%f", GET_DOUBLE_VAL(row[col])); - break; - case TSDB_DATA_TYPE_BINARY: - *(pstr++) = '\''; - converStringToReadable((char *)row[col], fields[col].bytes, tbuf, COMMAND_SIZE); - pstr = stpcpy(pstr, tbuf); - *(pstr++) = '\''; - break; - case TSDB_DATA_TYPE_NCHAR: - convertNCharToReadable((char *)row[col], fields[col].bytes, tbuf, COMMAND_SIZE); - pstr += sprintf(pstr, "\'%s\'", tbuf); - break; - case TSDB_DATA_TYPE_TIMESTAMP: - if (!arguments->mysqlFlag) { - pstr += sprintf(pstr, "%" PRId64 "", *(int64_t *)row[col]); - } else { - char buf[64] = "\0"; - int64_t ts = *((int64_t *)row[col]); - time_t tt = (time_t)(ts / 1000); - struct tm *ptm = localtime(&tt); - strftime(buf, 64, "%y-%m-%d %H:%M:%S", ptm); - pstr += sprintf(pstr, "\'%s.%03d\'", buf, (int)(ts % 1000)); - } - break; - default: - break; - } - } - - pstr += sprintf(pstr, ") "); - - totalRows++; - count++; - fprintf(fp, "%s", tmpBuffer); - - if (count >= arguments->data_batch) { - fprintf(fp, ";\n"); - count = 0; - } //else { - //fprintf(fp, "\\\n"); - //} - } - - atomic_add_fetch_64(&totalDumpOutRows, totalRows); - - fprintf(fp, "\n"); - - if (tbuf) { - free(tbuf); - } - - taos_free_result(tmpResult); - tmpResult = NULL; - free(tmpCommand); - free(tmpBuffer); - return 0; -} - -int taosCheckParam(struct arguments *arguments) { - if (arguments->all_databases && arguments->databases) { - fprintf(stderr, "conflict option --all-databases and --databases\n"); - return -1; - } - - if (arguments->start_time > arguments->end_time) { - fprintf(stderr, "start time is larger than end time\n"); - return -1; - } - - if (arguments->arg_list_len == 0) { - if ((!arguments->all_databases) && (!arguments->isDumpIn)) { - fprintf(stderr, "taosdump requires parameters\n"); - return -1; - } - } -/* - if (arguments->isDumpIn && (strcmp(arguments->outpath, DEFAULT_DUMP_FILE) != 0)) { - fprintf(stderr, "duplicate parameter input and output file path\n"); - return -1; - } -*/ - if (!arguments->isDumpIn && arguments->encode != NULL) { - fprintf(stderr, "invalid option in dump out\n"); - return -1; - } - - if (arguments->table_batch <= 0) { - fprintf(stderr, "invalid option in dump out\n"); - return -1; - } - - return 0; -} - -bool isEmptyCommand(char *cmd) { - char *pchar = cmd; - - while (*pchar != '\0') { - if (*pchar != ' ') return false; - pchar++; - } - - return true; -} - -void taosReplaceCtrlChar(char *str) { - _Bool ctrlOn = false; - char *pstr = NULL; - - for (pstr = str; *str != '\0'; ++str) { - if (ctrlOn) { - switch (*str) { - case 'n': - *pstr = '\n'; - pstr++; - break; - case 'r': - *pstr = '\r'; - pstr++; - break; - case 't': - *pstr = '\t'; - pstr++; - break; - case '\\': - *pstr = '\\'; - pstr++; - break; - case '\'': - *pstr = '\''; - pstr++; - break; - default: - break; - } - ctrlOn = false; - } else { - if (*str == '\\') { - ctrlOn = true; - } else { - *pstr = *str; - pstr++; - } - } - } - - *pstr = '\0'; -} - -char *ascii_literal_list[] = { - "\\x00", "\\x01", "\\x02", "\\x03", "\\x04", "\\x05", "\\x06", "\\x07", "\\x08", "\\t", "\\n", "\\x0b", "\\x0c", - "\\r", "\\x0e", "\\x0f", "\\x10", "\\x11", "\\x12", "\\x13", "\\x14", "\\x15", "\\x16", "\\x17", "\\x18", "\\x19", - "\\x1a", "\\x1b", "\\x1c", "\\x1d", "\\x1e", "\\x1f", " ", "!", "\\\"", "#", "$", "%", "&", - "\\'", "(", ")", "*", "+", ",", "-", ".", "/", "0", "1", "2", "3", - "4", "5", "6", "7", "8", "9", ":", ";", "<", "=", ">", "?", "@", - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", - "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", - "[", "\\\\", "]", "^", "_", "`", "a", "b", "c", "d", "e", "f", "g", - "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", - "u", "v", "w", "x", "y", "z", "{", "|", "}", "~", "\\x7f", "\\x80", "\\x81", - "\\x82", "\\x83", "\\x84", "\\x85", "\\x86", "\\x87", "\\x88", "\\x89", "\\x8a", "\\x8b", "\\x8c", "\\x8d", "\\x8e", - "\\x8f", "\\x90", "\\x91", "\\x92", "\\x93", "\\x94", "\\x95", "\\x96", "\\x97", "\\x98", "\\x99", "\\x9a", "\\x9b", - "\\x9c", "\\x9d", "\\x9e", "\\x9f", "\\xa0", "\\xa1", "\\xa2", "\\xa3", "\\xa4", "\\xa5", "\\xa6", "\\xa7", "\\xa8", - "\\xa9", "\\xaa", "\\xab", "\\xac", "\\xad", "\\xae", "\\xaf", "\\xb0", "\\xb1", "\\xb2", "\\xb3", "\\xb4", "\\xb5", - "\\xb6", "\\xb7", "\\xb8", "\\xb9", "\\xba", "\\xbb", "\\xbc", "\\xbd", "\\xbe", "\\xbf", "\\xc0", "\\xc1", "\\xc2", - "\\xc3", "\\xc4", "\\xc5", "\\xc6", "\\xc7", "\\xc8", "\\xc9", "\\xca", "\\xcb", "\\xcc", "\\xcd", "\\xce", "\\xcf", - "\\xd0", "\\xd1", "\\xd2", "\\xd3", "\\xd4", "\\xd5", "\\xd6", "\\xd7", "\\xd8", "\\xd9", "\\xda", "\\xdb", "\\xdc", - "\\xdd", "\\xde", "\\xdf", "\\xe0", "\\xe1", "\\xe2", "\\xe3", "\\xe4", "\\xe5", "\\xe6", "\\xe7", "\\xe8", "\\xe9", - "\\xea", "\\xeb", "\\xec", "\\xed", "\\xee", "\\xef", "\\xf0", "\\xf1", "\\xf2", "\\xf3", "\\xf4", "\\xf5", "\\xf6", - "\\xf7", "\\xf8", "\\xf9", "\\xfa", "\\xfb", "\\xfc", "\\xfd", "\\xfe", "\\xff"}; - -int converStringToReadable(char *str, int size, char *buf, int bufsize) { - char *pstr = str; - char *pbuf = buf; - while (size > 0) { - if (*pstr == '\0') break; - pbuf = stpcpy(pbuf, ascii_literal_list[((uint8_t)(*pstr))]); - pstr++; - size--; - } - *pbuf = '\0'; - return 0; -} - -int convertNCharToReadable(char *str, int size, char *buf, int bufsize) { - char *pstr = str; - char *pbuf = buf; - // TODO - wchar_t wc; - while (size > 0) { - if (*pstr == '\0') break; - int byte_width = mbtowc(&wc, pstr, MB_CUR_MAX); - if (byte_width < 0) { - fprintf(stderr, "mbtowc() return fail.\n"); - exit(-1); - } - - if ((int)wc < 256) { - pbuf = stpcpy(pbuf, ascii_literal_list[(int)wc]); - } else { - memcpy(pbuf, pstr, byte_width); - pbuf += byte_width; - } - pstr += byte_width; - } - - *pbuf = '\0'; - - return 0; -} - -void taosDumpCharset(FILE *fp) { - char charsetline[256]; - - (void)fseek(fp, 0, SEEK_SET); - sprintf(charsetline, "#!%s\n", tsCharset); - (void)fwrite(charsetline, strlen(charsetline), 1, fp); -} - -void taosLoadFileCharset(FILE *fp, char *fcharset) { - char * line = NULL; - size_t line_size = 0; - - (void)fseek(fp, 0, SEEK_SET); - ssize_t size = getline(&line, &line_size, fp); - if (size <= 2) { - goto _exit_no_charset; - } - - if (strncmp(line, "#!", 2) != 0) { - goto _exit_no_charset; - } - if (line[size - 1] == '\n') { - line[size - 1] = '\0'; - size--; - } - strcpy(fcharset, line + 2); - - taosTFree(line); - return; - -_exit_no_charset: - (void)fseek(fp, 0, SEEK_SET); - *fcharset = '\0'; - taosTFree(line); - return; -} - -// ======== dumpIn support multi threads functions ================================// - -static char **tsDumpInSqlFiles = NULL; -static int32_t tsSqlFileNum = 0; -static char tsDbSqlFile[TSDB_FILENAME_LEN] = {0}; -static char tsfCharset[64] = {0}; -static int taosGetFilesNum(const char *directoryName, const char *prefix) -{ - char cmd[1024] = { 0 }; - sprintf(cmd, "ls %s/*.%s | wc -l ", directoryName, prefix); - - FILE *fp = popen(cmd, "r"); - if (fp == NULL) { - fprintf(stderr, "ERROR: failed to execute:%s, error:%s\n", cmd, strerror(errno)); - exit(0); - } - - int fileNum = 0; - if (fscanf(fp, "%d", &fileNum) != 1) { - fprintf(stderr, "ERROR: failed to execute:%s, parse result error\n", cmd); - exit(0); - } - - if (fileNum <= 0) { - fprintf(stderr, "ERROR: directory:%s is empry\n", directoryName); - exit(0); - } - - pclose(fp); - return fileNum; -} - -static void taosParseDirectory(const char *directoryName, const char *prefix, char **fileArray, int totalFiles) -{ - char cmd[1024] = { 0 }; - sprintf(cmd, "ls %s/*.%s | sort", directoryName, prefix); - - FILE *fp = popen(cmd, "r"); - if (fp == NULL) { - fprintf(stderr, "ERROR: failed to execute:%s, error:%s\n", cmd, strerror(errno)); - exit(0); - } - - int fileNum = 0; - while (fscanf(fp, "%128s", fileArray[fileNum++])) { - if (strcmp(fileArray[fileNum-1], tsDbSqlFile) == 0) { - fileNum--; - } - if (fileNum >= totalFiles) { - break; - } - } - - if (fileNum != totalFiles) { - fprintf(stderr, "ERROR: directory:%s changed while read\n", directoryName); - pclose(fp); - exit(0); - } - - pclose(fp); -} - -static void taosCheckTablesSQLFile(const char *directoryName) -{ - char cmd[1024] = { 0 }; - sprintf(cmd, "ls %s/dbs.sql", directoryName); - - FILE *fp = popen(cmd, "r"); - if (fp == NULL) { - fprintf(stderr, "ERROR: failed to execute:%s, error:%s\n", cmd, strerror(errno)); - exit(0); - } - - while (fscanf(fp, "%128s", tsDbSqlFile)) { - break; - } - - pclose(fp); -} - -static void taosMallocSQLFiles() -{ - tsDumpInSqlFiles = (char**)calloc(tsSqlFileNum, sizeof(char*)); - for (int i = 0; i < tsSqlFileNum; i++) { - tsDumpInSqlFiles[i] = calloc(1, TSDB_FILENAME_LEN); - } -} - -static void taosFreeSQLFiles() -{ - for (int i = 0; i < tsSqlFileNum; i++) { - taosTFree(tsDumpInSqlFiles[i]); - } - taosTFree(tsDumpInSqlFiles); -} - -static void taosGetDirectoryFileList(char *inputDir) -{ - struct stat fileStat; - if (stat(inputDir, &fileStat) < 0) { - fprintf(stderr, "ERROR: %s not exist\n", inputDir); - exit(0); - } - - if (fileStat.st_mode & S_IFDIR) { - taosCheckTablesSQLFile(inputDir); - tsSqlFileNum = taosGetFilesNum(inputDir, "sql"); - int totalSQLFileNum = tsSqlFileNum; - if (tsDbSqlFile[0] != 0) { - tsSqlFileNum--; - } - taosMallocSQLFiles(); - taosParseDirectory(inputDir, "sql", tsDumpInSqlFiles, tsSqlFileNum); - fprintf(stdout, "\nstart to dispose %d files in %s\n", totalSQLFileNum, inputDir); - } - else { - fprintf(stderr, "ERROR: %s is not a directory\n", inputDir); - exit(0); - } -} - -static FILE* taosOpenDumpInFile(char *fptr) { - wordexp_t full_path; - - if (wordexp(fptr, &full_path, 0) != 0) { - fprintf(stderr, "ERROR: illegal file name: %s\n", fptr); - return NULL; - } - - char *fname = full_path.we_wordv[0]; - - FILE *f = fopen(fname, "r"); - if (f == NULL) { - fprintf(stderr, "ERROR: failed to open file %s\n", fname); - wordfree(&full_path); - return NULL; - } - - wordfree(&full_path); - - return f; -} - -int taosDumpInOneFile_old(TAOS * taos, FILE* fp, char* fcharset, char* encode) { - char *command = NULL; - char *lcommand = NULL; - int tsize = 0; - char *line = NULL; - _Bool isRun = true; - size_t line_size = 0; - char *pstr = NULL; - char *lstr = NULL; - size_t inbytesleft = 0; - size_t outbytesleft = COMMAND_SIZE; - char *tcommand = NULL; - char *charsetOfFile = NULL; - iconv_t cd = (iconv_t)(-1); - - command = (char *)malloc(COMMAND_SIZE); - lcommand = (char *)malloc(COMMAND_SIZE); - if (command == NULL || lcommand == NULL) { - fprintf(stderr, "failed to connect to allocate memory\n"); - goto _dumpin_exit_failure; - } - - // Resolve locale - if (*fcharset != '\0') { - charsetOfFile = fcharset; - } else { - charsetOfFile = encode; - } - - if (charsetOfFile != NULL && strcasecmp(tsCharset, charsetOfFile) != 0) { - cd = iconv_open(tsCharset, charsetOfFile); - if (cd == ((iconv_t)(-1))) { - fprintf(stderr, "Failed to open iconv handle\n"); - goto _dumpin_exit_failure; - } - } - - pstr = command; - int64_t linenu = 0; - while (1) { - ssize_t size = getline(&line, &line_size, fp); - linenu++; - if (size <= 0) break; - if (size == 1) { - if (pstr != command) { - inbytesleft = pstr - command; - memset(lcommand, 0, COMMAND_SIZE); - pstr = command; - lstr = lcommand; - outbytesleft = COMMAND_SIZE; - if (cd != ((iconv_t)(-1))) { - iconv(cd, &pstr, &inbytesleft, &lstr, &outbytesleft); - tcommand = lcommand; - } else { - tcommand = command; - } - - taosReplaceCtrlChar(tcommand); - - if (queryDB(taos, tcommand) != 0) { - fprintf(stderr, "error sql: linenu: %" PRId64 " failed\n", linenu); - exit(0); - } - - pstr = command; - pstr[0] = '\0'; - tsize = 0; - isRun = true; - } - - continue; - } - - /* if (line[0] == '-' && line[1] == '-') continue; */ - - line[size - 1] = 0; - - if (tsize + size - 1 > COMMAND_SIZE) { - fprintf(stderr, "command is too long\n"); - goto _dumpin_exit_failure; - } - - if (line[size - 2] == '\\') { - line[size - 2] = ' '; - isRun = false; - } else { - isRun = true; - } - - memcpy(pstr, line, size - 1); - pstr += (size - 1); - *pstr = '\0'; - - if (!isRun) continue; - - if (command != pstr && !isEmptyCommand(command)) { - inbytesleft = pstr - command; - memset(lcommand, 0, COMMAND_SIZE); - pstr = command; - lstr = lcommand; - outbytesleft = COMMAND_SIZE; - if (cd != ((iconv_t)(-1))) { - iconv(cd, &pstr, &inbytesleft, &lstr, &outbytesleft); - tcommand = lcommand; - } else { - tcommand = command; - } - taosReplaceCtrlChar(tcommand); - if (queryDB(taos, tcommand) != 0) { - fprintf(stderr, "error sql: linenu:%" PRId64 " failed\n", linenu); - exit(0); - } - } - - pstr = command; - *pstr = '\0'; - tsize = 0; - } - - if (pstr != command) { - inbytesleft = pstr - command; - memset(lcommand, 0, COMMAND_SIZE); - pstr = command; - lstr = lcommand; - outbytesleft = COMMAND_SIZE; - if (cd != ((iconv_t)(-1))) { - iconv(cd, &pstr, &inbytesleft, &lstr, &outbytesleft); - tcommand = lcommand; - } else { - tcommand = command; - } - taosReplaceCtrlChar(lcommand); - if (queryDB(taos, tcommand) != 0) - fprintf(stderr, "error sql: linenu:%" PRId64 " failed \n", linenu); - } - - if (cd != ((iconv_t)(-1))) iconv_close(cd); - taosTFree(line); - taosTFree(command); - taosTFree(lcommand); - taos_close(taos); - fclose(fp); - return 0; - -_dumpin_exit_failure: - if (cd != ((iconv_t)(-1))) iconv_close(cd); - taosTFree(command); - taosTFree(lcommand); - taos_close(taos); - fclose(fp); - return -1; -} - -int taosDumpInOneFile(TAOS * taos, FILE* fp, char* fcharset, char* encode, char* fileName) { - int read_len = 0; - char * cmd = NULL; - size_t cmd_len = 0; - char * line = NULL; - size_t line_len = 0; - - cmd = (char *)malloc(COMMAND_SIZE); - if (cmd == NULL) { - fprintf(stderr, "failed to allocate memory\n"); - return -1; - } - - int lineNo = 0; - while ((read_len = getline(&line, &line_len, fp)) != -1) { - ++lineNo; - if (read_len >= COMMAND_SIZE) continue; - line[--read_len] = '\0'; - - //if (read_len == 0 || isCommentLine(line)) { // line starts with # - if (read_len == 0 ) { - continue; - } - - if (line[read_len - 1] == '\\') { - line[read_len - 1] = ' '; - memcpy(cmd + cmd_len, line, read_len); - cmd_len += read_len; - continue; - } - - memcpy(cmd + cmd_len, line, read_len); - cmd[read_len + cmd_len]= '\0'; - if (queryDB(taos, cmd)) { - fprintf(stderr, "error sql: linenu:%d, file:%s\n", lineNo, fileName); - } - - memset(cmd, 0, COMMAND_SIZE); - cmd_len = 0; - } - - taosTFree(cmd); - taosTFree(line); - fclose(fp); - return 0; -} - -void* taosDumpInWorkThreadFp(void *arg) -{ - SThreadParaObj *pThread = (SThreadParaObj*)arg; - for (int32_t f = 0; f < tsSqlFileNum; ++f) { - if (f % pThread->totalThreads == pThread->threadIndex) { - char *SQLFileName = tsDumpInSqlFiles[f]; - FILE* fp = taosOpenDumpInFile(SQLFileName); - if (NULL == fp) { - continue; - } - fprintf(stderr, "Success Open input file: %s\n", SQLFileName); - taosDumpInOneFile(pThread->taosCon, fp, tsfCharset, tsArguments.encode, SQLFileName); - } - } - - return NULL; -} - -static void taosStartDumpInWorkThreads(struct arguments *args) -{ - pthread_attr_t thattr; - SThreadParaObj *pThread; - int32_t totalThreads = args->thread_num; - - if (totalThreads > tsSqlFileNum) { - totalThreads = tsSqlFileNum; - } - - SThreadParaObj *threadObj = (SThreadParaObj *)calloc(totalThreads, sizeof(SThreadParaObj)); - for (int32_t t = 0; t < totalThreads; ++t) { - pThread = threadObj + t; - pThread->threadIndex = t; - pThread->totalThreads = totalThreads; - pThread->taosCon = taos_connect(args->host, args->user, args->password, NULL, args->port); - if (pThread->taosCon == NULL) { - fprintf(stderr, "ERROR: thread:%d failed connect to TDengine, error:%s\n", pThread->threadIndex, taos_errstr(pThread->taosCon)); - exit(0); - } - - pthread_attr_init(&thattr); - pthread_attr_setdetachstate(&thattr, PTHREAD_CREATE_JOINABLE); - - if (pthread_create(&(pThread->threadID), &thattr, taosDumpInWorkThreadFp, (void*)pThread) != 0) { - fprintf(stderr, "ERROR: thread:%d failed to start\n", pThread->threadIndex); - exit(0); - } - } - - for (int t = 0; t < totalThreads; ++t) { - pthread_join(threadObj[t].threadID, NULL); - } - - for (int t = 0; t < totalThreads; ++t) { - taos_close(threadObj[t].taosCon); - } - free(threadObj); -} - - -int taosDumpIn(struct arguments *arguments) { - assert(arguments->isDumpIn); - - TAOS *taos = NULL; - FILE *fp = NULL; - - taos = taos_connect(arguments->host, arguments->user, arguments->password, NULL, arguments->port); - if (taos == NULL) { - fprintf(stderr, "failed to connect to TDengine server\n"); - return -1; - } - - taosGetDirectoryFileList(arguments->inpath); - - if (tsDbSqlFile[0] != 0) { - fp = taosOpenDumpInFile(tsDbSqlFile); - if (NULL == fp) { - fprintf(stderr, "failed to open input file %s\n", tsDbSqlFile); - return -1; - } - fprintf(stderr, "Success Open input file: %s\n", tsDbSqlFile); - - taosLoadFileCharset(fp, tsfCharset); - - taosDumpInOneFile(taos, fp, tsfCharset, arguments->encode, tsDbSqlFile); - } - - taosStartDumpInWorkThreads(arguments); - - taos_close(taos); - taosFreeSQLFiles(); - return 0; -} - - diff --git a/src/kit/taosmigrate/CMakeLists.txt b/src/kit/taosmigrate/CMakeLists.txt deleted file mode 100644 index fdd9dd88861c356d63174d9515df3c3a8910a4e4..0000000000000000000000000000000000000000 --- a/src/kit/taosmigrate/CMakeLists.txt +++ /dev/null @@ -1,18 +0,0 @@ -CMAKE_MINIMUM_REQUIRED(VERSION 2.8) -PROJECT(TDengine) - -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - 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/mnode/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/vnode/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) - AUX_SOURCE_DIRECTORY(. SRC) - - ADD_EXECUTABLE(taosmigrate ${SRC}) - TARGET_LINK_LIBRARIES(taosmigrate common cJson osdetail tutil) -ENDIF () - -SET_SOURCE_FILES_PROPERTIES(./taosmigrate.c PROPERTIES COMPILE_FLAGS -w) diff --git a/src/kit/taosmigrate/taosmigrate.c b/src/kit/taosmigrate/taosmigrate.c deleted file mode 100644 index 3ef73ef169a59a8569a520f9c4def32a1de2f644..0000000000000000000000000000000000000000 --- a/src/kit/taosmigrate/taosmigrate.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include "taosmigrate.h" - - -/* The options we understand. */ -static struct argp_option options[] = { - {0, 'r', "data dir", 0, "data dir", 0}, - {0, 'd', "dnodeId", 0, "dnode id", 1}, - {0, 'p', "port", 0, "dnode port", 1}, - {0, 'f', "fqdn", 0, "dnode fqdn", 1}, - {0, 'g', "multi dnodes", 0, "multi dnode info, e.g. \"2 7030 fqdn1, 3 8030 fqdn2\"", 2}, - {0}}; - -/* Used by main to communicate with parse_opt. */ -struct arguments { - char* dataDir; - int32_t dnodeId; - uint16_t port; - char* fqdn; - char* dnodeGroups; - char** arg_list; - int arg_list_len; -}; - -/* Parse a single option. */ -static error_t parse_opt(int key, char *arg, struct argp_state *state) { - struct arguments *arguments = state->input; - switch (key) { - case 'r': - arguments->dataDir = arg; - break; - case 'd': - arguments->dnodeId = atoi(arg); - break; - case 'p': - arguments->port = atoi(arg); - break; - case 'f': - arguments->fqdn = arg; - break; - case 'g': - arguments->dnodeGroups = arg; - break; - case ARGP_KEY_ARG: - arguments->arg_list = &state->argv[state->next - 1]; - arguments->arg_list_len = state->argc - state->next + 1; - state->next = state->argc; - - argp_usage(state); - break; - - default: - return ARGP_ERR_UNKNOWN; - } - return 0; -} - -static struct argp argp = {options, parse_opt, 0, 0}; -struct arguments arguments = {NULL, 0, 0, NULL, NULL, NULL, 0}; -SdnodeGroup tsDnodeGroup = {0}; - -int tSystemShell(const char * cmd) -{ - FILE * fp; - int res; - char buf[1024]; - if (cmd == NULL) { - printf("tSystem cmd is NULL!\n"); - return -1; - } - - if ((fp = popen(cmd, "r") ) == NULL) { - printf("popen cmd:%s error: %s/n", cmd, strerror(errno)); - return -1; - } else { - while(fgets(buf, sizeof(buf), fp)) { - printf("popen result:%s", buf); - } - - if ((res = pclose(fp)) == -1) { - printf("close popen file pointer fp error!\n"); - } else { - printf("popen res is :%d\n", res); - } - - return res; - } -} - -void taosMvFile(char* destFile, char *srcFile) { - char shellCmd[1024+1] = {0}; - - //(void)snprintf(shellCmd, 1024, "cp -rf %s %s", srcDir, destDir); - (void)snprintf(shellCmd, 1024, "mv -f %s %s", srcFile, destFile); - tSystemShell(shellCmd); -} - -SdnodeIfo* getDnodeInfo(int32_t dnodeId) -{ - for (int32_t i = 0; i < tsDnodeGroup.dnodeNum; i++) { - if (dnodeId == tsDnodeGroup.dnodeArray[i].dnodeId) { - return &(tsDnodeGroup.dnodeArray[i]); - } - } - - return NULL; -} - -void parseOneDnodeInfo(char* buf, SdnodeIfo* pDnodeInfo) -{ - char *ptr; - char *p; - int32_t i = 0; - ptr = strtok_r(buf, " ", &p); - while(ptr != NULL) { - if (0 == i) { - pDnodeInfo->dnodeId = atoi(ptr); - } else if (1 == i) { - pDnodeInfo->port = atoi(ptr); - } else if (2 == i) { - tstrncpy(pDnodeInfo->fqdn, ptr, TSDB_FQDN_LEN); - } else { - printf("input parameter error near:%s\n", buf); - exit(-1); - } - i++; - ptr = strtok_r(NULL, " ", &p); - } - - snprintf(pDnodeInfo->ep, TSDB_EP_LEN, "%s:%d", pDnodeInfo->fqdn, pDnodeInfo->port); -} - -void saveDnodeGroups() -{ - if ((NULL != arguments.fqdn) && (arguments.dnodeId > 0) && (0 != arguments.port)) { - //printf("dnodeId:%d port:%d fqdn:%s ep:%s\n", arguments.dnodeId, arguments.port, arguments.fqdn, arguments.ep); - - tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum].dnodeId = arguments.dnodeId; - tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum].port = arguments.port; - tstrncpy(tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum].fqdn, arguments.fqdn, TSDB_FQDN_LEN); - snprintf(tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum].ep, TSDB_EP_LEN, "%s:%d", tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum].fqdn, tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum].port); - - tsDnodeGroup.dnodeNum++; - } - - if (NULL == arguments.dnodeGroups) { - return; - } - - //printf("dnodeGroups:%s\n", arguments.dnodeGroups); - - char buf[1024]; - char* str = NULL; - char* start = arguments.dnodeGroups; - while (NULL != (str = strstr(start, ","))) { - memcpy(buf, start, str - start); - // parse one dnode info: dnodeId port fqdn ep - parseOneDnodeInfo(buf, &(tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum])); - tsDnodeGroup.dnodeNum++; - // next - start = str + 1; - str = NULL; - } - - if (strlen(start)) { - parseOneDnodeInfo(start, &(tsDnodeGroup.dnodeArray[tsDnodeGroup.dnodeNum])); - tsDnodeGroup.dnodeNum++; - } -} - -int32_t main(int32_t argc, char *argv[]) { - memset(&tsDnodeGroup, 0, sizeof(SdnodeGroup)); - - argp_parse(&argp, argc, argv, 0, 0, &arguments); - - if ((NULL == arguments.dataDir) || ((NULL == arguments.dnodeGroups) - && (NULL == arguments.fqdn || arguments.dnodeId < 1 || 0 == arguments.port))) { - printf("input parameter error!\n"); - return -1; - } - - saveDnodeGroups(); - - printf("===================arguments:==================\n"); - printf("oldWal:%s\n", arguments.dataDir); - for (int32_t i = 0; i < tsDnodeGroup.dnodeNum; i++) { - printf("dnodeId:%d port:%d fqdn:%s ep:%s\n", tsDnodeGroup.dnodeArray[i].dnodeId, - tsDnodeGroup.dnodeArray[i].port, - tsDnodeGroup.dnodeArray[i].fqdn, - tsDnodeGroup.dnodeArray[i].ep); - } - printf("===========================\n"); - - // 1. modify wal for mnode - char mnodeWal[TSDB_FILENAME_LEN*2] = {0}; - (void)snprintf(mnodeWal, TSDB_FILENAME_LEN*2, "%s/mnode/wal/wal0", arguments.dataDir); - walModWalFile(mnodeWal); - - // 2. modfiy dnode config: mnodeEpSet.json - char dnodeEpSet[TSDB_FILENAME_LEN*2] = {0}; - (void)snprintf(dnodeEpSet, TSDB_FILENAME_LEN*2, "%s/dnode/mnodeEpSet.json", arguments.dataDir); - modDnodeEpSet(dnodeEpSet); - - // 3. modify vnode config: config.json - char vnodeDir[TSDB_FILENAME_LEN*2] = {0}; - (void)snprintf(vnodeDir, TSDB_FILENAME_LEN*2, "%s/vnode", arguments.dataDir); - modAllVnode(vnodeDir); - - return 0; -} - diff --git a/src/kit/taosmigrate/taosmigrate.h b/src/kit/taosmigrate/taosmigrate.h deleted file mode 100644 index 9fb3c92db284033cdfc2dcaa736e088a9b84f14f..0000000000000000000000000000000000000000 --- a/src/kit/taosmigrate/taosmigrate.h +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ -#ifndef TAOS_MIGRATE_H -#define TAOS_MIGRATE_H - -#ifdef __cplusplus -extern "C" { -#endif - -#define _GNU_SOURCE - -#ifndef _ALPINE -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "taosdef.h" -#include "tutil.h" -#include "twal.h" -#include "tchecksum.h" -#include "mnodeDef.h" -#include "mnodeSdb.h" -#include "cJSON.h" -#include "taosmsg.h" -#include "tglobal.h" -#include "tsdb.h" - -//#include "vnode.h" -#include "vnodeInt.h" - -#define MAX_DNODE_NUM 128 - - -typedef struct _SdnodeIfo { - int32_t dnodeId; - uint16_t port; - char fqdn[TSDB_FQDN_LEN+1]; - char ep[TSDB_EP_LEN+1]; -} SdnodeIfo; - -typedef struct _SdnodeGroup { - int32_t dnodeNum; - SdnodeIfo dnodeArray[MAX_DNODE_NUM]; -} SdnodeGroup; - -int tSystemShell(const char * cmd); -void taosMvFile(char* destFile, char *srcFile) ; -void walModWalFile(char* walfile); -SdnodeIfo* getDnodeInfo(int32_t dnodeId); -void modDnodeEpSet(char* dnodeEpSet); -void modAllVnode(char *vnodeDir); - -#endif diff --git a/src/kit/taosmigrate/taosmigrateDnodeCfg.c b/src/kit/taosmigrate/taosmigrateDnodeCfg.c deleted file mode 100644 index 7f6fd03feab28c5e71ac6c390160bde8dabf4b67..0000000000000000000000000000000000000000 --- a/src/kit/taosmigrate/taosmigrateDnodeCfg.c +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include "taosmigrate.h" - -//#include "dnodeInt.h" -//#include "dnodeMgmt.h" -//#include "dnodeVRead.h" -//#include "dnodeVWrite.h" -//#include "dnodeModule.h" - -static SDMMnodeInfos tsDnodeIpInfos = {0}; - -static bool dnodeReadMnodeInfos(char* dnodeEpSet) { - FILE *fp = fopen(dnodeEpSet, "r"); - if (!fp) { - printf("failed to read mnodeEpSet.json, file not exist\n"); - return false; - } - - bool ret = false; - int maxLen = 2000; - char *content = calloc(1, maxLen + 1); - int len = fread(content, 1, maxLen, fp); - if (len <= 0) { - free(content); - fclose(fp); - printf("failed to read mnodeEpSet.json, content is null\n"); - return false; - } - - content[len] = 0; - cJSON* root = cJSON_Parse(content); - if (root == NULL) { - printf("failed to read mnodeEpSet.json, invalid json format\n"); - goto PARSE_OVER; - } - - cJSON* inUse = cJSON_GetObjectItem(root, "inUse"); - if (!inUse || inUse->type != cJSON_Number) { - printf("failed to read mnodeEpSet.json, inUse not found\n"); - goto PARSE_OVER; - } - tsDnodeIpInfos.inUse = inUse->valueint; - - cJSON* nodeNum = cJSON_GetObjectItem(root, "nodeNum"); - if (!nodeNum || nodeNum->type != cJSON_Number) { - printf("failed to read mnodeEpSet.json, nodeNum not found\n"); - goto PARSE_OVER; - } - tsDnodeIpInfos.nodeNum = nodeNum->valueint; - - cJSON* nodeInfos = cJSON_GetObjectItem(root, "nodeInfos"); - if (!nodeInfos || nodeInfos->type != cJSON_Array) { - printf("failed to read mnodeEpSet.json, nodeInfos not found\n"); - goto PARSE_OVER; - } - - int size = cJSON_GetArraySize(nodeInfos); - if (size != tsDnodeIpInfos.nodeNum) { - printf("failed to read mnodeEpSet.json, nodeInfos size not matched\n"); - goto PARSE_OVER; - } - - for (int i = 0; i < size; ++i) { - cJSON* nodeInfo = cJSON_GetArrayItem(nodeInfos, i); - if (nodeInfo == NULL) continue; - - cJSON *nodeId = cJSON_GetObjectItem(nodeInfo, "nodeId"); - if (!nodeId || nodeId->type != cJSON_Number) { - printf("failed to read mnodeEpSet.json, nodeId not found\n"); - goto PARSE_OVER; - } - tsDnodeIpInfos.nodeInfos[i].nodeId = nodeId->valueint; - - cJSON *nodeEp = cJSON_GetObjectItem(nodeInfo, "nodeEp"); - if (!nodeEp || nodeEp->type != cJSON_String || nodeEp->valuestring == NULL) { - printf("failed to read mnodeEpSet.json, nodeName not found\n"); - goto PARSE_OVER; - } - strncpy(tsDnodeIpInfos.nodeInfos[i].nodeEp, nodeEp->valuestring, TSDB_EP_LEN); - - SdnodeIfo* pDnodeInfo = getDnodeInfo(tsDnodeIpInfos.nodeInfos[i].nodeId); - if (NULL == pDnodeInfo) { - continue; - } - - tstrncpy(tsDnodeIpInfos.nodeInfos[i].nodeEp, pDnodeInfo->ep, TSDB_EP_LEN); - } - - ret = true; - - //printf("read mnode epSet successed, numOfEps:%d inUse:%d\n", tsDnodeIpInfos.nodeNum, tsDnodeIpInfos.inUse); - //for (int32_t i = 0; i < tsDnodeIpInfos.nodeNum; i++) { - // printf("mnode:%d, %s\n", tsDnodeIpInfos.nodeInfos[i].nodeId, tsDnodeIpInfos.nodeInfos[i].nodeEp); - //} - -PARSE_OVER: - free(content); - cJSON_Delete(root); - fclose(fp); - return ret; -} - - -static void dnodeSaveMnodeInfos(char* dnodeEpSet) { - FILE *fp = fopen(dnodeEpSet, "w"); - if (!fp) return; - - int32_t len = 0; - int32_t maxLen = 2000; - char * content = calloc(1, maxLen + 1); - - len += snprintf(content + len, maxLen - len, "{\n"); - len += snprintf(content + len, maxLen - len, " \"inUse\": %d,\n", tsDnodeIpInfos.inUse); - len += snprintf(content + len, maxLen - len, " \"nodeNum\": %d,\n", tsDnodeIpInfos.nodeNum); - len += snprintf(content + len, maxLen - len, " \"nodeInfos\": [{\n"); - for (int32_t i = 0; i < tsDnodeIpInfos.nodeNum; i++) { - len += snprintf(content + len, maxLen - len, " \"nodeId\": %d,\n", tsDnodeIpInfos.nodeInfos[i].nodeId); - len += snprintf(content + len, maxLen - len, " \"nodeEp\": \"%s\"\n", tsDnodeIpInfos.nodeInfos[i].nodeEp); - if (i < tsDnodeIpInfos.nodeNum -1) { - len += snprintf(content + len, maxLen - len, " },{\n"); - } else { - len += snprintf(content + len, maxLen - len, " }]\n"); - } - } - len += snprintf(content + len, maxLen - len, "}\n"); - - fwrite(content, 1, len, fp); - fflush(fp); - fclose(fp); - free(content); - - printf("mod mnode epSet successed\n"); -} - -void modDnodeEpSet(char* dnodeEpSet) -{ - (void)dnodeReadMnodeInfos(dnodeEpSet); - dnodeSaveMnodeInfos(dnodeEpSet); - return; -} - - diff --git a/src/kit/taosmigrate/taosmigrateMnodeWal.c b/src/kit/taosmigrate/taosmigrateMnodeWal.c deleted file mode 100644 index 28e2b7772b29641c5cb2f736606c6cb03169402e..0000000000000000000000000000000000000000 --- a/src/kit/taosmigrate/taosmigrateMnodeWal.c +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include "taosmigrate.h" - -static void recordWrite(int fd, SWalHead *pHead) { - - taosCalcChecksumAppend(0, (uint8_t *)pHead, sizeof(SWalHead)); - - int contLen = pHead->len + sizeof(SWalHead); - - if(write(fd, pHead, contLen) != contLen) { - printf("failed to write(%s)", strerror(errno)); - exit(-1); - } -} - -static void recordMod(SWalHead* pHead) -{ - SDnodeObj *pDnode; - - ESdbTable tableId = (ESdbTable)(pHead->msgType / 10); - - switch (tableId) { - case SDB_TABLE_DNODE: - case SDB_TABLE_MNODE: - pDnode = (SDnodeObj *)pHead->cont; - - printf("dnodeId:%d port:%d fqdn:%s ep:%s\n", pDnode->dnodeId, pDnode->dnodePort, pDnode->dnodeFqdn, pDnode->dnodeEp); - - SdnodeIfo* pDnodeInfo = getDnodeInfo(pDnode->dnodeId); - if (NULL == pDnodeInfo) { - break; - } - - pDnode->dnodePort = pDnodeInfo->port; - tstrncpy(pDnode->dnodeFqdn, pDnodeInfo->fqdn, sizeof(pDnode->dnodeFqdn)); - tstrncpy(pDnode->dnodeEp, pDnodeInfo->ep, sizeof(pDnode->dnodeEp)); - break; - #if 0 - case SDB_TABLE_ACCOUNT: - SAcctObj *pAcct = (SDnodeObj *)pHead->cont; - break; - case SDB_TABLE_USER: - SUserObj *pUser = (SDnodeObj *)pHead->cont; - break; - case SDB_TABLE_DB: - SDbObj *pDb = (SDnodeObj *)pHead->cont; - break; - case SDB_TABLE_VGROUP: - SVgObj *pVgroup = (SDnodeObj *)pHead->cont; - break; - case SDB_TABLE_STABLE: - SSuperTableObj *pStable = (SDnodeObj *)pHead->cont; - break; - case SDB_TABLE_CTABLE: - SChildTableObj *pCTable = (SDnodeObj *)pHead->cont; - break; - #endif - default: - break; - } -} - -void walModWalFile(char* walfile) { - char *buffer = malloc(1024000); // size for one record - if (buffer == NULL) { - printf("failed to malloc:%s\n", strerror(errno)); - return ; - } - - SWalHead *pHead = (SWalHead *)buffer; - - int rfd = open(walfile, O_RDONLY); - if (rfd < 0) { - printf("failed to open %s failed:%s\n", walfile, strerror(errno)); - free(buffer); - return ; - } - - char newWalFile[32] = "wal0"; - int wfd = open(newWalFile, O_WRONLY | O_CREAT, S_IRWXU | S_IRWXG | S_IRWXO); - - if (wfd < 0) { - printf("wal:%s, failed to open(%s)\n", newWalFile, strerror(errno)); - free(buffer); - close(rfd); - return ; - } - - printf("start to mod %s into %s\n", walfile, newWalFile); - - while (1) { - memset(buffer, 0, 1024000); - int ret = read(rfd, pHead, sizeof(SWalHead)); - if ( ret == 0) break; - - if (ret != sizeof(SWalHead)) { - printf("wal:%s, failed to read head, skip, ret:%d(%s)\n", walfile, ret, strerror(errno)); - break; - } - - if (!taosCheckChecksumWhole((uint8_t *)pHead, sizeof(SWalHead))) { - printf("wal:%s, cksum is messed up, skip the rest of file\n", walfile); - break; - } - - if (pHead->len >= 1024000 - sizeof(SWalHead)) { - printf("wal:%s, SWalHead.len(%d) overflow, skip the rest of file\n", walfile, pHead->len); - break; - } - - ret = read(rfd, pHead->cont, pHead->len); - if ( ret != pHead->len) { - printf("wal:%s, failed to read body, skip, len:%d ret:%d\n", walfile, pHead->len, ret); - break; - } - - recordMod(pHead); - recordWrite(wfd, pHead); - } - - close(rfd); - close(wfd); - free(buffer); - - taosMvFile(walfile, newWalFile); - - return ; -} - - - diff --git a/src/kit/taosmigrate/taosmigrateVnodeCfg.c b/src/kit/taosmigrate/taosmigrateVnodeCfg.c deleted file mode 100644 index 472671c22c4dc0d578d03452a4ceef3ff16395c2..0000000000000000000000000000000000000000 --- a/src/kit/taosmigrate/taosmigrateVnodeCfg.c +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2019 TAOS Data, Inc. - * - * This program is free software: you can use, redistribute, and/or modify - * it under the terms of the GNU Affero General Public License, version 3 - * or later ("AGPL"), as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. - * - * You should have received a copy of the GNU Affero General Public License - * along with this program. If not, see . - */ - -#include "taosmigrate.h" - - -static int32_t saveVnodeCfg(SVnodeObj *pVnode, char* cfgFile) -{ - FILE *fp = fopen(cfgFile, "w"); - if (!fp) { - printf("failed to open vnode cfg file for write, file:%s error:%s\n", cfgFile, strerror(errno)); - return errno; - } - - int32_t len = 0; - int32_t maxLen = 1000; - char * content = calloc(1, maxLen + 1); - if (content == NULL) { - fclose(fp); - return -1; - } - - len += snprintf(content + len, maxLen - len, "{\n"); - len += snprintf(content + len, maxLen - len, " \"db\": \"%s\",\n", pVnode->db); - len += snprintf(content + len, maxLen - len, " \"cfgVersion\": %d,\n", pVnode->cfgVersion); - len += snprintf(content + len, maxLen - len, " \"cacheBlockSize\": %d,\n", pVnode->tsdbCfg.cacheBlockSize); - len += snprintf(content + len, maxLen - len, " \"totalBlocks\": %d,\n", pVnode->tsdbCfg.totalBlocks); - len += snprintf(content + len, maxLen - len, " \"daysPerFile\": %d,\n", pVnode->tsdbCfg.daysPerFile); - len += snprintf(content + len, maxLen - len, " \"daysToKeep\": %d,\n", pVnode->tsdbCfg.keep); - len += snprintf(content + len, maxLen - len, " \"daysToKeep1\": %d,\n", pVnode->tsdbCfg.keep1); - len += snprintf(content + len, maxLen - len, " \"daysToKeep2\": %d,\n", pVnode->tsdbCfg.keep2); - len += snprintf(content + len, maxLen - len, " \"minRowsPerFileBlock\": %d,\n", pVnode->tsdbCfg.minRowsPerFileBlock); - len += snprintf(content + len, maxLen - len, " \"maxRowsPerFileBlock\": %d,\n", pVnode->tsdbCfg.maxRowsPerFileBlock); - len += snprintf(content + len, maxLen - len, " \"precision\": %d,\n", pVnode->tsdbCfg.precision); - len += snprintf(content + len, maxLen - len, " \"compression\": %d,\n", pVnode->tsdbCfg.compression); - len += snprintf(content + len, maxLen - len, " \"walLevel\": %d,\n", pVnode->walCfg.walLevel); - len += snprintf(content + len, maxLen - len, " \"fsync\": %d,\n", pVnode->walCfg.fsyncPeriod); - len += snprintf(content + len, maxLen - len, " \"replica\": %d,\n", pVnode->syncCfg.replica); - len += snprintf(content + len, maxLen - len, " \"wals\": %d,\n", pVnode->walCfg.wals); - len += snprintf(content + len, maxLen - len, " \"quorum\": %d,\n", pVnode->syncCfg.quorum); - - len += snprintf(content + len, maxLen - len, " \"nodeInfos\": [{\n"); - for (int32_t i = 0; i < pVnode->syncCfg.replica; i++) { - len += snprintf(content + len, maxLen - len, " \"nodeId\": %d,\n", pVnode->syncCfg.nodeInfo[i].nodeId); - len += snprintf(content + len, maxLen - len, " \"nodeEp\": \"%s:%d\"\n", pVnode->syncCfg.nodeInfo[i].nodeFqdn, pVnode->syncCfg.nodeInfo[i].nodePort); - - if (i < pVnode->syncCfg.replica - 1) { - len += snprintf(content + len, maxLen - len, " },{\n"); - } else { - len += snprintf(content + len, maxLen - len, " }]\n"); - } - } - len += snprintf(content + len, maxLen - len, "}\n"); - - fwrite(content, 1, len, fp); - fflush(fp); - fclose(fp); - free(content); - - printf("mod vnode cfg %s successed\n", cfgFile); - - return 0; -} - -static int32_t readVnodeCfg(SVnodeObj *pVnode, char* cfgFile) -{ - cJSON *root = NULL; - char *content = NULL; - int maxLen = 1000; - int32_t ret = -1; - - FILE *fp = fopen(cfgFile, "r"); - if (!fp) { - printf("failed to open vnode cfg file:%s to read, error:%s\n", cfgFile, strerror(errno)); - goto PARSE_OVER; - } - - content = calloc(1, maxLen + 1); - if (content == NULL) { - goto PARSE_OVER; - } - - int len = fread(content, 1, maxLen, fp); - if (len <= 0) { - printf("failed to read vnode cfg, content is null, error:%s\n", strerror(errno)); - goto PARSE_OVER; - } - - content[maxLen] = (char)0; - - root = cJSON_Parse(content); - if (root == NULL) { - printf("failed to json parse %s, invalid json format\n", cfgFile); - goto PARSE_OVER; - } - - cJSON *db = cJSON_GetObjectItem(root, "db"); - if (!db || db->type != cJSON_String || db->valuestring == NULL) { - printf("vgId:%d, failed to read vnode cfg, db not found\n", pVnode->vgId); - goto PARSE_OVER; - } - strcpy(pVnode->db, db->valuestring); - - cJSON *cfgVersion = cJSON_GetObjectItem(root, "cfgVersion"); - if (!cfgVersion || cfgVersion->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, cfgVersion not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->cfgVersion = cfgVersion->valueint; - - cJSON *cacheBlockSize = cJSON_GetObjectItem(root, "cacheBlockSize"); - if (!cacheBlockSize || cacheBlockSize->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, cacheBlockSize not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.cacheBlockSize = cacheBlockSize->valueint; - - cJSON *totalBlocks = cJSON_GetObjectItem(root, "totalBlocks"); - if (!totalBlocks || totalBlocks->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, totalBlocks not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.totalBlocks = totalBlocks->valueint; - - // cJSON *maxTables = cJSON_GetObjectItem(root, "maxTables"); - // if (!maxTables || maxTables->type != cJSON_Number) { - // printf("vgId:%d, failed to read vnode cfg, maxTables not found\n", pVnode->vgId); - // goto PARSE_OVER; - // } - // pVnode->tsdbCfg.maxTables = maxTables->valueint; - - cJSON *daysPerFile = cJSON_GetObjectItem(root, "daysPerFile"); - if (!daysPerFile || daysPerFile->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, daysPerFile not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.daysPerFile = daysPerFile->valueint; - - cJSON *daysToKeep = cJSON_GetObjectItem(root, "daysToKeep"); - if (!daysToKeep || daysToKeep->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, daysToKeep not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.keep = daysToKeep->valueint; - - cJSON *daysToKeep1 = cJSON_GetObjectItem(root, "daysToKeep1"); - if (!daysToKeep1 || daysToKeep1->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, daysToKeep1 not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.keep1 = daysToKeep1->valueint; - - cJSON *daysToKeep2 = cJSON_GetObjectItem(root, "daysToKeep2"); - if (!daysToKeep2 || daysToKeep2->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, daysToKeep2 not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.keep2 = daysToKeep2->valueint; - - cJSON *minRowsPerFileBlock = cJSON_GetObjectItem(root, "minRowsPerFileBlock"); - if (!minRowsPerFileBlock || minRowsPerFileBlock->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, minRowsPerFileBlock not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.minRowsPerFileBlock = minRowsPerFileBlock->valueint; - - cJSON *maxRowsPerFileBlock = cJSON_GetObjectItem(root, "maxRowsPerFileBlock"); - if (!maxRowsPerFileBlock || maxRowsPerFileBlock->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, maxRowsPerFileBlock not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.maxRowsPerFileBlock = maxRowsPerFileBlock->valueint; - - // cJSON *commitTime = cJSON_GetObjectItem(root, "commitTime"); - // if (!commitTime || commitTime->type != cJSON_Number) { - // printf("vgId:%d, failed to read vnode cfg, commitTime not found\n", pVnode->vgId); - // goto PARSE_OVER; - // } - // pVnode->tsdbCfg.commitTime = (int8_t)commitTime->valueint; - - cJSON *precision = cJSON_GetObjectItem(root, "precision"); - if (!precision || precision->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, precision not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.precision = (int8_t)precision->valueint; - - cJSON *compression = cJSON_GetObjectItem(root, "compression"); - if (!compression || compression->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, compression not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->tsdbCfg.compression = (int8_t)compression->valueint; - - cJSON *walLevel = cJSON_GetObjectItem(root, "walLevel"); - if (!walLevel || walLevel->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, walLevel not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->walCfg.walLevel = (int8_t) walLevel->valueint; - - cJSON *fsyncPeriod = cJSON_GetObjectItem(root, "fsync"); - if (!fsyncPeriod || fsyncPeriod->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, fsyncPeriod not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->walCfg.fsyncPeriod = fsyncPeriod->valueint; - - cJSON *wals = cJSON_GetObjectItem(root, "wals"); - if (!wals || wals->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, wals not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->walCfg.wals = (int8_t)wals->valueint; - pVnode->walCfg.keep = 0; - - cJSON *replica = cJSON_GetObjectItem(root, "replica"); - if (!replica || replica->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, replica not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->syncCfg.replica = (int8_t)replica->valueint; - - cJSON *quorum = cJSON_GetObjectItem(root, "quorum"); - if (!quorum || quorum->type != cJSON_Number) { - printf("vgId: %d, failed to read vnode cfg, quorum not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->syncCfg.quorum = (int8_t)quorum->valueint; - - cJSON *nodeInfos = cJSON_GetObjectItem(root, "nodeInfos"); - if (!nodeInfos || nodeInfos->type != cJSON_Array) { - printf("vgId:%d, failed to read vnode cfg, nodeInfos not found\n", pVnode->vgId); - goto PARSE_OVER; - } - - int size = cJSON_GetArraySize(nodeInfos); - if (size != pVnode->syncCfg.replica) { - printf("vgId:%d, failed to read vnode cfg, nodeInfos size not matched\n", pVnode->vgId); - goto PARSE_OVER; - } - - for (int i = 0; i < size; ++i) { - cJSON *nodeInfo = cJSON_GetArrayItem(nodeInfos, i); - if (nodeInfo == NULL) continue; - - cJSON *nodeId = cJSON_GetObjectItem(nodeInfo, "nodeId"); - if (!nodeId || nodeId->type != cJSON_Number) { - printf("vgId:%d, failed to read vnode cfg, nodeId not found\n", pVnode->vgId); - goto PARSE_OVER; - } - pVnode->syncCfg.nodeInfo[i].nodeId = nodeId->valueint; - - cJSON *nodeEp = cJSON_GetObjectItem(nodeInfo, "nodeEp"); - if (!nodeEp || nodeEp->type != cJSON_String || nodeEp->valuestring == NULL) { - printf("vgId:%d, failed to read vnode cfg, nodeFqdn not found\n", pVnode->vgId); - goto PARSE_OVER; - } - - taosGetFqdnPortFromEp(nodeEp->valuestring, pVnode->syncCfg.nodeInfo[i].nodeFqdn, &pVnode->syncCfg.nodeInfo[i].nodePort); - //pVnode->syncCfg.nodeInfo[i].nodePort += TSDB_PORT_SYNC; - - - SdnodeIfo* pDnodeInfo = getDnodeInfo(pVnode->syncCfg.nodeInfo[i].nodeId); - if (NULL == pDnodeInfo) { - continue; - } - - pVnode->syncCfg.nodeInfo[i].nodePort = pDnodeInfo->port; - tstrncpy(pVnode->syncCfg.nodeInfo[i].nodeFqdn, pDnodeInfo->fqdn, TSDB_FQDN_LEN); - } - - ret = 0; - //printf("read vnode cfg successfully, replcia:%d\n", pVnode->syncCfg.replica); - //for (int32_t i = 0; i < pVnode->syncCfg.replica; i++) { - // printf("dnode:%d, %s:%d\n", pVnode->syncCfg.nodeInfo[i].nodeId, pVnode->syncCfg.nodeInfo[i].nodeFqdn, pVnode->syncCfg.nodeInfo[i].nodePort); - //} - -PARSE_OVER: - taosTFree(content); - cJSON_Delete(root); - if (fp) fclose(fp); - return ret; -} - -static void modVnodeCfg(char* vnodeCfg) -{ - int32_t ret; - SVnodeObj vnodeObj = {0}; - ret = readVnodeCfg(&vnodeObj, vnodeCfg); - if (0 != ret) { - printf("read vnode cfg %s fail!\n", vnodeCfg); - return ; - } - - (void)saveVnodeCfg(&vnodeObj, vnodeCfg); - - return ; -} - -void modAllVnode(char *vnodeDir) -{ - DIR *dir = opendir(vnodeDir); - if (dir == NULL) return; - - char filename[1024]; - struct dirent *de = NULL; - while ((de = readdir(dir)) != NULL) { - if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue; - - if ((de->d_type & DT_DIR) && (strncmp(de->d_name, "vnode", 5) == 0)) { - memset(filename, 0, 1024); - snprintf(filename, 1023, "%s/%s/config.json", vnodeDir, de->d_name); - modVnodeCfg(filename); - } - } - - closedir(dir); -} - diff --git a/src/mnode/CMakeLists.txt b/src/mnode/CMakeLists.txt index f5b9fbf74763bc331c809e0f5d5d6b9eca6593d8..ff5c9335b654edbdb7bbf6c081b38b265923d645 100644 --- a/src/mnode/CMakeLists.txt +++ b/src/mnode/CMakeLists.txt @@ -1,11 +1,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) +IF (TD_LINUX) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/dnode/inc) @@ -13,5 +9,4 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) AUX_SOURCE_DIRECTORY(src SRC) ADD_LIBRARY(mnode ${SRC}) - #TARGET_LINK_LIBRARIES(mnode trpc tutil pthread) ENDIF () \ No newline at end of file diff --git a/src/os/inc/osMath.h b/src/os/inc/osMath.h index 168f6607f05c2b013762e30e7eb07bf5e87ab389..9935f94d39ef0431b7c9b1a524b956e6fafe9f4f 100644 --- a/src/os/inc/osMath.h +++ b/src/os/inc/osMath.h @@ -21,6 +21,7 @@ extern "C" { #endif #define POW2(x) ((x) * (x)) +#define ABS(x) ((x) > 0 ? (x) : -(x)) #ifndef TAOS_OS_FUNC_MATH #define SWAP(a, b, c) \ diff --git a/src/os/inc/osSocket.h b/src/os/inc/osSocket.h index 10fed022bb9cafbb7c613473fab6b9c4b9e5d277..b9be39307ce9c2d6e75b67fa00bc0f365ea5f5ec 100644 --- a/src/os/inc/osSocket.h +++ b/src/os/inc/osSocket.h @@ -32,6 +32,7 @@ extern "C" { x = FD_INITIALIZER; \ } \ } + typedef int SOCKET; #endif #define taosClose(x) taosCloseSocket(x) @@ -54,11 +55,11 @@ extern "C" { #endif // TAOS_OS_FUNC_SOCKET -int taosSetNonblocking(int sock, int on); +int taosSetNonblocking(SOCKET sock, int on); void taosBlockSIGPIPE(); // TAOS_OS_FUNC_SOCKET_SETSOCKETOPT -int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen); +int taosSetSockOpt(SOCKET socketfd, int level, int optname, void *optval, int optlen); #ifdef __cplusplus } diff --git a/src/os/inc/osWindows.h b/src/os/inc/osWindows.h index 1118b3c64b7bd1296a2b083143e444a665c2264e..bdfb4acb5bb2ae2f3be1e6fa7c930377e1f975a9 100644 --- a/src/os/inc/osWindows.h +++ b/src/os/inc/osWindows.h @@ -85,11 +85,13 @@ extern "C" { #define TAOS_OS_FUNC_SOCKET #define TAOS_OS_FUNC_SOCKET_SETSOCKETOPT #define TAOS_OS_FUNC_SOCKET_OP - #define taosSend(sockfd, buf, len, flags) send(sockfd, buf, len, flags) - #define taosSendto(sockfd, buf, len, flags, dest_addr, addrlen) sendto(sockfd, buf, len, flags, dest_addr, addrlen) - #define taosWriteSocket(fd, buf, len) send(fd, buf, len, 0) - #define taosReadSocket(fd, buf, len) recv(fd, buf, len, 0) - #define taosCloseSocket(fd) closesocket(fd) + #define taosSend(sockfd, buf, len, flags) send((SOCKET)sockfd, buf, len, flags) + #define taosSendto(sockfd, buf, len, flags, dest_addr, addrlen) sendto((SOCKET)sockfd, buf, len, flags, dest_addr, addrlen) + #define taosWriteSocket(fd, buf, len) send((SOCKET)fd, buf, len, 0) + #define taosReadSocket(fd, buf, len) recv((SOCKET)fd, buf, len, 0) + #define taosCloseSocket(fd) closesocket((SOCKET)fd) +typedef SOCKET eventfd_t; +#define eventfd(a, b) -1 #define TAOS_OS_FUNC_STRING_WCHAR int twcslen(const wchar_t *wcs); @@ -105,6 +107,9 @@ extern "C" { #define taosStrdupImp(str) _strdup(str) #define taosStrndupImp(str, size) _strndup(str, size) +char *stpcpy (char *dest, const char *src); +char *stpncpy (char *dest, const char *src, size_t n); + #define TAOS_OS_FUNC_SYSINFO #define TAOS_OS_FUNC_TIME_DEF diff --git a/src/os/src/alpine/CMakeLists.txt b/src/os/src/alpine/CMakeLists.txt index 79cbf917e2cf4cfa41492379452c7210da0d5e5e..b5e739c24ce7ec3ef3ffc537ca8769706f7b56de 100644 --- a/src/os/src/alpine/CMakeLists.txt +++ b/src/os/src/alpine/CMakeLists.txt @@ -1,12 +1,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -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) AUX_SOURCE_DIRECTORY(. SRC) - ADD_LIBRARY(os ${SRC}) TARGET_LINK_LIBRARIES(os m rt) diff --git a/src/os/src/darwin/CMakeLists.txt b/src/os/src/darwin/CMakeLists.txt index 1568d16164629ddaadc34ffe52c7ab460767fdc2..c4cb28aa05e4716ca98c2687ce41d436b1300bb2 100644 --- a/src/os/src/darwin/CMakeLists.txt +++ b/src/os/src/darwin/CMakeLists.txt @@ -1,10 +1,5 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -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) AUX_SOURCE_DIRECTORY(. SRC) - ADD_LIBRARY(os ${SRC}) diff --git a/src/os/src/darwin/darwinSocket.c b/src/os/src/darwin/darwinSocket.c index e51f2c4fba4f91474189709b9b410bb886a2e9b3..69a4666d34394ef71da1d18559f8ba2f8f9cb290 100644 --- a/src/os/src/darwin/darwinSocket.c +++ b/src/os/src/darwin/darwinSocket.c @@ -16,7 +16,7 @@ #define _DEFAULT_SOURCE #include "os.h" -int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen) { +int taosSetSockOpt(SOCKET socketfd, int level, int optname, void *optval, int optlen) { if (level == SOL_SOCKET && optname == SO_SNDBUF) { return 0; } diff --git a/src/os/src/detail/CMakeLists.txt b/src/os/src/detail/CMakeLists.txt index 3ea7f97985f52ac96f625ba5f366441f486684a9..9f710e3ddffbe9342857cc3e92348f70c586f86e 100644 --- a/src/os/src/detail/CMakeLists.txt +++ b/src/os/src/detail/CMakeLists.txt @@ -1,16 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF (TD_WINDOWS) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/iconv) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/regex) -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) INCLUDE_DIRECTORIES(.) AUX_SOURCE_DIRECTORY(. SRC) SET_SOURCE_FILES_PROPERTIES(osSysinfo.c PROPERTIES COMPILE_FLAGS -w) diff --git a/src/os/src/detail/osSocket.c b/src/os/src/detail/osSocket.c index 7e4031eff930ff143ae1ba7f61390bd6621ec6fe..c8ad6a5acccc81fc08ebf1b9e542817914949452 100644 --- a/src/os/src/detail/osSocket.c +++ b/src/os/src/detail/osSocket.c @@ -19,7 +19,7 @@ #ifndef TAOS_OS_FUNC_SOCKET -int taosSetNonblocking(int sock, int on) { +int taosSetNonblocking(SOCKET sock, int on) { int flags = 0; if ((flags = fcntl(sock, F_GETFL, 0)) < 0) { uError("fcntl(F_GETFL) error: %d (%s)\n", errno, strerror(errno)); @@ -53,7 +53,7 @@ void taosBlockSIGPIPE() { #ifndef TAOS_OS_FUNC_SOCKET_SETSOCKETOPT -int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen) { +int taosSetSockOpt(SOCKET socketfd, int level, int optname, void *optval, int optlen) { return setsockopt(socketfd, level, optname, optval, (socklen_t)optlen); } diff --git a/src/os/src/linux64/CMakeLists.txt b/src/os/src/linux64/CMakeLists.txt index 0c577374ed855ad79efc4bd7c591587dea5e9f37..752326cc1de74550afac386ad5ac84f6d2f48990 100644 --- a/src/os/src/linux64/CMakeLists.txt +++ b/src/os/src/linux64/CMakeLists.txt @@ -1,10 +1,6 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -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) AUX_SOURCE_DIRECTORY(. SRC) ADD_LIBRARY(os ${SRC}) diff --git a/src/os/src/windows/CMakeLists.txt b/src/os/src/windows/CMakeLists.txt index 60fab63cd12a3f2c976c458c6be686009350ee96..131533c5c5d92acc9478807762c86029f01b2167 100644 --- a/src/os/src/windows/CMakeLists.txt +++ b/src/os/src/windows/CMakeLists.txt @@ -1,15 +1,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -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}/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) AUX_SOURCE_DIRECTORY(. SRC) - ADD_LIBRARY(os ${SRC}) TARGET_LINK_LIBRARIES(os winmm IPHLPAPI ws2_32) diff --git a/src/os/src/windows/w64Dir.c b/src/os/src/windows/w64Dir.c new file mode 100644 index 0000000000000000000000000000000000000000..7816dac0d61c22155a8cdbcf55e6d87d932762c2 --- /dev/null +++ b/src/os/src/windows/w64Dir.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019 TAOS Data, Inc. + * + * This program is free software: you can use, redistribute, and/or modify + * it under the terms of the GNU Affero General Public License, version 3 + * or later ("AGPL"), as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#define _DEFAULT_SOURCE +#include "os.h" +#include "tulog.h" + +void taosRemoveDir(char *rootDir) { + uError("%s not implemented yet", __FUNCTION__); +} + +int taosMkDir(const char *path, mode_t mode) { + uError("%s not implemented yet", __FUNCTION__); + return -1; +} + +void taosMvDir(char* destDir, char *srcDir) { + uError("%s not implemented yet", __FUNCTION__); +} diff --git a/src/os/src/windows/w64Socket.c b/src/os/src/windows/w64Socket.c index dbe501b6454000adf8e250e0acfbed980ac55785..dd8961da4048f499bf339147506c767f7ead60e2 100644 --- a/src/os/src/windows/w64Socket.c +++ b/src/os/src/windows/w64Socket.c @@ -34,7 +34,7 @@ void taosWinSocketInit() { } } -int taosSetNonblocking(int sock, int on) { +int taosSetNonblocking(SOCKET sock, int on) { u_long mode; if (on) { mode = 1; @@ -48,7 +48,7 @@ int taosSetNonblocking(int sock, int on) { void taosBlockSIGPIPE() {} -int taosSetSockOpt(int socketfd, int level, int optname, void *optval, int optlen) { +int taosSetSockOpt(SOCKET socketfd, int level, int optname, void *optval, int optlen) { if (level == SOL_SOCKET && optname == TCP_KEEPCNT) { return 0; } diff --git a/src/os/src/windows/w64String.c b/src/os/src/windows/w64String.c index e3ac7d88322b9b1722460c7c0415d7a6c932c620..0d9a28e288d9ea5885769b4fa3537dd9ba689f6e 100644 --- a/src/os/src/windows/w64String.c +++ b/src/os/src/windows/w64String.c @@ -129,3 +129,28 @@ int tasoUcs4Compare(void *f1_ucs4, void *f2_ucs4, int bytes) { return ret; #endif } + + +/* Copy memory to memory until the specified number of bytes +has been copied, return pointer to following byte. +Overlap is NOT handled correctly. */ +void *mempcpy(void *dest, const void *src, size_t len) { + return (char*)memcpy(dest, src, len) + len; +} + +/* Copy SRC to DEST, returning the address of the terminating '\0' in DEST. */ +char *stpcpy (char *dest, const char *src) { + size_t len = strlen (src); + return (char*)memcpy(dest, src, len + 1) + len; +} + +/* Copy no more than N characters of SRC to DEST, returning the address of + the terminating '\0' in DEST, if any, or else DEST + N. */ +char *stpncpy (char *dest, const char *src, size_t n) { + size_t size = strnlen (src, n); + memcpy (dest, src, size); + dest += size; + if (size == n) + return dest; + return memset (dest, '\0', n - size); +} \ No newline at end of file diff --git a/src/plugins/http/CMakeLists.txt b/src/plugins/http/CMakeLists.txt index 4dbfde8ce69960bffebb3558ab476601415ce40b..94f5305f289ecb01e445effc3a159d9c56db3631 100644 --- a/src/plugins/http/CMakeLists.txt +++ b/src/plugins/http/CMakeLists.txt @@ -1,20 +1,16 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/zlib-1.2.11/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/zlib-1.2.11/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(src SRC) + +IF (TD_LINUX) ADD_LIBRARY(http ${SRC}) -# TARGET_LINK_LIBRARIES(http taos_static z) TARGET_LINK_LIBRARIES(http taos z) IF (TD_ADMIN) diff --git a/src/plugins/monitor/CMakeLists.txt b/src/plugins/monitor/CMakeLists.txt index 9b6cbfeef3dc6b8fdc4271888c7615912a247a42..ba30edd0e48590a124fadda7723b7c22a7e92061 100644 --- a/src/plugins/monitor/CMakeLists.txt +++ b/src/plugins/monitor/CMakeLists.txt @@ -1,16 +1,12 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(./src SRC) + +IF (TD_LINUX) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(./src SRC) ADD_LIBRARY(monitor ${SRC}) -# TARGET_LINK_LIBRARIES(monitor taos_static) TARGET_LINK_LIBRARIES(monitor taos) ENDIF () diff --git a/src/plugins/mqtt/CMakeLists.txt b/src/plugins/mqtt/CMakeLists.txt index 929232cfe1b6564b2fd0586d11b629279a7a8365..72312ffcec5899fc997b55f81d7262cb67b6c309 100644 --- a/src/plugins/mqtt/CMakeLists.txt +++ b/src/plugins/mqtt/CMakeLists.txt @@ -1,20 +1,15 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(src SRC) + +IF (TD_LINUX) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/MQTT-C/include) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/MQTT-C/examples/templates) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) ADD_LIBRARY(mqtt ${SRC}) -# TARGET_LINK_LIBRARIES(mqtt taos_static cJson mqttc) TARGET_LINK_LIBRARIES(mqtt taos cJson mqttc) IF (TD_ADMIN) diff --git a/src/query/CMakeLists.txt b/src/query/CMakeLists.txt index 625b85d908537c361b446bee1bb6b94d5e2140e5..b9e7ff59e5f8a2bb28b570918385302465a1acc7 100644 --- a/src/query/CMakeLists.txt +++ b/src/query/CMakeLists.txt @@ -1,20 +1,17 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -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) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/tsdb/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(inc) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - AUX_SOURCE_DIRECTORY(src SRC) - ADD_LIBRARY(query ${SRC}) - TARGET_LINK_LIBRARIES(query tsdb tutil m rt) -ENDIF () - -ADD_SUBDIRECTORY(tests) +AUX_SOURCE_DIRECTORY(src SRC) +ADD_LIBRARY(query ${SRC}) SET_SOURCE_FILES_PROPERTIES(src/sql.c PROPERTIES COMPILE_FLAGS -w) +IF (TD_LINUX) + TARGET_LINK_LIBRARIES(query tsdb tutil m rt) + ADD_SUBDIRECTORY(tests) +ELSEIF (TD_WINDOWS) + TARGET_LINK_LIBRARIES(query tutil) +ENDIF () diff --git a/src/query/inc/qUtil.h b/src/query/inc/qUtil.h index ed7c7e8845317ac754758b8553e3f65ba8da4544..b7f57bf1b5a622a8d1f72632b18ced7fb4985872 100644 --- a/src/query/inc/qUtil.h +++ b/src/query/inc/qUtil.h @@ -52,7 +52,7 @@ static FORCE_INLINE char *getPosInResultPage(SQueryRuntimeEnv *pRuntimeEnv, int3 SQuery *pQuery = pRuntimeEnv->pQuery; // tFilePage *page = getResBufPage(pRuntimeEnv->pResultBuf, pResult->pos.pageId); - int32_t realRowId = pResult->pos.rowId * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pRuntimeEnv->topBotQuery, pRuntimeEnv->stableQuery); + int32_t realRowId = (int32_t)(pResult->pos.rowId * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pRuntimeEnv->topBotQuery, pRuntimeEnv->stableQuery)); return ((char *)page->data) + pRuntimeEnv->offset[columnIndex] * pRuntimeEnv->numOfRowsPerPage + pQuery->pSelectExpr[columnIndex].bytes * realRowId; } diff --git a/src/query/src/qAst.c b/src/query/src/qAst.c index 44051c7e3b26f8dad68ae7af17eaf9748dbf26ce..e2d609a62c98feabb0c9b52d1832fc7afc986541 100644 --- a/src/query/src/qAst.c +++ b/src/query/src/qAst.c @@ -1044,7 +1044,7 @@ tExprNode* exprTreeFromTableName(const char* tbnameCond) { } else if (*e == ',') { size_t len = e - cond; char* p = exception_malloc(len + VARSTR_HEADER_SIZE); - STR_WITH_SIZE_TO_VARSTR(p, cond, len); + STR_WITH_SIZE_TO_VARSTR(p, cond, (VarDataLenT)len); cond += len; taosArrayPush(pVal->arr, &p); } @@ -1054,7 +1054,7 @@ tExprNode* exprTreeFromTableName(const char* tbnameCond) { size_t len = strlen(cond) + VARSTR_HEADER_SIZE; char* p = exception_malloc(len); - STR_WITH_SIZE_TO_VARSTR(p, cond, len - VARSTR_HEADER_SIZE); + STR_WITH_SIZE_TO_VARSTR(p, cond, (VarDataLenT)(len - VARSTR_HEADER_SIZE)); taosArrayPush(pVal->arr, &p); } diff --git a/src/query/src/qExecutor.c b/src/query/src/qExecutor.c index 1277e7bfbb0107a2dcb0703c59fd086a1894acfe..22c2bb5c9a39a8eec40b3fbd2645ef3ec79b68bf 100644 --- a/src/query/src/qExecutor.c +++ b/src/query/src/qExecutor.c @@ -49,6 +49,11 @@ #define SDATA_BLOCK_INITIALIZER (SDataBlockInfo) {{0}, 0} +#define TIME_WINDOW_COPY(_dst, _src) do {\ + _dst.skey = _src.skey;\ + _dst.ekey = _src.ekey;\ +} while (0); + enum { // when query starts to execute, this status will set QUERY_NOT_COMPLETED = 0x1u, @@ -149,7 +154,7 @@ bool doFilterData(SQuery *pQuery, int32_t elemPos) { for (int32_t k = 0; k < pQuery->numOfFilterCols; ++k) { SSingleColumnFilterInfo *pFilterInfo = &pQuery->pFilterInfo[k]; - char *pElem = pFilterInfo->pData + pFilterInfo->info.bytes * elemPos; + char *pElem = (char*)pFilterInfo->pData + pFilterInfo->info.bytes * elemPos; if (isNull(pElem, pFilterInfo->info.type)) { return false; } @@ -395,7 +400,7 @@ static SWindowResult *doSetTimeWindowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SWin // more than the capacity, reallocate the resources if (pWindowResInfo->size >= pWindowResInfo->capacity) { - int64_t newCap = pWindowResInfo->capacity * 1.5; + int64_t newCap = (int64_t)(pWindowResInfo->capacity * 1.5f); char *t = realloc(pWindowResInfo->pResult, newCap * sizeof(SWindowResult)); if (t == NULL) { longjmp(pRuntimeEnv->env, TSDB_CODE_QRY_OUT_OF_MEMORY); @@ -403,14 +408,14 @@ static SWindowResult *doSetTimeWindowFromKey(SQueryRuntimeEnv *pRuntimeEnv, SWin pWindowResInfo->pResult = (SWindowResult *)t; - int32_t inc = newCap - pWindowResInfo->capacity; + int32_t inc = (int32_t)newCap - pWindowResInfo->capacity; memset(&pWindowResInfo->pResult[pWindowResInfo->capacity], 0, sizeof(SWindowResult) * inc); for (int32_t i = pWindowResInfo->capacity; i < newCap; ++i) { createQueryResultInfo(pQuery, &pWindowResInfo->pResult[i], pRuntimeEnv->stableQuery, pRuntimeEnv->interBufSize); } - pWindowResInfo->capacity = newCap; + pWindowResInfo->capacity = (int32_t)newCap; } // add a new result set for a new group @@ -499,7 +504,7 @@ static int32_t addNewWindowResultBuf(SWindowResult *pWindowRes, SDiskbasedResult // set the number of rows in current disk page if (pWindowRes->pos.pageId == -1) { // not allocated yet, allocate new buffer pWindowRes->pos.pageId = pageId; - pWindowRes->pos.rowId = pData->num++; + pWindowRes->pos.rowId = (int32_t)(pData->num++); assert(pWindowRes->pos.pageId >= 0); } @@ -803,7 +808,7 @@ static FORCE_INLINE TSKEY reviseWindowEkey(SQuery *pQuery, STimeWindow *pWindow) //todo binary search static void* getDataBlockImpl(SArray* pDataBlock, int32_t colId) { - int32_t numOfCols = taosArrayGetSize(pDataBlock); + int32_t numOfCols = (int32_t)taosArrayGetSize(pDataBlock); for (int32_t i = 0; i < numOfCols; ++i) { SColumnInfoData *p = taosArrayGet(pDataBlock, i); @@ -847,7 +852,7 @@ static char *getDataBlock(SQueryRuntimeEnv *pRuntimeEnv, SArithmeticSupport *sas } // here the pQuery->colList and sas->colList are identical - int32_t numOfCols = taosArrayGetSize(pDataBlock); + int32_t numOfCols = (int32_t)taosArrayGetSize(pDataBlock); for (int32_t i = 0; i < pQuery->numOfCols; ++i) { SColumnInfo *pColMsg = &pQuery->colList[i]; @@ -1065,7 +1070,7 @@ static char *getGroupbyColumnData(SQuery *pQuery, int16_t *type, int16_t *bytes, * stage, the remain tables may not have the required column in cache actually. So, the validation of required * column in cache with the corresponding schema is reinforced. */ - int32_t numOfCols = taosArrayGetSize(pDataBlock); + int32_t numOfCols = (int32_t)taosArrayGetSize(pDataBlock); for (int32_t i = 0; i < numOfCols; ++i) { SColumnInfoData *p = taosArrayGet(pDataBlock, i); @@ -1089,7 +1094,7 @@ static int32_t doTSJoinFilter(SQueryRuntimeEnv *pRuntimeEnv, int32_t offset) { return TS_JOIN_TAG_NOT_EQUALS; } - TSKEY key = *(TSKEY *)(pCtx[0].aInputElemBuf + TSDB_KEYSIZE * offset); + TSKEY key = *(TSKEY *)((char*)pCtx[0].aInputElemBuf + TSDB_KEYSIZE * offset); #if defined(_DEBUG_VIEW) printf("elem in comp ts file:%" PRId64 ", key:%" PRId64 ", tag:%"PRIu64", query order:%d, ts order:%d, traverse:%d, index:%d\n", @@ -1328,7 +1333,7 @@ static int32_t tableApplyFunctionsOnBlock(SQueryRuntimeEnv *pRuntimeEnv, SDataBl if (QUERY_IS_INTERVAL_QUERY(pQuery)) { numOfRes = doCheckQueryCompleted(pRuntimeEnv, lastKey, pWindowResInfo); } else { - numOfRes = getNumOfResult(pRuntimeEnv); + numOfRes = (int32_t)getNumOfResult(pRuntimeEnv); // update the number of output result if (numOfRes > 0 && pQuery->checkBuffer == 1) { @@ -1406,7 +1411,7 @@ void setExecParams(SQuery *pQuery, SQLFunctionCtx *pCtx, void* inputData, TSKEY } } else if (functionId == TSDB_FUNC_INTERP) { SInterpInfoDetail *pInterpInfo = GET_RES_INFO(pCtx)->interResultBuf; - pInterpInfo->type = pQuery->fillType; + pInterpInfo->type = (int8_t)pQuery->fillType; pInterpInfo->ts = pQuery->window.skey; pInterpInfo->primaryCol = (colId == PRIMARYKEY_TIMESTAMP_COL_INDEX); @@ -1705,7 +1710,7 @@ static bool needReverseScan(SQuery *pQuery) { } if (functionId == TSDB_FUNC_LAST || functionId == TSDB_FUNC_LAST_DST) { - int32_t order = pQuery->pSelectExpr[i].base.arg->argValue.i64; + int32_t order = (int32_t)pQuery->pSelectExpr[i].base.arg->argValue.i64; return order != pQuery->order.order; } } @@ -1914,7 +1919,7 @@ static int32_t getInitialPageNum(SQInfo *pQInfo) { num = 128; } else if (QUERY_IS_INTERVAL_QUERY(pQuery)) { // time window query, allocate one page for each table size_t s = pQInfo->tableqinfoGroupInfo.numOfTables; - num = MAX(s, INITIAL_RESULT_ROWS_VALUE); + num = (int32_t)(MAX(s, INITIAL_RESULT_ROWS_VALUE)); } else { // for super table query, one page for each subset num = 1; // pQInfo->pSidSet->numOfSubSet; } @@ -1926,7 +1931,7 @@ static int32_t getInitialPageNum(SQInfo *pQInfo) { static void getIntermediateBufInfo(SQueryRuntimeEnv* pRuntimeEnv, int32_t* ps, int32_t* rowsize) { SQuery* pQuery = pRuntimeEnv->pQuery; - *rowsize = pQuery->rowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pRuntimeEnv->topBotQuery, pRuntimeEnv->stableQuery); + *rowsize = (int32_t)(pQuery->rowSize * GET_ROW_PARAM_FOR_MULTIOUTPUT(pQuery, pRuntimeEnv->topBotQuery, pRuntimeEnv->stableQuery)); int32_t overhead = sizeof(tFilePage); // one page contains at least two rows @@ -1977,8 +1982,8 @@ static bool needToLoadDataBlock(SQueryRuntimeEnv* pRuntimeEnv, SDataStatis *pDat SDataStatis* pDataBlockst = &pDataStatis[index]; if (pFilterInfo->info.type == TSDB_DATA_TYPE_FLOAT) { - float minval = *(double *)(&pDataBlockst->min); - float maxval = *(double *)(&pDataBlockst->max); + float minval = (float)(*(double *)(&pDataBlockst->min)); + float maxval = (float)(*(double *)(&pDataBlockst->max)); for (int32_t i = 0; i < pFilterInfo->numOfFilters; ++i) { if (pFilterInfo->pFilters[i].fp(&pFilterInfo->pFilters[i], (char *)&minval, (char *)&maxval)) { @@ -2219,8 +2224,8 @@ static void ensureOutputBuffer(SQueryRuntimeEnv* pRuntimeEnv, SDataBlockInfo* pB SResultRec *pRec = &pQuery->rec; if (pQuery->rec.capacity - pQuery->rec.rows < pBlockInfo->rows) { - int32_t remain = pRec->capacity - pRec->rows; - int32_t newSize = pRec->capacity + (pBlockInfo->rows - remain); + int32_t remain = (int32_t)(pRec->capacity - pRec->rows); + int32_t newSize = (int32_t)(pRec->capacity + (pBlockInfo->rows - remain)); for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { int32_t bytes = pQuery->pSelectExpr[i].bytes; @@ -2399,7 +2404,7 @@ void setTagVal(SQueryRuntimeEnv *pRuntimeEnv, void *pTable, void *tsdb) { if (pQuery->numOfOutput == 1 && pExprInfo->base.functionId == TSDB_FUNC_TS_COMP) { assert(pExprInfo->base.numOfParams == 1); - int16_t tagColId = pExprInfo->base.arg->argValue.i64; + int16_t tagColId = (int16_t)pExprInfo->base.arg->argValue.i64; SColumnInfo* pColInfo = doGetTagColumnInfoById(pQuery->tagColList, pQuery->numOfTags, tagColId); doSetTagValueInParam(tsdb, pTable, tagColId, &pRuntimeEnv->pCtx[0].tag, pColInfo->type, pColInfo->bytes); @@ -2424,7 +2429,7 @@ void setTagVal(SQueryRuntimeEnv *pRuntimeEnv, void *pTable, void *tsdb) { pFuncMsg->colInfo.colIndex == PRIMARYKEY_TIMESTAMP_COL_INDEX) { assert(pFuncMsg->numOfParams == 1); - int16_t tagColId = pExprInfo->base.arg->argValue.i64; + int16_t tagColId = (int16_t)pExprInfo->base.arg->argValue.i64; SColumnInfo* pColInfo = doGetTagColumnInfoById(pQuery->tagColList, pQuery->numOfTags, tagColId); doSetTagValueInParam(tsdb, pTable, tagColId, &pRuntimeEnv->pCtx[0].tag, pColInfo->type, pColInfo->bytes); @@ -2632,7 +2637,7 @@ int32_t mergeIntoGroupResult(SQInfo *pQInfo) { int64_t st = taosGetTimestampMs(); int32_t ret = TSDB_CODE_SUCCESS; - int32_t numOfGroups = GET_NUM_OF_TABLEGROUP(pQInfo); + int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pQInfo)); while (pQInfo->groupIndex < numOfGroups) { SArray *group = GET_TABLEGROUP(pQInfo, pQInfo->groupIndex); @@ -2668,9 +2673,9 @@ void copyResToQueryResultBuf(SQInfo *pQInfo, SQuery *pQuery) { } // check if all results has been sent to client - int32_t numOfGroup = GET_NUM_OF_TABLEGROUP(pQInfo); + int32_t numOfGroup = (int32_t)(GET_NUM_OF_TABLEGROUP(pQInfo)); if (pQInfo->numOfGroupResultPages == 0 && pQInfo->groupIndex == numOfGroup) { - pQInfo->tableIndex = pQInfo->tableqinfoGroupInfo.numOfTables; // set query completed + pQInfo->tableIndex = (int32_t)pQInfo->tableqinfoGroupInfo.numOfTables; // set query completed return; } } @@ -2681,7 +2686,7 @@ void copyResToQueryResultBuf(SQInfo *pQInfo, SQuery *pQuery) { int32_t id = getGroupResultId(pQInfo->groupIndex - 1); SIDList list = getDataBufPagesIdList(pResultBuf, pQInfo->offset + id); - int32_t size = taosArrayGetSize(list); + int32_t size = (int32_t)(taosArrayGetSize(list)); int32_t offset = 0; for (int32_t j = 0; j < size; ++j) { @@ -2695,7 +2700,7 @@ void copyResToQueryResultBuf(SQInfo *pQInfo, SQuery *pQuery) { } // rows += pData->num; - offset += pData->num; + offset += (int32_t)pData->num; } assert(pQuery->rec.rows == 0); @@ -2880,7 +2885,7 @@ int32_t flushFromResultBuf(SQInfo *pQInfo) { int32_t pageId = -1; int32_t capacity = pResultBuf->numOfRowsPerPage; - int32_t remain = pQuery->sdata[0]->num; + int32_t remain = (int32_t)pQuery->sdata[0]->num; int32_t offset = 0; while (remain > 0) { @@ -2999,7 +3004,7 @@ void disableFuncInReverseScan(SQInfo *pQInfo) { } } - int32_t numOfGroups = GET_NUM_OF_TABLEGROUP(pQInfo); + int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pQInfo)); for(int32_t i = 0; i < numOfGroups; ++i) { SArray *group = GET_TABLEGROUP(pQInfo, i); @@ -3084,7 +3089,7 @@ void forwardCtxOutputBuf(SQueryRuntimeEnv *pRuntimeEnv, int64_t output) { * * diff function is handled in multi-output function */ - pRuntimeEnv->pCtx[j].ptsOutputBuf += TSDB_KEYSIZE * output; + pRuntimeEnv->pCtx[j].ptsOutputBuf = (char*)pRuntimeEnv->pCtx[j].ptsOutputBuf + TSDB_KEYSIZE * output; } RESET_RESULT_INFO(pRuntimeEnv->pCtx[j].resultInfo); @@ -3144,7 +3149,7 @@ void skipResults(SQueryRuntimeEnv *pRuntimeEnv) { } } - updateNumOfResult(pRuntimeEnv, pQuery->rec.rows); + updateNumOfResult(pRuntimeEnv, (int32_t)pQuery->rec.rows); } } @@ -3214,10 +3219,13 @@ static SQueryStatusInfo getQueryStatusInfo(SQueryRuntimeEnv *pRuntimeEnv, TSKEY .status = pQuery->status, .windowIndex = pRuntimeEnv->windowResInfo.curIndex, .lastKey = start, - .w = pQuery->window, - .curWindow = {.skey = start, .ekey = pTableQueryInfo->win.ekey}, }; + TIME_WINDOW_COPY(info.w, pQuery->window); + TIME_WINDOW_COPY(info.curWindow, pTableQueryInfo->win); + + info.curWindow.skey = start; + return info; } @@ -3246,12 +3254,13 @@ static void setEnvBeforeReverseScan(SQueryRuntimeEnv *pRuntimeEnv, SQueryStatusI SET_REVERSE_SCAN_FLAG(pRuntimeEnv); STsdbQueryCond cond = { - .twindow = pQuery->window, .order = pQuery->order.order, .colList = pQuery->colList, .numOfCols = pQuery->numOfCols, }; + TIME_WINDOW_COPY(cond.twindow, pQuery->window); + // clean unused handle if (pRuntimeEnv->pSecQueryHandle != NULL) { tsdbCleanupQueryHandle(pRuntimeEnv->pSecQueryHandle); @@ -3327,12 +3336,13 @@ void scanOneTableDataBlocks(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) { } STsdbQueryCond cond = { - .twindow = qstatus.curWindow, .order = pQuery->order.order, .colList = pQuery->colList, .numOfCols = pQuery->numOfCols, }; + TIME_WINDOW_COPY(cond.twindow, qstatus.curWindow); + if (pRuntimeEnv->pSecQueryHandle != NULL) { tsdbCleanupQueryHandle(pRuntimeEnv->pSecQueryHandle); } @@ -3395,7 +3405,7 @@ void finalizeQueryResult(SQueryRuntimeEnv *pRuntimeEnv) { * set the number of output results for group by normal columns, the number of output rows usually is 1 except * the top and bottom query */ - buf->numOfRows = getNumOfResult(pRuntimeEnv); + buf->numOfRows = (uint16_t)getNumOfResult(pRuntimeEnv); } } else { @@ -3697,7 +3707,7 @@ static int32_t doCopyToSData(SQInfo *pQInfo, SWindowResInfo *pResultInfo, int32_ * to SQuery object's result buffer */ if (numOfRowsToCopy > pQuery->rec.capacity - numOfResult) { - numOfRowsToCopy = pQuery->rec.capacity - numOfResult; + numOfRowsToCopy = (int32_t)pQuery->rec.capacity - numOfResult; pQInfo->offset += numOfRowsToCopy; } else { pQInfo->offset = 0; @@ -3811,7 +3821,7 @@ bool queryHasRemainResults(SQueryRuntimeEnv* pRuntimeEnv) { * first result row in the actual result set will fill nothing. */ if (Q_STATUS_EQUAL(pQuery->status, QUERY_COMPLETED)) { - int32_t numOfTotal = getFilledNumOfRes(pFillInfo, pQuery->window.ekey, pQuery->rec.capacity); + int32_t numOfTotal = (int32_t)getFilledNumOfRes(pFillInfo, pQuery->window.ekey, (int32_t)pQuery->rec.capacity); return numOfTotal > 0; } @@ -3869,7 +3879,7 @@ int32_t doFillGapsInResults(SQueryRuntimeEnv* pRuntimeEnv, tFilePage **pDst, int SFillInfo* pFillInfo = pRuntimeEnv->pFillInfo; while (1) { - int32_t ret = taosGenerateDataBlock(pFillInfo, (tFilePage**) pQuery->sdata, pQuery->rec.capacity); + int32_t ret = (int32_t)taosGenerateDataBlock(pFillInfo, (tFilePage**)pQuery->sdata, (int32_t)pQuery->rec.capacity); // todo apply limit output function /* reached the start position of according to offset value, return immediately */ @@ -3882,7 +3892,7 @@ int32_t doFillGapsInResults(SQueryRuntimeEnv* pRuntimeEnv, tFilePage **pDst, int qDebug("QInfo:%p initial numOfRows:%d, generate filled result:%d rows, offset:%" PRId64 ". Discard due to offset, remain:%" PRId64 ", new offset:%d", pQInfo, pFillInfo->numOfRows, ret, pQuery->limit.offset, ret - pQuery->limit.offset, 0); - ret -= pQuery->limit.offset; + ret -= (int32_t)pQuery->limit.offset; // todo !!!!there exactly number of interpo is not valid. // todo refactor move to the beginning of buffer for (int32_t i = 0; i < pQuery->numOfOutput; ++i) { @@ -3931,9 +3941,9 @@ static void updateOffsetVal(SQueryRuntimeEnv *pRuntimeEnv, SDataBlockInfo *pBloc } if (QUERY_IS_ASC_QUERY(pQuery)) { - pQuery->pos = pQuery->limit.offset; + pQuery->pos = (int32_t)pQuery->limit.offset; } else { - pQuery->pos = pBlockInfo->rows - pQuery->limit.offset - 1; + pQuery->pos = pBlockInfo->rows - (int32_t)pQuery->limit.offset - 1; } assert(pQuery->pos >= 0 && pQuery->pos <= pBlockInfo->rows - 1); @@ -4138,12 +4148,13 @@ static int32_t setupQueryHandle(void* tsdb, SQInfo* pQInfo, bool isSTableQuery) } STsdbQueryCond cond = { - .twindow = pQuery->window, .order = pQuery->order.order, .colList = pQuery->colList, .numOfCols = pQuery->numOfCols, }; + TIME_WINDOW_COPY(cond.twindow, pQuery->window); + if (!isSTableQuery && (pQInfo->tableqinfoGroupInfo.numOfTables == 1) && (cond.order == TSDB_ORDER_ASC) @@ -4177,7 +4188,7 @@ static SFillColInfo* taosCreateFillColInfo(SQuery* pQuery) { SExprInfo* pExprInfo = &pQuery->pSelectExpr[i]; pFillCol[i].col.bytes = pExprInfo->bytes; - pFillCol[i].col.type = pExprInfo->type; + pFillCol[i].col.type = (int8_t)pExprInfo->type; pFillCol[i].col.offset = offset; pFillCol[i].flag = TSDB_COL_NORMAL; // always be ta normal column for table query pFillCol[i].functionId = pExprInfo->base.functionId; @@ -4248,7 +4259,7 @@ int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, void *tsdb, int32_t vgId, bo threshold = 4000; } else { type = TSDB_DATA_TYPE_INT; // group id - threshold = GET_NUM_OF_TABLEGROUP(pQInfo); + threshold = (int32_t)(GET_NUM_OF_TABLEGROUP(pQInfo)); if (threshold < 8) { threshold = 8; } @@ -4288,8 +4299,8 @@ int32_t doInitQInfo(SQInfo *pQInfo, STSBuf *pTsBuf, void *tsdb, int32_t vgId, bo TSKEY ek = MAX(pQuery->window.skey, pQuery->window.ekey); getAlignQueryTimeWindow(pQuery, pQuery->window.skey, sk, ek, &w); - pRuntimeEnv->pFillInfo = taosInitFillInfo(pQuery->order.order, w.skey, 0, pQuery->rec.capacity, pQuery->numOfOutput, - pQuery->slidingTime, pQuery->slidingTimeUnit, pQuery->precision, + pRuntimeEnv->pFillInfo = taosInitFillInfo(pQuery->order.order, w.skey, 0, (int32_t)pQuery->rec.capacity, pQuery->numOfOutput, + pQuery->slidingTime, pQuery->slidingTimeUnit, (int8_t)pQuery->precision, pQuery->fillType, pColInfo); } @@ -4471,12 +4482,13 @@ static void sequentialTableProcess(SQInfo *pQInfo) { numOfGroups, group); STsdbQueryCond cond = { - .twindow = pQuery->window, .colList = pQuery->colList, .order = pQuery->order.order, .numOfCols = pQuery->numOfCols, }; + TIME_WINDOW_COPY(cond.twindow, pQuery->window); + SArray *g1 = taosArrayInit(1, POINTER_BYTES); SArray *tx = taosArrayClone(group); taosArrayPush(g1, &tx); @@ -4543,12 +4555,13 @@ static void sequentialTableProcess(SQInfo *pQInfo) { qDebug("QInfo:%p group by normal columns group:%d, total group:%zu", pQInfo, pQInfo->groupIndex, numOfGroups); STsdbQueryCond cond = { - .twindow = pQuery->window, .colList = pQuery->colList, .order = pQuery->order.order, .numOfCols = pQuery->numOfCols, }; + TIME_WINDOW_COPY(cond.twindow, pQuery->window); + SArray *g1 = taosArrayInit(1, POINTER_BYTES); SArray *tx = taosArrayClone(group); taosArrayPush(g1, &tx); @@ -4662,7 +4675,7 @@ static void sequentialTableProcess(SQInfo *pQInfo) { // the limitation of output result is reached, set the query completed if (limitResults(pRuntimeEnv)) { - pQInfo->tableIndex = pQInfo->tableqinfoGroupInfo.numOfTables; + pQInfo->tableIndex = (int32_t)pQInfo->tableqinfoGroupInfo.numOfTables; break; } @@ -4748,12 +4761,13 @@ static void doSaveContext(SQInfo *pQInfo) { } STsdbQueryCond cond = { - .twindow = pQuery->window, .order = pQuery->order.order, .colList = pQuery->colList, .numOfCols = pQuery->numOfCols, }; + TIME_WINDOW_COPY(cond.twindow, pQuery->window); + // clean unused handle if (pRuntimeEnv->pSecQueryHandle != NULL) { tsdbCleanupQueryHandle(pRuntimeEnv->pSecQueryHandle); @@ -4985,7 +4999,7 @@ static void tableIntervalProcessImpl(SQueryRuntimeEnv *pRuntimeEnv, TSKEY start) // maxOutput <= 0, means current query does not generate any results int32_t numOfClosed = numOfClosedTimeWindow(&pRuntimeEnv->windowResInfo); - int32_t c = MIN(numOfClosed, pQuery->limit.offset); + int32_t c = (int32_t)(MIN(numOfClosed, pQuery->limit.offset)); clearFirstNTimeWindow(pRuntimeEnv, c); pQuery->limit.offset -= c; } @@ -5029,7 +5043,7 @@ static void tableIntervalProcess(SQInfo *pQInfo, STableQueryInfo* pTableInfo) { limitResults(pRuntimeEnv); break; } else { - taosFillSetStartInfo(pRuntimeEnv->pFillInfo, pQuery->rec.rows, pQuery->window.ekey); + taosFillSetStartInfo(pRuntimeEnv->pFillInfo, (int32_t)pQuery->rec.rows, pQuery->window.ekey); taosFillCopyInputDataFromFilePage(pRuntimeEnv->pFillInfo, (tFilePage**) pQuery->sdata); numOfFilled = 0; @@ -5536,7 +5550,7 @@ static int32_t createQFunctionExprFromMsg(SQueryTableMsg *pQueryMsg, SExprInfo * } } - int32_t param = pExprs[i].base.arg[0].argValue.i64; + int32_t param = (int32_t)pExprs[i].base.arg[0].argValue.i64; if (getResultDataInfo(type, bytes, pExprs[i].base.functionId, param, &pExprs[i].type, &pExprs[i].bytes, &pExprs[i].interBytes, 0, isSuperTable) != TSDB_CODE_SUCCESS) { taosTFree(pExprs); @@ -5561,7 +5575,7 @@ static int32_t createQFunctionExprFromMsg(SQueryTableMsg *pQueryMsg, SExprInfo * SColumnInfo *pCol = &pQueryMsg->colList[j]; int32_t ret = - getResultDataInfo(pCol->type, pCol->bytes, functId, pExprs[i].base.arg[0].argValue.i64, + getResultDataInfo(pCol->type, pCol->bytes, functId, (int32_t)pExprs[i].base.arg[0].argValue.i64, &pExprs[i].type, &pExprs[i].bytes, &pExprs[i].interBytes, tagLen, isSuperTable); assert(ret == TSDB_CODE_SUCCESS); } @@ -5730,7 +5744,7 @@ static void freeQInfo(SQInfo *pQInfo); static void calResultBufSize(SQuery* pQuery) { const int32_t RESULT_MSG_MIN_SIZE = 1024 * (1024 + 512); // bytes const int32_t RESULT_MSG_MIN_ROWS = 8192; - const float RESULT_THRESHOLD_RATIO = 0.85; + const float RESULT_THRESHOLD_RATIO = 0.85f; if (isProjQuery(pQuery)) { int32_t numOfRes = RESULT_MSG_MIN_SIZE / pQuery->rowSize; @@ -5739,10 +5753,10 @@ static void calResultBufSize(SQuery* pQuery) { } pQuery->rec.capacity = numOfRes; - pQuery->rec.threshold = numOfRes * RESULT_THRESHOLD_RATIO; + pQuery->rec.threshold = (int32_t)(numOfRes * RESULT_THRESHOLD_RATIO); } else { // in case of non-prj query, a smaller output buffer will be used. pQuery->rec.capacity = 4096; - pQuery->rec.threshold = pQuery->rec.capacity * RESULT_THRESHOLD_RATIO; + pQuery->rec.threshold = (int32_t)(pQuery->rec.capacity * RESULT_THRESHOLD_RATIO); } } @@ -5871,7 +5885,7 @@ static SQInfo *createQInfoImpl(SQueryTableMsg *pQueryMsg, SArray* pTableIdList, window.skey = pQueryMsg->window.skey; } - void* buf = pQInfo->pBuf + index * sizeof(STableQueryInfo); + void* buf = (char*)pQInfo->pBuf + index * sizeof(STableQueryInfo); STableQueryInfo* item = createTableQueryInfo(&pQInfo->runtimeEnv, pTable, window, buf); if (item == NULL) { goto _cleanup; @@ -6026,7 +6040,7 @@ static void freeQInfo(SQInfo *pQInfo) { // todo refactor, extract method to destroytableDataInfo if (pQInfo->tableqinfoGroupInfo.pGroupList != NULL) { - int32_t numOfGroups = GET_NUM_OF_TABLEGROUP(pQInfo); + int32_t numOfGroups = (int32_t)(GET_NUM_OF_TABLEGROUP(pQInfo)); for (int32_t i = 0; i < numOfGroups; ++i) { SArray *p = GET_TABLEGROUP(pQInfo, i); @@ -6129,7 +6143,7 @@ static int32_t doDumpQueryResult(SQInfo *pQInfo, char *data) { setQueryStatus(pQuery, QUERY_OVER); } } else { - doCopyQueryResultToMsg(pQInfo, pQuery->rec.rows, data); + doCopyQueryResultToMsg(pQInfo, (int32_t)pQuery->rec.rows, data); } pQuery->rec.total += pQuery->rec.rows; @@ -6423,7 +6437,7 @@ int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *co size += sizeof(int32_t); size += sizeof(STableIdInfo) * taosArrayGetSize(pQInfo->arrTableIdInfo); - *contLen = size + sizeof(SRetrieveTableRsp); + *contLen = (int32_t)(size + sizeof(SRetrieveTableRsp)); // todo proper handle failed to allocate memory, // current solution only avoid crash, but cannot return error code to client @@ -6432,7 +6446,7 @@ int32_t qDumpRetrieveResult(qinfo_t qinfo, SRetrieveTableRsp **pRsp, int32_t *co return TSDB_CODE_QRY_OUT_OF_MEMORY; } - (*pRsp)->numOfRows = htonl(pQuery->rec.rows); + (*pRsp)->numOfRows = htonl((int32_t)pQuery->rec.rows); int32_t code = pQInfo->code; if (code == TSDB_CODE_SUCCESS) { @@ -6567,15 +6581,15 @@ static void buildTagQueryResult(SQInfo* pQInfo) { *(int64_t*) pQuery->sdata[0]->data = num; count = 1; - pQInfo->tableIndex = num; //set query completed + pQInfo->tableIndex = (int32_t)num; //set query completed qDebug("QInfo:%p create count(tbname) query, res:%d rows:1", pQInfo, count); } else { // return only the tags|table name etc. count = 0; SSchema tbnameSchema = tGetTableNameColumnSchema(); - int32_t maxNumOfTables = pQuery->rec.capacity; + int32_t maxNumOfTables = (int32_t)pQuery->rec.capacity; if (pQuery->limit.limit >= 0 && pQuery->limit.limit < pQuery->rec.capacity) { - maxNumOfTables = pQuery->limit.limit; + maxNumOfTables = (int32_t)pQuery->limit.limit; } while(pQInfo->tableIndex < num && count < maxNumOfTables) { diff --git a/src/query/src/qExtbuffer.c b/src/query/src/qExtbuffer.c index 21b5361acba93c1345b4153ab4417dca9985285c..fcc17a0c9ec98a1e366d3678170f8c0992973518 100644 --- a/src/query/src/qExtbuffer.c +++ b/src/query/src/qExtbuffer.c @@ -172,7 +172,7 @@ int16_t tExtMemBufferPut(tExtMemBuffer *pMemBuffer, void *data, int32_t numOfRow pMemBuffer->numOfElemsInBuffer += numOfRows; pMemBuffer->numOfTotalElems += numOfRows; } else { - int32_t numOfRemainEntries = pMemBuffer->numOfElemsPerPage - pLast->item.num; + int32_t numOfRemainEntries = pMemBuffer->numOfElemsPerPage - (int32_t)pLast->item.num; tColModelAppend(pMemBuffer->pColumnModel, &pLast->item, data, 0, numOfRemainEntries, numOfRows); pMemBuffer->numOfElemsInBuffer += numOfRemainEntries; @@ -270,7 +270,7 @@ int32_t tExtMemBufferFlush(tExtMemBuffer *pMemBuffer) { return ret; } - pMemBuffer->fileMeta.numOfElemsInFile += first->item.num; + pMemBuffer->fileMeta.numOfElemsInFile += (uint32_t)first->item.num; pMemBuffer->fileMeta.nFileSize += 1; tFilePagesItem *ptmp = first; @@ -322,7 +322,7 @@ void tExtMemBufferClear(tExtMemBuffer *pMemBuffer) { } bool tExtMemBufferLoadData(tExtMemBuffer *pMemBuffer, tFilePage *pFilePage, int32_t flushoutId, int32_t pageIdx) { - if (flushoutId < 0 || flushoutId > pMemBuffer->fileMeta.flushoutData.nLength) { + if (flushoutId < 0 || flushoutId > (int32_t)pMemBuffer->fileMeta.flushoutData.nLength) { return false; } @@ -1011,8 +1011,8 @@ void tColModelErase(SColumnModel *pModel, tFilePage *inputBuffer, int32_t blockC } int32_t removed = e - s + 1; - int32_t remain = inputBuffer->num - removed; - int32_t secPart = inputBuffer->num - e - 1; + int32_t remain = (int32_t)inputBuffer->num - removed; + int32_t secPart = (int32_t)inputBuffer->num - e - 1; /* start from the second column */ for (int32_t i = 0; i < pModel->numOfCols; ++i) { diff --git a/src/query/src/qFill.c b/src/query/src/qFill.c index e65d793dc9b6cb3a59e25ad78106895378d70f25..ac44feb5760c1b1dae5bd501b73a7a40e0fcf5e8 100644 --- a/src/query/src/qFill.c +++ b/src/query/src/qFill.c @@ -155,14 +155,14 @@ int64_t getFilledNumOfRes(SFillInfo* pFillInfo, TSKEY ekey, int32_t maxNumOfRows if (numOfRows > 0) { // still fill gap within current data block, not generating data after the result set. TSKEY lastKey = tsList[pFillInfo->numOfRows - 1]; - numOfRes = (int64_t)(labs(lastKey - pFillInfo->start) / pFillInfo->slidingTime) + 1; + numOfRes = (int64_t)(ABS(lastKey - pFillInfo->start) / pFillInfo->slidingTime) + 1; assert(numOfRes >= numOfRows); } else { // reach the end of data if ((ekey1 < pFillInfo->start && FILL_IS_ASC_FILL(pFillInfo)) || (ekey1 > pFillInfo->start && !FILL_IS_ASC_FILL(pFillInfo))) { return 0; } else { // the numOfRes rows are all filled with specified policy - numOfRes = (labs(ekey1 - pFillInfo->start) / pFillInfo->slidingTime) + 1; + numOfRes = (ABS(ekey1 - pFillInfo->start) / pFillInfo->slidingTime) + 1; } } @@ -185,34 +185,34 @@ static double linearInterpolationImpl(double v1, double v2, double k1, double k2 int taosDoLinearInterpolation(int32_t type, SPoint* point1, SPoint* point2, SPoint* point) { switch (type) { case TSDB_DATA_TYPE_INT: { - *(int32_t*)point->val = (int32_t) linearInterpolationImpl(*(int32_t*)point1->val, *(int32_t*)point2->val, point1->key, - point2->key, point->key); + *(int32_t*)point->val = (int32_t)linearInterpolationImpl(*(int32_t*)point1->val, *(int32_t*)point2->val, (double)point1->key, + (double)point2->key, (double)point->key); break; } case TSDB_DATA_TYPE_FLOAT: { - *(float*)point->val = - linearInterpolationImpl(*(float*)point1->val, *(float*)point2->val, point1->key, point2->key, point->key); + *(float*)point->val = (float) + linearInterpolationImpl(*(float*)point1->val, *(float*)point2->val, (double)point1->key, (double)point2->key, (double)point->key); break; }; case TSDB_DATA_TYPE_DOUBLE: { *(double*)point->val = - linearInterpolationImpl(*(double*)point1->val, *(double*)point2->val, point1->key, point2->key, point->key); + linearInterpolationImpl(*(double*)point1->val, *(double*)point2->val, (double)point1->key, (double)point2->key, (double)point->key); break; }; case TSDB_DATA_TYPE_TIMESTAMP: case TSDB_DATA_TYPE_BIGINT: { - *(int64_t*)point->val = (int64_t) linearInterpolationImpl(*(int64_t*)point1->val, *(int64_t*)point2->val, point1->key, - point2->key, point->key); + *(int64_t*)point->val = (int64_t)linearInterpolationImpl((double)(*(int64_t*)point1->val), (double)(*(int64_t*)point2->val), (double)point1->key, + (double)point2->key, (double)point->key); break; }; case TSDB_DATA_TYPE_SMALLINT: { - *(int16_t*)point->val = (int16_t) linearInterpolationImpl(*(int16_t*)point1->val, *(int16_t*)point2->val, point1->key, - point2->key, point->key); + *(int16_t*)point->val = (int16_t)linearInterpolationImpl(*(int16_t*)point1->val, *(int16_t*)point2->val, (double)point1->key, + (double)point2->key, (double)point->key); break; }; case TSDB_DATA_TYPE_TINYINT: { *(int8_t*) point->val = (int8_t) - linearInterpolationImpl(*(int8_t*)point1->val, *(int8_t*)point2->val, point1->key, point2->key, point->key); + linearInterpolationImpl(*(int8_t*)point1->val, *(int8_t*)point2->val, (double)point1->key, (double)point2->key, (double)point->key); break; }; default: { @@ -467,7 +467,7 @@ int32_t generateDataBlockImpl(SFillInfo* pFillInfo, tFilePage** data, int32_t nu int64_t taosGenerateDataBlock(SFillInfo* pFillInfo, tFilePage** output, int32_t capacity) { int32_t remain = taosNumOfRemainRows(pFillInfo); // todo use iterator? - int32_t rows = getFilledNumOfRes(pFillInfo, pFillInfo->endKey, capacity); + int32_t rows = (int32_t)getFilledNumOfRes(pFillInfo, pFillInfo->endKey, capacity); int32_t numOfRes = generateDataBlockImpl(pFillInfo, output, remain, rows, pFillInfo->pData); assert(numOfRes == rows); diff --git a/src/query/src/qHistogram.c b/src/query/src/qHistogram.c index 7835d824699c46b2daa4a805ae163b5240f2c4e0..703ee2c52129a067d1070cfbe567087ec48a7a6e 100644 --- a/src/query/src/qHistogram.c +++ b/src/query/src/qHistogram.c @@ -482,10 +482,10 @@ int64_t tHistogramSum(SHistogramInfo* pHisto, double v) { } } - double m1 = pHisto->elems[slotIdx].num; + double m1 = (double)pHisto->elems[slotIdx].num; double v1 = pHisto->elems[slotIdx].val; - double m2 = pHisto->elems[slotIdx + 1].num; + double m2 = (double)pHisto->elems[slotIdx + 1].num; double v2 = pHisto->elems[slotIdx + 1].val; double estNum = m1 + (m2 - m1) * (v - v1) / (v2 - v1); @@ -538,7 +538,7 @@ double* tHistogramUniform(SHistogramInfo* pHisto, double* ratio, int32_t num) { pVal[i] = pHisto->elems[j].val; } - double start = pHisto->elems[j].num; + double start = (double)pHisto->elems[j].num; double range = pHisto->elems[j + 1].num - start; if (range == 0) { diff --git a/src/query/src/qParserImpl.c b/src/query/src/qParserImpl.c index f556e2dd53b69a4293939fe97224371733dcdda2..d8f12da642851babe493cc85dec4dc1b3dcfe888 100644 --- a/src/query/src/qParserImpl.c +++ b/src/query/src/qParserImpl.c @@ -158,7 +158,7 @@ tSQLExpr *tSQLExprCreateFunction(tSQLExprList *pList, SSQLToken *pFuncToken, SSQ pExpr->nSQLOptr = optType; pExpr->pParam = pList; - int32_t len = (endToken->z + endToken->n) - pFuncToken->z; + int32_t len = (int32_t)((endToken->z + endToken->n) - pFuncToken->z); pExpr->operand.z = pFuncToken->z; pExpr->operand.n = len; // raw field name @@ -468,7 +468,7 @@ void tSQLSetColumnInfo(TAOS_FIELD *pField, SSQLToken *pName, TAOS_FIELD *pType) int32_t maxLen = sizeof(pField->name) / sizeof(pField->name[0]); // truncate the column name - if (pName->n >= maxLen) { + if ((int32_t)pName->n >= maxLen) { pName->n = maxLen - 1; } @@ -524,7 +524,7 @@ SQuerySQL *tSetQuerySQLElems(SSQLToken *pSelectToken, tSQLExprList *pSelection, SQuerySQL *pQuery = calloc(1, sizeof(SQuerySQL)); pQuery->selectToken = *pSelectToken; - pQuery->selectToken.n = strlen(pQuery->selectToken.z); // all later sql string are belonged to the stream sql + pQuery->selectToken.n = (uint32_t)strlen(pQuery->selectToken.z); // all later sql string are belonged to the stream sql pQuery->pSelection = pSelection; pQuery->from = pFrom; diff --git a/src/query/src/qPercentile.c b/src/query/src/qPercentile.c index 7f5fa08cf1bffa423a24650d4f5e2b66b089625f..19775075fc34249bc5d772fb34b3dc6408f2ed44 100644 --- a/src/query/src/qPercentile.c +++ b/src/query/src/qPercentile.c @@ -55,18 +55,18 @@ static tFilePage *loadIntoBucketFromDisk(tMemBucket *pMemBucket, int32_t segIdx, // load data in disk to memory tFilePage *pPage = (tFilePage *)calloc(1, pMemBuffer->pageSize); - for (int32_t i = 0; i < pMemBuffer->fileMeta.flushoutData.nLength; ++i) { + for (uint32_t i = 0; i < pMemBuffer->fileMeta.flushoutData.nLength; ++i) { tFlushoutInfo *pFlushInfo = &pMemBuffer->fileMeta.flushoutData.pFlushoutInfo[i]; int32_t ret = fseek(pMemBuffer->file, pFlushInfo->startPageId * pMemBuffer->pageSize, SEEK_SET); UNUSED(ret); for (uint32_t j = 0; j < pFlushInfo->numOfPages; ++j) { - ret = fread(pPage, pMemBuffer->pageSize, 1, pMemBuffer->file); + ret = (int32_t)fread(pPage, pMemBuffer->pageSize, 1, pMemBuffer->file); UNUSED(ret); assert(pPage->num > 0); - tColModelAppend(pDesc->pColumnModel, buffer, pPage->data, 0, pPage->num, pPage->num); + tColModelAppend(pDesc->pColumnModel, buffer, pPage->data, 0, (int32_t)pPage->num, (int32_t)pPage->num); printf("id: %d count: %" PRIu64 "\n", j, buffer->num); } } @@ -78,12 +78,12 @@ static tFilePage *loadIntoBucketFromDisk(tMemBucket *pMemBucket, int32_t segIdx, // load data in pMemBuffer to buffer tFilePagesItem *pListItem = pMemBuffer->pHead; while (pListItem != NULL) { - tColModelAppend(pDesc->pColumnModel, buffer, pListItem->item.data, 0, pListItem->item.num, - pListItem->item.num); + tColModelAppend(pDesc->pColumnModel, buffer, pListItem->item.data, 0, (int32_t)pListItem->item.num, + (int32_t)pListItem->item.num); pListItem = pListItem->pNext; } - tColDataQSort(pDesc, buffer->num, 0, buffer->num - 1, buffer->data, TSDB_ORDER_ASC); + tColDataQSort(pDesc, (int32_t)buffer->num, 0, (int32_t)buffer->num - 1, buffer->data, TSDB_ORDER_ASC); pDesc->pColumnModel->capacity = oldCapacity; // restore value return buffer; @@ -883,7 +883,7 @@ double getPercentileImpl(tMemBucket *pMemBucket, int32_t count, double fraction) if (sz != pMemBuffer->pageSize) { uError("MemBucket:%p, read tmp file %s failed", pMemBucket, pMemBuffer->path); } else { - tMemBucketPut(pMemBucket, pPage->data, pPage->num); + tMemBucketPut(pMemBucket, pPage->data, (int32_t)pPage->num); } } diff --git a/src/query/src/qResultbuf.c b/src/query/src/qResultbuf.c index b73a7cc8875357cfde30f8125a28d7d1664b37e3..a300cc63825d97356417f6a24d393c922ebe35ec 100644 --- a/src/query/src/qResultbuf.c +++ b/src/query/src/qResultbuf.c @@ -6,7 +6,7 @@ #include "queryLog.h" #include "taoserror.h" -#define GET_DATA_PAYLOAD(_p) ((_p)->pData + POINTER_BYTES) +#define GET_DATA_PAYLOAD(_p) ((tFilePage*)(((char*)(_p)->pData) + POINTER_BYTES)) int32_t createDiskbasedResultBuffer(SDiskbasedResultBuf** pResultBuf, int32_t rowSize, int32_t pagesize, int32_t inMemBufSize, const void* handle) { @@ -95,8 +95,8 @@ static int32_t allocatePositionInFile(SDiskbasedResultBuf* pResultBuf, size_t si SFreeListItem* pi = taosArrayGet(pResultBuf->pFree, i); if (pi->len >= size) { offset = pi->offset; - pi->offset += size; - pi->len -= size; + pi->offset += (int32_t)size; + pi->len -= (int32_t)size; return offset; } @@ -172,7 +172,7 @@ static char* flushPageToDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { // load file block data in disk static char* loadPageFromDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { int32_t ret = fseek(pResultBuf->file, pg->info.offset, SEEK_SET); - ret = fread(GET_DATA_PAYLOAD(pg), 1, pg->info.length, pResultBuf->file); + ret = (int32_t)fread(GET_DATA_PAYLOAD(pg), 1, pg->info.length, pResultBuf->file); if (ret != pg->info.length) { terrno = errno; return NULL; @@ -183,7 +183,7 @@ static char* loadPageFromDisk(SDiskbasedResultBuf* pResultBuf, SPageInfo* pg) { int32_t fullSize = 0; doDecompressData(GET_DATA_PAYLOAD(pg), pg->info.length, &fullSize, pResultBuf); - return GET_DATA_PAYLOAD(pg); + return (char*)GET_DATA_PAYLOAD(pg); } #define NO_AVAILABLE_PAGES(_b) ((_b)->numOfPages >= (_b)->inMemPages) @@ -246,7 +246,7 @@ static char* evicOneDataPage(SDiskbasedResultBuf* pResultBuf) { // all pages are referenced by user, try to allocate new space if (pn == NULL) { int32_t prev = pResultBuf->inMemPages; - pResultBuf->inMemPages = pResultBuf->inMemPages * 1.5; + pResultBuf->inMemPages = (int32_t)(pResultBuf->inMemPages * 1.5f); qWarn("%p in memory buf page not sufficient, expand from %d to %d, page size:%d", pResultBuf, prev, pResultBuf->inMemPages, pResultBuf->pageSize); diff --git a/src/query/src/qTokenizer.c b/src/query/src/qTokenizer.c index b54dc32fb39d5e0f194a7d2e333a8e682a303c19..d0191ec7324a664e2e5454b96c44291b66b7b59e 100644 --- a/src/query/src/qTokenizer.c +++ b/src/query/src/qTokenizer.c @@ -254,12 +254,12 @@ static const char isIdChar[] = { static void* KeywordHashTable = NULL; -static void doInitKeywordsTable() { +static void doInitKeywordsTable(void) { int numOfEntries = tListLen(keywordTable); KeywordHashTable = taosHashInit(numOfEntries, MurmurHash3_32, false); for (int32_t i = 0; i < numOfEntries; i++) { - keywordTable[i].len = strlen(keywordTable[i].name); + keywordTable[i].len = (uint8_t)strlen(keywordTable[i].name); void* ptr = &keywordTable[i]; taosHashPut(KeywordHashTable, keywordTable[i].name, keywordTable[i].len, (void*)&ptr, POINTER_BYTES); } diff --git a/src/query/src/qTsbuf.c b/src/query/src/qTsbuf.c index fe39fe4e4a0632c5893bb93bca6d3e38900ebefa..ab7678a22bb516625b6b6a6826ce8aab35b131e4 100644 --- a/src/query/src/qTsbuf.c +++ b/src/query/src/qTsbuf.c @@ -75,7 +75,7 @@ STSBuf* tsBufCreateFromFile(const char* path, bool autoDelete) { return NULL; } - if (header.numOfVnode > pTSBuf->numOfAlloc) { + if ((int32_t)header.numOfVnode > pTSBuf->numOfAlloc) { pTSBuf->numOfAlloc = header.numOfVnode; STSVnodeBlockInfoEx* tmp = realloc(pTSBuf->pData, sizeof(STSVnodeBlockInfoEx) * pTSBuf->numOfAlloc); if (tmp == NULL) { @@ -171,7 +171,7 @@ static STSVnodeBlockInfoEx* tsBufGetLastVnodeInfo(STSBuf* pTSBuf) { static STSVnodeBlockInfoEx* addOneVnodeInfo(STSBuf* pTSBuf, int32_t vnodeId) { if (pTSBuf->numOfAlloc <= pTSBuf->numOfVnodes) { uint32_t newSize = (uint32_t)(pTSBuf->numOfAlloc * 1.5); - assert(newSize > pTSBuf->numOfAlloc); + assert((int32_t)newSize > pTSBuf->numOfAlloc); STSVnodeBlockInfoEx* tmp = (STSVnodeBlockInfoEx*)realloc(pTSBuf->pData, sizeof(STSVnodeBlockInfoEx) * newSize); if (tmp == NULL) { @@ -288,7 +288,7 @@ STSBlock* readDataFromDisk(STSBuf* pTSBuf, int32_t order, bool decomp) { * set the right position for the reversed traverse, the reversed traverse is started from * the end of each comp data block */ - int32_t ret = fseek(pTSBuf->f, -sizeof(pBlock->padding), SEEK_CUR); + int32_t ret = fseek(pTSBuf->f, -(int32_t)(sizeof(pBlock->padding)), SEEK_CUR); size_t sz = fread(&pBlock->padding, sizeof(pBlock->padding), 1, pTSBuf->f); UNUSED(sz); @@ -474,7 +474,7 @@ static int32_t tsBufFindBlockByTag(STSBuf* pTSBuf, STSVnodeBlockInfo* pBlockInfo offset = pBlockInfo->offset + pBlockInfo->compLen; } - if (fseek(pTSBuf->f, offset, SEEK_SET) != 0) { + if (fseek(pTSBuf->f, (int32_t)offset, SEEK_SET) != 0) { return -1; } @@ -524,7 +524,7 @@ static void tsBufGetBlock(STSBuf* pTSBuf, int32_t vnodeIndex, int32_t blockIndex * may exceed the maximum allowed size during *tsBufAppend* function by invoking expandBuffer function */ if (s > pTSBuf->tsData.allocSize) { - expandBuffer(&pTSBuf->tsData, s); + expandBuffer(&pTSBuf->tsData, (int32_t)s); } pTSBuf->tsData.len = @@ -737,7 +737,7 @@ int32_t tsBufMerge(STSBuf* pDestBuf, const STSBuf* pSrcBuf, int32_t vnodeId) { assert(r == 0); int64_t offset = getDataStartOffset(); - int32_t size = pSrcBuf->fileSize - offset; + int32_t size = (int32_t)pSrcBuf->fileSize - (int32_t)offset; ssize_t rc = taosFSendFile(pDestBuf->f, pSrcBuf->f, &offset, size); @@ -896,7 +896,7 @@ static int32_t doUpdateVnodeInfo(STSBuf* pTSBuf, int64_t offset, STSVnodeBlockIn return -1; } - if (fseek(pTSBuf->f, offset, SEEK_SET) != 0) { + if (fseek(pTSBuf->f, (int32_t)offset, SEEK_SET) != 0) { return -1; } diff --git a/src/rpc/CMakeLists.txt b/src/rpc/CMakeLists.txt index 15a8923d2126df480165f082b33f5919e8aac351..f94b4aeb6d21277b6b845587cd35a2c98e0bc0b0 100644 --- a/src/rpc/CMakeLists.txt +++ b/src/rpc/CMakeLists.txt @@ -1,25 +1,10 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -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) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc) INCLUDE_DIRECTORIES(inc) - -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - AUX_SOURCE_DIRECTORY(src SRC) -ELSEIF (TD_DARWIN_64) - AUX_SOURCE_DIRECTORY(src SRC) -ELSEIF (TD_WINDOWS_64) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) - AUX_SOURCE_DIRECTORY(src SRC) -ENDIF () +AUX_SOURCE_DIRECTORY(src SRC) ADD_LIBRARY(trpc ${SRC}) TARGET_LINK_LIBRARIES(trpc tutil lz4 common) ADD_SUBDIRECTORY(test) - diff --git a/src/rpc/src/rpcTcp.c b/src/rpc/src/rpcTcp.c index c69456b8e282dcad61d3c30fca89efabdc8ecbda..ac617edfc322b08299ff998a2f42df9577f613d3 100644 --- a/src/rpc/src/rpcTcp.c +++ b/src/rpc/src/rpcTcp.c @@ -21,6 +21,9 @@ #include "rpcLog.h" #include "rpcHead.h" #include "rpcTcp.h" +#ifdef WINDOWS +#include "wepoll.h" +#endif #ifndef EPOLLWAKEUP #define EPOLLWAKEUP (1u << 29) @@ -28,7 +31,7 @@ typedef struct SFdObj { void *signature; - int fd; // TCP socket FD + SOCKET fd; // TCP socket FD int closedByApp; // 1: already closed by App void *thandle; // handle from upper layer, like TAOS uint32_t ip; @@ -44,7 +47,7 @@ typedef struct SThreadObj { pthread_mutex_t mutex; uint32_t ip; bool stop; - int pollFd; + SOCKET pollFd; int numOfFds; int threadId; char label[TSDB_LABEL_LEN]; @@ -53,7 +56,7 @@ typedef struct SThreadObj { } SThreadObj; typedef struct { - int fd; + SOCKET fd; uint32_t ip; uint16_t port; char label[TSDB_LABEL_LEN]; @@ -64,7 +67,7 @@ typedef struct { } SServerObj; static void *taosProcessTcpData(void *param); -static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, int fd); +static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, SOCKET fd); static void taosFreeFdObj(SFdObj *pFdObj); static void taosReportBrokenLink(SFdObj *pFdObj); static void *taosAcceptTcpConnection(void *arg); @@ -120,7 +123,7 @@ void *taosInitTcpServer(uint32_t ip, uint16_t port, char *label, int numOfThread break; } - pThreadObj->pollFd = epoll_create(10); // size does not matter + pThreadObj->pollFd = (int64_t)epoll_create(10); // size does not matter if (pThreadObj->pollFd < 0) { tError("%s failed to create TCP epoll", label); code = -1; @@ -163,7 +166,7 @@ static void taosStopTcpThread(SThreadObj* pThreadObj) { pThreadObj->stop = true; eventfd_t fd = -1; - if (pThreadObj->thread && pThreadObj->pollFd >=0) { + if (taosCheckPthreadValid(pThreadObj->thread) && pThreadObj->pollFd >= 0) { // signal the thread to stop, try graceful method first, // and use pthread_cancel when failed struct epoll_event event = { .events = EPOLLIN }; @@ -179,9 +182,9 @@ static void taosStopTcpThread(SThreadObj* pThreadObj) { } } - if (pThreadObj->thread) pthread_join(pThreadObj->thread, NULL); - if (pThreadObj->pollFd >=0) close(pThreadObj->pollFd); - if (fd != -1) close(fd); + if (taosCheckPthreadValid(pThreadObj->thread)) pthread_join(pThreadObj->thread, NULL); + if (pThreadObj->pollFd >=0) taosCloseSocket(pThreadObj->pollFd); + if (fd != -1) taosCloseSocket(fd); while (pThreadObj->pHead) { SFdObj *pFdObj = pThreadObj->pHead; @@ -195,7 +198,7 @@ void taosStopTcpServer(void *handle) { if (pServerObj == NULL) return; if(pServerObj->fd >=0) shutdown(pServerObj->fd, SHUT_RD); - if(pServerObj->thread) pthread_join(pServerObj->thread, NULL); + if (taosCheckPthreadValid(pServerObj->thread)) pthread_join(pServerObj->thread, NULL); tDebug("%s TCP server is stopped", pServerObj->label); } @@ -218,7 +221,7 @@ void taosCleanUpTcpServer(void *handle) { } static void *taosAcceptTcpConnection(void *arg) { - int connFd = -1; + SOCKET connFd = -1; struct sockaddr_in caddr; int threadId = 0; SThreadObj *pThreadObj; @@ -252,7 +255,7 @@ static void *taosAcceptTcpConnection(void *arg) { tDebug("%s new TCP connection from %s:%hu, fd:%d FD:%p numOfFds:%d", pServerObj->label, inet_ntoa(caddr.sin_addr), pFdObj->port, connFd, pFdObj, pThreadObj->numOfFds); } else { - close(connFd); + taosCloseSocket(connFd); tError("%s failed to malloc FdObj(%s) for connection from:%s:%hu", pServerObj->label, strerror(errno), inet_ntoa(caddr.sin_addr), htons(caddr.sin_port)); } @@ -262,7 +265,7 @@ static void *taosAcceptTcpConnection(void *arg) { threadId = threadId % pServerObj->numOfThreads; } - close(pServerObj->fd); + taosCloseSocket(pServerObj->fd); return NULL; } @@ -283,7 +286,7 @@ void *taosInitTcpClient(uint32_t ip, uint16_t port, char *label, int num, void * return NULL; } - pThreadObj->pollFd = epoll_create(10); // size does not matter + pThreadObj->pollFd = (SOCKET)epoll_create(10); // size does not matter if (pThreadObj->pollFd < 0) { tError("%s failed to create TCP client epoll", label); free(pThreadObj); @@ -298,7 +301,7 @@ void *taosInitTcpClient(uint32_t ip, uint16_t port, char *label, int num, void * int code = pthread_create(&(pThreadObj->thread), &thattr, taosProcessTcpData, (void *)(pThreadObj)); pthread_attr_destroy(&thattr); if (code != 0) { - close(pThreadObj->pollFd); + taosCloseSocket(pThreadObj->pollFd); free(pThreadObj); terrno = TAOS_SYSTEM_ERROR(errno); tError("%s failed to create TCP read data thread(%s)", label, strerror(errno)); @@ -330,7 +333,7 @@ void taosCleanUpTcpClient(void *chandle) { void *taosOpenTcpClientConnection(void *shandle, void *thandle, uint32_t ip, uint16_t port) { SThreadObj * pThreadObj = shandle; - int fd = taosOpenTcpClientSocket(ip, port, pThreadObj->ip); + SOCKET fd = taosOpenTcpClientSocket(ip, port, pThreadObj->ip); if (fd < 0) return NULL; struct sockaddr_in sin; @@ -350,7 +353,7 @@ void *taosOpenTcpClientConnection(void *shandle, void *thandle, uint32_t ip, uin tDebug("%s %p TCP connection to 0x%x:%hu is created, localPort:%hu FD:%p numOfFds:%d", pThreadObj->label, thandle, ip, port, localPort, pFdObj, pThreadObj->numOfFds); } else { - close(fd); + taosCloseSocket(fd); tError("%s failed to malloc client FdObj(%s)", pThreadObj->label, strerror(errno)); } @@ -502,7 +505,7 @@ static void *taosProcessTcpData(void *param) { return NULL; } -static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, int fd) { +static SFdObj *taosMallocFdObj(SThreadObj *pThreadObj, SOCKET fd) { struct epoll_event event; SFdObj *pFdObj = (SFdObj *)calloc(sizeof(SFdObj), 1); diff --git a/src/rpc/src/rpcUdp.c b/src/rpc/src/rpcUdp.c index 7e59210caee47c533ed44fcc94eed11b5aa1b29d..8e24aed8f789f03ef324c05922c38ecefe747256 100644 --- a/src/rpc/src/rpcUdp.c +++ b/src/rpc/src/rpcUdp.c @@ -31,7 +31,7 @@ typedef struct { int index; - int fd; + SOCKET fd; uint16_t port; // peer port uint16_t localPort; // local port char label[TSDB_LABEL_LEN]; // copy from udpConnSet; diff --git a/src/rpc/test/CMakeLists.txt b/src/rpc/test/CMakeLists.txt index ac7ea8e4c119fd82ea6b1fc7b45a7c7dcab0c792..286c8e168067f5691030eb1e58e16b5c751ab672 100644 --- a/src/rpc/test/CMakeLists.txt +++ b/src/rpc/test/CMakeLists.txt @@ -1,13 +1,9 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -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) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/rpc/inc) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) +IF (TD_LINUX_64) LIST(APPEND CLIENT_SRC ./rclient.c) ADD_EXECUTABLE(rclient ${CLIENT_SRC}) TARGET_LINK_LIBRARIES(rclient trpc) @@ -20,5 +16,3 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) ADD_EXECUTABLE(rserver ${SERVER_SRC}) TARGET_LINK_LIBRARIES(rserver trpc) ENDIF () - - diff --git a/src/rpc/test/rclient.c b/src/rpc/test/rclient.c index e2d9d388f9af91f12fa0fba0e892ba256555552e..6ec2d8244512eb0ccce24bd45ce5c7aafa2b1399 100644 --- a/src/rpc/test/rclient.c +++ b/src/rpc/test/rclient.c @@ -183,7 +183,7 @@ int main(int argc, char *argv[]) { gettimeofday(&systemTime, NULL); endTime = systemTime.tv_sec*1000000 + systemTime.tv_usec; - float usedTime = (endTime - startTime)/1000.0; // mseconds + float usedTime = (endTime - startTime)/1000.0f; // mseconds tInfo("it takes %.3f mseconds to send %d requests to server", usedTime, numOfReqs*appThreads); tInfo("Performance: %.3f requests per second, msgSize:%d bytes", 1000.0*numOfReqs*appThreads/usedTime, msgSize); diff --git a/src/sync/CMakeLists.txt b/src/sync/CMakeLists.txt index 9b7def6a68956b8a889a5d5cb81980e30a747321..efdf2bd185cb5db46d7f0918725ebe8886d5bd98 100644 --- a/src/sync/CMakeLists.txt +++ b/src/sync/CMakeLists.txt @@ -1,16 +1,11 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - 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) - INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(src SRC) + +IF (TD_LINUX) LIST(REMOVE_ITEM SRC ./src/tarbitrator.c) - ADD_LIBRARY(sync ${SRC}) TARGET_LINK_LIBRARIES(sync tutil pthread common) diff --git a/src/sync/test/CMakeLists.txt b/src/sync/test/CMakeLists.txt index 89d739080f0bf327deca784350f58b8cc53b7933..a309539024c32a25f64fb4c092e8197f8ecbe123 100644 --- a/src/sync/test/CMakeLists.txt +++ b/src/sync/test/CMakeLists.txt @@ -1,11 +1,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - 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) +IF (TD_LINUX_64) INCLUDE_DIRECTORIES(../inc) LIST(APPEND CLIENT_SRC ./syncClient.c) diff --git a/src/tsdb/CMakeLists.txt b/src/tsdb/CMakeLists.txt index 450afe337bb287f204567e743d1aee5b37f86ba3..cef1d0bba7ada660ef5f8059c264b2bdfd0056d2 100644 --- a/src/tsdb/CMakeLists.txt +++ b/src/tsdb/CMakeLists.txt @@ -1,19 +1,15 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - 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) - # INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/vnode/common/inc) - - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(src SRC) +IF (TD_LINUX) ADD_LIBRARY(tsdb ${SRC}) TARGET_LINK_LIBRARIES(tsdb common tutil) - # Someone has no gtest directory, so comment it # ADD_SUBDIRECTORY(tests) +ELSEIF (TD_WINDOWS) + ADD_LIBRARY(tsdb ${SRC}) + TARGET_LINK_LIBRARIES(tsdb common tutil) ENDIF () diff --git a/src/tsdb/inc/tsdbMain.h b/src/tsdb/inc/tsdbMain.h index 2f90fa392123ed66460029331da40b2f9d3b1edc..6119f7086c6575a629dbb822425a775f394f9a3a 100644 --- a/src/tsdb/inc/tsdbMain.h +++ b/src/tsdb/inc/tsdbMain.h @@ -15,6 +15,7 @@ #ifndef _TD_TSDB_MAIN_H_ #define _TD_TSDB_MAIN_H_ +#include "os.h" #include "hash.h" #include "tcoding.h" #include "tglobal.h" @@ -67,7 +68,7 @@ typedef struct STable { char* sql; void* cqhandle; SRWLatch latch; // TODO: implementa latch functions - T_REF_DECLARE(); + T_REF_DECLARE() } STable; typedef struct { @@ -115,7 +116,7 @@ typedef struct { } STableData; typedef struct { - T_REF_DECLARE(); + T_REF_DECLARE() SRWLatch latch; TSKEY keyFirst; TSKEY keyLast; @@ -128,10 +129,19 @@ typedef struct { } SMemTable; enum { TSDB_UPDATE_META, TSDB_DROP_META }; + +#ifdef WINDOWS +#pragma pack(push ,1) +typedef struct { +#else typedef struct __attribute__((packed)){ +#endif char act; uint64_t uid; } SActObj; +#ifdef WINDOWS +#pragma pack(pop) +#endif typedef struct { int len; diff --git a/src/util/CMakeLists.txt b/src/util/CMakeLists.txt index d91ef075ef980215a03389c3e9d4c826fd41bf35..b2778b69d93be9c86bb948223967d755fed9bbbe 100644 --- a/src/util/CMakeLists.txt +++ b/src/util/CMakeLists.txt @@ -1,16 +1,10 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -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) - -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/lz4/inc) - AUX_SOURCE_DIRECTORY(src SRC) - ADD_LIBRARY(tutil ${SRC}) +AUX_SOURCE_DIRECTORY(src SRC) +ADD_LIBRARY(tutil ${SRC}) + +IF (TD_LINUX) TARGET_LINK_LIBRARIES(tutil pthread osdetail m rt lz4) ADD_SUBDIRECTORY(tests) @@ -29,18 +23,8 @@ IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) MESSAGE(STATUS "Failed to find iconv, use default encoding method") ENDIF () -ELSEIF (TD_WINDOWS_64) - 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}/src/inc) - AUX_SOURCE_DIRECTORY(src SRC) - ADD_LIBRARY(tutil ${SRC}) - TARGET_LINK_LIBRARIES(tutil iconv regex pthread osdetail winmm IPHLPAPI ws2_32 lz4) -ELSEIF(TD_DARWIN_64) - AUX_SOURCE_DIRECTORY(src SRC) - ADD_LIBRARY(tutil ${SRC}) +ELSEIF (TD_WINDOWS) + TARGET_LINK_LIBRARIES(tutil iconv regex pthread osdetail winmm IPHLPAPI ws2_32 lz4 wepoll) +ELSEIF(TD_DARWIN) TARGET_LINK_LIBRARIES(tutil iconv pthread osdetail lz4) ENDIF() - -# TARGET_LINK_LIBRARIES(tutil mstorage) diff --git a/src/util/inc/tsocket.h b/src/util/inc/tsocket.h index 97abc16333ae08cec2387045d8ae458de43b3a06..f14e8dbb356e131bbd580f8c5310bea944e71033 100644 --- a/src/util/inc/tsocket.h +++ b/src/util/inc/tsocket.h @@ -20,17 +20,17 @@ extern "C" { #endif -int taosReadn(int sock, char *buffer, int len); -int taosWriteMsg(int fd, void *ptr, int nbytes); -int taosReadMsg(int fd, void *ptr, int nbytes); -int taosNonblockwrite(int fd, char *ptr, int nbytes); -int taosCopyFds(int sfd, int dfd, int64_t len); -int taosSetNonblocking(int sock, int on); +int taosReadn(SOCKET sock, char *buffer, int len); +int taosWriteMsg(SOCKET fd, void *ptr, int nbytes); +int taosReadMsg(SOCKET fd, void *ptr, int nbytes); +int taosNonblockwrite(SOCKET fd, char *ptr, int nbytes); +int taosCopyFds(SOCKET sfd, SOCKET dfd, int64_t len); +int taosSetNonblocking(SOCKET sock, int on); -int taosOpenUdpSocket(uint32_t localIp, uint16_t localPort); -int taosOpenTcpClientSocket(uint32_t ip, uint16_t port, uint32_t localIp); -int taosOpenTcpServerSocket(uint32_t ip, uint16_t port); -int taosKeepTcpAlive(int sockFd); +SOCKET taosOpenUdpSocket(uint32_t localIp, uint16_t localPort); +SOCKET taosOpenTcpClientSocket(uint32_t ip, uint16_t port, uint32_t localIp); +SOCKET taosOpenTcpServerSocket(uint32_t ip, uint16_t port); +int taosKeepTcpAlive(SOCKET sockFd); int taosGetFqdn(char *); uint32_t taosGetIpFromFqdn(const char *); diff --git a/src/util/inc/tutil.h b/src/util/inc/tutil.h index e312513ff3f1f2294360ab2fce25310bcd9bf6d7..fe5c038c5169d88814c7807d550ebadaba8ebacd 100644 --- a/src/util/inc/tutil.h +++ b/src/util/inc/tutil.h @@ -44,10 +44,10 @@ int taosCheckVersion(char *input_client_version, char *input_server_version, in char * taosIpStr(uint32_t ipInt); uint32_t ip2uint(const char *const ip_addr); -static FORCE_INLINE void taosEncryptPass(uint8_t *inBuf, unsigned int inLen, char *target) { +static FORCE_INLINE void taosEncryptPass(uint8_t *inBuf, size_t inLen, char *target) { MD5_CTX context; MD5Init(&context); - MD5Update(&context, inBuf, inLen); + MD5Update(&context, inBuf, (unsigned int)inLen); MD5Final(&context); memcpy(target, context.digest, TSDB_KEY_LEN); } diff --git a/src/util/src/tsocket.c b/src/util/src/tsocket.c index 6f4d2b8afd81f3bb85405f2d6a1f0f71144878f3..9abda0e1961ebea1112e7e6226cfa552155273a2 100644 --- a/src/util/src/tsocket.c +++ b/src/util/src/tsocket.c @@ -90,7 +90,7 @@ uint32_t ip2uint(const char *const ip_addr) { return *((unsigned int *)ip); } -int taosWriteMsg(int fd, void *buf, int nbytes) { +int taosWriteMsg(SOCKET fd, void *buf, int nbytes) { int nleft, nwritten; char *ptr = (char *)buf; @@ -112,7 +112,7 @@ int taosWriteMsg(int fd, void *buf, int nbytes) { return (nbytes - nleft); } -int taosReadMsg(int fd, void *buf, int nbytes) { +int taosReadMsg(SOCKET fd, void *buf, int nbytes) { int nleft, nread; char *ptr = (char *)buf; @@ -139,7 +139,7 @@ int taosReadMsg(int fd, void *buf, int nbytes) { return (nbytes - nleft); } -int taosNonblockwrite(int fd, char *ptr, int nbytes) { +int taosNonblockwrite(SOCKET fd, char *ptr, int nbytes) { taosSetNonblocking(fd, 1); int nleft, nwritten, nready; @@ -152,7 +152,7 @@ int taosNonblockwrite(int fd, char *ptr, int nbytes) { tv.tv_usec = 0; FD_ZERO(&fset); FD_SET(fd, &fset); - if ((nready = select(fd + 1, NULL, &fset, NULL, &tv)) == 0) { + if ((nready = select((int)(fd + 1), NULL, &fset, NULL, &tv)) == 0) { errno = ETIMEDOUT; uError("fd %d timeout, no enough space to write", fd); break; @@ -181,7 +181,7 @@ int taosNonblockwrite(int fd, char *ptr, int nbytes) { return (nbytes - nleft); } -int taosReadn(int fd, char *ptr, int nbytes) { +int taosReadn(SOCKET fd, char *ptr, int nbytes) { int nread, nready, nleft = nbytes; fd_set fset; @@ -192,7 +192,7 @@ int taosReadn(int fd, char *ptr, int nbytes) { tv.tv_usec = 0; FD_ZERO(&fset); FD_SET(fd, &fset); - if ((nready = select(fd + 1, NULL, &fset, NULL, &tv)) == 0) { + if ((nready = select((int)(fd + 1), NULL, &fset, NULL, &tv)) == 0) { errno = ETIMEDOUT; uError("fd %d timeout\n", fd); break; @@ -219,9 +219,9 @@ int taosReadn(int fd, char *ptr, int nbytes) { return (nbytes - nleft); } -int taosOpenUdpSocket(uint32_t ip, uint16_t port) { +SOCKET taosOpenUdpSocket(uint32_t ip, uint16_t port) { struct sockaddr_in localAddr; - int sockFd; + SOCKET sockFd; int bufSize = 1024000; uDebug("open udp socket:0x%x:%hu", ip, port); @@ -238,32 +238,32 @@ int taosOpenUdpSocket(uint32_t ip, uint16_t port) { if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_SNDBUF, (void *)&bufSize, sizeof(bufSize)) != 0) { uError("failed to set the send buffer size for UDP socket\n"); - close(sockFd); + taosCloseSocket(sockFd); return -1; } if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_RCVBUF, (void *)&bufSize, sizeof(bufSize)) != 0) { uError("failed to set the receive buffer size for UDP socket\n"); - close(sockFd); + taosCloseSocket(sockFd); return -1; } /* bind socket to local address */ if (bind(sockFd, (struct sockaddr *)&localAddr, sizeof(localAddr)) < 0) { uError("failed to bind udp socket: %d (%s), 0x%x:%hu", errno, strerror(errno), ip, port); - close(sockFd); + taosCloseSocket(sockFd); return -1; } return sockFd; } -int taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientIp) { - int sockFd = 0; +SOCKET taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientIp) { + SOCKET sockFd = 0; struct sockaddr_in serverAddr, clientAddr; int ret; - sockFd = (int)socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + sockFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); if (sockFd < 0) { uError("failed to open the socket: %d (%s)", errno, strerror(errno)); @@ -274,11 +274,11 @@ int taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientI int reuse = 1; if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) < 0) { uError("setsockopt SO_REUSEADDR failed: %d (%s)", errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; }; - if ( clientIp != 0) { + if (clientIp != 0) { memset((char *)&clientAddr, 0, sizeof(clientAddr)); clientAddr.sin_family = AF_INET; clientAddr.sin_addr.s_addr = clientIp; @@ -288,7 +288,7 @@ int taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientI if (bind(sockFd, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0) { uError("bind tcp client socket failed, client(0x%x:0), dest(0x%x:%d), reason:(%s)", clientIp, destIp, destPort, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } } @@ -302,7 +302,7 @@ int taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientI if (ret != 0) { //uError("failed to connect socket, ip:0x%x, port:%hu(%s)", destIp, destPort, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); sockFd = -1; } else { taosKeepTcpAlive(sockFd); @@ -311,39 +311,39 @@ int taosOpenTcpClientSocket(uint32_t destIp, uint16_t destPort, uint32_t clientI return sockFd; } -int taosKeepTcpAlive(int sockFd) { +int taosKeepTcpAlive(SOCKET sockFd) { int alive = 1; if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_KEEPALIVE, (void *)&alive, sizeof(alive)) < 0) { uError("fd:%d setsockopt SO_KEEPALIVE failed: %d (%s)", sockFd, errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } int probes = 3; if (taosSetSockOpt(sockFd, SOL_TCP, TCP_KEEPCNT, (void *)&probes, sizeof(probes)) < 0) { uError("fd:%d setsockopt SO_KEEPCNT failed: %d (%s)", sockFd, errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } int alivetime = 10; if (taosSetSockOpt(sockFd, SOL_TCP, TCP_KEEPIDLE, (void *)&alivetime, sizeof(alivetime)) < 0) { uError("fd:%d setsockopt SO_KEEPIDLE failed: %d (%s)", sockFd, errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } int interval = 3; if (taosSetSockOpt(sockFd, SOL_TCP, TCP_KEEPINTVL, (void *)&interval, sizeof(interval)) < 0) { uError("fd:%d setsockopt SO_KEEPINTVL failed: %d (%s)", sockFd, errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } int nodelay = 1; if (taosSetSockOpt(sockFd, IPPROTO_TCP, TCP_NODELAY, (void *)&nodelay, sizeof(nodelay)) < 0) { uError("fd:%d setsockopt TCP_NODELAY failed %d (%s)", sockFd, errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } @@ -352,16 +352,16 @@ int taosKeepTcpAlive(int sockFd) { linger.l_linger = 3; if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_LINGER, (void *)&linger, sizeof(linger)) < 0) { uError("setsockopt SO_LINGER failed: %d (%s)", errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } return 0; } -int taosOpenTcpServerSocket(uint32_t ip, uint16_t port) { +SOCKET taosOpenTcpServerSocket(uint32_t ip, uint16_t port) { struct sockaddr_in serverAdd; - int sockFd; + SOCKET sockFd; int reuse; uDebug("open tcp server socket:0x%x:%hu", ip, port); @@ -380,26 +380,26 @@ int taosOpenTcpServerSocket(uint32_t ip, uint16_t port) { reuse = 1; if (taosSetSockOpt(sockFd, SOL_SOCKET, SO_REUSEADDR, (void *)&reuse, sizeof(reuse)) < 0) { uError("setsockopt SO_REUSEADDR failed: %d (%s)", errno, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; }; /* bind socket to server address */ if (bind(sockFd, (struct sockaddr *)&serverAdd, sizeof(serverAdd)) < 0) { uError("bind tcp server socket failed, 0x%x:%hu(%s)", ip, port, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } if (taosKeepTcpAlive(sockFd) < 0) { uError("failed to set tcp server keep-alive option, 0x%x:%hu(%s)", ip, port, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } if (listen(sockFd, 10) < 0) { uError("listen tcp server socket failed, 0x%x:%hu(%s)", ip, port, strerror(errno)); - close(sockFd); + taosCloseSocket(sockFd); return -1; } @@ -413,7 +413,7 @@ void tinet_ntoa(char *ipstr, unsigned int ip) { #define COPY_SIZE 32768 // sendfile shall be used -int taosCopyFds(int sfd, int dfd, int64_t len) { +int taosCopyFds(SOCKET sfd, SOCKET dfd, int64_t len) { int64_t leftLen; int readLen, writeLen; char temp[COPY_SIZE]; diff --git a/src/vnode/CMakeLists.txt b/src/vnode/CMakeLists.txt index 9b6b03209e6fc9abce2ee4871de649c9cc688dbe..09cfa632fbfaaa77b32c09b49f051c0714b33564 100644 --- a/src/vnode/CMakeLists.txt +++ b/src/vnode/CMakeLists.txt @@ -1,19 +1,14 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - 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/query/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/tsdb/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/dnode/inc) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) - INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) - INCLUDE_DIRECTORIES(inc) - AUX_SOURCE_DIRECTORY(src SRC) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/query/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/tsdb/inc) +INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/dnode/inc) +INCLUDE_DIRECTORIES(${TD_ENTERPRISE_DIR}/src/inc) +INCLUDE_DIRECTORIES(inc) +AUX_SOURCE_DIRECTORY(src SRC) +IF (TD_LINUX) ADD_LIBRARY(vnode ${SRC}) TARGET_LINK_LIBRARIES(vnode tsdb tcq) ENDIF () diff --git a/src/wal/CMakeLists.txt b/src/wal/CMakeLists.txt index a9c20f643a18eefad94dfb245fcd9692048ee3bf..e7d5ae15108175a20aa2deaae797cb6777d1984f 100644 --- a/src/wal/CMakeLists.txt +++ b/src/wal/CMakeLists.txt @@ -1,15 +1,12 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -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(inc) - AUX_SOURCE_DIRECTORY(${CMAKE_CURRENT_SOURCE_DIR}/src SRC) -ADD_LIBRARY(twal ${SRC}) -TARGET_LINK_LIBRARIES(twal tutil common) - -ADD_SUBDIRECTORY(test) +IF (TD_LINUX) + ADD_LIBRARY(twal ${SRC}) + TARGET_LINK_LIBRARIES(twal tutil common) + ADD_SUBDIRECTORY(test) +ENDIF () diff --git a/src/wal/test/CMakeLists.txt b/src/wal/test/CMakeLists.txt index bfa6aa15401ef4aa0550ebc154a41969446f2e99..6fdb03710e65aedfb6220ca2f9fc43ce9dbfad0d 100644 --- a/src/wal/test/CMakeLists.txt +++ b/src/wal/test/CMakeLists.txt @@ -1,11 +1,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) - 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) +IF (TD_LINUX_64) INCLUDE_DIRECTORIES(../inc) LIST(APPEND WALTEST_SRC ./waltest.c) diff --git a/tests/comparisonTest/tdengine/CMakeLists.txt b/tests/comparisonTest/tdengine/CMakeLists.txt index ccdeefcdaf5a111b62f3d3bae09bf52da2c6b726..2555bdce913d81eab5bd3728b3a35199bef2b7ca 100644 --- a/tests/comparisonTest/tdengine/CMakeLists.txt +++ b/tests/comparisonTest/tdengine/CMakeLists.txt @@ -1,12 +1,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.8) PROJECT(TDengine) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) -INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) -INCLUDE_DIRECTORIES(${TD_OS_DIR}/inc) - -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) +IF (TD_LINUX_64) add_executable(tdengineTest tdengineTest.c) target_link_libraries(tdengineTest taos_static tutil common pthread) ENDIF() diff --git a/tests/examples/c/CMakeLists.txt b/tests/examples/c/CMakeLists.txt index 81d912fc00d9d543cbee9835ef6c791b1b67542f..59bcb6eaff349e8b20fa13995d1a7297f9185a50 100644 --- a/tests/examples/c/CMakeLists.txt +++ b/tests/examples/c/CMakeLists.txt @@ -1,16 +1,8 @@ PROJECT(TDengine) -IF (TD_WINDOWS_64) - INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) +IF (TD_LINUX) + INCLUDE_DIRECTORIES(. ${TD_COMMUNITY_DIR}/src/inc ${TD_COMMUNITY_DIR}/src/client/inc ${TD_COMMUNITY_DIR}/inc) + AUX_SOURCE_DIRECTORY(. SRC) + ADD_EXECUTABLE(demo demo.c) + TARGET_LINK_LIBRARIES(demo taos_static trpc tutil pthread ) ENDIF () - -INCLUDE_DIRECTORIES(. ${TD_COMMUNITY_DIR}/src/inc ${TD_COMMUNITY_DIR}/src/client/inc ${TD_COMMUNITY_DIR}/inc) -AUX_SOURCE_DIRECTORY(. SRC) -ADD_EXECUTABLE(demo demo.c) -TARGET_LINK_LIBRARIES(demo taos_static trpc tutil pthread ) - - - - - - diff --git a/tests/test/c/CMakeLists.txt b/tests/test/c/CMakeLists.txt index 4736c1ebed80d899b4b31d4dce395b7cc278761a..cc8bc78e33ac47a49b34e3914484e2feb0644616 100644 --- a/tests/test/c/CMakeLists.txt +++ b/tests/test/c/CMakeLists.txt @@ -6,7 +6,7 @@ INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/os/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/util/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/common/inc) -IF ((TD_LINUX_64) OR (TD_LINUX_32 AND TD_ARM)) +IF (TD_LINUX) #add_executable(insertPerTable insertPerTable.c) #target_link_libraries(insertPerTable taos_static pthread) diff --git a/tests/tsim/CMakeLists.txt b/tests/tsim/CMakeLists.txt index 0a11a8f14ed0a8855471a5875b2ba8668c5410cc..64adce59454472cc765bfc194d5ab58b287465d4 100644 --- a/tests/tsim/CMakeLists.txt +++ b/tests/tsim/CMakeLists.txt @@ -1,14 +1,10 @@ PROJECT(TDengine) -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) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/src/client/inc) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/cJson/inc) INCLUDE_DIRECTORIES(inc) -IF (TD_WINDOWS_64) +IF (TD_WINDOWS) INCLUDE_DIRECTORIES(${TD_COMMUNITY_DIR}/deps/pthread) ENDIF ()