Determine the signedness of standard types

This commit is contained in:
apio 2022-11-21 19:01:12 +01:00
parent d97992c519
commit 30c7c0ad57
3 changed files with 48 additions and 5 deletions

View File

@ -11,6 +11,19 @@ add_library(minitar STATIC ${SOURCES})
set_target_properties(minitar PROPERTIES OUTPUT_NAME mtar) set_target_properties(minitar PROPERTIES OUTPUT_NAME mtar)
include(CheckSourceCompiles)
# Check for signedness of standard types
check_source_compiles(C "#include <sys/types.h>\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 <sys/types.h>\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 <sys/types.h>\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 <sys/types.h>\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 <sys/types.h>\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) if (MSVC)
target_compile_options(minitar PRIVATE /W4 /WX) target_compile_options(minitar PRIVATE /W4 /WX)
else() else()

5
src/config.h.in Normal file
View File

@ -0,0 +1,5 @@
#cmakedefine UNSIGNED_SIZE_TYPE
#cmakedefine UNSIGNED_TIME_TYPE
#cmakedefine UNSIGNED_MODE_TYPE
#cmakedefine UNSIGNED_GID_TYPE
#cmakedefine UNSIGNED_UID_TYPE

View File

@ -1,5 +1,6 @@
#define _POSIX_C_SOURCE 200809L // for strndup #define _POSIX_C_SOURCE 200809L // for strndup
#define _IN_MINITAR #define _IN_MINITAR
#include "config.h"
#include "minitar.h" #include "minitar.h"
#include "tar.h" #include "tar.h"
#include <stdio.h> #include <stdio.h>
@ -33,18 +34,42 @@ void minitar_parse_tar_header(const struct tar_header* hdr, struct minitar_entry
metadata->name[256] = '\0'; 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->mode = (mode_t)strtol(hdr->mode, NULL, 8);
metadata->uid = (uid_t)strtoul(hdr->uid, NULL, 8); #endif
metadata->gid = (gid_t)strtoul(hdr->gid, NULL, 8);
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"); 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); metadata->size = (size_t)strtoull(sizeptr, NULL, 8);
#else
metadata->size = (size_t)strtoll(sizeptr, NULL, 8);
#endif
free(sizeptr); 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"); 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); free(timeptr);
switch (hdr->typeflag) switch (hdr->typeflag)