commit 1309de5c161360202372427f06cfb98e799f737d
Author: david.sorber <david.sorber@jacobs.com>
Date:   Thu Jan 18 08:03:28 2024 -0500

    Initial commit with project skeleton.

diff --git a/CMakeLists.txt b/CMakeLists.txt
new file mode 100644
index 0000000..94d2b4b
--- /dev/null
+++ b/CMakeLists.txt
@@ -0,0 +1,109 @@
+cmake_minimum_required(VERSION 3.22)
+project("copytool")
+cmake_policy(SET CMP0054 NEW)
+
+################################################################################
+# Check GCC version
+################################################################################
+IF ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
+    # Require at least gcc 7.5
+    IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.5)
+        MESSAGE(FATAL_ERROR "GCC version must be at least 7.5!")
+    ENDIF()
+ENDIF()
+
+# This is a neat trick to prevent in source builds
+IF (CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR)
+    MESSAGE(FATAL_ERROR "Prevented in-tree build. This is bad practice; you "
+                        "should be running cmake from inside a build directory.")
+ENDIF()
+
+
+# Use /etc/os-release to determine Linux flavor and version
+EXECUTE_PROCESS(COMMAND bash -c "grep \"^NAME=\" /etc/os-release | cut -c7- | rev | cut -c2- | rev"
+    OUTPUT_VARIABLE DISTRIB_ID
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+EXECUTE_PROCESS(COMMAND bash -c "grep \"^VERSION_ID=\" /etc/os-release | cut -c13- | rev | cut -c2- | rev"
+    OUTPUT_VARIABLE DISTRIB_RELEASE
+    OUTPUT_STRIP_TRAILING_WHITESPACE
+)
+
+# Output the parsed ID and release version
+MESSAGE(STATUS "DISTRIB_ID:      " ${DISTRIB_ID})        
+MESSAGE(STATUS "DISTRIB_RELEASE: " ${DISTRIB_RELEASE})
+
+
+################################################################################
+# Configuration
+################################################################################
+
+# Do not let CMake add the build directory path to RPATH. This means that CL/SL
+# cannot be run from the build directory and must be properly installed.
+SET(CMAKE_SKIP_BUILD_RPATH  TRUE)
+
+# Do not allow CMake to find libraries in /usr/local as that's where things
+# like CUDA end up (e.g. /usr/local/cuda-11.3/)
+# BIG NOTE: CMAKE_IGNORE_PATH must be a list of full paths *NOT* prefixes
+SET(CMAKE_IGNORE_PATH "/usr/local/;/usr/local/lib;/usr/local/lib/cmake;"
+                      "/usr/local/cuda/targets/x86_64-linux/lib")
+
+# Uncomment this line to enable AddressSanitizer; remember to also disable
+# tcmalloc. NOTE: although the gold linker is faster for general usage it has
+# several bugs when used with LTO and has therefore been removed from the 
+# line below (-fuse-ld=gold).
+# SET(CMAKE_CXX_FLAGS "-fsanitize=undefined -fno-sanitize=vptr -fno-omit-frame-pointer")
+# SET(CMAKE_CXX_FLAGS "-fsanitize=address -fno-omit-frame-pointer")
+# SET(CMAKE_CXX_FLAGS "-fsanitize=thread -fno-omit-frame-pointer")
+
+#
+# Set the compile flags
+#
+SET(CMAKE_CXX_STANDARD 17)
+SET(CMAKE_CXX_STANDARD_REQUIRED ON)
+# NOTE: gnu extensions are essentially required for proper 128 bit integer support
+#       See: https://quuxplusone.github.io/blog/2019/02/28/is-int128-integral/
+SET(CMAKE_CXX_EXTENSIONS ON)
+SET(CMAKE_CXX_VISIBILITY_PRESET hidden)
+
+SET(CMAKE_C_STANDARD 11)
+SET(CMAKE_C_STANDARD_REQUIRED ON)
+SET(CMAKE_C_VISIBILITY_PRESET hidden)
+
+# Ensure symbols from statically linked libraries are hidden
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wl,--exclude-libs=ALL")
+
+# Enable warnings 
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wextra -Wno-unused-parameter")
+SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wno-unused-parameter")
+
+# Set the library install path depending on the Linux flavor
+SET(LIBRARY_INSTALL_PATH "")
+IF (DISTRIB_ID STREQUAL "Ubuntu")
+    SET(LIBRARY_INSTALL_PATH "/usr/lib/x86_64-linux-gnu/")
+ELSE()
+	# CentOS/RedHat/Rocky/ALMA
+    SET(LIBRARY_INSTALL_PATH "/usr/lib64/")
+ENDIF()
+
+################################################################################
+# Target
+################################################################################
+
+ADD_EXECUTABLE(copytool ${CMAKE_CURRENT_SOURCE_DIR}/src/copytool_main.cc)
+
+################################################################################
+# Create uninstall target
+################################################################################
+CONFIGURE_FILE(
+    ${CMAKE_SOURCE_DIR}/cmake/cmake_uninstall.cmake
+    ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
+@ONLY)
+
+# Only add the target if there isn't one defined already
+IF(NOT TARGET uninstall)
+    ADD_CUSTOM_TARGET(uninstall
+        ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake
+    )
+ENDIF()
diff --git a/cmake/cmake_uninstall.cmake b/cmake/cmake_uninstall.cmake
new file mode 100644
index 0000000..9ae1ae4
--- /dev/null
+++ b/cmake/cmake_uninstall.cmake
@@ -0,0 +1,32 @@
+# http://www.vtk.org/Wiki/CMake_FAQ#Can_I_do_.22make_uninstall.22_with_CMake.3F
+
+IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+  MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"")
+ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
+
+FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
+STRING(REGEX REPLACE "\n" ";" files "${files}")
+FOREACH(file ${files})
+  MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"")
+  IF(EXISTS "$ENV{DESTDIR}${file}")
+    EXEC_PROGRAM(
+      "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+      OUTPUT_VARIABLE rm_out
+      RETURN_VALUE rm_retval
+      )
+    IF(NOT "${rm_retval}" STREQUAL 0)
+      MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
+    ENDIF(NOT "${rm_retval}" STREQUAL 0)
+  ELSEIF(IS_SYMLINK "$ENV{DESTDIR}${file}")
+    EXEC_PROGRAM(
+      "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
+      OUTPUT_VARIABLE rm_out
+      RETURN_VALUE rm_retval
+      )
+    IF(NOT "${rm_retval}" STREQUAL 0)
+      MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"")
+    ENDIF(NOT "${rm_retval}" STREQUAL 0)
+  ELSE(EXISTS "$ENV{DESTDIR}${file}")
+    MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.")
+  ENDIF(EXISTS "$ENV{DESTDIR}${file}")
+ENDFOREACH(file)
diff --git a/src/copytool_main.cc b/src/copytool_main.cc
new file mode 100644
index 0000000..21de4e5
--- /dev/null
+++ b/src/copytool_main.cc
@@ -0,0 +1,28 @@
+#include <cstdint>
+#include <filesystem>
+#include <iostream>
+#include <string>
+#include <thread>
+
+namespace sfs = std::filesystem;
+
+
+int main(int argc, char** argv)
+{
+    std::cout << "Sendfile Copy Util\n" << std::endl;
+
+    if (argc < 2)
+    {
+        std::cerr << "ERROR: please specify input path\n" << std::endl;
+        return -1;
+    }
+
+    const std::string inputPath(argv[1]);
+
+    for (const auto& dirEntry : sfs::recursive_directory_iterator(inputPath))
+    {
+        std::cout << "PATH: " << dirEntry << std::endl;
+    }
+
+    return 0;
+}
