1 /* Read and write a vips file.
2 *
3 * 22/5/08
4 * - from im_open.c, im_openin.c, im_desc_hd.c, im_readhist.c,
5 * im_openout.c
6 * 19/3/09
7 * - block mmaps of nodata images
8 * 12/5/09
9 * - fix signed/unsigned warnings
10 * 12/10/09
11 * - heh argh reading history always stopped after the first line
12 * 9/12/09
13 * - only wholly map input files on im_incheck() ... this reduces VM use,
14 * especially with large numbers of small files
15 * 14/2/11
16 * - renamed to vips.c from im_open_vips.c, some stuff chopped out for
17 * image.c ... this file now just does read / write to disc
18 * 28/3/11
19 * - moved to vips_ namespace
20 * 25/2/17
21 * - use expat for xml read, printf for xml write
22 * 16/8/17
23 * - validate strs as being utf-8 before we write
24 * 9/4/18 Alexander--
25 * - use O_TMPFILE, if available
26 * 23/7/18
27 * - escape ASCII control characters in XML
28 * 29/8/19
29 * - verify bands/format for coded images
30 */
31
32 /*
33
34 This file is part of VIPS.
35
36 VIPS is free software; you can redistribute it and/or modify
37 it under the terms of the GNU Lesser General Public License as published by
38 the Free Software Foundation; either version 2 of the License, or
39 (at your option) any later version.
40
41 This program is distributed in the hope that it will be useful,
42 but WITHOUT ANY WARRANTY; without even the implied warranty of
43 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
44 GNU Lesser General Public License for more details.
45
46 You should have received a copy of the GNU Lesser General Public License
47 along with this program; if not, write to the Free Software
48 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
49 02110-1301 USA
50
51 */
52
53 /*
54
55 These files are distributed with VIPS - http://www.vips.ecs.soton.ac.uk
56
57 */
58
59 /*
60 #define SHOW_HEADER
61 #define DEBUG
62 */
63
64 /* Enable linux extensions like O_TMPFILE, if available.
65 */
66 #define _GNU_SOURCE
67
68 #ifdef HAVE_CONFIG_H
69 #include <config.h>
70 #endif /*HAVE_CONFIG_H*/
71 #include <vips/intl.h>
72
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76 #include <ctype.h>
77
78 #include <stdio.h>
79 #include <assert.h>
80 #include <stdlib.h>
81 #include <string.h>
82 #include <sys/types.h>
83 #include <sys/stat.h>
84 #include <fcntl.h>
85 #ifdef HAVE_SYS_FILE_H
86 #include <sys/file.h>
87 #endif /*HAVE_SYS_FILE_H*/
88 #ifdef HAVE_UNISTD_H
89 #include <unistd.h>
90 #endif /*HAVE_UNISTD_H*/
91 #ifdef HAVE_IO_H
92 #include <io.h>
93 #endif /*HAVE_IO_H*/
94 #include <expat.h>
95 #include <errno.h>
96
97 #include <vips/vips.h>
98
99 #ifdef G_OS_WIN32
100 #include <windows.h>
101 #endif /*G_OS_WIN32*/
102
103 #include <vips/debug.h>
104 #include <vips/internal.h>
105
106 /**
107 * SECTION: vips
108 * @short_description: startup, shutdown, version
109 * @stability: Stable
110 * @see_also: <link linkend="VipsOperation">VipsOperation</link>
111 * @include: vips/vips.h
112 *
113 * Start VIPS up, shut VIPS down, get version information, relocation.
114 *
115 * VIPS is a relocatable package, meaning you can move the directory tree you
116 * compiled it to at runtime and it will still be able to find all data files.
117 * This is required for OS X and Windows, but slightly unusual in the Unix
118 * world. See vips_init() and vips_guess_prefix().
119 */
120
121 /* Open mode for image write.
122 *
123 * We use O_RDWR not O_WRONLY since after writing we may want to rewind the
124 * image and read from it.
125 */
126 #define MODE_WRITE CLOEXEC (BINARYIZE (O_RDWR | O_CREAT | O_TRUNC))
127
128 /* Mode for read/write. This is if we might later want to mmaprw () the file.
129 */
130 #define MODE_READWRITE CLOEXEC (BINARYIZE (O_RDWR))
131
132 /* Mode for read only. This is the fallback if READWRITE fails.
133 */
134 #define MODE_READONLY CLOEXEC (BINARYIZE (O_RDONLY))
135
136 /* Our XML namespace.
137 */
138 #define NAMESPACE_URI "http://www.vips.ecs.soton.ac.uk/"
139
140 /* Open for read for image files.
141 */
142 int
vips__open_image_read(const char * filename)143 vips__open_image_read( const char *filename )
144 {
145 int fd;
146
147 /* Try to open read-write, so that calls to vips_image_inplace() will
148 * work. When we later mmap this file, we set read-only, so there
149 * is little danger of scrubbing over files we own.
150 */
151 fd = vips_tracked_open( filename, MODE_READWRITE, 0 );
152 if( fd == -1 )
153 /* Open read-write failed. Fall back to open read-only.
154 */
155 fd = vips_tracked_open( filename, MODE_READONLY, 0 );
156
157 if( fd == -1 ) {
158 vips_error_system( errno, "VipsImage",
159 _( "unable to open \"%s\"" ), filename );
160 return( -1 );
161 }
162
163 return( fd );
164 }
165
166 /* Open for write for image files.
167 */
168 int
vips__open_image_write(const char * filename,gboolean temp)169 vips__open_image_write( const char *filename, gboolean temp )
170 {
171 int flags;
172 int fd;
173
174 fd = -1;
175
176 #ifndef O_TMPFILE
177 if( temp )
178 g_info( "vips__open_image_write: O_TMPFILE not available" );
179 #endif /*!O_TMPFILE*/
180
181 #ifdef O_TMPFILE
182 /* Linux-only extension creates an unlinked file. CREAT and TRUNC must
183 * be clear. The filename arg to open() must name a directory.
184 *
185 * This can fail since not all filesystems support it. In this case,
186 * we open as a regular file and rely on the delete-on-close
187 * mechanism, see vips_image_delete().
188 */
189 if( temp ) {
190 char *dirname;
191
192 g_info( "vips__open_image_write: opening with O_TMPFILE" );
193 dirname = g_path_get_dirname( filename );
194 fd = vips_tracked_open( dirname, O_TMPFILE | O_RDWR , 0644 );
195 g_free( dirname );
196
197 if( fd < 0 )
198 g_info( "vips__open_image_write: O_TMPFILE failed!" );
199 }
200 #endif /*O_TMPFILE*/
201
202 flags = MODE_WRITE;
203
204 #ifdef _O_TEMPORARY
205 /* On Windows, setting _O_TEMPORARY will delete the file automatically
206 * on process exit, even if the processes crashes.
207 */
208 if( temp ) {
209 g_info( "vips__open_image_write: setting _O_TEMPORARY" );
210 flags |= _O_TEMPORARY;
211 }
212 #endif /*_O_TEMPORARY*/
213
214 if( fd < 0 ) {
215 g_info( "vips__open_image_write: simple open" );
216 fd = vips_tracked_open( filename, flags, 0644 );
217 }
218
219 if( fd < 0 ) {
220 g_info( "vips__open_image_write: failed!" );
221 vips_error_system( errno, "VipsImage",
222 _( "unable to write to \"%s\"" ), filename );
223 return( -1 );
224 }
225
226 return( fd );
227 }
228
229 /* Predict the size of the header plus pixel data. Don't use off_t,
230 * it's sometimes only 32 bits (eg. on many windows build environments) and we
231 * want to always be 64 bit.
232 */
233 static gint64
image_pixel_length(VipsImage * image)234 image_pixel_length( VipsImage *image )
235 {
236 gint64 psize;
237
238 switch( image->Coding ) {
239 case VIPS_CODING_LABQ:
240 case VIPS_CODING_RAD:
241 case VIPS_CODING_NONE:
242 psize = VIPS_IMAGE_SIZEOF_IMAGE( image );
243 break;
244
245 default:
246 psize = image->Length;
247 break;
248 }
249
250 return( psize + image->sizeof_header );
251 }
252
253 /* Copy 2 and 4 bytes, optionally swapping byte order.
254 */
255 void
vips__copy_4byte(int swap,unsigned char * to,unsigned char * from)256 vips__copy_4byte( int swap, unsigned char *to, unsigned char *from )
257 {
258 guint32 *in = (guint32 *) from;
259 guint32 *out = (guint32 *) to;
260
261 if( swap )
262 *out = GUINT32_SWAP_LE_BE( *in );
263 else
264 *out = *in;
265 }
266
267 void
vips__copy_2byte(gboolean swap,unsigned char * to,unsigned char * from)268 vips__copy_2byte( gboolean swap, unsigned char *to, unsigned char *from )
269 {
270 guint16 *in = (guint16 *) from;
271 guint16 *out = (guint16 *) to;
272
273 if( swap )
274 *out = GUINT16_SWAP_LE_BE( *in );
275 else
276 *out = *in;
277 }
278
279 guint32
vips__file_magic(const char * filename)280 vips__file_magic( const char *filename )
281 {
282 guint32 magic;
283
284 if( vips__get_bytes( filename, (unsigned char *) &magic, 4 ) == 4 &&
285 (magic == VIPS_MAGIC_INTEL ||
286 magic == VIPS_MAGIC_SPARC) )
287 return( magic );
288
289 return( 0 );
290 }
291
292 /* offset, read, write functions.
293 */
294 typedef struct _FieldIO {
295 glong offset;
296 int size;
297 void (*copy)( gboolean swap, unsigned char *to, unsigned char *from );
298 } FieldIO;
299
300 static FieldIO fields[] = {
301 { G_STRUCT_OFFSET( VipsImage, Xsize ), 4, vips__copy_4byte },
302 { G_STRUCT_OFFSET( VipsImage, Ysize ), 4, vips__copy_4byte },
303 { G_STRUCT_OFFSET( VipsImage, Bands ), 4, vips__copy_4byte },
304 { G_STRUCT_OFFSET( VipsImage, Bbits ), 4, vips__copy_4byte },
305 { G_STRUCT_OFFSET( VipsImage, BandFmt ), 4, vips__copy_4byte },
306 { G_STRUCT_OFFSET( VipsImage, Coding ), 4, vips__copy_4byte },
307 { G_STRUCT_OFFSET( VipsImage, Type ), 4, vips__copy_4byte },
308 { G_STRUCT_OFFSET( VipsImage, Xres_float ), 4, vips__copy_4byte },
309 { G_STRUCT_OFFSET( VipsImage, Yres_float ), 4, vips__copy_4byte },
310 { G_STRUCT_OFFSET( VipsImage, Length ), 4, vips__copy_4byte },
311 { G_STRUCT_OFFSET( VipsImage, Compression ), 2, vips__copy_2byte },
312 { G_STRUCT_OFFSET( VipsImage, Level ), 2, vips__copy_2byte },
313 { G_STRUCT_OFFSET( VipsImage, Xoffset ), 4, vips__copy_4byte },
314 { G_STRUCT_OFFSET( VipsImage, Yoffset ), 4, vips__copy_4byte }
315 };
316
317 int
vips__read_header_bytes(VipsImage * im,unsigned char * from)318 vips__read_header_bytes( VipsImage *im, unsigned char *from )
319 {
320 gboolean swap;
321 int i;
322 GEnumValue *value;
323
324 #ifdef SHOW_HEADER
325 printf( "vips__read_header_bytes: file bytes:\n" );
326 for( i = 0; i < im->sizeof_header; i++ )
327 printf( "%2d - 0x%02x\n", i, from[i] );
328 #endif /*SHOW_HEADER*/
329
330 /* The magic number is always written MSB first, we may need to swap.
331 */
332 vips__copy_4byte( !vips_amiMSBfirst(),
333 (unsigned char *) &im->magic, from );
334 from += 4;
335 if( im->magic != VIPS_MAGIC_INTEL &&
336 im->magic != VIPS_MAGIC_SPARC ) {
337 vips_error( "VipsImage",
338 _( "\"%s\" is not a VIPS image" ), im->filename );
339 return( -1 );
340 }
341
342 /* We need to swap for other fields if the file byte order is
343 * different from ours.
344 */
345 swap = vips_amiMSBfirst() != vips_image_isMSBfirst( im );
346
347 for( i = 0; i < VIPS_NUMBER( fields ); i++ ) {
348 fields[i].copy( swap,
349 &G_STRUCT_MEMBER( unsigned char, im, fields[i].offset ),
350 from );
351 from += fields[i].size;
352 }
353
354 /* Set this ourselves ... bbits is deprecated in the file format.
355 */
356 im->Bbits = vips_format_sizeof( im->BandFmt ) << 3;
357
358 /* We read xres/yres as floats to a staging area, then copy to double
359 * in the main fields.
360 */
361 im->Xres = im->Xres_float;
362 im->Yres = im->Yres_float;
363
364 /* Some protection against malicious files. We also check predicted
365 * (based on these values) against real file length, see below.
366 */
367 im->Xsize = VIPS_CLIP( 1, im->Xsize, VIPS_MAX_COORD );
368 im->Ysize = VIPS_CLIP( 1, im->Ysize, VIPS_MAX_COORD );
369 im->Bands = VIPS_CLIP( 1, im->Bands, VIPS_MAX_COORD );
370 im->BandFmt = VIPS_CLIP( 0, im->BandFmt, VIPS_FORMAT_LAST - 1 );
371
372 /* Coding and Type have missing values, so we look up in the enum.
373 */
374 value = g_enum_get_value( g_type_class_ref( VIPS_TYPE_INTERPRETATION ),
375 im->Type );
376 if( !value ||
377 strcmp( value->value_nick, "last" ) == 0 )
378 im->Type = VIPS_INTERPRETATION_ERROR;
379 value = g_enum_get_value( g_type_class_ref( VIPS_TYPE_CODING ),
380 im->Coding );
381 if( !value ||
382 strcmp( value->value_nick, "last" ) == 0 )
383 im->Coding = VIPS_CODING_ERROR;
384
385 /* Offset, Res, etc. don't affect vips file layout, just
386 * pixel interpretation, don't clip them.
387 */
388
389 /* Coding values imply Bands and BandFmt settings --- make sure they
390 * are sane.
391 */
392 switch( im->Coding ) {
393 case VIPS_CODING_ERROR:
394 vips_error( "VipsImage",
395 "%s", _( "unknown coding" ) );
396 return( -1 );
397
398 case VIPS_CODING_NONE:
399 break;
400
401 case VIPS_CODING_LABQ:
402 if( im->Bands != 4 ||
403 im->BandFmt != VIPS_FORMAT_UCHAR ) {
404 vips_error( "VipsImage",
405 "%s", _( "malformed LABQ image" ) );
406 return( -1 );
407 }
408 break;
409
410 case VIPS_CODING_RAD:
411 if( im->Bands != 4 ||
412 im->BandFmt != VIPS_FORMAT_UCHAR ) {
413 vips_error( "VipsImage",
414 "%s", _( "malformed RAD image" ) );
415 return( -1 );
416 }
417 break;
418
419 default:
420 g_assert_not_reached();
421 break;
422 }
423
424 return( 0 );
425 }
426
427 int
vips__write_header_bytes(VipsImage * im,unsigned char * to)428 vips__write_header_bytes( VipsImage *im, unsigned char *to )
429 {
430 /* Swap if the byte order we are asked to write the header in is
431 * different from ours.
432 */
433 gboolean swap = vips_amiMSBfirst() != vips_image_isMSBfirst( im );
434
435 int i;
436 unsigned char *q;
437
438 /* We set xres/yres as floats in a staging area, then copy those
439 * smaller values to the file.
440 */
441 im->Xres_float = im->Xres;
442 im->Yres_float = im->Yres;
443
444 /* Always write the magic number MSB first.
445 */
446 vips__copy_4byte( !vips_amiMSBfirst(),
447 to, (unsigned char *) &im->magic );
448 q = to + 4;
449
450 for( i = 0; i < VIPS_NUMBER( fields ); i++ ) {
451 fields[i].copy( swap,
452 q,
453 &G_STRUCT_MEMBER( unsigned char, im,
454 fields[i].offset ) );
455 q += fields[i].size;
456 }
457
458 /* Pad spares with zeros.
459 */
460 while( q - to < im->sizeof_header )
461 *q++ = 0;
462
463 #ifdef SHOW_HEADER
464 printf( "vips__write_header_bytes: file bytes:\n" );
465 for( i = 0; i < im->sizeof_header; i++ )
466 printf( "%2d - 0x%02x\n", i, to[i] );
467 #endif /*SHOW_HEADER*/
468
469 return( 0 );
470 }
471
472 /* Read a chunk of an fd into memory. Add a '\0' at the end.
473 */
474 static char *
read_chunk(int fd,gint64 offset,size_t length)475 read_chunk( int fd, gint64 offset, size_t length )
476 {
477 char *buf;
478
479 if( vips__seek( fd, offset, SEEK_SET ) == -1 )
480 return( NULL );
481 if( !(buf = vips_malloc( NULL, length + 1 )) )
482 return( NULL );
483 if( read( fd, buf, length ) != (ssize_t) length ) {
484 g_free( buf );
485 vips_error( "VipsImage", "%s", _( "unable to read history" ) );
486 return( NULL );
487 }
488 buf[length] = '\0';
489
490 return( buf );
491 }
492
493 /* Does it look like an image has an extension block?
494 */
495 int
vips__has_extension_block(VipsImage * im)496 vips__has_extension_block( VipsImage *im )
497 {
498 gint64 psize;
499
500 psize = image_pixel_length( im );
501 g_assert( im->file_length > 0 );
502
503 return( im->file_length - psize > 0 );
504 }
505
506 /* Read everything after the pixels into memory.
507 */
508 void *
vips__read_extension_block(VipsImage * im,int * size)509 vips__read_extension_block( VipsImage *im, int *size )
510 {
511 gint64 psize;
512 void *buf;
513
514 psize = image_pixel_length( im );
515 g_assert( im->file_length > 0 );
516 if( im->file_length - psize > 100 * 1024 * 1024 ) {
517 vips_error( "VipsImage",
518 "%s", _( "more than 100 megabytes of XML? "
519 "sufferin' succotash!" ) );
520 return( NULL );
521 }
522 if( im->file_length - psize == 0 )
523 return( NULL );
524 if( !(buf = read_chunk( im->fd, psize, im->file_length - psize )) )
525 return( NULL );
526 if( size )
527 *size = im->file_length - psize;
528
529 #ifdef DEBUG
530 printf( "vips__read_extension_block: read %d bytes from %s\n",
531 (int) (im->file_length - psize), im->filename );
532 printf( "data: \"%s\"\n", (char *) buf );
533 #endif /*DEBUG*/
534
535 return( buf );
536 }
537
538 static int
parser_read_fd(XML_Parser parser,int fd)539 parser_read_fd( XML_Parser parser, int fd )
540 {
541 const int chunk_size = 1024;
542
543 gint64 bytes_read;
544 gint64 len;
545
546 bytes_read = 0;
547
548 do {
549 void *buf;
550
551 if( !(buf = XML_GetBuffer( parser, chunk_size )) ) {
552 vips_error( "VipsImage",
553 "%s", _( "unable to allocate read buffer" ) );
554 return( -1 );
555 }
556 len = read( fd, buf, chunk_size );
557 if( len == -1 ) {
558 vips_error( "VipsImage",
559 "%s", _( "read error while fetching XML" ) );
560 return( -1 );
561 }
562
563 /* Allow missing XML block.
564 */
565 if( bytes_read == 0 &&
566 len == 0 )
567 break;
568 bytes_read += len;
569
570 if( !XML_ParseBuffer( parser, len, len == 0 ) ) {
571 vips_error( "VipsImage", "%s", _( "XML parse error" ) );
572 return( -1 );
573 }
574 } while( len > 0 );
575
576 return( 0 );
577 }
578
579 #define MAX_PARSE_ATTR (256)
580
581 /* What we track during expat parse.
582 */
583 typedef struct _VipsExpatParse {
584 VipsImage *image;
585
586 /* Set on error.
587 */
588 gboolean error;
589
590 /* TRUE for in header section.
591 */
592 gboolean header;
593
594 /* For the current node, the type and name.
595 */
596 XML_Char type[MAX_PARSE_ATTR];
597 XML_Char name[MAX_PARSE_ATTR];
598
599 /* Accumulate data here.
600 */
601 VipsDbuf dbuf;
602 } VipsExpatParse;
603
604 static void
parser_element_start_handler(void * user_data,const XML_Char * name,const XML_Char ** atts)605 parser_element_start_handler( void *user_data,
606 const XML_Char *name, const XML_Char **atts )
607 {
608 VipsExpatParse *vep = (VipsExpatParse *) user_data;
609 const XML_Char **p;
610
611 #ifdef DEBUG
612 printf( "parser_element_start: %s\n", name );
613 for( p = atts; *p; p += 2 )
614 printf( "%s = %s\n", p[0], p[1] );
615 #endif /*DEBUG*/
616
617 if( strcmp( name, "field" ) == 0 ) {
618 for( p = atts; *p; p += 2 ) {
619 if( strcmp( p[0], "name" ) == 0 )
620 vips_strncpy( vep->name, p[1], MAX_PARSE_ATTR );
621 if( strcmp( p[0], "type" ) == 0 )
622 vips_strncpy( vep->type, p[1], MAX_PARSE_ATTR );
623 }
624
625 vips_dbuf_reset( &vep->dbuf );
626 }
627 else if( strcmp( name, "header" ) == 0 )
628 vep->header = TRUE;
629 else if( strcmp( name, "meta" ) == 0 )
630 vep->header = FALSE;
631 else if( strcmp( name, "root" ) == 0 ) {
632 for( p = atts; *p; p += 2 )
633 if( strcmp( p[0], "xmlns" ) == 0 &&
634 !vips_isprefix( NAMESPACE_URI "vips", p[1] ) ) {
635 vips_error( "VipsImage", "%s",
636 _( "incorrect namespace in XML" ) );
637 vep->error = TRUE;
638 }
639 }
640 }
641
642 /* Chop history into lines, add each one as a refstring.
643 */
644 static void
set_history(VipsImage * im,char * history)645 set_history( VipsImage *im, char *history )
646 {
647 GSList *history_list;
648 char *p, *q;
649
650 /* There can be history there already if we're rewinding.
651 */
652 VIPS_FREEF( vips__gslist_gvalue_free, im->history_list );
653
654 history_list = NULL;
655
656 for( p = history; *p; p = q ) {
657 if( (q = strchr( p, '\n' )) ) {
658 *q = '\0';
659 q += 1;
660 }
661 else
662 q = p + strlen( p );
663
664 history_list = g_slist_prepend( history_list,
665 vips__gvalue_ref_string_new( p ) );
666 }
667
668 im->history_list = g_slist_reverse( history_list );
669 }
670
671 static int
set_meta(VipsImage * image,GType gtype,const char * name,const char * data)672 set_meta( VipsImage *image, GType gtype, const char *name, const char *data )
673 {
674 GValue save_value = { 0 };
675 GValue value = { 0 };
676
677 g_value_init( &save_value, VIPS_TYPE_SAVE_STRING );
678 vips_value_set_save_string( &save_value, data );
679
680 g_value_init( &value, gtype );
681 if( !g_value_transform( &save_value, &value ) ) {
682 g_value_unset( &save_value );
683 vips_error( "VipsImage", "%s",
684 _( "error transforming from save format" ) );
685 return( -1 );
686 }
687
688 vips_image_set( image, name, &value );
689 g_value_unset( &save_value );
690 g_value_unset( &value );
691
692 return( 0 );
693 }
694
695 static void
parser_element_end_handler(void * user_data,const XML_Char * name)696 parser_element_end_handler( void *user_data, const XML_Char *name )
697 {
698 VipsExpatParse *vep = (VipsExpatParse *) user_data;
699
700 #ifdef DEBUG
701 printf( "parser_element_end_handler: %s\n", name );
702 #endif /*DEBUG*/
703
704 if( strcmp( name, "field" ) == 0 ) {
705 if( vep->header ) {
706 if( strcmp( name, "Hist" ) == 0 )
707 set_history( vep->image,
708 (char *) vips_dbuf_string( &vep->dbuf,
709 NULL ) );
710 }
711 else {
712 GType gtype = g_type_from_name( vep->type );
713
714 /* Can we convert from VIPS_SAVE_STRING to type?
715 */
716 if( gtype &&
717 g_value_type_transformable(
718 VIPS_TYPE_SAVE_STRING, gtype ) &&
719 set_meta( vep->image,
720 gtype, vep->name,
721 (char *) vips_dbuf_string( &vep->dbuf,
722 NULL ) ) )
723 vep->error = TRUE;
724 }
725 }
726 }
727
728 static void
parser_data_handler(void * user_data,const XML_Char * data,int len)729 parser_data_handler( void *user_data, const XML_Char *data, int len )
730 {
731 VipsExpatParse *vep = (VipsExpatParse *) user_data;
732
733 #ifdef DEBUG
734 printf( "parser_data_handler: %d bytes\n", len );
735 #endif /*DEBUG*/
736
737 vips_dbuf_write( &vep->dbuf, (unsigned char *) data, len );
738 }
739
740 /* Called at the end of vips open ... get any XML after the pixel data
741 * and read it in.
742 */
743 static int
readhist(VipsImage * im)744 readhist( VipsImage *im )
745 {
746 XML_Parser parser;
747 VipsExpatParse vep;
748
749 if( vips__seek( im->fd, image_pixel_length( im ), SEEK_SET ) == -1 )
750 return( -1 );
751
752 parser = XML_ParserCreate( "UTF-8" );
753
754 vep.image = im;
755 vips_dbuf_init( &vep.dbuf );
756 vep.error = FALSE;
757 XML_SetUserData( parser, &vep );
758
759 XML_SetElementHandler( parser,
760 parser_element_start_handler, parser_element_end_handler );
761 XML_SetCharacterDataHandler( parser, parser_data_handler );
762
763 if( parser_read_fd( parser, im->fd ) ||
764 vep.error ) {
765 vips_dbuf_destroy( &vep.dbuf );
766 XML_ParserFree( parser );
767 return( -1 );
768 }
769
770 vips_dbuf_destroy( &vep.dbuf );
771 XML_ParserFree( parser );
772
773 return( 0 );
774 }
775
776 int
vips__write_extension_block(VipsImage * im,void * buf,int size)777 vips__write_extension_block( VipsImage *im, void *buf, int size )
778 {
779 gint64 length;
780 gint64 psize;
781
782 psize = image_pixel_length( im );
783 if( (length = vips_file_length( im->fd )) == -1 )
784 return( -1 );
785 if( length < psize ) {
786 vips_error( "VipsImage", "%s", _( "file has been truncated" ) );
787 return( -1 );
788 }
789
790 if( vips__ftruncate( im->fd, psize ) ||
791 vips__seek( im->fd, psize, SEEK_SET ) == -1 )
792 return( -1 );
793 if( vips__write( im->fd, buf, size ) )
794 return( -1 );
795
796 #ifdef DEBUG
797 printf( "vips__write_extension_block: written %d bytes of XML to %s\n",
798 size, im->filename );
799 #endif /*DEBUG*/
800
801 return( 0 );
802 }
803
804 /* Append a string to a buffer, but escape " as \".
805 */
806 static void
target_write_quotes(VipsTarget * target,const char * str)807 target_write_quotes( VipsTarget *target, const char *str )
808 {
809 const char *p;
810 size_t len;
811
812 for( p = str; *p; p += len ) {
813 len = strcspn( p, "\"" );
814
815 vips_target_write( target, (unsigned char *) p, len );
816 if( p[len] == '"' )
817 vips_target_writes( target, "\\" );
818 }
819 }
820
821 static void *
build_xml_meta(VipsMeta * meta,VipsTarget * target,void * b)822 build_xml_meta( VipsMeta *meta, VipsTarget *target, void *b )
823 {
824 GType type = G_VALUE_TYPE( &meta->value );
825
826 const char *str;
827
828 /* If we can transform to VIPS_TYPE_SAVE_STRING and back, we can save
829 * and restore.
830 */
831 if( g_value_type_transformable( type, VIPS_TYPE_SAVE_STRING ) &&
832 g_value_type_transformable( VIPS_TYPE_SAVE_STRING, type ) ) {
833 GValue save_value = { 0 };
834
835 g_value_init( &save_value, VIPS_TYPE_SAVE_STRING );
836 if( !g_value_transform( &meta->value, &save_value ) ) {
837 vips_error( "VipsImage", "%s",
838 _( "error transforming to save format" ) );
839 return( meta );
840 }
841
842 /* We need to validate the str to make sure we'll be able to
843 * read it back.
844 */
845 str = vips_value_get_save_string( &save_value );
846 if( g_utf8_validate( str, -1, NULL ) ) {
847 vips_target_writef( target,
848 " <field type=\"%s\" name=\"",
849 g_type_name( type ) );
850 target_write_quotes( target, meta->name );
851 vips_target_writes( target, "\">" );
852 vips_target_write_amp( target, str );
853 vips_target_writes( target, "</field>\n" );
854 }
855
856 g_value_unset( &save_value );
857 }
858
859 return( NULL );
860 }
861
862 /* Make the xml we append to vips images after the pixel data.
863 */
864 static char *
build_xml(VipsImage * image)865 build_xml( VipsImage *image )
866 {
867 VipsTarget *target;
868 const char *str;
869 char *result;
870
871 target = vips_target_new_to_memory();
872
873 vips_target_writef( target, "<?xml version=\"1.0\"?>\n" );
874 vips_target_writef( target, "<root xmlns=\"%svips/%d.%d.%d\">\n",
875 NAMESPACE_URI,
876 VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION, VIPS_MICRO_VERSION );
877 vips_target_writef( target, " <header>\n" );
878
879 str = vips_image_get_history( image );
880 if( g_utf8_validate( str, -1, NULL ) ) {
881 vips_target_writef( target,
882 " <field type=\"%s\" name=\"Hist\">",
883 g_type_name( VIPS_TYPE_REF_STRING ) );
884 vips_target_write_amp( target, str );
885 vips_target_writef( target, "</field>\n" );
886 }
887
888 vips_target_writef( target, " </header>\n" );
889 vips_target_writef( target, " <meta>\n" );
890
891 if( vips_slist_map2( image->meta_traverse,
892 (VipsSListMap2Fn) build_xml_meta, target, NULL ) ) {
893 VIPS_UNREF( target );
894 return( NULL );
895 }
896
897 vips_target_writef( target, " </meta>\n" );
898 vips_target_writef( target, "</root>\n" );
899
900 result = vips_target_steal_text( target );
901
902 VIPS_UNREF( target );
903
904 return( result );
905 }
906
907 static void *
vips__xml_properties_meta(VipsImage * image,const char * field,GValue * value,void * a)908 vips__xml_properties_meta( VipsImage *image,
909 const char *field, GValue *value, void *a )
910 {
911 VipsTarget *target = (VipsTarget *) a;
912 GType type = G_VALUE_TYPE( value );
913
914 const char *str;
915
916 /* If we can transform to VIPS_TYPE_SAVE_STRING and back, we can save
917 * and restore.
918 */
919 if( g_value_type_transformable( type, VIPS_TYPE_SAVE_STRING ) &&
920 g_value_type_transformable( VIPS_TYPE_SAVE_STRING, type ) ) {
921 GValue save_value = { 0 };
922
923 g_value_init( &save_value, VIPS_TYPE_SAVE_STRING );
924 if( !g_value_transform( value, &save_value ) ) {
925 vips_error( "VipsImage", "%s",
926 _( "error transforming to save format" ) );
927 return( target );
928 }
929 str = vips_value_get_save_string( &save_value );
930
931 vips_target_writef( target, " <property>\n" );
932 vips_target_writef( target, " <name>" );
933 vips_target_write_amp( target, field );
934 vips_target_writef( target, "</name>\n" );
935 vips_target_writef( target, " <value type=\"%s\">",
936 g_type_name( type ) );
937 vips_target_write_amp( target, str );
938 vips_target_writef( target, "</value>\n" );
939 vips_target_writef( target, " </property>\n" );
940
941 g_value_unset( &save_value );
942 }
943
944 return( NULL );
945 }
946
947 /* Make the xml we write to vips-properties in dzsave, or to TIFF. A simple
948 * dump of all vips metadata. Free with g_free().
949 */
950 char *
vips__xml_properties(VipsImage * image)951 vips__xml_properties( VipsImage *image )
952 {
953 VipsTarget *target;
954 char *date;
955 char *result;
956
957 date = vips__get_iso8601();
958
959 target = vips_target_new_to_memory();
960 vips_target_writef( target, "<?xml version=\"1.0\"?>\n" );
961 vips_target_writef( target, "<image xmlns=\"%s/dzsave\" "
962 "date=\"%s\" version=\"%d.%d.%d\">\n",
963 NAMESPACE_URI,
964 date,
965 VIPS_MAJOR_VERSION, VIPS_MINOR_VERSION, VIPS_MICRO_VERSION );
966 vips_target_writef( target, " <properties>\n" );
967
968 g_free( date );
969
970 if( vips_image_map( image, vips__xml_properties_meta, target ) ) {
971 VIPS_UNREF( target );
972 return( NULL );
973 }
974
975 vips_target_writef( target, " </properties>\n" );
976 vips_target_writef( target, "</image>\n" );
977
978 result = vips_target_steal_text( target );
979
980 VIPS_UNREF( target );
981
982 return( result );
983 }
984
985 /* Append XML to output fd.
986 */
987 int
vips__writehist(VipsImage * image)988 vips__writehist( VipsImage *image )
989 {
990 char *xml;
991
992 assert( image->dtype == VIPS_IMAGE_OPENOUT );
993 assert( image->fd != -1 );
994
995 if( !(xml = build_xml( image )) )
996 return( -1 );
997
998 if( vips__write_extension_block( image, xml, strlen( xml ) ) ) {
999 g_free( xml );
1000 return( -1 );
1001 }
1002
1003 #ifdef DEBUG
1004 printf( "vips__writehist: saved XML is: \"%s\"\n", xml );
1005 #endif /*DEBUG*/
1006
1007 g_free( xml );
1008
1009 return( 0 );
1010 }
1011
1012 /* Open the filename, read the header, some sanity checking.
1013 */
1014 int
vips_image_open_input(VipsImage * image)1015 vips_image_open_input( VipsImage *image )
1016 {
1017 /* We don't use im->sizeof_header here, but we know we're reading a
1018 * VIPS image anyway.
1019 */
1020 unsigned char header[VIPS_SIZEOF_HEADER];
1021
1022 gint64 psize;
1023 gint64 rsize;
1024
1025 image->dtype = VIPS_IMAGE_OPENIN;
1026
1027 /* We may have an fd already, see vips_image_rewind_output().
1028 */
1029 if( image->fd == -1 ) {
1030 image->fd = vips__open_image_read( image->filename );
1031 if( image->fd == -1 )
1032 return( -1 );
1033 }
1034
1035 vips__seek( image->fd, 0, SEEK_SET );
1036 if( read( image->fd, header, VIPS_SIZEOF_HEADER ) !=
1037 VIPS_SIZEOF_HEADER ||
1038 vips__read_header_bytes( image, header ) ) {
1039 vips_error_system( errno, "VipsImage",
1040 _( "unable to read header for \"%s\"" ),
1041 image->filename );
1042 return( -1 );
1043 }
1044
1045 /* Predict and check the file size. Only issue a warning, we want to be
1046 * able to read all the header fields we can, even if the actual data
1047 * isn't there.
1048 */
1049 psize = image_pixel_length( image );
1050 if( (rsize = vips_file_length( image->fd )) == -1 )
1051 return( -1 );
1052 image->file_length = rsize;
1053 if( psize > rsize )
1054 g_warning( _( "unable to read data for \"%s\", %s" ),
1055 image->filename, _( "file has been truncated" ) );
1056
1057 /* Set demand style. This suits a disc file we read sequentially.
1058 */
1059 image->dhint = VIPS_DEMAND_STYLE_THINSTRIP;
1060
1061 /* Set the history part of im descriptor. Don't return an error if this
1062 * fails (due to eg. corrupted XML) because it's probably mostly
1063 * harmless.
1064 */
1065 if( readhist( image ) ) {
1066 g_warning( _( "error reading vips image metadata: %s" ),
1067 vips_error_buffer() );
1068 vips_error_clear();
1069 }
1070
1071 return( 0 );
1072 }
1073
1074 int
vips_image_open_output(VipsImage * image)1075 vips_image_open_output( VipsImage *image )
1076 {
1077 if( image->fd == -1 ) {
1078 /* Don't use im->sizeof_header here, but we know we're
1079 * writing a VIPS image anyway.
1080 */
1081 unsigned char header[VIPS_SIZEOF_HEADER];
1082
1083 if( (image->fd = vips__open_image_write( image->filename,
1084 image->delete_on_close )) < 0 )
1085 return( -1 );
1086
1087 /* We always write in native mode, so we must overwrite the
1088 * magic we read from the file originally.
1089 */
1090 image->magic = vips_amiMSBfirst() ?
1091 VIPS_MAGIC_SPARC : VIPS_MAGIC_INTEL;
1092
1093 if( vips__write_header_bytes( image, header ) ||
1094 vips__write( image->fd, header, VIPS_SIZEOF_HEADER ) )
1095 return( -1 );
1096 }
1097
1098 return( 0 );
1099 }
1100