diff --git a/.gitignore b/.gitignore index 55c8283bdf..e986f7faf8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ compile +build .pytest_cache .dirstamp a.out diff --git a/ChangeLog b/ChangeLog index a6bed66826..fed1ad14dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,6 @@ 21/11/21 started 8.13 - configure fails for requested but unmet dependencies [remicollet] - add support for another quantiser [DarthSim] -- add "extend", "background" and "premultiplied" to mapim to fix edge - antialiasing [GavinJoyce] - add support for HDR HEIC and AVIF images - add spngsave - jpeg2000 load left-justifies bitdepth @@ -17,6 +15,7 @@ - add maxerror to gifsave [dloebl] - update libnsgif API [tlsa] - deprecate "properties" option to dzsave (now always on) +- add vips_configure() ... set various config options 26/11/21 started 8.12.3 - better arg checking for hist_find_ndim [travisbell] diff --git a/libvips/iofuncs/Makefile.am b/libvips/iofuncs/Makefile.am index ec5988450f..2130fd9a89 100644 --- a/libvips/iofuncs/Makefile.am +++ b/libvips/iofuncs/Makefile.am @@ -3,6 +3,7 @@ noinst_LTLIBRARIES = libiofuncs.la libiofuncs_la_SOURCES = \ ginputsource.c \ sourceginput.c \ + configure.c \ connection.c \ source.c \ sourcecustom.c \ diff --git a/libvips/iofuncs/configure.c b/libvips/iofuncs/configure.c new file mode 100644 index 0000000000..98aada95dc --- /dev/null +++ b/libvips/iofuncs/configure.c @@ -0,0 +1,249 @@ +/* vips_configure(): set/clear various libvips settings + * + * 11/04/22 + * - from configure.c + */ + +/* + + This file is part of VIPS. + + VIPS 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 of the License, or + (at your option) any later version. + + This program 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + 02110-1301 USA + + */ + +/* + + These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk + + */ + +#ifdef HAVE_CONFIG_H +#include +#endif /*HAVE_CONFIG_H*/ +#include + +#include +#include + +#ifdef HAVE_UNISTD_H +#include +#endif /*HAVE_UNISTD_H*/ +#include +#include +#include + +#include +#include + +typedef struct _VipsConfigure { + VipsOperation parent_instance; + + /* Block all untrusted operations. + */ + gboolean untrusted_block; + + /* Block a specific operation. + */ + char *operation_block; + + /* Unblock a specific operation. + */ + char *operation_unblock; + + /* Enable leak reporting. + */ + gboolean leak; + + /* Enable profiling + */ + gboolean profile; + + /* Threadpool size. + */ + int concurrency; + + /* Max size of pipe. + */ + gint64 pipe_read_limit; + + /* Trace libvips operation cache actions. + */ + gboolean cache_trace; + + /* Number of recent operations to cache. + */ + int cache_max; + + /* Maximum memory to use for operation caching. + */ + gint64 cache_max_mem; + + /* Maximum number of open files we allow in the cache. + */ + int cache_max_files; + +} VipsConfigure; + +typedef VipsOperationClass VipsConfigureClass; + +G_DEFINE_TYPE( VipsConfigure, vips_configure, VIPS_TYPE_OPERATION ); + +static int +vips_configure_build( VipsObject *object ) +{ + VipsConfigure *configure = (VipsConfigure *) object; + + if( VIPS_OBJECT_CLASS( vips_configure_parent_class )->build( object ) ) + return( -1 ); + + if( vips_object_argument_isset( object, "untrusted_block" ) ) + vips_block_untrusted_set( configure->untrusted_block ); + + if( vips_object_argument_isset( object, "operation_block" ) ) + vips_operation_block_set( configure->operation_block, TRUE ); + if( vips_object_argument_isset( object, "operation_unblock" ) ) + vips_operation_block_set( configure->operation_block, FALSE ); + + return( 0 ); +} + +static void +vips_configure_class_init( VipsConfigureClass *class ) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS( class ); + VipsObjectClass *vobject_class = VIPS_OBJECT_CLASS( class ); + VipsOperationClass *operation_class = VIPS_OPERATION_CLASS( class ); + + gobject_class->set_property = vips_object_set_property; + gobject_class->get_property = vips_object_get_property; + + vobject_class->nickname = "configure"; + vobject_class->description = _( "set various library options" ); + vobject_class->build = vips_configure_build; + + /* Commands can have side-effects, so don't cache them. + */ + operation_class->flags = VIPS_OPERATION_NOCACHE; + + VIPS_ARG_BOOL( class, "untrusted_block", 2, + _( "Block untrusted" ), + _( "Block all untrusted operations from running" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsConfigure, untrusted_block ), + FALSE ); + + VIPS_ARG_STRING( class, "operation_block", 3, + _( "Block operation" ), + _( "Block an operation (and any subclasses) from running" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsConfigure, operation_block ), + NULL ); + + VIPS_ARG_STRING( class, "operation_unblock", 4, + _( "Unblock operation" ), + _( "Unblock an operation (and any subclasses) from running" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsConfigure, operation_unblock ), + NULL ); + + VIPS_ARG_INT( class, "concurrency", 5, + _( "Concurrency" ), + _( "Set threadpool size" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsConfigure, concurrency ), + 0, 1024, 0 ); + + VIPS_ARG_UINT64( class, "pipe_read_limit", 6, + _( "Pipe read limit" ), + _( "Maxiumum number of bytes to buffer for pipe read" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsConfigure, pipe_read_limit ), + 0, 1024L * 1024L * 1024L * 1024L, 1024L * 1024L * 1024L ); + + VIPS_ARG_INT( class, "cache_max", 7, + _( "Cache max size" ), + _( "Maxium number of operations to cache" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsConfigure, cache_max ), + 0, 100000, 100 ); + + VIPS_ARG_UINT64( class, "cache_max_mem", 8, + _( "Cache max memory size" ), + _( "Maxium amount of memory for the operation cache" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsConfigure, cache_max_mem ), + 0, 1024L * 1024L * 1024L * 1024L, 100 * 1024L * 1024L ); + + VIPS_ARG_INT( class, "cache_max_files", 9, + _( "Cache max open files" ), + _( "Maxium number of open files in operation cache" ), + VIPS_ARGUMENT_OPTIONAL_INPUT, + G_STRUCT_OFFSET( VipsConfigure, cache_max_files ), + 0, 100000, 100 ); + +} + +static void +vips_configure_init( VipsConfigure *configure ) +{ + configure->concurrency = -1; + configure->pipe_read_limit = 1024L * 1024L * 1024L; + configure->cache_max = 100; + configure->cache_max_mem = 100 * 1024L * 1024L; + configure->cache_max_files = 100; +} + +/** + * vips_configure: + * @name: not used + * @...: %NULL-terminated list of optional named arguments + * + * Optional arguments: + * + * * @untrusted_block: %gboolean, Block all untrusted operations from running + * * @operation_block : %gchararray, Block an operation from running + * * @operation_unblock : %gchararray, Unblock an operation from running + * + * vips_configure() can be used to set a number of libvips configure + * options. + * + * If @untrusted_block is set, all libvips operations which have been tagged + * as unsafe for untrusted input will be blocked. All subclasses of these + * operations are also blocked. See vips_block_untrusted_set(). + * + * If @operation_block is set, the named libvips operation is blocked. All + * subclasses of this operation are also blocked. See + * vips_operation_block_set(). + * + * If @operation_unblock is set, the named libvips operation is unblocked. All + * subclasses of this operation are also unblocked. See + * vips_operation_block_set(). + * + * Returns: 0 on success, -1 on failure. + */ +int +vips_configure( const char *name, ... ) +{ + va_list ap; + int result; + + va_start( ap, name ); + result = vips_call_split( "configure", ap, name ); + va_end( ap ); + + return( result ); +} diff --git a/libvips/iofuncs/init.c b/libvips/iofuncs/init.c index dd560d0cb1..9ddeee7edf 100644 --- a/libvips/iofuncs/init.c +++ b/libvips/iofuncs/init.c @@ -434,6 +434,7 @@ int vips_init( const char *argv0 ) { extern GType vips_system_get_type( void ); + extern GType vips_configure_get_type( void ); extern GType write_thread_state_get_type( void ); extern GType sink_memory_thread_state_get_type( void ); extern GType render_thread_state_get_type( void ); @@ -578,6 +579,7 @@ vips_init( const char *argv0 ) /* Start up packages. */ (void) vips_system_get_type(); + (void) vips_configure_get_type(); vips_arithmetic_operation_init(); vips_conversion_operation_init(); vips_create_operation_init(); diff --git a/libvips/iofuncs/meson.build b/libvips/iofuncs/meson.build index eec82036bb..e103e1db43 100644 --- a/libvips/iofuncs/meson.build +++ b/libvips/iofuncs/meson.build @@ -1,6 +1,7 @@ iofuncs_sources = files( 'ginputsource.c', 'sourceginput.c', + 'configure.c', 'connection.c', 'source.c', 'sourcecustom.c', diff --git a/libvips/iofuncs/operation.c b/libvips/iofuncs/operation.c index 5043fc2260..44777fee19 100644 --- a/libvips/iofuncs/operation.c +++ b/libvips/iofuncs/operation.c @@ -33,6 +33,7 @@ /* #define VIPS_DEBUG +#define DEBUG */ #ifdef HAVE_CONFIG_H @@ -1432,9 +1433,9 @@ vips_operation_block_set_operation( VipsOperationClass *class, gboolean *state ) { g_assert( VIPS_IS_OPERATION_CLASS( class ) ); -#ifdef VIPS_DEBUG +#ifdef DEBUG if( ((class->flags & VIPS_OPERATION_BLOCKED) != 0) != *state ) - VIPS_DEBUG_MSG( "vips_operation_block_set_operation: " + printf( "vips_operation_block_set_operation: " "setting block state on %s = %d\n", VIPS_OBJECT_CLASS( class )->nickname, *state ); #endif diff --git a/libvips/iofuncs/source.c b/libvips/iofuncs/source.c index d8d778e4de..2214b7e0d5 100644 --- a/libvips/iofuncs/source.c +++ b/libvips/iofuncs/source.c @@ -1,4 +1,4 @@ -/* A byte source/sink .. it can be a pipe, file descriptor, memory area, +/* A byte source/sink .. it can be a pipe, file descriptor, memory area, * socket, node.js stream, etc. * * 19/6/14