]>
Commit | Line | Data |
---|---|---|
8414a40c VZ |
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 |