diff --git a/CMakeLists.txt b/CMakeLists.txt index 454d1f6..cd20d2f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,6 +11,19 @@ add_library(minitar STATIC ${SOURCES}) set_target_properties(minitar PROPERTIES OUTPUT_NAME mtar) +include(CheckSourceCompiles) + +# Check for signedness of standard types +check_source_compiles(C "#include \nint main(int argc, char** argv){ char is_unsigned_size_type[(size_t)0 < (size_t)-1 ? 1 : -1]; }" UNSIGNED_SIZE_TYPE) +check_source_compiles(C "#include \nint main(int argc, char** argv){ char is_unsigned_time_type[(time_t)0 < (time_t)-1 ? 1 : -1]; }" UNSIGNED_TIME_TYPE) +check_source_compiles(C "#include \nint main(int argc, char** argv){ char is_unsigned_mode_type[(mode_t)0 < (mode_t)-1 ? 1 : -1]; }" UNSIGNED_MODE_TYPE) +check_source_compiles(C "#include \nint main(int argc, char** argv){ char is_unsigned_gid_type[(gid_t)0 < (gid_t)-1 ? 1 : -1]; }" UNSIGNED_GID_TYPE) +check_source_compiles(C "#include \nint main(int argc, char** argv){ char is_unsigned_uid_type[(uid_t)0 < (uid_t)-1 ? 1 : -1]; }" UNSIGNED_UID_TYPE) + +configure_file("${CMAKE_CURRENT_SOURCE_DIR}/src/config.h.in" "${CMAKE_CURRENT_BINARY_DIR}/config.h" @ONLY) + +target_include_directories(minitar PRIVATE "${CMAKE_CURRENT_BINARY_DIR}") + if (MSVC) target_compile_options(minitar PRIVATE /W4 /WX) else() diff --git a/src/config.h.in b/src/config.h.in new file mode 100644 index 0000000..7d2eac8 --- /dev/null +++ b/src/config.h.in @@ -0,0 +1,5 @@ +#cmakedefine UNSIGNED_SIZE_TYPE +#cmakedefine UNSIGNED_TIME_TYPE +#cmakedefine UNSIGNED_MODE_TYPE +#cmakedefine UNSIGNED_GID_TYPE +#cmakedefine UNSIGNED_UID_TYPE \ No newline at end of file diff --git a/src/util.c b/src/util.c index a98acc7..5fe2d96 100644 --- a/src/util.c +++ b/src/util.c @@ -1,5 +1,6 @@ #define _POSIX_C_SOURCE 200809L // for strndup #define _IN_MINITAR +#include "config.h" #include "minitar.h" #include "tar.h" #include @@ -33,18 +34,42 @@ void minitar_parse_tar_header(const struct tar_header* hdr, struct minitar_entry metadata->name[256] = '\0'; } +#ifdef UNSIGNED_MODE_TYPE + metadata->mode = (mode_t)strtoul(hdr->mode, NULL, 8); +#else metadata->mode = (mode_t)strtol(hdr->mode, NULL, 8); - metadata->uid = (uid_t)strtoul(hdr->uid, NULL, 8); - metadata->gid = (gid_t)strtoul(hdr->gid, NULL, 8); +#endif - char* sizeptr = strndup(hdr->size, 12); +#ifdef UNSIGNED_UID_TYPE + metadata->uid = (uid_t)strtoul(hdr->uid, NULL, 8); +#else + metadata->uid = (uid_t)strtol(hdr->uid, NULL, 8); +#endif + +#ifdef UNSIGNED_GID_TYPE + metadata->gid = (gid_t)strtoul(hdr->gid, NULL, 8); +#else + metadata->gid = (gid_t)strtol(hdr->uid, NULL, 8); +#endif + + char* sizeptr = strndup( + hdr->size, 12); // The hdr->size field is not null-terminated, yet strndup returns a null-terminated string. if (!sizeptr) minitar_panic("Failed to allocate memory to duplicate a tar header's size field"); +#ifdef UNSIGNED_SIZE_TYPE metadata->size = (size_t)strtoull(sizeptr, NULL, 8); +#else + metadata->size = (size_t)strtoll(sizeptr, NULL, 8); +#endif free(sizeptr); - char* timeptr = strndup(hdr->mtime, 12); + char* timeptr = strndup( + hdr->mtime, 12); // The hdr->mtime field is not null-terminated, yet strndup returns a null-terminated string. if (!timeptr) minitar_panic("Failed to allocate memory to duplicate a tar header's mtime field"); - metadata->mtime = (time_t)strtol(timeptr, NULL, 8); +#ifdef UNSIGNED_TIME_TYPE + metadata->mtime = (time_t)strtoull(timeptr, NULL, 8); +#else + metadata->mtime = (time_t)strtoll(timeptr, NULL, 8); +#endif free(timeptr); switch (hdr->typeflag)