From e7bea197d3eaed2b38afb2334376d46ef1b70631 Mon Sep 17 00:00:00 2001 From: Konstantin Kushnir Date: Sat, 12 Oct 2024 15:51:05 +0000 Subject: [PATCH] Allow to build without Tcl callbacks --- .github/workflows/linux-build.yml | 3 ++ ChangeLog | 1 + TODO.txt | 4 -- configure | 71 ++++++++++++++++++++++++++----- configure.in | 44 ++++++++++++------- generic/cookfs.h | 1 + generic/pages.c | 36 +++++++++++++--- generic/pages.h | 5 ++- generic/pagesCmd.c | 63 ++++++++++++++++----------- generic/pagesCompr.c | 22 ++++++++++ generic/pagesCompr.h | 2 + generic/pagesInt.h | 4 ++ generic/vfsCmd.c | 28 +++++++++--- pkgconfig.tcl.in | 1 + tests/common.tcl | 2 + tests/pages.test | 45 +++++++++++++++----- tests/pagesAsync.test | 52 ++++++++++++++++------ tests/pagesEncrypt.test | 8 +++- tests/pkgconfig.test | 1 + tests/vfs.test | 33 +++++++++++++- tests/vfsThread.test | 4 +- 21 files changed, 337 insertions(+), 93 deletions(-) diff --git a/.github/workflows/linux-build.yml b/.github/workflows/linux-build.yml index 250b071..fc23334 100644 --- a/.github/workflows/linux-build.yml +++ b/.github/workflows/linux-build.yml @@ -36,6 +36,9 @@ jobs: - compiler: gcc configure: "--disable-c-crypto" description: "no crypto" + - compiler: gcc + configure: "--disable-tcl-callbacks" + description: "no tcl-callbacks" name: build (${{ matrix.compiler }}, ${{ matrix.description }}) steps: - name: Checkout diff --git a/ChangeLog b/ChangeLog index c209850..cdc22f0 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,6 +2,7 @@ * Add a fileset feature to VFS * Allow to link with zlib directly (without Tcl layer) * Allow to link with mbedtls and use its crypto functions + * Allow to build without Tcl callbacks 2024-10-10 Konstantin Kushnir * Add a fileset feature to fsindex diff --git a/TODO.txt b/TODO.txt index 6ac112e..1e67e1b 100644 --- a/TODO.txt +++ b/TODO.txt @@ -18,10 +18,6 @@ * Add documentation as HTML to github pages -* Add ability to disable custom compression to reduce size footprint when it is not needed - -* Add ability to disable async compression to reduce size footprint when it is not needed - * Update bzip2 and use it as a submodule. Perhaps this will get rid of its compile-time warnings. * Add ability/subcommand to copy files from/to cookfs more efficiently than using 'file copy'. diff --git a/configure b/configure index 3685e8c..6ccbee1 100755 --- a/configure +++ b/configure @@ -659,6 +659,7 @@ GREP COOKFS_PKGCONFIG_USECPKGCONFIG COOKFS_PKGCONFIG_FEATURE_CRYPTO COOKFS_PKGCONFIG_USECCRYPTO +COOKFS_PKGCONFIG_USECALLBACKS COOKFS_PKGCONFIG_USETCLCMDS COOKFS_PKGCONFIG_USECWRITER COOKFS_PKGCONFIG_USECVFS @@ -798,7 +799,6 @@ enable_bz2 enable_lzma enable_zstd enable_brotli -enable_tcl_fallback enable_c_pages enable_c_fsindex enable_c_readerchannel @@ -808,6 +808,7 @@ enable_c_vfs enable_c_writer enable_c_crypto enable_tcl_commands +enable_tcl_callbacks with_zlib with_mbedtls ' @@ -1454,7 +1455,6 @@ Optional Features: --disable-lzma Use lzma compression. Defaults to true --enable-zstd Use zstd compression. Defaults to false --enable-brotli Use brotli compression. Defaults to false - --enable-tcl-fallback Install Tcl scripts if load fails. Defaults to false --disable-c-pages Use pages handling written in C. Defaults to true --disable-c-fsindex Use index handling written in C. Defaults to true --disable-c-readerchannel Use reader handler written in C. Defaults to true @@ -1464,6 +1464,7 @@ Optional Features: --disable-c-writer Use writer handler written in C. Defaults to true --disable-c-crypto Use crypto functions written in C. Defaults to true --disable-tcl-commands Enable Tcl commands for objects. Defaults to true + --disable-tcl-callbacks Enable Tcl callbacks for compression. Defaults to true Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -8796,14 +8797,6 @@ else $as_nop USEBROTLI=no fi -# Check whether --enable-tcl-fallback was given. -if test ${enable_tcl_fallback+y} -then : - enableval=$enable_tcl_fallback; USEFALLBACK=${enableval} -else $as_nop - USEFALLBACK=no -fi - # Check whether --enable-c-pages was given. if test ${enable_c_pages+y} then : @@ -8876,6 +8869,14 @@ else $as_nop USETCLCMDS=yes fi +# Check whether --enable-tcl-callbacks was given. +if test ${enable_tcl_callbacks+y} +then : + enableval=$enable_tcl_callbacks; USECALLBACKS=${enableval} +else $as_nop + USECALLBACKS=yes +fi + # Check whether --with-zlib was given. @@ -8941,7 +8942,7 @@ if test ${USECPAGES} = yes; then COOKFS_PKGCONFIG_USECPAGES=1 COOKFS_PKGCONFIG_FEATURE_ASIDE=1 - vars="pgindex.c pageObj.c pages.c pagesCompr.c pagesAsync.c pagesComprZlib.c pagesComprCustom.c pagesCmd.c" + vars="pgindex.c pageObj.c pages.c pagesCompr.c pagesComprZlib.c pagesCmd.c" for i in $vars; do case $i in \$*) @@ -10119,6 +10120,52 @@ else COOKFS_PKGCONFIG_USETCLCMDS=1 fi +if test ${USECALLBACKS} = yes; then + printf "%s\n" "#define COOKFS_USECALLBACKS 1" >>confdefs.h + + COOKFS_PKGCONFIG_USECALLBACKS=1 + if test ${USECPAGES} = yes; then + + vars="pagesAsync.c pagesComprCustom.c" + for i in $vars; do + case $i in + \$*) + # allow $-var names + PKG_SOURCES="$PKG_SOURCES $i" + PKG_OBJECTS="$PKG_OBJECTS $i" + ;; + *) + # check for existence - allows for generic/win/unix VPATH + # To add more dirs here (like 'src'), you have to update VPATH + # in Makefile.in as well + if test ! -f "${srcdir}/$i" -a ! -f "${srcdir}/generic/$i" \ + -a ! -f "${srcdir}/win/$i" -a ! -f "${srcdir}/unix/$i" \ + -a ! -f "${srcdir}/macosx/$i" \ + ; then + as_fn_error $? "could not find source file '$i'" "$LINENO" 5 + fi + PKG_SOURCES="$PKG_SOURCES $i" + # this assumes it is in a VPATH dir + i=`basename $i` + # handle user calling this before or after TEA_SETUP_COMPILER + if test x"${OBJEXT}" != x ; then + j="`echo $i | sed -e 's/\.[^.]*$//'`.${OBJEXT}" + else + j="`echo $i | sed -e 's/\.[^.]*$//'`.\${OBJEXT}" + fi + PKG_OBJECTS="$PKG_OBJECTS $j" + ;; + esac + done + + + + fi +else + COOKFS_PKGCONFIG_USECALLBACKS=0 +fi + + @@ -10165,6 +10212,8 @@ if test ${USECPKGCONFIG} = yes; then printf "%s\n" "#define COOKFS_PKGCONFIG_USETCLCMDS $COOKFS_PKGCONFIG_USETCLCMDS" >>confdefs.h + printf "%s\n" "#define COOKFS_PKGCONFIG_USECALLBACKS $COOKFS_PKGCONFIG_USECALLBACKS" >>confdefs.h + printf "%s\n" "#define COOKFS_PKGCONFIG_USECCRYPTO $COOKFS_PKGCONFIG_USECCRYPTO" >>confdefs.h printf "%s\n" "#define COOKFS_PKGCONFIG_FEATURE_CRYPTO $COOKFS_PKGCONFIG_FEATURE_CRYPTO" >>confdefs.h diff --git a/configure.in b/configure.in index f7030bf..b1a87bf 100644 --- a/configure.in +++ b/configure.in @@ -117,21 +117,21 @@ if test "${SHARED_BUILD}" = "1"; then AC_DEFINE(USE_TCL_STUBS, 1, [Use Tcl stubs]) fi -AC_ARG_ENABLE(internal-debug, [ --enable-internal-debug Enable internal debugging mechanism. Defaults to false],INTERNALDEBUG=${enableval}, INTERNALDEBUG=no) -AC_ARG_ENABLE(bz2, [ --enable-bz2 Use bz2 compression. Defaults to false], USEBZ2=${enableval}, USEBZ2=no) -AC_ARG_ENABLE(lzma, [ --disable-lzma Use lzma compression. Defaults to true], USELZMA=${enableval}, USELZMA=yes) -AC_ARG_ENABLE(zstd, [ --enable-zstd Use zstd compression. Defaults to false], USEZSTD=${enableval}, USEZSTD=no) -AC_ARG_ENABLE(brotli, [ --enable-brotli Use brotli compression. Defaults to false], USEBROTLI=${enableval}, USEBROTLI=no) -AC_ARG_ENABLE(tcl-fallback, [ --enable-tcl-fallback Install Tcl scripts if load fails. Defaults to false], USEFALLBACK=${enableval}, USEFALLBACK=no) -AC_ARG_ENABLE(c-pages, [ --disable-c-pages Use pages handling written in C. Defaults to true], USECPAGES=${enableval}, USECPAGES=yes) -AC_ARG_ENABLE(c-fsindex, [ --disable-c-fsindex Use index handling written in C. Defaults to true], USECFSINDEX=${enableval}, USECFSINDEX=yes) -AC_ARG_ENABLE(c-readerchannel, [ --disable-c-readerchannel Use reader handler written in C. Defaults to true], USECREADERCHAN=${enableval}, USECREADERCHAN=yes) -AC_ARG_ENABLE(c-writerchannel, [ --disable-c-writerchannel Use writer handler written in C. Defaults to true], USECWRITERCHAN=${enableval}, USECWRITERCHAN=yes) -AC_ARG_ENABLE(c-pkgconfig, [ --disable-c-pkgconfig Use pkgconfig written in C. Defaults to true], USECPKGCONFIG=${enableval}, USECPKGCONFIG=yes) -AC_ARG_ENABLE(c-vfs, [ --disable-c-vfs Use VFS support written in C. Defaults to true], USECVFS=${enableval}, USECVFS=yes) -AC_ARG_ENABLE(c-writer, [ --disable-c-writer Use writer handler written in C. Defaults to true], USECWRITER=${enableval}, USECWRITER=yes) -AC_ARG_ENABLE(c-crypto, [ --disable-c-crypto Use crypto functions written in C. Defaults to true], USECCRYPTO=${enableval}, USECCRYPTO=yes) -AC_ARG_ENABLE(tcl-commands, [ --disable-tcl-commands Enable Tcl commands for objects. Defaults to true], USETCLCMDS=${enableval}, USETCLCMDS=yes) +AC_ARG_ENABLE(internal-debug, [ --enable-internal-debug Enable internal debugging mechanism. Defaults to false], INTERNALDEBUG=${enableval}, INTERNALDEBUG=no) +AC_ARG_ENABLE(bz2, [ --enable-bz2 Use bz2 compression. Defaults to false], USEBZ2=${enableval}, USEBZ2=no) +AC_ARG_ENABLE(lzma, [ --disable-lzma Use lzma compression. Defaults to true], USELZMA=${enableval}, USELZMA=yes) +AC_ARG_ENABLE(zstd, [ --enable-zstd Use zstd compression. Defaults to false], USEZSTD=${enableval}, USEZSTD=no) +AC_ARG_ENABLE(brotli, [ --enable-brotli Use brotli compression. Defaults to false], USEBROTLI=${enableval}, USEBROTLI=no) +AC_ARG_ENABLE(c-pages, [ --disable-c-pages Use pages handling written in C. Defaults to true], USECPAGES=${enableval}, USECPAGES=yes) +AC_ARG_ENABLE(c-fsindex, [ --disable-c-fsindex Use index handling written in C. Defaults to true], USECFSINDEX=${enableval}, USECFSINDEX=yes) +AC_ARG_ENABLE(c-readerchannel, [ --disable-c-readerchannel Use reader handler written in C. Defaults to true], USECREADERCHAN=${enableval}, USECREADERCHAN=yes) +AC_ARG_ENABLE(c-writerchannel, [ --disable-c-writerchannel Use writer handler written in C. Defaults to true], USECWRITERCHAN=${enableval}, USECWRITERCHAN=yes) +AC_ARG_ENABLE(c-pkgconfig, [ --disable-c-pkgconfig Use pkgconfig written in C. Defaults to true], USECPKGCONFIG=${enableval}, USECPKGCONFIG=yes) +AC_ARG_ENABLE(c-vfs, [ --disable-c-vfs Use VFS support written in C. Defaults to true], USECVFS=${enableval}, USECVFS=yes) +AC_ARG_ENABLE(c-writer, [ --disable-c-writer Use writer handler written in C. Defaults to true], USECWRITER=${enableval}, USECWRITER=yes) +AC_ARG_ENABLE(c-crypto, [ --disable-c-crypto Use crypto functions written in C. Defaults to true], USECCRYPTO=${enableval}, USECCRYPTO=yes) +AC_ARG_ENABLE(tcl-commands, [ --disable-tcl-commands Enable Tcl commands for objects. Defaults to true], USETCLCMDS=${enableval}, USETCLCMDS=yes) +AC_ARG_ENABLE(tcl-callbacks, [ --disable-tcl-callbacks Enable Tcl callbacks for compression. Defaults to true], USECALLBACKS=${enableval}, USECALLBACKS=yes) AC_ARG_WITH([zlib], [AS_HELP_STRING([--with-zlib=PATH], [prefix where zlib is installed (optional)])], WITH_ZLIB="${withval}", WITH_ZLIB="no") AC_ARG_WITH([mbedtls], [AS_HELP_STRING([--with-mbedtls=PATH], [prefix where mbedtls is installed (optional)])], WITH_MBEDTLS="${withval}", WITH_MBEDTLS="no") @@ -148,7 +148,7 @@ if test ${USECPAGES} = yes; then AC_DEFINE(COOKFS_USECPAGES) COOKFS_PKGCONFIG_USECPAGES=1 COOKFS_PKGCONFIG_FEATURE_ASIDE=1 - TEA_ADD_SOURCES([pgindex.c pageObj.c pages.c pagesCompr.c pagesAsync.c pagesComprZlib.c pagesComprCustom.c pagesCmd.c]) + TEA_ADD_SOURCES([pgindex.c pageObj.c pages.c pagesCompr.c pagesComprZlib.c pagesCmd.c]) # enable bz2 files only if pages are handled using C if test ${USEBZ2} = yes; then @@ -448,6 +448,16 @@ else COOKFS_PKGCONFIG_USETCLCMDS=1 fi +if test ${USECALLBACKS} = yes; then + AC_DEFINE(COOKFS_USECALLBACKS) + COOKFS_PKGCONFIG_USECALLBACKS=1 + if test ${USECPAGES} = yes; then + TEA_ADD_SOURCES([pagesAsync.c pagesComprCustom.c]) + fi +else + COOKFS_PKGCONFIG_USECALLBACKS=0 +fi + AC_SUBST(COOKFS_PKGCONFIG_FEATURE_ASIDE) AC_SUBST(COOKFS_PKGCONFIG_USECPAGES) AC_SUBST(COOKFS_PKGCONFIG_USECREADERCHAN) @@ -461,6 +471,7 @@ AC_SUBST(COOKFS_PKGCONFIG_FEATURE_METADATA) AC_SUBST(COOKFS_PKGCONFIG_USECVFS) AC_SUBST(COOKFS_PKGCONFIG_USECWRITER) AC_SUBST(COOKFS_PKGCONFIG_USETCLCMDS) +AC_SUBST(COOKFS_PKGCONFIG_USECALLBACKS) AC_SUBST(COOKFS_PKGCONFIG_USECCRYPTO) AC_SUBST(COOKFS_PKGCONFIG_FEATURE_CRYPTO) @@ -480,6 +491,7 @@ if test ${USECPKGCONFIG} = yes; then AC_DEFINE_UNQUOTED(COOKFS_PKGCONFIG_USECVFS, $COOKFS_PKGCONFIG_USECVFS) AC_DEFINE_UNQUOTED(COOKFS_PKGCONFIG_USECWRITER, $COOKFS_PKGCONFIG_USECWRITER) AC_DEFINE_UNQUOTED(COOKFS_PKGCONFIG_USETCLCMDS, $COOKFS_PKGCONFIG_USETCLCMDS) + AC_DEFINE_UNQUOTED(COOKFS_PKGCONFIG_USECALLBACKS, $COOKFS_PKGCONFIG_USECALLBACKS) AC_DEFINE_UNQUOTED(COOKFS_PKGCONFIG_USECCRYPTO, $COOKFS_PKGCONFIG_USECCRYPTO) AC_DEFINE_UNQUOTED(COOKFS_PKGCONFIG_FEATURE_CRYPTO, $COOKFS_PKGCONFIG_FEATURE_CRYPTO) diff --git a/generic/cookfs.h b/generic/cookfs.h index 638f362..2103ccd 100644 --- a/generic/cookfs.h +++ b/generic/cookfs.h @@ -217,6 +217,7 @@ static Tcl_Config const cookfs_pkgconfig[] = { {"feature-brotli", STRINGIFY(COOKFS_PKGCONFIG_USEBROTLI)}, {"feature-metadata", STRINGIFY(COOKFS_PKGCONFIG_FEATURE_METADATA)}, {"tcl-commands", STRINGIFY(COOKFS_PKGCONFIG_USETCLCMDS)}, + {"tcl-callbacks", STRINGIFY(COOKFS_PKGCONFIG_USECALLBACKS)}, {"platform", COOKFS_PLATFORM}, {NULL, NULL} }; diff --git a/generic/pages.c b/generic/pages.c index 8869df1..85c1385 100644 --- a/generic/pages.c +++ b/generic/pages.c @@ -11,7 +11,9 @@ #include "pages.h" #include "pagesInt.h" #include "pagesCompr.h" +#if defined(COOKFS_USECALLBACKS) #include "pagesAsync.h" +#endif /* COOKFS_USECALLBACKS */ // For ptrdiff_t type #include @@ -359,8 +361,10 @@ int Cookfs_PagesSetPassword(Cookfs_Pages *p, Tcl_Obj *passObj) { Cookfs_PagesWantWrite(p); +#if defined(COOKFS_USECALLBACKS) // ensure all async pages are written while(Cookfs_AsyncCompressWait(p, 1)) {}; +#endif /* COOKFS_USECALLBACKS */ if (passObj == NULL || !Tcl_GetCharLength(passObj)) { CookfsLog2(printf("reset password as it is NULL or an empty string")); @@ -478,9 +482,12 @@ Cookfs_Pages *Cookfs_PagesInit(Tcl_Interp *interp, Tcl_Obj *fileName, int currentCompression, int currentCompressionLevel, Tcl_Obj *password, int encryptKey, int encryptLevel, char *fileSignature, int useFoffset, Tcl_WideInt foffset, - int isAside, int asyncDecompressQueueSize, + int isAside, +#if defined(COOKFS_USECALLBACKS) + int asyncDecompressQueueSize, Tcl_Obj *compressCommand, Tcl_Obj *decompressCommand, Tcl_Obj *asyncCompressCommand, Tcl_Obj *asyncDecompressCommand, +#endif /* COOKFS_USECALLBACKS */ Tcl_Obj **err) { @@ -508,6 +515,7 @@ Cookfs_Pages *Cookfs_PagesInit(Tcl_Interp *interp, Tcl_Obj *fileName, rc->isAside = isAside; Cookfs_PagesInitCompr(rc); +#if defined(COOKFS_USECALLBACKS) if (Cookfs_SetCompressCommands(rc, compressCommand, decompressCommand, asyncCompressCommand, asyncDecompressCommand) != TCL_OK) { if (interp != NULL) { Tcl_SetObjResult(interp, Tcl_NewStringObj(COOKFS_PAGES_ERRORMSG ": unable to initialize compression", -1)); @@ -515,6 +523,7 @@ Cookfs_Pages *Cookfs_PagesInit(Tcl_Interp *interp, Tcl_Obj *fileName, ckfree((void *) rc); return NULL; } +#endif /* COOKFS_USECALLBACKS */ #ifdef TCL_THREADS /* initialize thread locks */ @@ -570,8 +579,9 @@ Cookfs_Pages *Cookfs_PagesInit(Tcl_Interp *interp, Tcl_Obj *fileName, rc->pagesIndex = NULL; rc->dataAsidePages = NULL; rc->dataPagesIsAside = isAside; - rc->dataIndex = NULL; + +#if defined(COOKFS_USECALLBACKS) rc->asyncPageSize = 0; rc->asyncDecompressQueue = 0; // TODO: un-hardcode! @@ -589,6 +599,7 @@ Cookfs_Pages *Cookfs_PagesInit(Tcl_Interp *interp, Tcl_Obj *fileName, rc->asyncCommandWait = NULL; rc->asyncCommandFinalize = NULL; } +#endif /* COOKFS_USECALLBACKS */ rc->pageHash = COOKFS_HASH_MD5; #ifdef USE_VFS_COMMANDS_FOR_ZIP @@ -897,11 +908,13 @@ Tcl_WideInt Cookfs_PagesClose(Cookfs_Pages *p) { if ((!p->pagesUptodate) || (p->indexChanged)) { unsigned char buf[COOKFS_SUFFIX_BYTES]; +#if defined(COOKFS_USECALLBACKS) /* ensure all async pages are written */ while(Cookfs_AsyncCompressWait(p, 1)) {}; while(Cookfs_AsyncDecompressWait(p, -1, 1)) {}; Cookfs_AsyncCompressFinalize(p); Cookfs_AsyncDecompressFinalize(p); +#endif /* COOKFS_USECALLBACKS */ // Add initial stamp if needed Cookfs_PageAddStamp(p, 0); @@ -1191,6 +1204,7 @@ void Cookfs_PagesFini(Cookfs_Pages *p) { } } +#if defined(COOKFS_USECALLBACKS) if (p->asyncCommandProcess != NULL) { Tcl_DecrRefCount(p->asyncCommandProcess); } @@ -1200,6 +1214,7 @@ void Cookfs_PagesFini(Cookfs_Pages *p) { if (p->asyncCommandFinalize != NULL) { Tcl_DecrRefCount(p->asyncCommandFinalize); } +#endif /* COOKFS_USECALLBACKS */ /* clean up compression information */ Cookfs_PagesFiniCompr(p); @@ -1618,7 +1633,6 @@ int Cookfs_PageAddRaw(Cookfs_Pages *p, unsigned char *bytes, int objLength, Cookfs_PagesWantWrite(p); int idx; - int dataSize; unsigned char md5sum[16]; CookfsLog(printf("Cookfs_PageAdd: new page with [%d] bytes", objLength)) @@ -1732,14 +1746,18 @@ int Cookfs_PageAddRaw(Cookfs_Pages *p, unsigned char *bytes, int objLength, -1, objLength, md5sum); #endif /* COOKFS_USECCRYPTO */ +#if defined(COOKFS_USECALLBACKS) if (!Cookfs_AsyncPageAdd(p, idx, bytes, objLength)) { - dataSize = Cookfs_WritePage(p, idx, bytes, objLength, md5sum, NULL); +#endif /* COOKFS_USECALLBACKS */ + int dataSize = Cookfs_WritePage(p, idx, bytes, objLength, md5sum, NULL); if (dataSize < 0) { /* TODO: if writing failed, we can't be certain of archive state - need to handle this at vfs layer somehow */ CookfsLog(printf("Unable to compress page")) return -1; } +#if defined(COOKFS_USECALLBACKS) } +#endif /* COOKFS_USECALLBACKS */ p->pagesUptodate = 0; @@ -1787,15 +1805,17 @@ Cookfs_PageObj Cookfs_PageGet(Cookfs_Pages *p, int index, int weight, Cookfs_PagesWantRead(p); Cookfs_PageObj rc; - int preloadIndex = index + 1; CookfsLog(printf("Cookfs_PageGet: index [%d] with weight [%d]", index, weight)) +#if defined(COOKFS_USECALLBACKS) + int preloadIndex = index + 1; for (; preloadIndex < Cookfs_PagesGetLength(p) ; preloadIndex++) { if (!Cookfs_AsyncPagePreload(p, preloadIndex)) { break; } } +#endif /* COOKFS_USECALLBACKS */ /* TODO: cleanup refcount for cached vs non-cached entries */ @@ -1806,6 +1826,7 @@ Cookfs_PageObj Cookfs_PageGet(Cookfs_Pages *p, int index, int weight, goto done; } +#if defined(COOKFS_USECALLBACKS) Cookfs_AsyncDecompressWaitIfLoading(p, index); for (; preloadIndex < Cookfs_PagesGetLength(p) ; preloadIndex++) { @@ -1813,6 +1834,7 @@ Cookfs_PageObj Cookfs_PageGet(Cookfs_Pages *p, int index, int weight, break; } } +#endif /* COOKFS_USECALLBACKS */ #ifdef TCL_THREADS Tcl_MutexLock(&p->mxCache); @@ -2595,8 +2617,10 @@ void Cookfs_PagesSetCompression(Cookfs_Pages *p, if (p->currentCompression != fileCompression || p->currentCompressionLevel != fileCompressionLevel) { +#if defined(COOKFS_USECALLBACKS) // ensure all async pages are written while(Cookfs_AsyncCompressWait(p, 1)) {}; +#endif /* COOKFS_USECALLBACKS */ p->currentCompression = fileCompression; p->currentCompressionLevel = fileCompressionLevel; } @@ -2686,12 +2710,14 @@ static Cookfs_PageObj CookfsPagesPageGetInt(Cookfs_Pages *p, int index, return NULL; } +#if defined(COOKFS_USECALLBACKS) buffer = Cookfs_AsyncPageGet(p, index); if (buffer != NULL) { Cookfs_PageObjIncrRefCount(buffer); CookfsLog2(printf("return: result from Cookfs_AsyncPageGet()")); return buffer; } +#endif /* COOKFS_USECALLBACKS */ #ifdef TCL_THREADS Tcl_MutexLock(&p->mxIO); diff --git a/generic/pages.h b/generic/pages.h index f659480..d471f1a 100644 --- a/generic/pages.h +++ b/generic/pages.h @@ -16,9 +16,12 @@ Cookfs_Pages *Cookfs_PagesInit(Tcl_Interp *interp, Tcl_Obj *fileName, int currentCompression, int currentCompressionLevel, Tcl_Obj *password, int encryptKey, int encryptLevel, char *fileSignature, int useFoffset, Tcl_WideInt foffset, int isAside, +#if defined(COOKFS_USECALLBACKS) int asyncDecompressQueueSize, Tcl_Obj *compressCommand, Tcl_Obj *decompressCommand, Tcl_Obj *asyncCompressCommand, - Tcl_Obj *asyncDecompressCommand, Tcl_Obj **err); + Tcl_Obj *asyncDecompressCommand, +#endif /* COOKFS_USECALLBACKS */ + Tcl_Obj **err); Tcl_WideInt Cookfs_PagesClose(Cookfs_Pages *p); Tcl_WideInt Cookfs_GetFilesize(Cookfs_Pages *p); diff --git a/generic/pagesCmd.c b/generic/pagesCmd.c index 89706c8..ece1745 100644 --- a/generic/pagesCmd.c +++ b/generic/pagesCmd.c @@ -162,9 +162,13 @@ static int CookfsRegisterPagesObjectCmd(ClientData clientData, Tcl_Interp *inter "-password", "-encryptkey", "-encryptlevel", #endif /* COOKFS_USECCRYPTO */ "-readonly", "-readwrite", "-compression", "-cachesize", - "-endoffset", "-compresscommand", "-decompresscommand", + "-endoffset", +#if defined(COOKFS_USECALLBACKS) + "-compresscommand", "-decompresscommand", "-asynccompresscommand", "-asyncdecompresscommand", - "-alwayscompress", "-asyncdecompressqueuesize", + "-asyncdecompressqueuesize", +#endif /* COOKFS_USECALLBACKS */ + "-alwayscompress", NULL }; enum { @@ -172,9 +176,13 @@ static int CookfsRegisterPagesObjectCmd(ClientData clientData, Tcl_Interp *inter optPassword, optEncryptKey, optEncryptLevel, #endif /* COOKFS_USECCRYPTO */ optReadonly, optReadwrite, optCompression, optCachesize, - optEndoffset, optCompressCommand, optDecompressCommand, + optEndoffset, +#if defined(COOKFS_USECALLBACKS) + optCompressCommand, optDecompressCommand, optAsyncCompressCommand, optAsyncDecompressCommand, - optAlwaysCompress, optAsyncDecompressQueue + optAsyncDecompressQueue, +#endif /* COOKFS_USECALLBACKS */ + optAlwaysCompress }; Cookfs_Pages *pages; int idx; @@ -185,13 +193,15 @@ static int CookfsRegisterPagesObjectCmd(ClientData clientData, Tcl_Interp *inter int oCachesize = -1; int useFoffset = 0; int alwaysCompress = 0; - int asyncDecompressQueueSize = 2; Tcl_WideInt foffset = 0; Tcl_Obj **tobjv = (Tcl_Obj **) objv; +#if defined(COOKFS_USECALLBACKS) + int asyncDecompressQueueSize = 2; Tcl_Obj *compressCmd = NULL; Tcl_Obj *asyncCompressCmd = NULL; Tcl_Obj *asyncDecompressCmd = NULL; Tcl_Obj *decompressCmd = NULL; +#endif /* COOKFS_USECALLBACKS */ Tcl_Obj *compression = NULL; Tcl_Obj *password = NULL; int encryptKey = 0; @@ -240,13 +250,13 @@ static int CookfsRegisterPagesObjectCmd(ClientData clientData, Tcl_Interp *inter compression = tobjv[1]; break; } +#if defined(COOKFS_USECALLBACKS) case optCompressCommand: { if (tobjc <= 3) { goto error; } tobjc--; tobjv++; - compressCmd = tobjv[1]; break; } @@ -256,7 +266,6 @@ static int CookfsRegisterPagesObjectCmd(ClientData clientData, Tcl_Interp *inter } tobjc--; tobjv++; - decompressCmd = tobjv[1]; break; } @@ -266,7 +275,6 @@ static int CookfsRegisterPagesObjectCmd(ClientData clientData, Tcl_Interp *inter } tobjc--; tobjv++; - asyncCompressCmd = tobjv[1]; break; } @@ -276,10 +284,22 @@ static int CookfsRegisterPagesObjectCmd(ClientData clientData, Tcl_Interp *inter } tobjc--; tobjv++; - asyncDecompressCmd = tobjv[1]; break; } + case optAsyncDecompressQueue: { + if (tobjc <= 3) { + goto error; + } + tobjc--; + tobjv++; + + if (Tcl_GetIntFromObj(interp, tobjv[1], &asyncDecompressQueueSize) != TCL_OK) { + return TCL_ERROR; + } + break; + } +#endif /* COOKFS_USECALLBACKS */ case optEndoffset: { if (tobjc <= 3) { goto error; @@ -323,19 +343,6 @@ static int CookfsRegisterPagesObjectCmd(ClientData clientData, Tcl_Interp *inter case optAlwaysCompress: alwaysCompress = 1; break; - case optAsyncDecompressQueue: - { - if (tobjc <= 3) { - goto error; - } - tobjc--; - tobjv++; - - if (Tcl_GetIntFromObj(interp, tobjv[1], &asyncDecompressQueueSize) != TCL_OK) { - return TCL_ERROR; - } - break; - } default: goto error; } @@ -360,8 +367,11 @@ static int CookfsRegisterPagesObjectCmd(ClientData clientData, Tcl_Interp *inter pages = Cookfs_PagesInit(interp, tobjv[1], oReadOnly, oCompression, oCompressionLevel, oCompression, oCompressionLevel, password, encryptKey, encryptLevel, NULL, useFoffset, foffset, 0, +#if defined(COOKFS_USECALLBACKS) asyncDecompressQueueSize, compressCmd, decompressCmd, asyncCompressCmd, - asyncDecompressCmd, &err); + asyncDecompressCmd, +#endif /* COOKFS_USECALLBACKS */ + &err); if (err != NULL) { Tcl_SetObjResult(interp, err); } @@ -861,7 +871,11 @@ static int CookfsPagesCmdAside(Cookfs_Pages *pages, Tcl_Interp *interp, int objc asidePages = Cookfs_PagesInit(pages->interp, objv[2], 0, pages->baseCompression, pages->baseCompressionLevel, pages->currentCompression, pages->currentCompressionLevel, - NULL, 0, -1, NULL, 0, 0, 1, 0, NULL, NULL, NULL, NULL, NULL); + NULL, 0, -1, NULL, 0, 0, 1, +#if defined(COOKFS_USECALLBACKS) + 0, NULL, NULL, NULL, NULL, +#endif /* COOKFS_USECALLBACKS */ + NULL); if (asidePages == NULL) { CookfsLog(printf("Failed to create add-aside pages object")) @@ -908,6 +922,7 @@ static int CookfsPagesCmdCompression(Cookfs_Pages *pages, Tcl_Interp *interp, in if (Cookfs_CompressionFromObj(interp, objv[2], &oCompression, &oCompressionLevel) != TCL_OK) { + Cookfs_PagesUnlock(pages); return TCL_ERROR; } Cookfs_PagesSetCompression(pages, oCompression, oCompressionLevel); diff --git a/generic/pagesCompr.c b/generic/pagesCompr.c index 73539da..fcf0d44 100644 --- a/generic/pagesCompr.c +++ b/generic/pagesCompr.c @@ -13,7 +13,9 @@ #include "pagesInt.h" #include "pagesCompr.h" #include "pagesComprZlib.h" +#if defined(COOKFS_USECALLBACKS) #include "pagesComprCustom.h" +#endif /* COOKFS_USECALLBACKS */ #ifdef COOKFS_USEBZ2 #include "pagesComprBz2.h" #endif @@ -27,8 +29,10 @@ #include "pagesComprBrotli.h" #endif +#if defined(COOKFS_USECALLBACKS) /* declarations of static and/or internal functions */ static Tcl_Obj **CookfsCreateCompressionCommand(Tcl_Interp *interp, Tcl_Obj *cmd, int *lenPtr, int additionalElements); +#endif /* COOKFS_USECALLBACKS */ #ifdef USE_VFS_COMMANDS_FOR_ZIP static int CookfsCheckCommandExists(Tcl_Interp *interp, const char *commandName); #endif @@ -49,7 +53,9 @@ const char *cookfsCompressionOptions[] = { #ifdef COOKFS_USEBROTLI "brotli", #endif +#if defined(COOKFS_USECALLBACKS) "custom", +#endif /* COOKFS_USECALLBACKS */ NULL }; @@ -68,7 +74,9 @@ const int cookfsCompressionOptionMap[] = { #ifdef COOKFS_USEBROTLI COOKFS_COMPRESSION_BROTLI, #endif +#if defined(COOKFS_USECALLBACKS) COOKFS_COMPRESSION_CUSTOM, +#endif /* COOKFS_USECALLBACKS */ -1 /* dummy entry */ }; @@ -341,6 +349,7 @@ void Cookfs_PagesFiniCompr(Cookfs_Pages *rc) { } #endif +#if defined(COOKFS_USECALLBACKS) /* clean up compress/decompress commands, if present - for non-aside pages only */ if (!rc->isAside) { if (rc->compressCommandPtr != NULL) { @@ -372,9 +381,13 @@ void Cookfs_PagesFiniCompr(Cookfs_Pages *rc) { ckfree((void *) rc->asyncDecompressCommandPtr); } } +#else + UNUSED(rc); +#endif /* COOKFS_USECALLBACKS */ } +#if defined(COOKFS_USECALLBACKS) /* *---------------------------------------------------------------------- * @@ -448,6 +461,7 @@ int Cookfs_SetCompressCommands(Cookfs_Pages *p, Tcl_Obj *compressCommand, Tcl_Ob return TCL_OK; } +#endif /* COOKFS_USECALLBACKS */ /* @@ -616,10 +630,12 @@ skipReading: ; // empty statement rc = CookfsReadPageZlib(p, dataCompressed->buf, sizeCompressed, dataUncompressed->buf, sizeUncompressed, err); break; +#if defined(COOKFS_USECALLBACKS) case COOKFS_COMPRESSION_CUSTOM: rc = CookfsReadPageCustom(p, dataCompressed->buf, sizeCompressed, dataUncompressed->buf, sizeUncompressed, err); break; +#endif /* COOKFS_USECALLBACKS */ #ifdef COOKFS_USEBZ2 case COOKFS_COMPRESSION_BZ2: rc = CookfsReadPageBz2(p, dataCompressed->buf, sizeCompressed, @@ -802,9 +818,11 @@ Tcl_Size Cookfs_WritePage(Cookfs_Pages *p, int idx, unsigned char *bytes, case COOKFS_COMPRESSION_ZLIB: pgCompressed = CookfsWritePageZlib(p, bytes, sizeUncompressed); break; +#if defined(COOKFS_USECALLBACKS) case COOKFS_COMPRESSION_CUSTOM: pgCompressed = CookfsWritePageCustom(p, bytes, sizeUncompressed); break; +#endif /* COOKFS_USECALLBACKS */ #ifdef COOKFS_USEBZ2 case COOKFS_COMPRESSION_BZ2: pgCompressed = CookfsWritePageBz2(p, bytes, sizeUncompressed); @@ -914,6 +932,8 @@ int Cookfs_WriteTclObj(Cookfs_Pages *p, int idx, Tcl_Obj *data, Tcl_Obj *compres /* definitions of static and/or internal functions */ +#if defined(COOKFS_USECALLBACKS) + /* *---------------------------------------------------------------------- * @@ -951,6 +971,8 @@ static Tcl_Obj **CookfsCreateCompressionCommand(Tcl_Interp *interp, Tcl_Obj *cmd *lenPtr = listObjc + additionalElements; return rc; } +#endif /* COOKFS_USECALLBACKS */ + #ifdef USE_VFS_COMMANDS_FOR_ZIP diff --git a/generic/pagesCompr.h b/generic/pagesCompr.h index 21636c3..4db51c5 100644 --- a/generic/pagesCompr.h +++ b/generic/pagesCompr.h @@ -17,11 +17,13 @@ int Cookfs_CompressionFromObj(Tcl_Interp *interp, Tcl_Obj *obj, void Cookfs_PagesInitCompr(Cookfs_Pages *rc); void Cookfs_PagesFiniCompr(Cookfs_Pages *rc); +#if defined(COOKFS_USECALLBACKS) int Cookfs_SetCompressCommands(Cookfs_Pages *p, Tcl_Obj *compressCommand, Tcl_Obj *decompressCommand, Tcl_Obj *asyncCompressCommand, Tcl_Obj *asyncDecompressCommand); +#endif /* COOKFS_USECALLBACKS */ void Cookfs_SeekToPage(Cookfs_Pages *p, int idx); diff --git a/generic/pagesInt.h b/generic/pagesInt.h index 96fda80..bf69069 100644 --- a/generic/pagesInt.h +++ b/generic/pagesInt.h @@ -143,6 +143,7 @@ struct _Cookfs_Pages { /* compression information */ int alwaysCompress; +#if defined(COOKFS_USECALLBACKS) int compressCommandLen; Tcl_Obj **compressCommandPtr; int decompressCommandLen; @@ -151,12 +152,14 @@ struct _Cookfs_Pages { Tcl_Obj **asyncCompressCommandPtr; int asyncDecompressCommandLen; Tcl_Obj **asyncDecompressCommandPtr; +#endif /* COOKFS_USECALLBACKS */ /* cache */ int cacheSize; int cacheMaxAge; Cookfs_CacheEntry cache[COOKFS_MAX_CACHE_PAGES]; +#if defined(COOKFS_USECALLBACKS) /* async compress */ Tcl_Obj *asyncCommandProcess; Tcl_Obj *asyncCommandWait; @@ -168,6 +171,7 @@ struct _Cookfs_Pages { int asyncDecompressQueue; int asyncDecompressQueueSize; int asyncDecompressIdx[COOKFS_MAX_PRELOAD_PAGES]; +#endif /* COOKFS_USECALLBACKS */ }; #ifdef TCL_THREADS diff --git a/generic/vfsCmd.c b/generic/vfsCmd.c index 4f4da61..db0d436 100644 --- a/generic/vfsCmd.c +++ b/generic/vfsCmd.c @@ -315,9 +315,12 @@ static int CookfsMountCmd(ClientData clientData, Tcl_Interp *interp, #ifdef COOKFS_USECCRYPTO "-password", "-encryptkey", "-encryptlevel", #endif /* COOKFS_USECCRYPTO */ - "-nocommand", "-compression", "-alwayscompress", "-compresscommand", +#if defined(COOKFS_USECALLBACKS) + "-compresscommand", "-asynccompresscommand", "-asyncdecompresscommand", - "-asyncdecompressqueuesize", "-decompresscommand", "-endoffset", + "-asyncdecompressqueuesize", "-decompresscommand", +#endif /* COOKFS_USECALLBACKS */ + "-nocommand", "-compression", "-alwayscompress", "-endoffset", "-setmetadata", "-readonly", "-writetomemory", "-pagesize", "-pagecachesize", "-volume", "-smallfilesize", "-smallfilebuffer", "-nodirectorymtime", "-pagehash", "-shared", "-fileset", @@ -331,9 +334,12 @@ static int CookfsMountCmd(ClientData clientData, Tcl_Interp *interp, #ifdef COOKFS_USECCRYPTO OPT_PASSWORD, OPT_ENCRYPTKEY, OPT_ENCRYPTLEVEL, #endif /* COOKFS_USECCRYPTO */ - OPT_NOCOMMAND, OPT_COMPRESSION, OPT_ALWAYSCOMPRESS, OPT_COMPRESSCOMMAND, +#if defined(COOKFS_USECALLBACKS) + OPT_COMPRESSCOMMAND, OPT_ASYNCCOMPRESSCOMMAND, OPT_ASYNCDECOMPRESSCOMMAND, - OPT_ASYNCDECOMPRESSQUEUESIZE, OPT_DECOMPRESSCOMMAND, OPT_ENDOFFSET, + OPT_ASYNCDECOMPRESSQUEUESIZE, OPT_DECOMPRESSCOMMAND, +#endif /* COOKFS_USECALLBACKS */ + OPT_NOCOMMAND, OPT_COMPRESSION, OPT_ALWAYSCOMPRESS, OPT_ENDOFFSET, OPT_SETMETADATA, OPT_READONLY, OPT_WRITETOMEMORY, OPT_PAGESIZE, OPT_PAGECACHESIZE, OPT_VOLUME, OPT_SMALLFILESIZE, OPT_SMALLFILEBUFFER, OPT_NODIRECTORYMTIME, OPT_PAGEHASH, OPT_SHARED, OPT_FILESET @@ -406,17 +412,23 @@ static int CookfsMountCmd(ClientData clientData, Tcl_Interp *interp, PROCESS_OPT_OBJ(OPT_PASSWORD, props->password); #endif /* COOKFS_USECCRYPTO */ PROCESS_OPT_OBJ(OPT_COMPRESSION, compression); +#if defined(COOKFS_USECALLBACKS) PROCESS_OPT_OBJ(OPT_COMPRESSCOMMAND, props->compresscommand); PROCESS_OPT_OBJ(OPT_ASYNCCOMPRESSCOMMAND, props->asynccompresscommand); PROCESS_OPT_OBJ(OPT_ASYNCDECOMPRESSCOMMAND, props->asyncdecompresscommand); PROCESS_OPT_OBJ(OPT_DECOMPRESSCOMMAND, props->decompresscommand); +#endif /* COOKFS_USECALLBACKS */ PROCESS_OPT_OBJ(OPT_SETMETADATA, props->setmetadata); PROCESS_OPT_OBJ(OPT_PAGEHASH, pagehash); PROCESS_OPT_OBJ(OPT_FILESET, props->fileset); // OPT_ASYNCDECOMPRESSQUEUESIZE / OPT_PAGECACHESIZE - are unsigned int // values - if (opt == OPT_ASYNCDECOMPRESSQUEUESIZE || opt == OPT_PAGECACHESIZE) { + if (opt == OPT_PAGECACHESIZE +#if defined(COOKFS_USECALLBACKS) + || opt == OPT_ASYNCDECOMPRESSQUEUESIZE +#endif /* COOKFS_USECALLBACKS */ + ) { int ival; if (Tcl_GetIntFromObj(interp, objv[idx], &ival) != TCL_OK @@ -428,7 +440,9 @@ static int CookfsMountCmd(ClientData clientData, Tcl_Interp *interp, goto error; } +#if defined(COOKFS_USECALLBACKS) PROCESS_OPT_INT(OPT_ASYNCDECOMPRESSQUEUESIZE, props->asyncdecompressqueuesize); +#endif /* COOKFS_USECALLBACKS */ PROCESS_OPT_INT(OPT_PAGECACHESIZE, props->pagecachesize); } @@ -589,6 +603,7 @@ int Cookfs_Mount(Tcl_Interp *interp, Tcl_Obj *archive, Tcl_Obj *local, goto error; } +#if defined(COOKFS_USECALLBACKS) if (props->shared && ( props->compresscommand != NULL || props->decompresscommand != NULL || @@ -599,6 +614,7 @@ int Cookfs_Mount(Tcl_Interp *interp, Tcl_Obj *archive, Tcl_Obj *local, " in thread-shared mode", -1)); goto error; } +#endif /* COOKFS_USECALLBACKS */ // if write to memory option was selected, open archive as read only anyway if (props->writetomemory) { @@ -694,9 +710,11 @@ int Cookfs_Mount(Tcl_Interp *interp, Tcl_Obj *archive, Tcl_Obj *local, NULL, 0, -1, #endif /* COOKFS_USECCRYPTO */ NULL, (props->endoffset == -1 ? 0 : 1), props->endoffset, 0, +#if defined(COOKFS_USECALLBACKS) props->asyncdecompressqueuesize, props->compresscommand, props->decompresscommand, props->asynccompresscommand, props->asyncdecompresscommand, +#endif /* COOKFS_USECALLBACKS */ NULL); if (pages == NULL) { diff --git a/pkgconfig.tcl.in b/pkgconfig.tcl.in index dca7db0..1f87d97 100644 --- a/pkgconfig.tcl.in +++ b/pkgconfig.tcl.in @@ -17,6 +17,7 @@ proc cookfs::pkgconfig {{command ""} {value ""} {newValue ""}} { c-crypto "@COOKFS_PKGCONFIG_USECCRYPTO@" tcl-commands "@COOKFS_PKGCONFIG_USETCLCMDS@" + tcl-callbacks "@COOKFS_PKGCONFIG_USECALLBACKS@" feature-aside "@COOKFS_PKGCONFIG_FEATURE_ASIDE@" feature-bzip2 "@COOKFS_PKGCONFIG_USEBZ2@" diff --git a/tests/common.tcl b/tests/common.tcl index 89303fe..ad509c6 100644 --- a/tests/common.tcl +++ b/tests/common.tcl @@ -37,6 +37,8 @@ namespace eval ::tcltest { testConstraint disabledCPages [expr { ![cookfs::pkgconfig get c-pages] }] testConstraint enabledTclCmds [cookfs::pkgconfig get tcl-commands] testConstraint disabledTclCmds [expr { ![cookfs::pkgconfig get tcl-commands] }] + testConstraint enabledTclCallbacks [cookfs::pkgconfig get tcl-callbacks] + testConstraint disabledTclCallbacks [expr { ![cookfs::pkgconfig get tcl-callbacks] }] testConstraint enabledCWriter [cookfs::pkgconfig get c-writer] testConstraint disabledCWriter [expr { ![cookfs::pkgconfig get c-writer] }] testConstraint enabledCFsindex [cookfs::pkgconfig get c-fsindex] diff --git a/tests/pages.test b/tests/pages.test index 6db8849..745fa6e 100644 --- a/tests/pages.test +++ b/tests/pages.test @@ -435,7 +435,9 @@ test cookfsPages-6.1 "Test multiple compression algorithms" -constraints {enable $pg delete } -ok -test cookfsPages-7.1 "Test custom compression algorithm" -constraints {enabledTclCmds} -setup { +test cookfsPages-7.1 "Test custom compression algorithm" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] set pg [cookfs::pages -compression custom -compresscommand testcompress -decompresscommand testdecompress $file] variable i0 @@ -455,7 +457,9 @@ test cookfsPages-7.1 "Test custom compression algorithm" -constraints {enabledTc testcompresscleanup } -ok -test cookfsPages-7.2 "Test custom compression algorithm - no decompress command error" -constraints {enabledTclCmds} -setup { +test cookfsPages-7.2 "Test custom compression algorithm - no decompress command error" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] set pg [cookfs::pages -compression custom -compresscommand testcompress $file] variable i0 @@ -470,7 +474,9 @@ test cookfsPages-7.2 "Test custom compression algorithm - no decompress command testcompresscleanup } -error {Unable to retrieve chunk: No decompresscommand specified} -test cookfsPages-7.3 "Test custom compression algorithm - no decompress command error when adding same page" -constraints {enabledTclCmds} -setup { +test cookfsPages-7.3 "Test custom compression algorithm - no decompress command error when adding same page" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] set pg [cookfs::pages -compression custom -compresscommand testcompress $file] } -body { @@ -481,7 +487,9 @@ test cookfsPages-7.3 "Test custom compression algorithm - no decompress command testcompresscleanup } -error {No decompresscommand specified} -test cookfsPages-7.4 "Test custom compression algorithm not used when size would not be smaller" -constraints {enabledTclCmds} -setup { +test cookfsPages-7.4 "Test custom compression algorithm not used when size would not be smaller" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] set data {QWERTYUIOPASDFGHJKLZXCVBNM0123456789} set pg [cookfs::pages -compression custom -compresscommand testcompress -decompresscommand testdecompress $file] @@ -502,7 +510,9 @@ test cookfsPages-7.4 "Test custom compression algorithm not used when size would testcompresscleanup } -ok -test cookfsPages-7.5 "Test custom compression algorithm not used when size would not be smaller with -alwayscompress" -constraints {enabledTclCmds} -setup { +test cookfsPages-7.5 "Test custom compression algorithm not used when size would not be smaller with -alwayscompress" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] set data {QWERTYUIOPASDFGHJKLZXCVBNM0123456789} set pg [cookfs::pages -compression custom -compresscommand testcompress -decompresscommand testdecompress -alwayscompress $file] @@ -677,7 +687,9 @@ test cookfsPages-10.3 "Test crc32 checksum algorithm after re-reading" -constrai $pg delete } -ok -test cookfsPages-10.4 "Test crc32 with large chunks" -constraints {enabledTclCmds} -setup { +test cookfsPages-10.4 "Test crc32 with large chunks" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] set pg [cookfs::pages -compression custom -compresscommand testcompress $file] } -body { @@ -689,7 +701,9 @@ test cookfsPages-10.4 "Test crc32 with large chunks" -constraints {enabledTclCmd testcompresscleanup } -error {No decompresscommand specified} -test cookfsPages-11.1 "Test increasing page cache" -constraints {enabledTclCmds} -setup { +test cookfsPages-11.1 "Test increasing page cache" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] set il {} set pg [cookfs::pages -compression custom -compresscommand testcompress -decompresscommand testdecompress $file] @@ -713,7 +727,9 @@ test cookfsPages-11.1 "Test increasing page cache" -constraints {enabledTclCmds} testcompresscleanup } -result 20 -test cookfsPages-11.2 "Test decreasing page cache" -constraints {enabledTclCmds} -setup { +test cookfsPages-11.2 "Test decreasing page cache" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] set il {} set pg [cookfs::pages -compression custom -compresscommand testcompress -decompresscommand testdecompress $file] @@ -784,12 +800,21 @@ test cookfsPages-12.2 "Test getting current page compression" -constraints {enab assertEq [$pg compression] "zlib" "Getting initial compression as zlib failed" $pg compression none assertEq [$pg compression] "none" "Getting compression as none failed" - $pg compression custom - assertEq [$pg compression] "custom" "Getting compression as custom failed" + $pg compression lzma + assertEq [$pg compression] "lzma" "Getting compression as lzma failed" } -cleanup { $pg delete } -ok +test cookfsPages-12.3 "Test getting current page compression to unknown compression" -constraints {enabledTclCmds} -setup { + set file [makeFile {} pages.cfs] + set pg [cookfs::pages -compression zlib $file] +} -body { + $pg compression foo +} -cleanup { + $pg delete +} -error {bad compression "foo": must be none, zlib, or lzma} + test cookfsPages-13.1 "Error message when index not found" -constraints {enabledTclCmds} -setup { set file [makeFile {} pages.cfs] } -body { diff --git a/tests/pagesAsync.test b/tests/pagesAsync.test index 61e5a96..f91716c 100644 --- a/tests/pagesAsync.test +++ b/tests/pagesAsync.test @@ -1,6 +1,8 @@ source [file join [file dirname [info script]] common.tcl] -test cookfsPagesAsync-1.1 "Ensure asynccompresscommand is called when no pages are created" -constraints {enabledTclCmds} -setup { +test cookfsPagesAsync-1.1 "Ensure asynccompresscommand is called when no pages are created" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] testasynccompress init 4 {} variable pg @@ -15,7 +17,9 @@ test cookfsPagesAsync-1.1 "Ensure asynccompresscommand is called when no pages a testasynccleanup } -result 1 -test cookfsPagesAsync-1.2 "Ensure asynccompresscommand finalize is called when no pages are created" -constraints {enabledTclCmds} -setup { +test cookfsPagesAsync-1.2 "Ensure asynccompresscommand finalize is called when no pages are created" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] set ::testasynccompressfinalized 0 testasynccompress init 4 {} @@ -31,7 +35,9 @@ test cookfsPagesAsync-1.2 "Ensure asynccompresscommand finalize is called when n testasynccleanup } -result 1 -test cookfsPagesAsync-1.3 "Create single page using async approach" -constraints {enabledTclCmds} -setup { +test cookfsPagesAsync-1.3 "Create single page using async approach" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] testasynccompress init 4 {} set pg [cookfs::pages -alwayscompress -compression custom \ @@ -45,7 +51,9 @@ test cookfsPagesAsync-1.3 "Create single page using async approach" -constraints testasynccleanup } -result 1 -test cookfsPagesAsync-1.4 "Create single page and delete pages object using async approach" -constraints {enabledTclCmds} -setup { +test cookfsPagesAsync-1.4 "Create single page and delete pages object using async approach" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] testasynccompress init 4 {} set pg [cookfs::pages -alwayscompress -compression custom \ @@ -60,7 +68,9 @@ test cookfsPagesAsync-1.4 "Create single page and delete pages object using asyn testasynccleanup } -result 2 -test cookfsPagesAsync-1.5 "Verify async page can be read" -constraints {enabledTclCmds} -setup { +test cookfsPagesAsync-1.5 "Verify async page can be read" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] testasynccompress init 4 {} set pg [cookfs::pages -alwayscompress -compression custom \ @@ -77,7 +87,9 @@ test cookfsPagesAsync-1.5 "Verify async page can be read" -constraints {enabledT testasynccleanup } -returnCodes {ok} -result "SAMPLE DATA SAMPLE DATA SAMPLE DATA" -test cookfsPagesAsync-1.6 "Verify multiple async pages can be read" -constraints {enabledTclCmds} -setup { +test cookfsPagesAsync-1.6 "Verify multiple async pages can be read" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] testasynccompress init 4 {} set pg [cookfs::pages -alwayscompress -compression custom \ @@ -103,7 +115,9 @@ test cookfsPagesAsync-1.6 "Verify multiple async pages can be read" -constraints testasynccleanup } -result 1024 -test cookfsPagesAsync-1.7 "Verify multiple async pages with repetitions can be read" -constraints {enabledTclCmds} -setup { +test cookfsPagesAsync-1.7 "Verify multiple async pages with repetitions can be read" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] testasynccompress init 4 {} set pg [cookfs::pages -alwayscompress -compression custom \ @@ -129,7 +143,9 @@ test cookfsPagesAsync-1.7 "Verify multiple async pages with repetitions can be r testasynccleanup } -result 512 -test cookfsPagesAsync-2.1 "Test custom async compression algorithm not used when size would not be smaller" -constraints {enabledTclCmds} -setup { +test cookfsPagesAsync-2.1 "Test custom async compression algorithm not used when size would not be smaller" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] testasynccompress init 4 {} set data {QWERTYUIOPASDFGHJKLZXCVBNM0123456789} @@ -153,7 +169,9 @@ test cookfsPagesAsync-2.1 "Test custom async compression algorithm not used when testasynccleanup } -ok -test cookfsPagesAsync-2.2 "Test custom async compression algorithm used when size would not be smaller with -alwayscompress" -constraints {enabledTclCmds} -setup { +test cookfsPagesAsync-2.2 "Test custom async compression algorithm used when size would not be smaller with -alwayscompress" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] testasynccompress init 4 {} set data {QWERTYUIOPASDFGHJKLZXCVBNM0123456789} @@ -177,7 +195,9 @@ test cookfsPagesAsync-2.2 "Test custom async compression algorithm used when siz testasynccleanup } -ok -test cookfsPagesAsync-3.1 "Test correctness of async pages writing with adding same pages" -constraints {enabledTclCmds} -setup { +test cookfsPagesAsync-3.1 "Test correctness of async pages writing with adding same pages" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] testasynccompress init 4 {} set idxlist {} @@ -209,7 +229,9 @@ test cookfsPagesAsync-3.1 "Test correctness of async pages writing with adding s testasynccleanup } -ok -test cookfsPagesAsync-4.1 "Verify async decompression does not call decompress command for subsequent pages" -constraints {enabledTclCmds} -setup { +test cookfsPagesAsync-4.1 "Verify async decompression does not call decompress command for subsequent pages" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] set idxlist {} testasyncdecompress init 4 {} @@ -242,7 +264,9 @@ test cookfsPagesAsync-4.1 "Verify async decompression does not call decompress c testasynccleanup } -result 0 -test cookfsPagesAsync-4.2 "Verify async decompression does not call decompress command for subsequent pages with random return order" -constraints {enabledTclCmds} -setup { +test cookfsPagesAsync-4.2 "Verify async decompression does not call decompress command for subsequent pages with random return order" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] set idxlist {} testasyncdecompress init 4 {} @@ -275,7 +299,9 @@ test cookfsPagesAsync-4.2 "Verify async decompression does not call decompress c testasynccleanup } -result 0 -test cookfsPagesAsync-4.3 "Verify async decompression does not async decompress multiple times" -constraints {enabledTclCmds} -setup { +test cookfsPagesAsync-4.3 "Verify async decompression does not async decompress multiple times" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] set idxlist {} testasyncdecompress init 4 {} diff --git a/tests/pagesEncrypt.test b/tests/pagesEncrypt.test index af14826..0209758 100644 --- a/tests/pagesEncrypt.test +++ b/tests/pagesEncrypt.test @@ -676,7 +676,9 @@ test cookfsPagesEncrypt-6.4 "Test password change for key encryption" -constrain catch { $pg delete } } -ok -test cookfsPagesEncrypt-7.1 "Test encryption with custom compression" -constraints {enabledTclCmds cookfsCrypto} -setup { +test cookfsPagesEncrypt-7.1 "Test encryption with custom compression" -constraints { + enabledTclCmds cookfsCrypto enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] set pg [cookfs::pages -compression custom -alwayscompress \ -compresscommand testcompress -decompresscommand testdecompress \ @@ -716,7 +718,9 @@ test cookfsPagesEncrypt-7.1 "Test encryption with custom compression" -constrain unset -nocomplain testcompresscount testdecompresscount } -ok -test cookfsPagesEncrypt-8.1 "Test encryption with async compression" -constraints {enabledTclCmds cookfsCrypto} -setup { +test cookfsPagesEncrypt-8.1 "Test encryption with async compression" -constraints { + enabledTclCmds cookfsCrypto enabledTclCallbacks +} -setup { set file [makeFile {} pages.cfs] set ::testasynccompressfinalized 0 set pg [cookfs::pages -compression custom -alwayscompress \ diff --git a/tests/pkgconfig.test b/tests/pkgconfig.test index 109596d..ef0bf9b 100644 --- a/tests/pkgconfig.test +++ b/tests/pkgconfig.test @@ -34,6 +34,7 @@ feature-metadata bool feature-zstd bool package-version version platform unknown +tcl-callbacks bool tcl-commands bool } diff --git a/tests/vfs.test b/tests/vfs.test index 371a24b..83a0a1f 100644 --- a/tests/vfs.test +++ b/tests/vfs.test @@ -588,7 +588,9 @@ test cookfsVfs-9.4 "Test deleting non-empty directories with complex structure" cookfs::Unmount $file } -result {testdir1,testfile1,testfile2} -test cookfsVfs-10.1 "Test changing compression without remounting" -constraints {enabledTclCmds} -setup { +test cookfsVfs-10.1.1 "Test changing compression without remounting, with custom compression" -constraints { + enabledTclCmds enabledTclCallbacks +} -setup { set file [makeBinFile {} pages.cfs] variable fc variable idx @@ -624,6 +626,35 @@ test cookfsVfs-10.1 "Test changing compression without remounting" -constraints testrawcleanup } -ok +test cookfsVfs-10.1.2 "Test changing compression without remounting, with custom compression" -constraints {enabledTclCmds} -setup { + set file [makeBinFile {} pages.cfs] + variable fc + variable idx + set fsid [cookfs::Mount $file $file -compression lzma -smallfilesize 32768 -alwayscompress] +} -body { + $fsid compression zlib + assertEq [$fsid compression] "zlib" "Getting compression does not return 'zlib'" + + makeBinFile [string repeat "TEST" 256] testfile1 $file + + $fsid compression none + assertEq [$fsid compression] "none" "Getting compression does not return 'none'" + + makeBinFile [string repeat "test" 256] testfile2 $file + + $fsid compression lzma + assertEq [$fsid compression] "lzma" "Getting compression does not return 'lzma'" + cookfs::Unmount $file + + set fc [viewBinFile $file] + + assertNotContain $fc [string repeat "TEST" 256] "File testfile1 should be compressed" + assertContain $fc [string repeat "test" 256] "File testfile2 should not be compressed" +} -cleanup { + catch { cookfs::Unmount $file } + testrawcleanup +} -ok + test cookfsVfs-11.1 "Test unmount using fsid" -setup { set file [makeBinFile {} pages.cfs] variable fsid diff --git a/tests/vfsThread.test b/tests/vfsThread.test index d606abc..d22c14a 100644 --- a/tests/vfsThread.test +++ b/tests/vfsThread.test @@ -135,7 +135,9 @@ test cookfsVfsThread-3.2 "Test simple read files from other thread from pages" - cookfs::Unmount $file } -result {TEST01XTEST02Y} -test cookfsVfsThread-4.1 "Test error for tcl commands for shared VFS" -constraints {threaded enabledCVfs} -setup { +test cookfsVfsThread-4.1 "Test error for tcl commands for shared VFS" -constraints { + threaded enabledCVfs enabledTclCallbacks +} -setup { set file [makeFile {} cookfs.cfs] } -body { assertErrMsg { cookfs::Mount $file $file -compression none -shared -compresscommand foo } \