summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEven Rouault <even.rouault@spatialys.com>2022-11-21 23:59:12 +0000
committerEven Rouault <even.rouault@spatialys.com>2022-11-21 23:59:12 +0000
commitd95b5b7628da6e0f446f7289059e1248de12dec9 (patch)
tree61529d7a0de59fa2f65899a56b7df70e0b335736
parente7e567536baddd491e124f6fc5e11e80e740934e (diff)
parentec18caeb67e751fb50b5777c9b4d7c9cf2a71683 (diff)
downloadlibtiff-git-d95b5b7628da6e0f446f7289059e1248de12dec9.tar.gz
Merge branch 'TIFFOpenEx' into 'master'
Add TIFFOpenExt(), TIFFOpenWExt() and TIFFFdOpenExt() with re-entrant error handlers See merge request libtiff/libtiff!413
-rw-r--r--doc/functions/TIFFError.rst8
-rw-r--r--doc/functions/TIFFOpen.rst39
-rw-r--r--doc/functions/TIFFWarning.rst3
-rw-r--r--libtiff/libtiff.def11
-rw-r--r--libtiff/libtiff.map11
-rw-r--r--libtiff/tif_error.c24
-rw-r--r--libtiff/tif_open.c58
-rw-r--r--libtiff/tif_unix.c58
-rw-r--r--libtiff/tif_warning.c6
-rw-r--r--libtiff/tif_win32.c50
-rw-r--r--libtiff/tiffio.h30
-rw-r--r--libtiff/tiffiop.h16
-rw-r--r--test/CMakeLists.txt5
-rw-r--r--test/Makefile.am4
-rw-r--r--test/test_error_handlers.c140
15 files changed, 393 insertions, 70 deletions
diff --git a/doc/functions/TIFFError.rst b/doc/functions/TIFFError.rst
index f03eef8c..797c1c0e 100644
--- a/doc/functions/TIFFError.rst
+++ b/doc/functions/TIFFError.rst
@@ -43,7 +43,13 @@ as *fd*, which represents the TIFF file handle (file descriptor).
.. TODO: Check description, how to setup a TIFFErrorExt handler and its file handle.
-With :c:func:`TIFFSetErrorHandlerExt` an extra error handler can be setup.
+With :c:func:`TIFFSetErrorHandlerExt` an extra error handler can be setup
+in order to write to a file. The file handle needs to be stored in
+``tif->tif_clientdata`` if the ``libtiff`` internal errors shall also
+be written to that file.
+
+Note that, starting with libtiff 4.5, a per-TIFF handler may also be installed
+with :c:func:`TIFFOpenExt` or :c:func:`TIFFClientOpenExt`
Note
----
diff --git a/doc/functions/TIFFOpen.rst b/doc/functions/TIFFOpen.rst
index 29c7cfc6..7566ef62 100644
--- a/doc/functions/TIFFOpen.rst
+++ b/doc/functions/TIFFOpen.rst
@@ -35,6 +35,22 @@ Synopsis
.. c:function:: thandle_t TIFFSetClientdata(TIFF* tif, thandle_t newvalue)
+.. c:function:: TIFFOpenOptions* TIFFOpenOptionsAlloc(void)
+
+.. c:function:: void TIFFOpenOptionsFree(TIFFOpenOptions*);
+
+.. c:function:: void TIFFOpenOptionsSetErrorHandlerExtR(TIFFOpenOptions* opts, TIFFErrorHandlerExtR handler, void* errorhandler_user_data)
+
+.. c:function:: void TIFFOpenOptionsSetWarningHandlerExtR(TIFFOpenOptions* opts, TIFFErrorHandlerExtR handler, void* warnhandler_user_data)
+
+.. c:function:: TIFF* TIFFOpenExt(const char* filename, const char* mode, TIFFOpenOptions* opts)
+
+.. c:function:: TIFF* TIFFOpenWExt(const wchar_t* name, const char* mode, TIFFOpenOptions* opts)
+
+.. c:function:: TIFF* TIFFFdOpenExt(const int fd, const char* filename, const char*mode, TIFFOpenOptions* opts)
+
+.. c:function:: TIFF* TIFFClientOpenExt(const char* filename, const char* mode, thandle_t clientdata, TIFFReadWriteProc readproc, TIFFReadWriteProc writeproc, TIFFSeekProc seekproc, TIFFCloseProc closeproc, TIFFSizeProc sizeproc, TIFFMapFileProc mapproc, TIFFUnmapFileProc unmapproc, TIFFOpenOptions* opts)
+
Description
-----------
@@ -86,6 +102,24 @@ first :c:func:`TIFFCleanup` should be called to free the internal
TIFF structure without closing the file handle and afterwards the
file should be closed using its file descriptor *fd*.
+:c:func:`TIFFOpenExt` (added in libtiff 4.5) is like :c:func:`TIFFOpen`, but options,
+such as re-entrant error and warning handlers may be passed. The opts argument
+may be NULL. Note that in the early stages of the execution of the function,
+the TIFF* argument passed to the re-entrant error handler (specified in opts)
+may be NULL.
+
+:c:func:`TIFFOpenWExt` (added in libtiff 4.5) is like :c:func:`TIFFOpenW`, but options,
+such as re-entrant error and warning handlers may be passed. The opts argument
+may be NULL. Note that in the early stages of the execution of the function,
+the TIFF* argument passed to the re-entrant error handler (specified in opts)
+may be NULL.
+
+:c:func:`TIFFFdOpenExt` (added in libtiff 4.5) is like :c:func:`TIFFFdOpen`, but options,
+such as re-entrant error and warning handlers may be passed. The opts argument
+may be NULL. Note that in the early stages of the execution of the function,
+the TIFF* argument passed to the re-entrant error handler (specified in opts)
+may be NULL.
+
:c:func:`TIFFSetFileName` sets the file name in the tif-structure
and returns the old file name.
@@ -123,6 +157,11 @@ The clientdata is used as open file's I/O descriptor within ``libtiff``.
When updating the file's clientdata with :c:func:`TIFFSetClientdata`,
the *fd* value is **not** updated.
+:c:func:`TIFFClientOpenExt` (added in libtiff 4.5) is like :c:func:`TIFFClientOpen`, but options,
+such as re-entrant error and warning handlers may be passed. The opts argument
+may be NULL. Note that in the early stages of the execution of the function,
+the TIFF* argument passed to the re-entrant error handler (specified in opts)
+may be NULL.
Options
-------
diff --git a/doc/functions/TIFFWarning.rst b/doc/functions/TIFFWarning.rst
index 38bfbf1c..2006696c 100644
--- a/doc/functions/TIFFWarning.rst
+++ b/doc/functions/TIFFWarning.rst
@@ -49,6 +49,9 @@ as *fd*, which represents the TIFF file handle (file descriptor).
With :c:func:`TIFFSetWarningHandlerExt` an extra warning handler can be
setup up.
+Note that, starting with libtiff 4.5, a per-TIFF handler may also be installed
+with :c:func:`TIFFOpenExt` or :c:func:`TIFFClientOpenExt`
+
Note
----
diff --git a/libtiff/libtiff.def b/libtiff/libtiff.def
index ee5486a6..975ad1fd 100644
--- a/libtiff/libtiff.def
+++ b/libtiff/libtiff.def
@@ -5,7 +5,7 @@ EXPORTS TIFFAccessTagMethods
TIFFCheckpointDirectory
TIFFCleanup
TIFFClientOpen
- TIFFClientOpenEx
+ TIFFClientOpenExt
TIFFClientdata
TIFFClose
TIFFComputeStrip
@@ -25,7 +25,9 @@ EXPORTS TIFFAccessTagMethods
TIFFDeferStrileArrayWriting
TIFFError
TIFFErrorExt
+ TIFFErrorExtR
TIFFFdOpen
+ TIFFFdOpenExt
TIFFFieldDataType
TIFFFieldName
TIFFFieldPassCount
@@ -78,7 +80,13 @@ EXPORTS TIFFAccessTagMethods
TIFFNumberOfStrips
TIFFNumberOfTiles
TIFFOpen
+ TIFFOpenExt
TIFFOpenW
+ TIFFOpenWExt
+ TIFFOpenOptionsAlloc
+ TIFFOpenOptionsFree
+ TIFFOpenOptionsSetErrorHandlerExtR
+ TIFFOpenOptionsSetWarningHandlerExtR
TIFFPrintDirectory
TIFFRGBAImageBegin
TIFFRGBAImageEnd
@@ -156,6 +164,7 @@ EXPORTS TIFFAccessTagMethods
TIFFVTileSize64
TIFFWarning
TIFFWarningExt
+ TIFFWarningExtR
TIFFWriteBufferSetup
TIFFWriteCheck
TIFFWriteCustomDirectory
diff --git a/libtiff/libtiff.map b/libtiff/libtiff.map
index 4c66ed41..c811a751 100644
--- a/libtiff/libtiff.map
+++ b/libtiff/libtiff.map
@@ -202,5 +202,14 @@ LIBTIFF_4.4 {
LIBTIFF_4.5 {
_TIFFClampDoubleToUInt32;
- TIFFClientOpenEx;
+ TIFFClientOpenExt;
+ TIFFFdOpenExt;
+ TIFFOpenExt;
+ TIFFOpenWExt;
+ TIFFErrorExtR;
+ TIFFWarningExtR;
+ TIFFOpenOptionsAlloc;
+ TIFFOpenOptionsFree;
+ TIFFOpenOptionsSetErrorHandlerExtR;
+ TIFFOpenOptionsSetWarningHandlerExtR;
} LIBTIFF_4.4;
diff --git a/libtiff/tif_error.c b/libtiff/tif_error.c
index 2bd74d52..4065d60a 100644
--- a/libtiff/tif_error.c
+++ b/libtiff/tif_error.c
@@ -77,16 +77,34 @@ TIFFErrorExt(thandle_t fd, const char* module, const char* fmt, ...)
}
}
-void TIFFSetErrorHandlerExtR(TIFF* tif, TIFFErrorHandlerExtR handler) {
- if (tif) tif->tif_errorhandler = handler;
+void _TIFFErrorEarly(TIFFOpenOptions* opts, thandle_t clientdata, const char* module, const char* fmt, ...)
+{
+ va_list ap;
+ if (opts && opts->errorhandler) {
+ va_start(ap, fmt);
+ int stop = opts->errorhandler(NULL, opts->errorhandler_user_data, module, fmt, ap);
+ va_end(ap);
+ if (stop) return;
+ }
+ if (_TIFFerrorHandler) {
+ va_start(ap, fmt);
+ (*_TIFFerrorHandler)(module, fmt, ap);
+ va_end(ap);
+ }
+ if (_TIFFerrorHandlerExt) {
+ va_start(ap, fmt);
+ (*_TIFFerrorHandlerExt)(clientdata, module, fmt, ap);
+ va_end(ap);
+ }
}
+
void TIFFErrorExtR(TIFF* tif, const char* module, const char* fmt, ...)
{
va_list ap;
if (tif && tif->tif_errorhandler) {
va_start(ap, fmt);
- int stop = (*tif->tif_errorhandler)(tif->tif_clientdata, module, fmt, ap);
+ int stop = (*tif->tif_errorhandler)(tif, tif->tif_errorhandler_user_data, module, fmt, ap);
va_end(ap);
if (stop) return;
}
diff --git a/libtiff/tif_open.c b/libtiff/tif_open.c
index c16a5e66..23e206d7 100644
--- a/libtiff/tif_open.c
+++ b/libtiff/tif_open.c
@@ -44,7 +44,7 @@ _tiffDummyUnmapProc(thandle_t fd, void* base, toff_t size)
}
int
-_TIFFgetMode(const char* mode, const char* module)
+_TIFFgetMode(TIFFOpenOptions* opts, thandle_t clientdata, const char* mode, const char* module)
{
int m = -1;
@@ -61,12 +61,35 @@ _TIFFgetMode(const char* mode, const char* module)
m |= O_TRUNC;
break;
default:
- TIFFErrorExt(0, module, "\"%s\": Bad mode", mode);
+ _TIFFErrorEarly(opts, clientdata, module, "\"%s\": Bad mode", mode);
break;
}
return (m);
}
+TIFFOpenOptions* TIFFOpenOptionsAlloc()
+{
+ TIFFOpenOptions* opts = (TIFFOpenOptions*)_TIFFcalloc(1, sizeof(TIFFOpenOptions));
+ return opts;
+}
+
+void TIFFOpenOptionsFree(TIFFOpenOptions* opts)
+{
+ _TIFFfree(opts);
+}
+
+void TIFFOpenOptionsSetErrorHandlerExtR(TIFFOpenOptions* opts, TIFFErrorHandlerExtR handler, void* errorhandler_user_data)
+{
+ opts->errorhandler = handler;
+ opts->errorhandler_user_data = errorhandler_user_data;
+}
+
+void TIFFOpenOptionsSetWarningHandlerExtR(TIFFOpenOptions* opts, TIFFErrorHandlerExtR handler, void* warnhandler_user_data)
+{
+ opts->warnhandler = handler;
+ opts->warnhandler_user_data = warnhandler_user_data;
+}
+
TIFF*
TIFFClientOpen(
const char* name, const char* mode,
@@ -79,12 +102,19 @@ TIFFClientOpen(
TIFFMapFileProc mapproc,
TIFFUnmapFileProc unmapproc
) {
- return TIFFClientOpenEx(name, mode, clientdata, readproc, writeproc, seekproc, closeproc,
- sizeproc, mapproc, unmapproc, NULL, NULL);
+ return TIFFClientOpenExt(name, mode, clientdata,
+ readproc,
+ writeproc,
+ seekproc,
+ closeproc,
+ sizeproc,
+ mapproc,
+ unmapproc,
+ NULL);
}
TIFF*
-TIFFClientOpenEx(
+TIFFClientOpenExt(
const char* name, const char* mode,
thandle_t clientdata,
TIFFReadWriteProc readproc,
@@ -94,10 +124,9 @@ TIFFClientOpenEx(
TIFFSizeProc sizeproc,
TIFFMapFileProc mapproc,
TIFFUnmapFileProc unmapproc,
- TIFFErrorHandlerExtR errorhandler,
- TIFFErrorHandlerExtR warnhandler)
+ TIFFOpenOptions* opts)
{
- static const char module[] = "TIFFClientOpenEx";
+ static const char module[] = "TIFFClientOpenExt";
TIFF *tif;
int m;
const char* cp;
@@ -128,12 +157,12 @@ TIFFClientOpenEx(
#endif
}
- m = _TIFFgetMode(mode, module);
+ m = _TIFFgetMode(opts, clientdata, mode, module);
if (m == -1)
goto bad2;
tif = (TIFF *)_TIFFmalloc((tmsize_t)(sizeof (TIFF) + strlen(name) + 1));
if (tif == NULL) {
- TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name);
+ _TIFFErrorEarly(opts, clientdata, module, "%s: Out of memory (TIFF structure)", name);
goto bad2;
}
_TIFFmemset(tif, 0, sizeof (*tif));
@@ -152,8 +181,13 @@ TIFFClientOpenEx(
tif->tif_sizeproc = sizeproc;
tif->tif_mapproc = mapproc ? mapproc : _tiffDummyMapProc;
tif->tif_unmapproc = unmapproc ? unmapproc : _tiffDummyUnmapProc;
- tif->tif_errorhandler = errorhandler;
- tif->tif_warnhandler = warnhandler;
+ if( opts )
+ {
+ tif->tif_errorhandler = opts->errorhandler;
+ tif->tif_errorhandler_user_data = opts->errorhandler_user_data;
+ tif->tif_warnhandler = opts->warnhandler;
+ tif->tif_warnhandler_user_data = opts->warnhandler_user_data;
+ }
if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
TIFFErrorExtR(tif, module,
diff --git a/libtiff/tif_unix.c b/libtiff/tif_unix.c
index cb543542..89ae0c17 100644
--- a/libtiff/tif_unix.c
+++ b/libtiff/tif_unix.c
@@ -202,18 +202,29 @@ _tiffUnmapProc(thandle_t fd, void* base, toff_t size)
TIFF*
TIFFFdOpen(int fd, const char* name, const char* mode)
{
+ return TIFFFdOpenExt(fd, name, mode, NULL);
+}
+
+TIFF*
+TIFFFdOpenExt(int fd, const char* name, const char* mode, TIFFOpenOptions* opts)
+{
TIFF* tif;
- fd_as_handle_union_t fdh;
- fdh.fd = fd;
- tif = TIFFClientOpen(name, mode,
- fdh.h,
- _tiffReadProc, _tiffWriteProc,
- _tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
- _tiffMapProc, _tiffUnmapProc);
- if (tif)
- tif->tif_fd = fd;
- return (tif);
+ fd_as_handle_union_t fdh;
+ fdh.fd = fd;
+ tif = TIFFClientOpenExt(name, mode,
+ fdh.h,
+ _tiffReadProc,
+ _tiffWriteProc,
+ _tiffSeekProc,
+ _tiffCloseProc,
+ _tiffSizeProc,
+ _tiffMapProc,
+ _tiffUnmapProc,
+ opts);
+ if (tif)
+ tif->tif_fd = fd;
+ return (tif);
}
/*
@@ -222,11 +233,17 @@ TIFFFdOpen(int fd, const char* name, const char* mode)
TIFF*
TIFFOpen(const char* name, const char* mode)
{
+ return TIFFOpenExt(name, mode, NULL);
+}
+
+TIFF*
+TIFFOpenExt(const char* name, const char* mode, TIFFOpenOptions* opts)
+{
static const char module[] = "TIFFOpen";
int m, fd;
TIFF* tif;
- m = _TIFFgetMode(mode, module);
+ m = _TIFFgetMode(opts, NULL, mode, module);
if (m == -1)
return ((TIFF*)0);
@@ -238,14 +255,14 @@ TIFFOpen(const char* name, const char* mode)
fd = open(name, m, 0666);
if (fd < 0) {
if (errno > 0 && strerror(errno) != NULL ) {
- TIFFErrorExt(0, module, "%s: %s", name, strerror(errno) );
+ _TIFFErrorEarly(opts, NULL, module, "%s: %s", name, strerror(errno) );
} else {
- TIFFErrorExt(0, module, "%s: Cannot open", name);
+ _TIFFErrorEarly(opts, NULL, module, "%s: Cannot open", name);
}
return ((TIFF *)0);
}
- tif = TIFFFdOpen((int)fd, name, mode);
+ tif = TIFFFdOpenExt((int)fd, name, mode, opts);
if(!tif)
close(fd);
return tif;
@@ -259,6 +276,11 @@ TIFFOpen(const char* name, const char* mode)
TIFF*
TIFFOpenW(const wchar_t* name, const char* mode)
{
+ return TIFFOpenWEx(name, mode, NULL);
+}
+TIFF*
+TIFFOpenWExt(const wchar_t* name, const char* mode, TIFFOpenOptions* opts)
+{
static const char module[] = "TIFFOpenW";
int m, fd;
int mbsize;
@@ -276,7 +298,7 @@ TIFFOpenW(const wchar_t* name, const char* mode)
fd = _wopen(name, m, 0666);
if (fd < 0) {
- TIFFErrorExt(0, module, "%ls: Cannot open", name);
+ _TIFFErrorEarly(opts, NULL, module, "%ls: Cannot open", name);
return ((TIFF *)0);
}
@@ -285,7 +307,7 @@ TIFFOpenW(const wchar_t* name, const char* mode)
if (mbsize > 0) {
mbname = _TIFFmalloc(mbsize);
if (!mbname) {
- TIFFErrorExt(0, module,
+ _TIFFErrorEarly(opts, NULL, module,
"Can't allocate space for filename conversion buffer");
return ((TIFF*)0);
}
@@ -294,8 +316,8 @@ TIFFOpenW(const wchar_t* name, const char* mode)
NULL, NULL);
}
- tif = TIFFFdOpen((int)fd, (mbname != NULL) ? mbname : "<unknown>",
- mode);
+ tif = TIFFFdOpenExt((int)fd, (mbname != NULL) ? mbname : "<unknown>",
+ mode, opts);
_TIFFfree(mbname);
diff --git a/libtiff/tif_warning.c b/libtiff/tif_warning.c
index aa26faca..29e26bec 100644
--- a/libtiff/tif_warning.c
+++ b/libtiff/tif_warning.c
@@ -77,16 +77,12 @@ TIFFWarningExt(thandle_t fd, const char* module, const char* fmt, ...)
}
}
-void TIFFSetWarningHandlerExtR(TIFF* tif, TIFFErrorHandlerExtR handler) {
- if (tif) tif->tif_warnhandler = handler;
-}
-
void TIFFWarningExtR(TIFF* tif, const char* module, const char* fmt, ...)
{
va_list ap;
if (tif && tif->tif_warnhandler) {
va_start(ap, fmt);
- int stop = (*tif->tif_warnhandler)(tif->tif_clientdata, module, fmt, ap);
+ int stop = (*tif->tif_warnhandler)(tif, tif->tif_warnhandler_user_data, module, fmt, ap);
va_end(ap);
if (stop) return;
}
diff --git a/libtiff/tif_win32.c b/libtiff/tif_win32.c
index d617a0f4..955957b7 100644
--- a/libtiff/tif_win32.c
+++ b/libtiff/tif_win32.c
@@ -232,9 +232,16 @@ _tiffUnmapProc(thandle_t fd, void* base, toff_t size)
TIFF*
TIFFFdOpen(int ifd, const char* name, const char* mode)
{
+ return TIFFFdOpenExt(ifd, name, mode, NULL);
+}
+
+TIFF*
+TIFFFdOpenExt(int ifd, const char* name, const char* mode, TIFFOpenOptions* opts)
+{
TIFF* tif;
int fSuppressMap;
int m;
+
fSuppressMap=0;
for (m=0; mode[m]!=0; m++)
{
@@ -244,11 +251,16 @@ TIFFFdOpen(int ifd, const char* name, const char* mode)
break;
}
}
- tif = TIFFClientOpen(name, mode, thandle_from_int(ifd),
- _tiffReadProc, _tiffWriteProc,
- _tiffSeekProc, _tiffCloseProc, _tiffSizeProc,
- fSuppressMap ? _tiffDummyMapProc : _tiffMapProc,
- fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc);
+
+ tif = TIFFClientOpenExt(name, mode, thandle_from_int(ifd),
+ _tiffReadProc,
+ _tiffWriteProc,
+ _tiffSeekProc,
+ _tiffCloseProc,
+ _tiffSizeProc,
+ fSuppressMap ? _tiffDummyMapProc : _tiffMapProc,
+ fSuppressMap ? _tiffDummyUnmapProc : _tiffUnmapProc,
+ opts);
if (tif)
tif->tif_fd = ifd;
return (tif);
@@ -262,13 +274,19 @@ TIFFFdOpen(int ifd, const char* name, const char* mode)
TIFF*
TIFFOpen(const char* name, const char* mode)
{
+ return TIFFOpenExt(name, mode, NULL);
+}
+
+TIFF*
+TIFFOpenExt(const char* name, const char* mode, TIFFOpenOptions* opts)
+{
static const char module[] = "TIFFOpen";
thandle_t fd;
int m;
DWORD dwMode;
TIFF* tif;
- m = _TIFFgetMode(mode, module);
+ m = _TIFFgetMode(opts, NULL, mode, module);
switch(m) {
case O_RDONLY: dwMode = OPEN_EXISTING; break;
@@ -285,11 +303,11 @@ TIFFOpen(const char* name, const char* mode)
(m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
NULL);
if (fd == INVALID_HANDLE_VALUE) {
- TIFFErrorExt(0, module, "%s: Cannot open", name);
+ _TIFFErrorEarly(opts, NULL, module, "%s: Cannot open", name);
return ((TIFF *)0);
}
- tif = TIFFFdOpen(thandle_to_int(fd), name, mode);
+ tif = TIFFFdOpenExt(thandle_to_int(fd), name, mode, opts);
if(!tif)
CloseHandle(fd);
return tif;
@@ -301,6 +319,12 @@ TIFFOpen(const char* name, const char* mode)
TIFF*
TIFFOpenW(const wchar_t* name, const char* mode)
{
+ return TIFFOpenWExt(name, mode, NULL);
+}
+
+TIFF*
+TIFFOpenWExt(const wchar_t* name, const char* mode, TIFFOpenOptions* opts)
+{
static const char module[] = "TIFFOpenW";
thandle_t fd;
int m;
@@ -309,7 +333,7 @@ TIFFOpenW(const wchar_t* name, const char* mode)
char *mbname;
TIFF *tif;
- m = _TIFFgetMode(mode, module);
+ m = _TIFFgetMode(opts, NULL, mode, module);
switch(m) {
case O_RDONLY: dwMode = OPEN_EXISTING; break;
@@ -326,7 +350,7 @@ TIFFOpenW(const wchar_t* name, const char* mode)
(m == O_RDONLY)?FILE_ATTRIBUTE_READONLY:FILE_ATTRIBUTE_NORMAL,
NULL);
if (fd == INVALID_HANDLE_VALUE) {
- TIFFErrorExt(0, module, "%S: Cannot open", name);
+ _TIFFErrorEarly(opts, NULL, module, "%S: Cannot open", name);
return ((TIFF *)0);
}
@@ -335,7 +359,7 @@ TIFFOpenW(const wchar_t* name, const char* mode)
if (mbsize > 0) {
mbname = (char *)_TIFFmalloc(mbsize);
if (!mbname) {
- TIFFErrorExt(0, module,
+ _TIFFErrorEarly(opts, NULL, module,
"Can't allocate space for filename conversion buffer");
return ((TIFF*)0);
}
@@ -344,8 +368,8 @@ TIFFOpenW(const wchar_t* name, const char* mode)
NULL, NULL);
}
- tif = TIFFFdOpen(thandle_to_int(fd),
- (mbname != NULL) ? mbname : "<unknown>", mode);
+ tif = TIFFFdOpenExt(thandle_to_int(fd),
+ (mbname != NULL) ? mbname : "<unknown>", mode, opts);
if(!tif)
CloseHandle(fd);
diff --git a/libtiff/tiffio.h b/libtiff/tiffio.h
index 0d6e4af2..7d12a88c 100644
--- a/libtiff/tiffio.h
+++ b/libtiff/tiffio.h
@@ -274,7 +274,7 @@ extern "C" {
#endif
typedef void (*TIFFErrorHandler)(const char*, const char*, va_list);
typedef void (*TIFFErrorHandlerExt)(thandle_t, const char*, const char*, va_list);
-typedef int (*TIFFErrorHandlerExtR)(thandle_t, const char*, const char*, va_list);
+typedef int (*TIFFErrorHandlerExtR)(TIFF*, void* user_data, const char*, const char*, va_list);
typedef tmsize_t (*TIFFReadWriteProc)(thandle_t, void*, tmsize_t);
typedef toff_t (*TIFFSeekProc)(thandle_t, toff_t, int);
typedef int (*TIFFCloseProc)(thandle_t);
@@ -460,28 +460,36 @@ extern TIFFErrorHandlerExt TIFFSetErrorHandlerExt(TIFFErrorHandlerExt);
extern TIFFErrorHandler TIFFSetWarningHandler(TIFFErrorHandler);
extern TIFFErrorHandlerExt TIFFSetWarningHandlerExt(TIFFErrorHandlerExt);
-extern void TIFFSetErrorHandlerExtR(TIFF*, TIFFErrorHandlerExtR);
-extern void TIFFSetWarningHandlerExtR(TIFF*, TIFFErrorHandlerExtR);
+extern void TIFFWarningExtR(TIFF*, const char*, const char*, ...) TIFF_ATTRIBUTE((__format__ (__printf__,3,4)));
+extern void TIFFErrorExtR(TIFF*, const char*, const char*, ...) TIFF_ATTRIBUTE((__format__ (__printf__,3,4)));
+
+typedef struct TIFFOpenOptions TIFFOpenOptions;
+extern TIFFOpenOptions* TIFFOpenOptionsAlloc(void);
+extern void TIFFOpenOptionsFree(TIFFOpenOptions*);
+extern void TIFFOpenOptionsSetErrorHandlerExtR(TIFFOpenOptions* opts, TIFFErrorHandlerExtR handler, void* errorhandler_user_data);
+extern void TIFFOpenOptionsSetWarningHandlerExtR(TIFFOpenOptions* opts, TIFFErrorHandlerExtR handler, void* warnhandler_user_data);
extern TIFF* TIFFOpen(const char*, const char*);
+extern TIFF* TIFFOpenExt(const char*, const char*, TIFFOpenOptions* opts);
# ifdef __WIN32__
extern TIFF* TIFFOpenW(const wchar_t*, const char*);
+extern TIFF* TIFFOpenWExt(const wchar_t*, const char*, TIFFOpenOptions* opts);
# endif /* __WIN32__ */
extern TIFF* TIFFFdOpen(int, const char*, const char*);
+extern TIFF* TIFFFdOpenExt(int, const char*, const char*, TIFFOpenOptions* opts);
extern TIFF* TIFFClientOpen(const char*, const char*,
thandle_t,
TIFFReadWriteProc, TIFFReadWriteProc,
TIFFSeekProc, TIFFCloseProc,
TIFFSizeProc,
TIFFMapFileProc, TIFFUnmapFileProc);
-extern TIFF* TIFFClientOpenEx(const char*, const char*,
- thandle_t,
- TIFFReadWriteProc, TIFFReadWriteProc,
- TIFFSeekProc, TIFFCloseProc,
- TIFFSizeProc,
- TIFFMapFileProc, TIFFUnmapFileProc,
- TIFFErrorHandlerExtR, TIFFErrorHandlerExtR);
-
+extern TIFF* TIFFClientOpenExt(const char*, const char*,
+ thandle_t,
+ TIFFReadWriteProc, TIFFReadWriteProc,
+ TIFFSeekProc, TIFFCloseProc,
+ TIFFSizeProc,
+ TIFFMapFileProc, TIFFUnmapFileProc,
+ TIFFOpenOptions* opts);
extern TIFFExtendProc TIFFSetTagExtender(TIFFExtendProc);
extern uint32_t TIFFComputeTile(TIFF* tif, uint32_t x, uint32_t y, uint32_t z, uint16_t s);
extern int TIFFCheckTile(TIFF* tif, uint32_t x, uint32_t y, uint32_t z, uint16_t s);
diff --git a/libtiff/tiffiop.h b/libtiff/tiffiop.h
index 1cca4f54..d52fc45f 100644
--- a/libtiff/tiffiop.h
+++ b/libtiff/tiffiop.h
@@ -199,7 +199,17 @@ struct tiff {
size_t tif_nfieldscompat;
/* Error handler support */
TIFFErrorHandlerExtR tif_errorhandler;
+ void* tif_errorhandler_user_data;
TIFFErrorHandlerExtR tif_warnhandler;
+ void* tif_warnhandler_user_data;
+};
+
+struct TIFFOpenOptions
+{
+ TIFFErrorHandlerExtR errorhandler; /* may be NULL */
+ void* errorhandler_user_data; /* may be NULL */
+ TIFFErrorHandlerExtR warnhandler; /* may be NULL */
+ void* warnhandler_user_data; /* may be NULL */
};
#define isPseudoTag(t) (t > 0xffff) /* is tag value normal or pseudo */
@@ -321,10 +331,7 @@ typedef size_t TIFFIOSize_t;
#if defined(__cplusplus)
extern "C" {
#endif
-extern void TIFFWarningExtR(TIFF*, const char*, const char*, ...) TIFF_ATTRIBUTE((__format__ (__printf__,3,4)));
-extern void TIFFErrorExtR(TIFF*, const char*, const char*, ...) TIFF_ATTRIBUTE((__format__ (__printf__,3,4)));
-
-extern int _TIFFgetMode(const char* mode, const char* module);
+extern int _TIFFgetMode(TIFFOpenOptions* opts, thandle_t clientdata, const char* mode, const char* module);
extern int _TIFFNoRowEncode(TIFF* tif, uint8_t* pp, tmsize_t cc, uint16_t s);
extern int _TIFFNoStripEncode(TIFF* tif, uint8_t* pp, tmsize_t cc, uint16_t s);
extern int _TIFFNoTileEncode(TIFF*, uint8_t* pp, tmsize_t cc, uint16_t s);
@@ -360,6 +367,7 @@ extern TIFFErrorHandler _TIFFwarningHandler;
extern TIFFErrorHandler _TIFFerrorHandler;
extern TIFFErrorHandlerExt _TIFFwarningHandlerExt;
extern TIFFErrorHandlerExt _TIFFerrorHandlerExt;
+void _TIFFErrorEarly(TIFFOpenOptions* opts, thandle_t clientdata, const char* module, const char* fmt, ...) TIFF_ATTRIBUTE((__format__ (__printf__,4,5)));
extern uint32_t _TIFFMultiply32(TIFF*, uint32_t, uint32_t, const char*);
extern uint64_t _TIFFMultiply64(TIFF*, uint64_t, uint64_t, const char*);
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 3554b214..d7c18584 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -175,6 +175,11 @@ target_sources(testtypes PRIVATE testtypes.c)
target_link_libraries(testtypes PRIVATE tiff tiff_port)
list(APPEND simple_tests testtypes)
+add_executable(test_error_handlers ../placeholder.h)
+target_sources(test_error_handlers PRIVATE test_error_handlers.c)
+target_link_libraries(test_error_handlers PRIVATE tiff tiff_port)
+list(APPEND simple_tests test_error_handlers)
+
if(WEBP_SUPPORT AND EMSCRIPTEN)
# Emscripten is pretty finnicky about linker flags.
# It needs --shared-memory if and only if atomics or bulk-memory is used.
diff --git a/test/Makefile.am b/test/Makefile.am
index 09a83065..bcb69a4f 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -75,7 +75,7 @@ endif
if TIFF_TESTS
check_PROGRAMS = \
ascii_tag long_tag short_tag strip_rw rewrite custom_dir custom_dir_EXIF_231 \
- defer_strile_loading defer_strile_writing test_directory \
+ defer_strile_loading defer_strile_writing test_directory test_error_handlers \
testtypes test_signed_tags $(JPEG_DEPENDENT_CHECK_PROG) $(STATIC_CHECK_PROGS)
endif
@@ -246,6 +246,8 @@ defer_strile_writing_SOURCES = defer_strile_writing.c
defer_strile_writing_LDADD = $(LIBTIFF)
test_directory_SOURCES = test_directory.c
test_directory_LDADD = $(LIBTIFF)
+test_error_handlers_SOURCES = test_error_handlers.c
+test_error_handlers_LDADD = $(LIBTIFF)
AM_CPPFLAGS = -I$(top_srcdir)/libtiff
diff --git a/test/test_error_handlers.c b/test/test_error_handlers.c
new file mode 100644
index 00000000..f0e8e3ea
--- /dev/null
+++ b/test/test_error_handlers.c
@@ -0,0 +1,140 @@
+/*
+ * Copyright (c) 2022, Even Rouault <even.rouault at spatialys.com>
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and
+ * its documentation for any purpose is hereby granted without fee, provided
+ * that (i) the above copyright notices and this permission notice appear in
+ * all copies of the software and related documentation, and (ii) the names of
+ * Sam Leffler and Silicon Graphics may not be used in any advertising or
+ * publicity relating to the software without the specific, prior written
+ * permission of Sam Leffler and Silicon Graphics.
+ *
+ * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
+ * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
+ * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
+ * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+ * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
+ * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+ * OF THIS SOFTWARE.
+ */
+
+/*
+ * TIFF Library
+ *
+ * Test error handlers
+ */
+
+#include "tif_config.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+
+#include "tiffio.h"
+
+#define ERROR_STRING_SIZE 1024
+
+typedef struct MyErrorHandlerUserDataStruct
+{
+ char* buffer;
+ size_t buffer_size;
+ TIFF* tif_got_from_callback;
+ char module[64];
+} MyErrorHandlerUserDataStruct;
+
+static int myErrorHandler(TIFF* tiff, void* user_data, const char* module, const char* fmt, va_list ap)
+{
+ MyErrorHandlerUserDataStruct* errorhandler_user_data = (MyErrorHandlerUserDataStruct*)user_data;
+ vsnprintf(errorhandler_user_data->buffer,
+ errorhandler_user_data->buffer_size,
+ fmt,
+ ap);
+ errorhandler_user_data->tif_got_from_callback = tiff;
+ snprintf(errorhandler_user_data->module, sizeof(errorhandler_user_data->module), "%s", module);
+ return 1;
+}
+
+int test_open_ext()
+{
+ int ret = 0;
+ char error_buffer[ERROR_STRING_SIZE] = {0};
+ char warn_buffer[ERROR_STRING_SIZE] = {0};
+ MyErrorHandlerUserDataStruct errorhandler_user_data =
+ {
+ .buffer = error_buffer,
+ .buffer_size = ERROR_STRING_SIZE
+ };
+ MyErrorHandlerUserDataStruct warnhandler_user_data =
+ {
+ .buffer = warn_buffer,
+ .buffer_size = ERROR_STRING_SIZE
+ };
+
+ TIFFOpenOptions* opts = TIFFOpenOptionsAlloc();
+ assert(opts);
+ TIFFOpenOptionsSetErrorHandlerExtR(opts, myErrorHandler, &errorhandler_user_data);
+ TIFFOpenOptionsSetWarningHandlerExtR(opts, myErrorHandler, &warnhandler_user_data);
+ TIFF* tif = TIFFOpenExt("test_error_handler.tif", "w", opts);
+ TIFFOpenOptionsFree(opts);
+
+ if( tif == NULL )
+ {
+ fprintf(stderr, "Cannot create test_error_handler.tif");
+ exit(1);
+ }
+
+ // Simulate an error emitted by libtiff
+ TIFFErrorExtR(tif, "my_error_module", "%s", "some error message");
+ if( strcmp(error_buffer, "some error message") != 0 )
+ {
+ fprintf(stderr, "Did not get expected error message\n");
+ ret = 1;
+ }
+ if( strcmp(errorhandler_user_data.module, "my_error_module") != 0 )
+ {
+ fprintf(stderr, "Did not get expected error module\n");
+ ret = 1;
+ }
+ if( errorhandler_user_data.tif_got_from_callback != tif)
+ {
+ fprintf(stderr, "errorhandler_user_data.tif_got_from_callback != tif\n");
+ ret = 1;
+ }
+
+ // Simulate a warning emitted by libtiff
+ TIFFWarningExtR(tif, "my_warning_module", "%s", "some warning message");
+ if( strcmp(warn_buffer, "some warning message") != 0 )
+ {
+ fprintf(stderr, "Did not get expected warning message\n");
+ ret = 1;
+ }
+ if( strcmp(warnhandler_user_data.module, "my_warning_module") != 0 )
+ {
+ fprintf(stderr, "Did not get expected warning module\n");
+ ret = 1;
+ }
+ if( warnhandler_user_data.tif_got_from_callback != tif)
+ {
+ fprintf(stderr, "warnhandler_user_data.tif_got_from_callback != tif\n");
+ ret = 1;
+ }
+
+ TIFFClose(tif);
+ unlink("test_error_handler.tif");
+ return ret;
+}
+
+int main()
+{
+ int ret = 0;
+ ret += test_open_ext(1);
+ return ret;
+}