]> git.saurik.com Git - wxWidgets.git/blob - src/tiff/contrib/mfs/mfs_file.c
fix bug with adding entries to a root group containing only subgroups (as shown by...
[wxWidgets.git] / src / tiff / 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