From 6843ab569a6b9d6cbd30f30aeb75f106eae05316 Mon Sep 17 00:00:00 2001 From: Alex Kotov Date: Sun, 13 Dec 2020 17:04:16 +0500 Subject: [PATCH] Truncate shared memory object --- configure.ac | 4 ++++ include/shmemq.h | 2 ++ src/main.c | 22 ++++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/configure.ac b/configure.ac index 3001647..f64d772 100644 --- a/configure.ac +++ b/configure.ac @@ -36,8 +36,10 @@ AC_CHECK_HEADERS([stdlib.h]) AC_CHECK_HEADERS([string.h]) AC_CHECK_HEADERS([sys/mman.h]) AC_CHECK_HEADERS([sys/stat.h]) +AC_CHECK_HEADERS([unistd.h]) AC_CHECK_FUNCS([ftruncate]) +AC_CHECK_FUNCS([fstat]) AC_CHECK_FUNCS([munmap]) AC_CHECK_FUNCS([strcpy]) AC_CHECK_FUNCS([strlen]) @@ -45,4 +47,6 @@ AC_CHECK_FUNCS([strlen]) AC_SEARCH_LIBS([shm_open], [rt]) AC_SEARCH_LIBS([shm_unlink], [rt]) +AC_CHECK_MEMBER([struct stat.st_size], [], [], [#include ]) + AC_OUTPUT diff --git a/include/shmemq.h b/include/shmemq.h index 0b1ae70..87b821f 100644 --- a/include/shmemq.h +++ b/include/shmemq.h @@ -21,6 +21,8 @@ enum Shmemq_Error { SHMEMQ_ERROR_MALLOC = 1, SHMEMQ_ERROR_INVALID_NAME = 2, SHMEMQ_ERROR_SHARED_MEMORY = 3, + SHMEMQ_ERROR_FSTAT = 4, + SHMEMQ_ERROR_FTRUNCATE = 5, }; struct Shmemq_FrameHeader { diff --git a/src/main.c b/src/main.c index cec77f4..0c15e3c 100644 --- a/src/main.c +++ b/src/main.c @@ -2,6 +2,8 @@ #include "config.h" #endif +#define _POSIX_C_SOURCE 200809L + #include #include @@ -9,6 +11,7 @@ #include #include #include +#include struct Shmemq *shmemq_new( const char *const name, @@ -59,6 +62,25 @@ enum Shmemq_Error shmemq_init( if (shmemq->shm_id == -1) return SHMEMQ_ERROR_SHARED_MEMORY; + struct stat statbuf; + + if (fstat(shmemq->shm_id, &statbuf) != 0) return SHMEMQ_ERROR_FSTAT; + + const size_t min_size = + shmemq->is_consumer ? sizeof(struct Shmemq_BufferHeader) : size; + + if ((size_t)statbuf.st_size < min_size) { + if (ftruncate(shmemq->shm_id, min_size) != 0) { + return SHMEMQ_ERROR_FTRUNCATE; + } + } + + if (fstat(shmemq->shm_id, &statbuf) != 0) return SHMEMQ_ERROR_FSTAT; + + if ((size_t)statbuf.st_size < size && !shmemq->is_consumer) { + if (ftruncate(shmemq->shm_id, size) != 0) return SHMEMQ_ERROR_FTRUNCATE; + } + shmemq->buffer = NULL; return SHMEMQ_ERROR_NONE;