1 /* Id */
2 
3 /*
4  * Copyright (c) 1988-1997 Sam Leffler
5  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and
8  * its documentation for any purpose is hereby granted without fee, provided
9  * that (i) the above copyright notices and this permission notice appear in
10  * all copies of the software and related documentation, and (ii) the names of
11  * Sam Leffler and Silicon Graphics may not be used in any advertising or
12  * publicity relating to the software without the specific, prior written
13  * permission of Sam Leffler and Silicon Graphics.
14  *
15  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24  * OF THIS SOFTWARE.
25  */
26 
27 /*
28  * TIFF Library.
29  */
30 #include "tiffiop.h"
31 
32 static const long typemask[13] = {
33         (long)0L,               /* TIFF_NOTYPE */
34         (long)0x000000ffL,      /* TIFF_BYTE */
35         (long)0xffffffffL,      /* TIFF_ASCII */
36         (long)0x0000ffffL,      /* TIFF_SHORT */
37         (long)0xffffffffL,      /* TIFF_LONG */
38         (long)0xffffffffL,      /* TIFF_RATIONAL */
39         (long)0x000000ffL,      /* TIFF_SBYTE */
40         (long)0x000000ffL,      /* TIFF_UNDEFINED */
41         (long)0x0000ffffL,      /* TIFF_SSHORT */
42         (long)0xffffffffL,      /* TIFF_SLONG */
43         (long)0xffffffffL,      /* TIFF_SRATIONAL */
44         (long)0xffffffffL,      /* TIFF_FLOAT */
45         (long)0xffffffffL,      /* TIFF_DOUBLE */
46 };
47 static const int bigTypeshift[13] = {
48         0,              /* TIFF_NOTYPE */
49         24,             /* TIFF_BYTE */
50         0,              /* TIFF_ASCII */
51         16,             /* TIFF_SHORT */
52         0,              /* TIFF_LONG */
53         0,              /* TIFF_RATIONAL */
54         24,             /* TIFF_SBYTE */
55         24,             /* TIFF_UNDEFINED */
56         16,             /* TIFF_SSHORT */
57         0,              /* TIFF_SLONG */
58         0,              /* TIFF_SRATIONAL */
59         0,              /* TIFF_FLOAT */
60         0,              /* TIFF_DOUBLE */
61 };
62 static const int litTypeshift[13] = {
63         0,              /* TIFF_NOTYPE */
64         0,              /* TIFF_BYTE */
65         0,              /* TIFF_ASCII */
66         0,              /* TIFF_SHORT */
67         0,              /* TIFF_LONG */
68         0,              /* TIFF_RATIONAL */
69         0,              /* TIFF_SBYTE */
70         0,              /* TIFF_UNDEFINED */
71         0,              /* TIFF_SSHORT */
72         0,              /* TIFF_SLONG */
73         0,              /* TIFF_SRATIONAL */
74         0,              /* TIFF_FLOAT */
75         0,              /* TIFF_DOUBLE */
76 };
77 
78 /*
79  * Dummy functions to fill the omitted client procedures.
80  */
81 static int
_tiffDummyMapProc(thandle_t fd,tdata_t * pbase,toff_t * psize)82 _tiffDummyMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
83 {
84         (void) fd; (void) pbase; (void) psize;
85         return (0);
86 }
87 
88 static void
_tiffDummyUnmapProc(thandle_t fd,tdata_t base,toff_t size)89 _tiffDummyUnmapProc(thandle_t fd, tdata_t base, toff_t size)
90 {
91         (void) fd; (void) base; (void) size;
92 }
93 
94 /*
95  * Initialize the shift & mask tables, and the
96  * byte swapping state according to the file
97  * contents and the machine architecture.
98  */
99 static void
TIFFInitOrder(TIFF * tif,int magic)100 TIFFInitOrder(TIFF* tif, int magic)
101 {
102         tif->tif_typemask = typemask;
103         if (magic == TIFF_BIGENDIAN) {
104                 tif->tif_typeshift = bigTypeshift;
105 #ifndef WORDS_BIGENDIAN
106                 tif->tif_flags |= TIFF_SWAB;
107 #endif
108         } else {
109                 tif->tif_typeshift = litTypeshift;
110 #ifdef WORDS_BIGENDIAN
111                 tif->tif_flags |= TIFF_SWAB;
112 #endif
113         }
114 }
115 
116 int
_TIFFgetMode(const char * mode,const char * module)117 _TIFFgetMode(const char* mode, const char* module)
118 {
119         int m = -1;
120 
121         switch (mode[0]) {
122         case 'r':
123                 m = O_RDONLY;
124                 if (mode[1] == '+')
125                         m = O_RDWR;
126                 break;
127         case 'w':
128         case 'a':
129                 m = O_RDWR|O_CREAT;
130                 if (mode[0] == 'w')
131                         m |= O_TRUNC;
132                 break;
133         default:
134                 TIFFErrorExt(0, module, "\"%s\": Bad mode", mode);
135                 break;
136         }
137         return (m);
138 }
139 
140 TIFF*
141 TEXPORT
TIFFClientOpen(const char * name,const char * mode,thandle_t clientdata,TIFFReadWriteProc readproc,TIFFReadWriteProc writeproc,TIFFSeekProc seekproc,TIFFCloseProc closeproc,TIFFSizeProc sizeproc,TIFFMapFileProc mapproc,TIFFUnmapFileProc unmapproc)142 TIFFClientOpen(
143         const char* name, const char* mode,
144         thandle_t clientdata,
145         TIFFReadWriteProc readproc,
146         TIFFReadWriteProc writeproc,
147         TIFFSeekProc seekproc,
148         TIFFCloseProc closeproc,
149         TIFFSizeProc sizeproc,
150         TIFFMapFileProc mapproc,
151         TIFFUnmapFileProc unmapproc
152 )
153 {
154         static const char module[] = "TIFFClientOpen";
155         TIFF *tif;
156         int m;
157         const char* cp;
158 
159         m = _TIFFgetMode(mode, module);
160         if (m == -1)
161                 goto bad2;
162         tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + strlen(name) + 1);
163         if (tif == NULL) {
164                 TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name);
165                 goto bad2;
166         }
167         _TIFFmemset(tif, 0, sizeof (*tif));
168         tif->tif_name = (char *)tif + sizeof (TIFF);
169         strcpy(tif->tif_name, name);
170         tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
171         tif->tif_curdir = (tdir_t) -1;          /* non-existent directory */
172         tif->tif_curoff = 0;
173         tif->tif_curstrip = (tstrip_t) -1;      /* invalid strip */
174         tif->tif_row = (uint32) -1;             /* read/write pre-increment */
175         tif->tif_clientdata = clientdata;
176         if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
177                 TIFFErrorExt(clientdata, module,
178                           "One of the client procedures is NULL pointer.");
179                 goto bad2;
180         }
181         tif->tif_readproc = readproc;
182         tif->tif_writeproc = writeproc;
183         tif->tif_seekproc = seekproc;
184         tif->tif_closeproc = closeproc;
185         tif->tif_sizeproc = sizeproc;
186         if (mapproc)
187                 tif->tif_mapproc = mapproc;
188         else
189                 tif->tif_mapproc = _tiffDummyMapProc;
190         if (unmapproc)
191                 tif->tif_unmapproc = unmapproc;
192         else
193                 tif->tif_unmapproc = _tiffDummyUnmapProc;
194         _TIFFSetDefaultCompressionState(tif);   /* setup default state */
195         /*
196          * Default is to return data MSB2LSB and enable the
197          * use of memory-mapped files and strip chopping when
198          * a file is opened read-only.
199          */
200         tif->tif_flags = FILLORDER_MSB2LSB;
201         if (m == O_RDONLY )
202             tif->tif_flags |= TIFF_MAPPED;
203 
204 #ifdef STRIPCHOP_DEFAULT
205         if (m == O_RDONLY || m == O_RDWR)
206                 tif->tif_flags |= STRIPCHOP_DEFAULT;
207 #endif
208 
209         /*
210          * Process library-specific flags in the open mode string.
211          * The following flags may be used to control intrinsic library
212          * behaviour that may or may not be desirable (usually for
213          * compatibility with some application that claims to support
214          * TIFF but only supports some braindead idea of what the
215          * vendor thinks TIFF is):
216          *
217          * 'l'          use little-endian byte order for creating a file
218          * 'b'          use big-endian byte order for creating a file
219          * 'L'          read/write information using LSB2MSB bit order
220          * 'B'          read/write information using MSB2LSB bit order
221          * 'H'          read/write information using host bit order
222          * 'M'          enable use of memory-mapped files when supported
223          * 'm'          disable use of memory-mapped files
224          * 'C'          enable strip chopping support when reading
225          * 'c'          disable strip chopping support
226          * 'h'          read TIFF header only, do not load the first IFD
227          *
228          * The use of the 'l' and 'b' flags is strongly discouraged.
229          * These flags are provided solely because numerous vendors,
230          * typically on the PC, do not correctly support TIFF; they
231          * only support the Intel little-endian byte order.  This
232          * support is not configured by default because it supports
233          * the violation of the TIFF spec that says that readers *MUST*
234          * support both byte orders.  It is strongly recommended that
235          * you not use this feature except to deal with busted apps
236          * that write invalid TIFF.  And even in those cases you should
237          * bang on the vendors to fix their software.
238          *
239          * The 'L', 'B', and 'H' flags are intended for applications
240          * that can optimize operations on data by using a particular
241          * bit order.  By default the library returns data in MSB2LSB
242          * bit order for compatibiltiy with older versions of this
243          * library.  Returning data in the bit order of the native cpu
244          * makes the most sense but also requires applications to check
245          * the value of the FillOrder tag; something they probably do
246          * not do right now.
247          *
248          * The 'M' and 'm' flags are provided because some virtual memory
249          * systems exhibit poor behaviour when large images are mapped.
250          * These options permit clients to control the use of memory-mapped
251          * files on a per-file basis.
252          *
253          * The 'C' and 'c' flags are provided because the library support
254          * for chopping up large strips into multiple smaller strips is not
255          * application-transparent and as such can cause problems.  The 'c'
256          * option permits applications that only want to look at the tags,
257          * for example, to get the unadulterated TIFF tag information.
258          */
259         for (cp = mode; *cp; cp++)
260                 switch (*cp) {
261                 case 'b':
262 #ifndef WORDS_BIGENDIAN
263                     if (m&O_CREAT)
264                                 tif->tif_flags |= TIFF_SWAB;
265 #endif
266                         break;
267                 case 'l':
268 #ifdef WORDS_BIGENDIAN
269                         if ((m&O_CREAT))
270                                 tif->tif_flags |= TIFF_SWAB;
271 #endif
272                         break;
273                 case 'B':
274                         tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
275                             FILLORDER_MSB2LSB;
276                         break;
277                 case 'L':
278                         tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
279                             FILLORDER_LSB2MSB;
280                         break;
281                 case 'H':
282                         tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
283                             HOST_FILLORDER;
284                         break;
285                 case 'M':
286                         if (m == O_RDONLY)
287                                 tif->tif_flags |= TIFF_MAPPED;
288                         break;
289                 case 'm':
290                         if (m == O_RDONLY)
291                                 tif->tif_flags &= ~TIFF_MAPPED;
292                         break;
293                 case 'C':
294                         if (m == O_RDONLY)
295                                 tif->tif_flags |= TIFF_STRIPCHOP;
296                         break;
297                 case 'c':
298                         if (m == O_RDONLY)
299                                 tif->tif_flags &= ~TIFF_STRIPCHOP;
300                         break;
301                 case 'h':
302                         tif->tif_flags |= TIFF_HEADERONLY;
303                         break;
304                 }
305         /*
306          * Read in TIFF header.
307          */
308         if (tif->tif_mode & O_TRUNC ||
309             !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
310                 if (tif->tif_mode == O_RDONLY) {
311                         TIFFErrorExt(tif->tif_clientdata, name, "Cannot read TIFF header");
312                         goto bad;
313                 }
314                 /*
315                  * Setup header and write.
316                  */
317 #ifdef WORDS_BIGENDIAN
318                 tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
319                     ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN;
320 #else
321                 tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
322                     ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN;
323 #endif
324                 tif->tif_header.tiff_version = TIFF_VERSION;
325                 if (tif->tif_flags & TIFF_SWAB)
326                         TIFFSwabShort(&tif->tif_header.tiff_version);
327                 tif->tif_header.tiff_diroff = 0;        /* filled in later */
328 
329 
330                 /*
331                  * The doc for "fopen" for some STD_C_LIBs says that if you
332                  * open a file for modify ("+"), then you must fseek (or
333                  * fflush?) between any freads and fwrites.  This is not
334                  * necessary on most systems, but has been shown to be needed
335                  * on Solaris.
336                  */
337                 TIFFSeekFile( tif, 0, SEEK_SET );
338 
339                 if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
340                         TIFFErrorExt(tif->tif_clientdata, name, "Error writing TIFF header");
341                         goto bad;
342                 }
343                 /*
344                  * Setup the byte order handling.
345                  */
346                 TIFFInitOrder(tif, tif->tif_header.tiff_magic);
347                 /*
348                  * Setup default directory.
349                  */
350                 if (!TIFFDefaultDirectory(tif))
351                         goto bad;
352                 tif->tif_diroff = 0;
353                 tif->tif_dirlist = NULL;
354                 tif->tif_dirnumber = 0;
355                 return (tif);
356         }
357         /*
358          * Setup the byte order handling.
359          */
360         if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN &&
361             tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN
362 #if MDI_SUPPORT
363             &&
364 #if HOST_BIGENDIAN
365             tif->tif_header.tiff_magic != MDI_BIGENDIAN
366 #else
367             tif->tif_header.tiff_magic != MDI_LITTLEENDIAN
368 #endif
369             ) {
370                 TIFFErrorExt(tif->tif_clientdata, name,  "Not a TIFF or MDI file, bad magic number %d (0x%x)",
371 #else
372             ) {
373                 TIFFErrorExt(tif->tif_clientdata, name,  "Not a TIFF file, bad magic number %d (0x%x)",
374 #endif
375                     tif->tif_header.tiff_magic,
376                     tif->tif_header.tiff_magic);
377                 goto bad;
378         }
379         TIFFInitOrder(tif, tif->tif_header.tiff_magic);
380         /*
381          * Swap header if required.
382          */
383         if (tif->tif_flags & TIFF_SWAB) {
384                 TIFFSwabShort(&tif->tif_header.tiff_version);
385                 TIFFSwabLong(&tif->tif_header.tiff_diroff);
386         }
387         /*
388          * Now check version (if needed, it's been byte-swapped).
389          * Note that this isn't actually a version number, it's a
390          * magic number that doesn't change (stupid).
391          */
392         if (tif->tif_header.tiff_version == TIFF_BIGTIFF_VERSION) {
393                 TIFFErrorExt(tif->tif_clientdata, name,
394                           "This is a BigTIFF file.  This format not supported\n"
395                           "by this version of libtiff." );
396                 goto bad;
397         }
398         if (tif->tif_header.tiff_version != TIFF_VERSION) {
399                 TIFFErrorExt(tif->tif_clientdata, name,
400                     "Not a TIFF file, bad version number %d (0x%x)",
401                     tif->tif_header.tiff_version,
402                     tif->tif_header.tiff_version);
403                 goto bad;
404         }
405         tif->tif_flags |= TIFF_MYBUFFER;
406         tif->tif_rawcp = tif->tif_rawdata = 0;
407         tif->tif_rawdatasize = 0;
408 
409         /*
410          * Sometimes we do not want to read the first directory (for example,
411          * it may be broken) and want to proceed to other directories. I this
412          * case we use the TIFF_HEADERONLY flag to open file and return
413          * immediately after reading TIFF header.
414          */
415         if (tif->tif_flags & TIFF_HEADERONLY)
416                 return (tif);
417 
418         /*
419          * Setup initial directory.
420          */
421         switch (mode[0]) {
422         case 'r':
423                 tif->tif_nextdiroff = tif->tif_header.tiff_diroff;
424                 /*
425                  * Try to use a memory-mapped file if the client
426                  * has not explicitly suppressed usage with the
427                  * 'm' flag in the open mode (see above).
428                  */
429                 if ((tif->tif_flags & TIFF_MAPPED) &&
430         !TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size))
431                         tif->tif_flags &= ~TIFF_MAPPED;
432                 if (TIFFReadDirectory(tif)) {
433                         tif->tif_rawcc = -1;
434                         tif->tif_flags |= TIFF_BUFFERSETUP;
435                         return (tif);
436                 }
437                 break;
438         case 'a':
439                 /*
440                  * New directories are automatically append
441                  * to the end of the directory chain when they
442                  * are written out (see TIFFWriteDirectory).
443                  */
444                 if (!TIFFDefaultDirectory(tif))
445                         goto bad;
446                 return (tif);
447         }
448 bad:
449         tif->tif_mode = O_RDONLY;       /* XXX avoid flush */
450         TIFFCleanup(tif);
451 bad2:
452         return ((TIFF*)0);
453 }
454 
455 /*
456  * Query functions to access private data.
457  */
458 
459 /*
460  * Return open file's name.
461  */
462 const char *
463 TIFFFileName(TIFF* tif)
464 {
465         return (tif->tif_name);
466 }
467 
468 /*
469  * Set the file name.
470  */
471 const char *
472 TIFFSetFileName(TIFF* tif, const char *name)
473 {
474         const char* old_name = tif->tif_name;
475         tif->tif_name = (char *)name;
476         return (old_name);
477 }
478 
479 /*
480  * Return open file's I/O descriptor.
481  */
482 int
483 TIFFFileno(TIFF* tif)
484 {
485         return (tif->tif_fd);
486 }
487 
488 /*
489  * Set open file's I/O descriptor, and return previous value.
490  */
491 int
492 TIFFSetFileno(TIFF* tif, int fd)
493 {
494         int old_fd = tif->tif_fd;
495         tif->tif_fd = fd;
496         return old_fd;
497 }
498 
499 /*
500  * Return open file's clientdata.
501  */
502 thandle_t
503 TIFFClientdata(TIFF* tif)
504 {
505         return (tif->tif_clientdata);
506 }
507 
508 /*
509  * Set open file's clientdata, and return previous value.
510  */
511 thandle_t
512 TIFFSetClientdata(TIFF* tif, thandle_t newvalue)
513 {
514         thandle_t m = tif->tif_clientdata;
515         tif->tif_clientdata = newvalue;
516         return m;
517 }
518 
519 /*
520  * Return read/write mode.
521  */
522 int
523 TIFFGetMode(TIFF* tif)
524 {
525         return (tif->tif_mode);
526 }
527 
528 /*
529  * Return read/write mode.
530  */
531 int
532 TIFFSetMode(TIFF* tif, int mode)
533 {
534         int old_mode = tif->tif_mode;
535         tif->tif_mode = mode;
536         return (old_mode);
537 }
538 
539 /*
540  * Return nonzero if file is organized in
541  * tiles; zero if organized as strips.
542  */
543 int
544 TEXPORT
545 TIFFIsTiled(TIFF* tif)
546 {
547         return (isTiled(tif));
548 }
549 
550 /*
551  * Return current row being read/written.
552  */
553 uint32
554 TIFFCurrentRow(TIFF* tif)
555 {
556         return (tif->tif_row);
557 }
558 
559 /*
560  * Return index of the current directory.
561  */
562 tdir_t
563 TIFFCurrentDirectory(TIFF* tif)
564 {
565         return (tif->tif_curdir);
566 }
567 
568 /*
569  * Return current strip.
570  */
571 tstrip_t
572 TIFFCurrentStrip(TIFF* tif)
573 {
574         return (tif->tif_curstrip);
575 }
576 
577 /*
578  * Return current tile.
579  */
580 ttile_t
581 TIFFCurrentTile(TIFF* tif)
582 {
583         return (tif->tif_curtile);
584 }
585 
586 /*
587  * Return nonzero if the file has byte-swapped data.
588  */
589 int
590 TIFFIsByteSwapped(TIFF* tif)
591 {
592         return ((tif->tif_flags & TIFF_SWAB) != 0);
593 }
594 
595 /*
596  * Return nonzero if the data is returned up-sampled.
597  */
598 int
599 TIFFIsUpSampled(TIFF* tif)
600 {
601         return (isUpSampled(tif));
602 }
603 
604 /*
605  * Return nonzero if the data is returned in MSB-to-LSB bit order.
606  */
607 int
608 TIFFIsMSB2LSB(TIFF* tif)
609 {
610         return (isFillOrder(tif, FILLORDER_MSB2LSB));
611 }
612 
613 /*
614  * Return nonzero if given file was written in big-endian order.
615  */
616 int
617 TIFFIsBigEndian(TIFF* tif)
618 {
619         return (tif->tif_header.tiff_magic == TIFF_BIGENDIAN);
620 }
621 
622 /*
623  * Return pointer to file read method.
624  */
625 TIFFReadWriteProc
626 TIFFGetReadProc(TIFF* tif)
627 {
628         return (tif->tif_readproc);
629 }
630 
631 /*
632  * Return pointer to file write method.
633  */
634 TIFFReadWriteProc
635 TIFFGetWriteProc(TIFF* tif)
636 {
637         return (tif->tif_writeproc);
638 }
639 
640 /*
641  * Return pointer to file seek method.
642  */
643 TIFFSeekProc
644 TIFFGetSeekProc(TIFF* tif)
645 {
646         return (tif->tif_seekproc);
647 }
648 
649 /*
650  * Return pointer to file close method.
651  */
652 TIFFCloseProc
653 TIFFGetCloseProc(TIFF* tif)
654 {
655         return (tif->tif_closeproc);
656 }
657 
658 /*
659  * Return pointer to file size requesting method.
660  */
661 TIFFSizeProc
662 TIFFGetSizeProc(TIFF* tif)
663 {
664         return (tif->tif_sizeproc);
665 }
666 
667 /*
668  * Return pointer to memory mapping method.
669  */
670 TIFFMapFileProc
671 TIFFGetMapFileProc(TIFF* tif)
672 {
673         return (tif->tif_mapproc);
674 }
675 
676 /*
677  * Return pointer to memory unmapping method.
678  */
679 TIFFUnmapFileProc
680 TIFFGetUnmapFileProc(TIFF* tif)
681 {
682         return (tif->tif_unmapproc);
683 }
684 
685 /* vim: set ts=8 sts=8 sw=8 noet: */
686