New comit of SDL2
[supertux.git] / src / SDL2 / external / tiff-4.0.3 / contrib / mfs / mfs_file.c
1 /*
2 --------------------------------------------------------------------------------
3 -   Module      :   mem_file.c
4 -   Description :   A general purpose library for manipulating a memory area
5 -                   as if it were a file.
6 -                   mfs_ stands for memory file system.
7 -   Author      :   Mike Johnson - Banctec AB 03/07/96
8 -                   
9 --------------------------------------------------------------------------------
10 */
11
12 /* 
13
14 Copyright (c) 1996 Mike Johnson
15 Copyright (c) 1996 BancTec AB
16
17 Permission to use, copy, modify, distribute, and sell this software
18 for any purpose is hereby granted without fee, provided
19 that (i) the above copyright notices and this permission notice appear in
20 all copies of the software and related documentation, and (ii) the names of
21 Mike Johnson and BancTec may not be used in any advertising or
22 publicity relating to the software.
23
24 THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
25 EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
26 WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
27
28 IN NO EVENT SHALL MIKE JOHNSON OR BANCTEC BE LIABLE FOR
29 ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
30 OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
31 WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
32 LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
33 OF THIS SOFTWARE.
34
35 */
36
37
38 /*
39 --------------------------------------------------------------------------------
40 -   Includes
41 --------------------------------------------------------------------------------
42 */
43
44 #include    <stdio.h>
45 #include    <stdlib.h>
46 #include    <string.h>
47
48 /*
49 --------------------------------------------------------------------------------
50 -   Definitions
51 --------------------------------------------------------------------------------
52 */
53
54 #define MAX_BUFFS   20
55 #define FALSE       0
56 #define TRUE        1
57
58 /*
59 --------------------------------------------------------------------------------
60 -   Globals
61 --------------------------------------------------------------------------------
62 */
63
64 static char *buf[MAX_BUFFS];        /* Memory for each open buf */
65 static long  buf_off[MAX_BUFFS];    /* File pointer for each buf */
66 static long  buf_size[MAX_BUFFS];   /* Count of bytes allocated for each buf */
67 static long  fds[MAX_BUFFS];        /* File descriptor status */
68 static int   buf_mode[MAX_BUFFS];   /* Mode of buffer (r, w, a) */
69
70 static int library_init_done = FALSE;
71
72
73 /*
74 --------------------------------------------------------------------------------
75 -   Function prototypes
76 --------------------------------------------------------------------------------
77 */
78
79 int mfs_open (void *ptr, int size, char *mode);
80 int mfs_lseek (int fd, int offset, int whence);
81 int mfs_read (int fd, void *buf, int size);
82 int mfs_write (int fd, void *buf, int size);
83 int mfs_size (int fd);
84 int mfs_map (int fd, char **addr, size_t *len);
85 int mfs_unmap (int fd);
86 int mfs_close (int fd);
87 static int extend_mem_file (int fd, int size);
88 static void mem_init ();
89
90 /*
91 --------------------------------------------------------------------------------
92 -   Function code
93 --------------------------------------------------------------------------------
94 */
95
96 /*
97 --------------------------------------------------------------------------------
98 -   Function    :   mfs_open ()
99 -
100 -   Arguments   :   Pointer to allocated buffer, initial size of buffer, 
101 -                   mode spec (r, w, a)
102 -
103 -   Returns     :   File descriptor or -1 if error.
104 -
105 -   Description :   Register this area of memory (which has been allocated
106 -                   and has a file read into it) under the mem_file library.
107 -                   A file descriptor is returned which can the be passed
108 -                   back to TIFFClientOpen and used as if it was a disk
109 -                   based fd.
110 -                   If the call is for mode 'w' then pass (void *)NULL as
111 -                   the buffer and zero size and the library will 
112 -                   allocate memory for you.
113 -                   If the mode is append then pass (void *)NULL and size
114 -                   zero or with a valid address.
115 -                   
116 --------------------------------------------------------------------------------
117 */
118
119 int mfs_open (void *buffer, int size, char *mode)
120 {
121     int ret, i;
122     void *tmp;
123
124     if (library_init_done == FALSE)
125     {
126         mem_init ();
127         library_init_done = TRUE;
128     }
129
130     ret = -1;
131
132     /* Find a free fd */
133
134     for (i = 0; i < MAX_BUFFS; i++)
135     {
136         if (fds[i] == -1)
137         {
138             ret = i;
139             break;
140         }
141     }
142
143     if (i == MAX_BUFFS)     /* No more free descriptors */
144     {
145         ret = -1;
146         errno = EMFILE;
147     }
148
149     if (ret >= 0 && *mode == 'r')
150     {
151         if (buffer == (void *)NULL)
152         {
153             ret = -1;
154             errno = EINVAL;
155         }
156         else
157         {
158             buf[ret] = (char *)buffer;
159             buf_size[ret] = size;
160             buf_off[ret] = 0;
161         }
162     }
163     else if (ret >= 0 && *mode == 'w')
164     {
165
166         if (buffer != (void *)NULL)
167         {
168             ret = -1;
169             errno = EINVAL;
170         }
171
172         else
173         {
174             tmp = malloc (0);   /* Get a pointer */
175             if (tmp == (void *)NULL)
176             {
177                 ret = -1;
178                 errno = EDQUOT;
179             }
180             else
181             {
182                 buf[ret] = (char *)tmp;
183                 buf_size[ret] = 0;
184                 buf_off[ret] = 0;
185             }
186         }
187     }
188     else if (ret >= 0 && *mode == 'a')
189     {
190         if (buffer == (void *) NULL)    /* Create space for client */
191         {
192             tmp = malloc (0);   /* Get a pointer */
193             if (tmp == (void *)NULL)
194             {
195                 ret = -1;
196                 errno = EDQUOT;
197             }
198             else
199             {
200                 buf[ret] = (char *)tmp;
201                 buf_size[ret] = 0;
202                 buf_off[ret] = 0;
203             }
204         }
205         else                            /* Client has file read in already */
206         {
207             buf[ret] = (char *)buffer;
208             buf_size[ret] = size;
209             buf_off[ret] = 0;
210         }
211     }
212     else        /* Some other invalid combination of parameters */
213     {
214         ret = -1;
215         errno = EINVAL;
216     }
217
218     if (ret != -1)
219     {
220         fds[ret] = 0;
221         buf_mode[ret] = *mode;
222     }
223
224     return (ret);
225 }
226
227 /*
228 --------------------------------------------------------------------------------
229 -   Function    :   mfs_lseek ()
230 -
231 -   Arguments   :   File descriptor, offset, whence
232 -
233 -   Returns     :   as per man lseek (2)
234 -
235 -   Description :   Does the same as lseek (2) except on a memory based file.
236 -                   Note: the memory area will be extended if the caller
237 -                   attempts to seek past the current end of file (memory).
238 -                   
239 --------------------------------------------------------------------------------
240 */
241
242 int mfs_lseek (int fd, int offset, int whence)
243 {
244     int ret;
245     long test_off;
246
247     if (fds[fd] == -1)  /* Not open */
248     {
249         ret = -1;
250         errno = EBADF;
251     }
252     else if (offset < 0 && whence == SEEK_SET)
253     {
254         ret = -1;
255         errno = EINVAL;
256     }
257     else
258     {
259         switch (whence)
260         {
261             case SEEK_SET:
262                 if (offset > buf_size[fd])
263                     extend_mem_file (fd, offset);
264                 buf_off[fd] = offset;
265                 ret = offset;
266                 break;
267
268             case SEEK_CUR:
269                 test_off = buf_off[fd] + offset;
270
271                 if (test_off < 0)
272                 {
273                     ret = -1;
274                     errno = EINVAL;
275                 }
276                 else
277                 {
278                     if (test_off > buf_size[fd])
279                         extend_mem_file (fd, test_off);
280                     buf_off[fd] = test_off;
281                     ret = test_off;
282                 }
283                 break;
284
285             case SEEK_END:
286                 test_off = buf_size[fd] + offset;
287
288                 if (test_off < 0)
289                 {
290                     ret = -1;
291                     errno = EINVAL;
292                 }
293                 else
294                 {
295                     if (test_off > buf_size[fd])
296                         extend_mem_file (fd, test_off);
297                     buf_off[fd] = test_off;
298                     ret = test_off;
299                 }
300                 break;
301
302             default:
303                 errno = EINVAL;
304                 ret = -1;
305                 break;
306         }
307     }
308
309     return (ret);
310 }   
311
312 /*
313 --------------------------------------------------------------------------------
314 -   Function    :   mfs_read ()
315 -
316 -   Arguments   :   File descriptor, buffer, size
317 -
318 -   Returns     :   as per man read (2)
319 -
320 -   Description :   Does the same as read (2) except on a memory based file.
321 -                   Note: An attempt to read past the end of memory currently
322 -                   allocated to the file will return 0 (End Of File)
323 -                   
324 --------------------------------------------------------------------------------
325 */
326
327 int mfs_read (int fd, void *clnt_buf, int size)
328 {
329     int ret;
330
331     if (fds[fd] == -1 || buf_mode[fd] != 'r')
332     {
333         /* File is either not open, or not opened for read */
334
335         ret = -1;
336         errno = EBADF;
337     }
338     else if (buf_off[fd] + size > buf_size[fd])
339     {
340         ret = 0;        /* EOF */
341     }
342     else
343     {
344         memcpy (clnt_buf, (void *) (buf[fd] + buf_off[fd]), size);
345         buf_off[fd] = buf_off[fd] + size;
346         ret = size;
347     }
348
349     return (ret);
350 }
351
352 /*
353 --------------------------------------------------------------------------------
354 -   Function    :   mfs_write ()
355 -
356 -   Arguments   :   File descriptor, buffer, size
357 -
358 -   Returns     :   as per man write (2)
359 -
360 -   Description :   Does the same as write (2) except on a memory based file.
361 -                   Note: the memory area will be extended if the caller
362 -                   attempts to write past the current end of file (memory).
363 -                   
364 --------------------------------------------------------------------------------
365 */
366
367 int mfs_write (int fd, void *clnt_buf, int size)
368 {
369     int ret;
370
371     if (fds[fd] == -1 || buf_mode[fd] == 'r')
372     {
373         /* Either the file is not open or it is opened for reading only */
374
375         ret = -1;
376         errno = EBADF;
377     }
378     else if (buf_mode[fd] == 'w')
379     {
380         /* Write */
381
382         if (buf_off[fd] + size > buf_size[fd])
383         {       
384             extend_mem_file (fd, buf_off[fd] + size);
385             buf_size[fd] = (buf_off[fd] + size);
386         }
387
388         memcpy ((buf[fd] + buf_off[fd]), clnt_buf, size);
389         buf_off[fd] = buf_off[fd] + size;
390
391         ret = size;
392     }
393     else
394     {
395         /* Append */
396
397         if (buf_off[fd] != buf_size[fd])
398             buf_off[fd] = buf_size[fd];
399
400         extend_mem_file (fd, buf_off[fd] + size);
401         buf_size[fd] += size;
402
403         memcpy ((buf[fd] + buf_off[fd]), clnt_buf, size);
404         buf_off[fd] = buf_off[fd] + size;
405
406         ret = size;
407     }
408
409     return (ret);
410 }
411
412 /*
413 --------------------------------------------------------------------------------
414 -   Function    :   mfs_size ()
415 -
416 -   Arguments   :   File descriptor
417 -
418 -   Returns     :   integer file size
419 -
420 -   Description :   This function returns the current size of the file in bytes.
421 -                   
422 --------------------------------------------------------------------------------
423 */
424
425 int mfs_size (int fd)
426 {
427     int ret;
428
429     if (fds[fd] == -1)  /* Not open */
430     {
431         ret = -1;
432         errno = EBADF;
433     }
434     else
435         ret = buf_size[fd];
436
437     return (ret);
438 }
439
440 /*
441 --------------------------------------------------------------------------------
442 -   Function    :   mfs_map ()
443 -
444 -   Arguments   :   File descriptor, ptr to address, ptr to length
445 -
446 -   Returns     :   Map status (succeeded or otherwise)
447 -
448 -   Description :   This function tells the client where the file is mapped
449 -                   in memory and what size the mapped area is. It is provided
450 -                   to satisfy the MapProc function in libtiff. It pretends
451 -                   that the file has been mmap (2)ped.
452 -                   
453 --------------------------------------------------------------------------------
454 */
455
456 int mfs_map (int fd, char **addr, size_t *len)
457 {
458     int ret; 
459
460     if (fds[fd] == -1)  /* Not open */
461     {
462         ret = -1;
463         errno = EBADF;
464     }
465     else
466     {
467         *addr = buf[fd];
468         *len = buf_size[fd];
469         ret = 0;
470     }
471
472     return (ret);
473 }
474
475 /*
476 --------------------------------------------------------------------------------
477 -   Function    :   mfs_unmap ()
478 -
479 -   Arguments   :   File descriptor
480 -
481 -   Returns     :   UnMap status (succeeded or otherwise)
482 -
483 -   Description :   This function does nothing as the file is always
484 -                   in memory.
485 -                   
486 --------------------------------------------------------------------------------
487 */
488
489 int mfs_unmap (int fd)
490 {
491     return (0);
492 }
493
494 /*
495 --------------------------------------------------------------------------------
496 -   Function    :   mfs_close ()
497 -
498 -   Arguments   :   File descriptor
499 -
500 -   Returns     :   close status (succeeded or otherwise)
501 -
502 -   Description :   Close the open memory file. (Make fd available again.)
503 -                   
504 --------------------------------------------------------------------------------
505 */
506
507 int mfs_close (int fd)
508 {
509     int ret; 
510
511     if (fds[fd] == -1)  /* Not open */
512     {
513         ret = -1;
514         errno = EBADF;
515     }
516     else
517     {
518         fds[fd] = -1;
519         ret = 0;
520     }
521
522     return (ret);
523 }
524
525 /*
526 --------------------------------------------------------------------------------
527 -   Function    :   extend_mem_file ()
528 -
529 -   Arguments   :   File descriptor, length to extend to.
530 -
531 -   Returns     :   0 - All OK, -1 - realloc () failed.
532 -
533 -   Description :   Increase the amount of memory allocated to a file.
534 -                   
535 --------------------------------------------------------------------------------
536 */
537
538 static int extend_mem_file (int fd, int size)
539 {
540     void *new_mem;
541     int ret;
542
543     if ((new_mem = realloc (buf[fd], size)) == (void *) NULL)
544         ret = -1;
545     else
546     {
547         buf[fd] = (char *) new_mem;
548         ret = 0;
549     }
550
551     return (ret);
552 }
553
554 /*
555 --------------------------------------------------------------------------------
556 -   Function    :   mem_init ()
557 -
558 -   Arguments   :   None
559 -
560 -   Returns     :   void
561 -
562 -   Description :   Initialise the library.
563 -                   
564 --------------------------------------------------------------------------------
565 */
566
567 static void mem_init ()
568 {
569     int i;
570
571     for (i = 0; i < MAX_BUFFS; i++)
572     {
573         fds[i] = -1;
574         buf[i] = (char *)NULL;
575         buf_size[i] = 0;
576         buf_off[i] = 0;
577     }
578 }
579
580 /*
581  * Local Variables:
582  * mode: c
583  * c-basic-offset: 8
584  * fill-column: 78
585  * End:
586  */