pax_global_header00006660000000000000000000000064137335673640014533gustar00rootroot0000000000000052 comment=6c20e2f12a029a3c7d6347a738bf188e1677571c libvolatilestream-0.2/000077500000000000000000000000001373356736400151165ustar00rootroot00000000000000libvolatilestream-0.2/CMakeLists.txt000066400000000000000000000022101373356736400176510ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.12) project(volatilestream VERSION 0.2.0 DESCRIPTION "FILE* stream as a temporary allocated memory buffer" HOMEPAGE_URL "https://github.com/rd235/libvolatilestream" LANGUAGES C) include(GNUInstallDirs) add_definitions(-D_GNU_SOURCE) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -pedantic") include_directories(${CMAKE_CURRENT_SOURCE_DIR}) set(HEADERS_INSTALL_PATH ${CMAKE_INSTALL_PREFIX}/include) set(LIBRARY_OUTPUT_PATH ${CMAKE_BINARY_DIR}/lib) set(VOLATILESTREAM_SOURCES volatilestream.c) add_library(volatilestream SHARED ${VOLATILESTREAM_SOURCES}) set_target_properties(volatilestream PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) configure_file(volatilestream.pc.in volatilestream.pc @ONLY) install(TARGETS volatilestream LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}) install(FILES volatilestream.h DESTINATION ${HEADERS_INSTALL_PATH}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/volatilestream.pc DESTINATION ${CMAKE_INSTALL_LIBDIR}/pkgconfig) add_subdirectory(man) add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${PROJECT_SOURCE_DIR}/Uninstall.cmake") libvolatilestream-0.2/README.md000066400000000000000000000051171373356736400164010ustar00rootroot00000000000000# libvolatilestream volatile stream = stdio FILE\* stream as a temporary dynamically allocated (and deallocated) memory buffer The `volstream_open` function opens a stdio stream as a temporary memory buffer. The buffer is dynamically allocated, grows as needed and it is automatically deallocated when the stream is closed. ```C FILE *volstream_open(void); ``` The following example writes all the command arguments in a volatile stream, then it rereads the volatile stream one byte at a time ```C int main(int argc, char *argv[]) { FILE *f = volstream_open(); int c; for (argv++; *argv; argv++) fprintf(f, "%s\n", *argv); fseek(f, 0, SEEK_SET); while ((c = getc(f)) != EOF) putchar(c); fclose(f); } ``` ## v.0.2 It is backwards compatible to v.0.1. New functions: ```C struct volstream; FILE *volstream_openv(struct volstream **vols); int volstream_trunc(struct volstream *vols, size_tlength); void *volstream_getbuf(struct volstream *vols); size_t volstream_getsize(struct volstream *vols); ``` The function `volstream_openv` has the same effect of `volstream_open` but it stores in _vols_ a pointer that can be later used for `volstream_trunc`, `volstream_getbuf` and `volstream_getsize`. `volstream_trunc` truncates the buffer to the requested _length_. If the current size of the buffer is larger than _length_ the extra data is lost. If the buffer is shorter it is extended and the extended part is filled with null bytes. `volstream_getbuf` and `volstream_getsize` return the current address and size of the buffer, respectively. These values remain valid only as long as the caller performs no further output on the stream or the stream is closed. `fflush` is required before `volstream_trunc`, `volstream_getbuf` and `volstream_getsize` to flush the stream buffers. The following example has the same effect of the one above but it rereads the arguments as a memory buffer. ``` #include #include #include int main(int argc, char *argv[]) { struct volstream *vols; FILE *f = volstream_openv(&vols); int c; for (argv++; *argv; argv++) { fprintf(f, "%s\n", *argv); } fflush(f); ssize_t s = volstream_getsize(vols); char *buf = volstream_getbuf(vols); write(STDOUT_FILENO, buf, s); fclose(f); } ``` ## Install libvolatilestream uses cmake. A standard installation procedure is: ``` $ mkdir build $ cd build $ cmake .. $ make $ sudo make install ``` Use ```-l volatilestream``` as a gcc/ld option to link the library. ## Uninstall In the build directory type: ``` $ sudo make uninstall ``` libvolatilestream-0.2/Uninstall.cmake000066400000000000000000000010361373356736400200710ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.13) set(MANIFEST "${CMAKE_CURRENT_BINARY_DIR}/install_manifest.txt") if(NOT EXISTS ${MANIFEST}) message(FATAL_ERROR "Cannot find install manifest: '${MANIFEST}'") endif() file(STRINGS ${MANIFEST} files) foreach(file ${files}) if(EXISTS ${file} OR IS_SYMLINK ${file}) message(STATUS "Removing: ${file}") execute_process( COMMAND rm -f ${file} RESULT_VARIABLE retcode ) if(NOT "${retcode}" STREQUAL "0") message(WARNING "Failed to remove: ${file}") endif() endif() endforeach(file) libvolatilestream-0.2/man/000077500000000000000000000000001373356736400156715ustar00rootroot00000000000000libvolatilestream-0.2/man/CMakeLists.txt000066400000000000000000000020101373356736400204220ustar00rootroot00000000000000cmake_minimum_required(VERSION 3.7) set(RONN_ORGANIZATION "VirtualSquare") set(RONN_ARGS --organization=${RONN_ORGANIZATION}) # ### ronn pages file(GLOB VU_RONN_PAGES ${CMAKE_CURRENT_SOURCE_DIR}/*.[1-8].ronn) set(VU_MAN_FILES) foreach(VU_RONN_PATH IN LISTS VU_RONN_PAGES) # VU_RONNPAGE: basename of VU_RONN_PATH get_filename_component(VU_RONNPAGE ${VU_RONN_PATH} NAME) # VU_MANPAGE: VU_RONNPAGE without the suffix string(REGEX REPLACE "\.ronn$" "" VU_MANPAGE ${VU_RONNPAGE}) list(APPEND VU_MAN_FILES ${VU_MANPAGE}) endforeach(VU_RONN_PATH) add_custom_target(${PROJECT_NAME}_manpages ALL make RONN_ARGS="${RONN_ARGS}" ${VU_MAN_FILES} WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) ### man pages file(GLOB VU_MAN_PAGES ${CMAKE_CURRENT_SOURCE_DIR}/*.[1-8]) foreach(VU_MAN_PATH IN LISTS VU_MAN_PAGES) get_filename_component(VU_MANPAGE ${VU_MAN_PATH} NAME) string(REGEX REPLACE ".*\\." "" MAN_CHAPTER ${VU_MANPAGE}) install(FILES ${VU_MAN_PATH} DESTINATION ${CMAKE_INSTALL_MANDIR}/man${MAN_CHAPTER}) endforeach(VU_MAN_PATH) libvolatilestream-0.2/man/Makefile000066400000000000000000000005551373356736400173360ustar00rootroot00000000000000RONN=ronn RONNOK := $(shell command -v ${RONN} 2> /dev/null) none: % : %.ronn ifdef RONNOK # copy copyright notice grep "^\.\\\\\"" $< > $@ || true # run ronn $(RONN) -r ${RONN_ARGS} --pipe $< >> $@ # delete useless trailing "" in .TH sed -i '/^\.TH /s/ ""$$//' $@ else echo "${RONN} is not available. Manpage $@ cannot be updated" >/dev/stderr >&2 endif libvolatilestream-0.2/man/volstream_open.3000066400000000000000000000102411373356736400210100ustar00rootroot00000000000000.\" Copyright (C) 2019 VirtualSquare. Project Leader: Renzo Davoli .\" .\" This is free documentation; you can redistribute it and/or .\" modify it under the terms of the GNU General Public License, .\" as published by the Free Software Foundation, either version 2 .\" of the License, or (at your option) any later version. .\" .\" The GNU General Public License's references to "object code" .\" and "executables" are to be interpreted as the output of any .\" document formatting or typesetting system, including .\" intermediate and printed output. .\" .\" This manual 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. See the .\" GNU General Public License for more details. .\" .\" You should have received a copy of the GNU General Public .\" License along with this manual; if not, write to the Free .\" Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, .\" MA 02110-1301 USA. .\" .\" generated with Ronn-NG/v0.10.0 .\" http://github.com/apjanke/ronn-ng/tree/0.10.0-SNAPSHOT .TH "VOLSTREAM_OPEN" "3" "September 2020" "VirtualSquare" .SH "NAME" \fBvolstream_open\fR \- create a FILE* stream as a volatile stream buffer .SH "SYNOPSIS" \fB#include \fR .P \fBFILE *volstream_open(void);\fR .P \fBstruct volstream;\fR .P \fBFILE *volstream_openv(struct volstream **\fR\fIvols\fR\fB);\fR .P \fBint volstream_trunc(struct volstream *\fR\fIvols\fR\fB, size_t\fR\fIlength\fR\fB);\fR .P \fBvoid *volstream_getbuf(struct volstream *\fR\fIvols\fR\fB);\fR .P \fBsize_t volstream_getsize(struct volstream *\fR\fIvols\fR\fB);\fR .SH "DESCRIPTION" A volatile stream is a stdio FILE* stream as a temporary dynamically allocated (and deallocated) memory buffer\. .P The \fBvolstream_open\fR function opens a stdio stream as a temporary memory buffer\. The buffer is dynamically allocated, grows as needed and it is automatically deallocated when the stream is closed\. .P The function \fBvolstream_openv\fR has the same effect of \fBvolstream_open\fR but it stores in \fIvols\fR a pointer that can be later used for \fBvolstream_trunc\fR, \fBvolstream_getbuf\fR and \fBvolstream_getsize\fR\. .P \fBvolstream_trunc\fR truncates the buffer to the requested \fIlength\fR\. If the current size of the buffer is larger than \fIlength\fR the extra data is lost\. If the buffer is shorter it is extended and the extended part is filled with null bytes\. .P \fBvolstream_getbuf\fR and \fBvolstream_getsize\fR return the current address and size of the buffer, respectively\. These values remain valid only as long as the caller performs no further output on the stream or the stream is closed\. .P \fBfflush\fR is required before \fBvolstream_trunc\fR, \fBvolstream_getbuf\fR and \fBvolstream_getsize\fR to flush the stream buffers\. .SH "RETURN VALUE" Upon successful completion \fBvolstream_open\fR and \fBvolstream_open\fR return a FILE pointer\. Otherwise, NULL is returned and errno is set to indicate the error\. .P \fBvolstream_trunc\fR returns \-1 in case of error, 0 otherwise\. .P \fBvolstream_getbuf\fR and \fBvolstream_getsize\fR return the current address and size of the buffer, respectively\. .SH "EXAMPLES" The following example writes all the command arguments in a volatile stream, then it rereads the volatile stream one byte at a time: .IP "" 4 .nf #include #include int main(int argc, char *argv[]) { FILE *f = volstream_open(); int c; for (argv++; *argv; argv++) fprintf(f, "%s\en", *argv); fseek(f, 0, SEEK_SET); while ((c = getc(f)) != EOF) putchar(c); fclose(f); } .fi .IP "" 0 .P The following example has the same effect but it rereads the arguments as a memory buffer\. .IP "" 4 .nf #include #include #include int main(int argc, char *argv[]) { struct volstream *vols; FILE *f = volstream_openv(&vols); int c; for (argv++; *argv; argv++) { fprintf(f, "%s\en", *argv); } fflush(f); ssize_t s = volstream_getsize(vols); char *buf = volstream_getbuf(vols); write(STDOUT_FILENO, buf, s); fclose(f); } .fi .IP "" 0 .SH "AUTHOR" VirtualSquare\. Project leader: Renzo Davoli\. libvolatilestream-0.2/man/volstream_open.3.ronn000066400000000000000000000074331373356736400217740ustar00rootroot00000000000000volstream_open(3) -- create a FILE* stream as a volatile stream buffer ===== ## SYNOPSIS `#include ` `FILE *volstream_open(void);` `struct volstream;` `FILE *volstream_openv(struct volstream **`_vols_`);` `int volstream_trunc(struct volstream *`_vols_`, size_t `_length_`);` `void *volstream_getbuf(struct volstream *`_vols_`);` `size_t volstream_getsize(struct volstream *`_vols_`);` ## DESCRIPTION A volatile stream is a stdio FILE* stream as a temporary dynamically allocated (and deallocated) memory buffer. The `volstream_open` function opens a stdio stream as a temporary memory buffer. The buffer is dynamically allocated, grows as needed and it is automatically deallocated when the stream is closed. The function `volstream_openv` has the same effect of `volstream_open` but it stores in _vols_ a pointer that can be later used for `volstream_trunc`, `volstream_getbuf` and `volstream_getsize`. `volstream_trunc` truncates the buffer to the requested _length_. If the current size of the buffer is larger than _length_ the extra data is lost. If the buffer is shorter it is extended and the extended part is filled with null bytes. `volstream_getbuf` and `volstream_getsize` return the current address and size of the buffer, respectively. These values remain valid only as long as the caller performs no further output on the stream or the stream is closed. `fflush` is required before `volstream_trunc`, `volstream_getbuf` and `volstream_getsize` to flush the stream buffers. ## RETURN VALUE Upon successful completion `volstream_open` and `volstream_open` return a FILE pointer. Otherwise, NULL is returned and errno is set to indicate the error. `volstream_trunc` returns -1 in case of error, 0 otherwise. `volstream_getbuf` and `volstream_getsize` return the current address and size of the buffer, respectively. ## EXAMPLES The following example writes all the command arguments in a volatile stream, then it rereads the volatile stream one byte at a time: ``` #include #include int main(int argc, char *argv[]) { FILE *f = volstream_open(); int c; for (argv++; *argv; argv++) fprintf(f, "%s\n", *argv); fseek(f, 0, SEEK_SET); while ((c = getc(f)) != EOF) putchar(c); fclose(f); } ``` The following example has the same effect but it rereads the arguments as a memory buffer. ``` #include #include #include int main(int argc, char *argv[]) { struct volstream *vols; FILE *f = volstream_openv(&vols); int c; for (argv++; *argv; argv++) { fprintf(f, "%s\n", *argv); } fflush(f); ssize_t s = volstream_getsize(vols); char *buf = volstream_getbuf(vols); write(STDOUT_FILENO, buf, s); fclose(f); } ``` ## AUTHOR VirtualSquare. Project leader: Renzo Davoli. libvolatilestream-0.2/volatilestream.c000066400000000000000000000127111373356736400203170ustar00rootroot00000000000000/* * volatilestreaam: * volatile stream = stdio FILE* stream as a temporary dynamically allocated * (and deallocated) memory buffer * * Copyright (C) 20182020 Renzo Davoli VirtualSquare team. * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at * your option) any later version. * * You should have received a copy of the GNU Lesser General Public License * along with this library; if not, see . * */ #include #include #include #include #include #define VOLSTREAM_PAGESIZE 4096 struct volstream { char *buf; size_t bufsize; size_t filelen; size_t filepos; }; static ssize_t volstream_read(void *cookie, char *buf, size_t size) { struct volstream *vols = cookie; ssize_t ret_value; if (vols->filepos + size <= vols->filelen) ret_value = size; else ret_value = vols->filelen - vols->filepos; if (ret_value > 0) { memcpy(buf, vols->buf + vols->filepos, ret_value); vols->filepos += ret_value; } return ret_value; } static inline void volstream_buf_expand(struct volstream *vols, size_t newfilesize) { if (newfilesize > vols->bufsize) { size_t newsize = (newfilesize + (VOLSTREAM_PAGESIZE - 1)) & ~(VOLSTREAM_PAGESIZE - 1); char *newbuf; newbuf = realloc(vols->buf, newsize); if (newbuf != NULL) { vols->buf = newbuf; vols->bufsize = newsize; } } } static inline void volstream_buf_shrink(struct volstream *vols, size_t newfilesize) { size_t newsize = (newfilesize + (VOLSTREAM_PAGESIZE - 1)) & ~(VOLSTREAM_PAGESIZE - 1); if (newsize == 0) newsize = VOLSTREAM_PAGESIZE; if (newsize < vols->bufsize - VOLSTREAM_PAGESIZE) { char *newbuf; newbuf = realloc(vols->buf, newsize); if (newbuf != NULL) { vols->buf = newbuf; vols->bufsize = newsize; } } } static ssize_t volstream_write(void *cookie, const char *buf, size_t size) { struct volstream *vols = cookie; ssize_t ret_value; volstream_buf_expand(vols, vols->filepos + size); if (vols->filepos + size <= vols->bufsize) ret_value = size; else ret_value = vols->bufsize - vols->filepos; if (ret_value > 0) { memcpy(vols->buf + vols->filepos, buf, ret_value); vols->filepos += ret_value; if (vols->filepos > vols->filelen) vols->filelen = vols->filepos; } return ret_value; } static int volstream_seek(void *cookie, off64_t *offset, int whence) { struct volstream *vols = cookie; off64_t newpos; switch (whence) { case SEEK_SET: newpos = *offset; break; case SEEK_CUR: newpos = vols->filepos + *offset; break; case SEEK_END: newpos = vols->filelen + *offset; break; default: return errno = EINVAL, -1; } if (newpos < 0) { return errno = EINVAL, -1; } else { if (newpos > vols->filelen) { volstream_buf_expand(vols, newpos); if (newpos > vols->bufsize) return errno = EINVAL, -1; if (newpos > vols->filelen) { memset(vols->buf + vols->filelen, 0, newpos - vols->filelen); vols->filelen = newpos; } } vols->filepos = newpos; *offset = newpos; return 0; } } static int volstream_close(void *cookie) { struct volstream *vols = cookie; free(vols->buf); free(vols); return 0; } int volstream_trunc(struct volstream *vols, size_t length) { if (length < 0) return errno = EINVAL, -1; else { if (length > vols->filelen) { volstream_buf_expand(vols, length); if (length > vols->bufsize) return errno = ENOMEM, -1; if (length > vols->filelen) memset(vols->buf + vols->filelen, 0, length - vols->filelen); } vols->filelen = length; volstream_buf_shrink(vols, length); return 0; } } void *volstream_getbuf(struct volstream *vols) { return vols->buf; } size_t volstream_getsize(struct volstream *vols) { return vols->filelen; } static cookie_io_functions_t volstream_f = { .read = volstream_read, .write = volstream_write, .seek = volstream_seek, .close = volstream_close }; FILE *volstream_openv(struct volstream **_vols) { FILE *volstream; struct volstream *vols = malloc(sizeof(struct volstream)); if (vols == NULL) goto err; vols->buf = malloc(VOLSTREAM_PAGESIZE); if (vols->buf == NULL) goto buferr; vols->bufsize = VOLSTREAM_PAGESIZE; vols->filelen = 0; vols->filepos = 0; volstream = fopencookie(vols, "r+", volstream_f); if (volstream == NULL) goto volstreamerr; if (_vols != NULL) *_vols = vols; return volstream; volstreamerr: free(vols->buf); free(vols); return NULL; buferr: free(vols); err: errno = ENOMEM; return NULL; } FILE *volstream_open(void) { return volstream_openv(NULL); } #if 0 int main(int argc, char *argv[]) { FILE *f = volstream_open(); int c; for (argv++; *argv; argv++) { fprintf(f, "%s\n", *argv); fflush(f); } fseek(f, 0, SEEK_SET); while ((c = getc(f)) != EOF) putchar(c == 0 ? '.' : c); fclose(f); } #endif #if 0 int main(int argc, char *argv[]) { struct volstream *vols; FILE *f = volstream_openv(&vols); int c; for (argv++; *argv; argv++) { fprintf(f, "%s\n", *argv); fflush(f); } fprintf(f,"FINE"); fflush(f); volstream_trunc(vols, 100); ssize_t s = volstream_getsize(vols); char *buf = volstream_getbuf(vols); ssize_t i; for (i=0; i FILE *volstream_open(void); struct volstream; int volstream_trunc(struct volstream *vols, size_t length); void *volstream_getbuf(struct volstream *vols); size_t volstream_getsize(struct volstream *vols); FILE *volstream_openv(struct volstream **vols); #endif libvolatilestream-0.2/volatilestream.pc.in000066400000000000000000000005511373356736400211030ustar00rootroot00000000000000prefix=@CMAKE_INSTALL_PREFIX@ exec_prefix="${prefix}/@CMAKE_INSTALL_BINDIR@" libdir="${prefix}/@CMAKE_INSTALL_LIBDIR@" includedir="${prefix}/@CMAKE_INSTALL_INCLUDEDIR@" Name: @PROJECT_NAME@ Description: @PROJECT_DESCRIPTION@ Version: @PROJECT_VERSION@ Requires: @PROJECT_PC_REQUIRES@ Cflags: -I${includedir} Libs: -L${libdir} -l@PROJECT_NAME@ @PRIVATE_LIBS@