123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586 |
- /*
- --------------------------------------------------------------------------------
- - Module : mem_file.c
- - Description : A general purpose library for manipulating a memory area
- - as if it were a file.
- - mfs_ stands for memory file system.
- - Author : Mike Johnson - Banctec AB 03/07/96
- -
- --------------------------------------------------------------------------------
- */
- /*
- Copyright (c) 1996 Mike Johnson
- Copyright (c) 1996 BancTec AB
- Permission to use, copy, modify, distribute, and sell this software
- for any purpose is hereby granted without fee, provided
- that (i) the above copyright notices and this permission notice appear in
- all copies of the software and related documentation, and (ii) the names of
- Mike Johnson and BancTec may not be used in any advertising or
- publicity relating to the software.
- THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
- EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
- WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
- IN NO EVENT SHALL MIKE JOHNSON OR BANCTEC BE LIABLE FOR
- ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
- OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
- LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
- OF THIS SOFTWARE.
- */
- /*
- --------------------------------------------------------------------------------
- - Includes
- --------------------------------------------------------------------------------
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- /*
- --------------------------------------------------------------------------------
- - Definitions
- --------------------------------------------------------------------------------
- */
- #define MAX_BUFFS 20
- #define FALSE 0
- #define TRUE 1
- /*
- --------------------------------------------------------------------------------
- - Globals
- --------------------------------------------------------------------------------
- */
- static char *buf[MAX_BUFFS]; /* Memory for each open buf */
- static long buf_off[MAX_BUFFS]; /* File pointer for each buf */
- static long buf_size[MAX_BUFFS]; /* Count of bytes allocated for each buf */
- static long fds[MAX_BUFFS]; /* File descriptor status */
- static int buf_mode[MAX_BUFFS]; /* Mode of buffer (r, w, a) */
- static int library_init_done = FALSE;
- /*
- --------------------------------------------------------------------------------
- - Function prototypes
- --------------------------------------------------------------------------------
- */
- int mfs_open (void *ptr, int size, char *mode);
- int mfs_lseek (int fd, int offset, int whence);
- int mfs_read (int fd, void *buf, int size);
- int mfs_write (int fd, void *buf, int size);
- int mfs_size (int fd);
- int mfs_map (int fd, char **addr, size_t *len);
- int mfs_unmap (int fd);
- int mfs_close (int fd);
- static int extend_mem_file (int fd, int size);
- static void mem_init ();
- /*
- --------------------------------------------------------------------------------
- - Function code
- --------------------------------------------------------------------------------
- */
- /*
- --------------------------------------------------------------------------------
- - Function : mfs_open ()
- -
- - Arguments : Pointer to allocated buffer, initial size of buffer,
- - mode spec (r, w, a)
- -
- - Returns : File descriptor or -1 if error.
- -
- - Description : Register this area of memory (which has been allocated
- - and has a file read into it) under the mem_file library.
- - A file descriptor is returned which can the be passed
- - back to TIFFClientOpen and used as if it was a disk
- - based fd.
- - If the call is for mode 'w' then pass (void *)NULL as
- - the buffer and zero size and the library will
- - allocate memory for you.
- - If the mode is append then pass (void *)NULL and size
- - zero or with a valid address.
- -
- --------------------------------------------------------------------------------
- */
- int mfs_open (void *buffer, int size, char *mode)
- {
- int ret, i;
- void *tmp;
- if (library_init_done == FALSE)
- {
- mem_init ();
- library_init_done = TRUE;
- }
- ret = -1;
- /* Find a free fd */
- for (i = 0; i < MAX_BUFFS; i++)
- {
- if (fds[i] == -1)
- {
- ret = i;
- break;
- }
- }
- if (i == MAX_BUFFS) /* No more free descriptors */
- {
- ret = -1;
- errno = EMFILE;
- }
- if (ret >= 0 && *mode == 'r')
- {
- if (buffer == (void *)NULL)
- {
- ret = -1;
- errno = EINVAL;
- }
- else
- {
- buf[ret] = (char *)buffer;
- buf_size[ret] = size;
- buf_off[ret] = 0;
- }
- }
- else if (ret >= 0 && *mode == 'w')
- {
- if (buffer != (void *)NULL)
- {
- ret = -1;
- errno = EINVAL;
- }
- else
- {
- tmp = malloc (0); /* Get a pointer */
- if (tmp == (void *)NULL)
- {
- ret = -1;
- errno = EDQUOT;
- }
- else
- {
- buf[ret] = (char *)tmp;
- buf_size[ret] = 0;
- buf_off[ret] = 0;
- }
- }
- }
- else if (ret >= 0 && *mode == 'a')
- {
- if (buffer == (void *) NULL) /* Create space for client */
- {
- tmp = malloc (0); /* Get a pointer */
- if (tmp == (void *)NULL)
- {
- ret = -1;
- errno = EDQUOT;
- }
- else
- {
- buf[ret] = (char *)tmp;
- buf_size[ret] = 0;
- buf_off[ret] = 0;
- }
- }
- else /* Client has file read in already */
- {
- buf[ret] = (char *)buffer;
- buf_size[ret] = size;
- buf_off[ret] = 0;
- }
- }
- else /* Some other invalid combination of parameters */
- {
- ret = -1;
- errno = EINVAL;
- }
- if (ret != -1)
- {
- fds[ret] = 0;
- buf_mode[ret] = *mode;
- }
- return (ret);
- }
- /*
- --------------------------------------------------------------------------------
- - Function : mfs_lseek ()
- -
- - Arguments : File descriptor, offset, whence
- -
- - Returns : as per man lseek (2)
- -
- - Description : Does the same as lseek (2) except on a memory based file.
- - Note: the memory area will be extended if the caller
- - attempts to seek past the current end of file (memory).
- -
- --------------------------------------------------------------------------------
- */
- int mfs_lseek (int fd, int offset, int whence)
- {
- int ret;
- long test_off;
- if (fds[fd] == -1) /* Not open */
- {
- ret = -1;
- errno = EBADF;
- }
- else if (offset < 0 && whence == SEEK_SET)
- {
- ret = -1;
- errno = EINVAL;
- }
- else
- {
- switch (whence)
- {
- case SEEK_SET:
- if (offset > buf_size[fd])
- extend_mem_file (fd, offset);
- buf_off[fd] = offset;
- ret = offset;
- break;
- case SEEK_CUR:
- test_off = buf_off[fd] + offset;
- if (test_off < 0)
- {
- ret = -1;
- errno = EINVAL;
- }
- else
- {
- if (test_off > buf_size[fd])
- extend_mem_file (fd, test_off);
- buf_off[fd] = test_off;
- ret = test_off;
- }
- break;
- case SEEK_END:
- test_off = buf_size[fd] + offset;
- if (test_off < 0)
- {
- ret = -1;
- errno = EINVAL;
- }
- else
- {
- if (test_off > buf_size[fd])
- extend_mem_file (fd, test_off);
- buf_off[fd] = test_off;
- ret = test_off;
- }
- break;
- default:
- errno = EINVAL;
- ret = -1;
- break;
- }
- }
- return (ret);
- }
- /*
- --------------------------------------------------------------------------------
- - Function : mfs_read ()
- -
- - Arguments : File descriptor, buffer, size
- -
- - Returns : as per man read (2)
- -
- - Description : Does the same as read (2) except on a memory based file.
- - Note: An attempt to read past the end of memory currently
- - allocated to the file will return 0 (End Of File)
- -
- --------------------------------------------------------------------------------
- */
- int mfs_read (int fd, void *clnt_buf, int size)
- {
- int ret;
- if (fds[fd] == -1 || buf_mode[fd] != 'r')
- {
- /* File is either not open, or not opened for read */
- ret = -1;
- errno = EBADF;
- }
- else if (buf_off[fd] + size > buf_size[fd])
- {
- ret = 0; /* EOF */
- }
- else
- {
- memcpy (clnt_buf, (void *) (buf[fd] + buf_off[fd]), size);
- buf_off[fd] = buf_off[fd] + size;
- ret = size;
- }
- return (ret);
- }
- /*
- --------------------------------------------------------------------------------
- - Function : mfs_write ()
- -
- - Arguments : File descriptor, buffer, size
- -
- - Returns : as per man write (2)
- -
- - Description : Does the same as write (2) except on a memory based file.
- - Note: the memory area will be extended if the caller
- - attempts to write past the current end of file (memory).
- -
- --------------------------------------------------------------------------------
- */
- int mfs_write (int fd, void *clnt_buf, int size)
- {
- int ret;
- if (fds[fd] == -1 || buf_mode[fd] == 'r')
- {
- /* Either the file is not open or it is opened for reading only */
- ret = -1;
- errno = EBADF;
- }
- else if (buf_mode[fd] == 'w')
- {
- /* Write */
- if (buf_off[fd] + size > buf_size[fd])
- {
- extend_mem_file (fd, buf_off[fd] + size);
- buf_size[fd] = (buf_off[fd] + size);
- }
- memcpy ((buf[fd] + buf_off[fd]), clnt_buf, size);
- buf_off[fd] = buf_off[fd] + size;
- ret = size;
- }
- else
- {
- /* Append */
- if (buf_off[fd] != buf_size[fd])
- buf_off[fd] = buf_size[fd];
- extend_mem_file (fd, buf_off[fd] + size);
- buf_size[fd] += size;
- memcpy ((buf[fd] + buf_off[fd]), clnt_buf, size);
- buf_off[fd] = buf_off[fd] + size;
- ret = size;
- }
- return (ret);
- }
- /*
- --------------------------------------------------------------------------------
- - Function : mfs_size ()
- -
- - Arguments : File descriptor
- -
- - Returns : integer file size
- -
- - Description : This function returns the current size of the file in bytes.
- -
- --------------------------------------------------------------------------------
- */
- int mfs_size (int fd)
- {
- int ret;
- if (fds[fd] == -1) /* Not open */
- {
- ret = -1;
- errno = EBADF;
- }
- else
- ret = buf_size[fd];
- return (ret);
- }
- /*
- --------------------------------------------------------------------------------
- - Function : mfs_map ()
- -
- - Arguments : File descriptor, ptr to address, ptr to length
- -
- - Returns : Map status (succeeded or otherwise)
- -
- - Description : This function tells the client where the file is mapped
- - in memory and what size the mapped area is. It is provided
- - to satisfy the MapProc function in libtiff. It pretends
- - that the file has been mmap (2)ped.
- -
- --------------------------------------------------------------------------------
- */
- int mfs_map (int fd, char **addr, size_t *len)
- {
- int ret;
- if (fds[fd] == -1) /* Not open */
- {
- ret = -1;
- errno = EBADF;
- }
- else
- {
- *addr = buf[fd];
- *len = buf_size[fd];
- ret = 0;
- }
- return (ret);
- }
- /*
- --------------------------------------------------------------------------------
- - Function : mfs_unmap ()
- -
- - Arguments : File descriptor
- -
- - Returns : UnMap status (succeeded or otherwise)
- -
- - Description : This function does nothing as the file is always
- - in memory.
- -
- --------------------------------------------------------------------------------
- */
- int mfs_unmap (int fd)
- {
- return (0);
- }
- /*
- --------------------------------------------------------------------------------
- - Function : mfs_close ()
- -
- - Arguments : File descriptor
- -
- - Returns : close status (succeeded or otherwise)
- -
- - Description : Close the open memory file. (Make fd available again.)
- -
- --------------------------------------------------------------------------------
- */
- int mfs_close (int fd)
- {
- int ret;
- if (fds[fd] == -1) /* Not open */
- {
- ret = -1;
- errno = EBADF;
- }
- else
- {
- fds[fd] = -1;
- ret = 0;
- }
- return (ret);
- }
- /*
- --------------------------------------------------------------------------------
- - Function : extend_mem_file ()
- -
- - Arguments : File descriptor, length to extend to.
- -
- - Returns : 0 - All OK, -1 - realloc () failed.
- -
- - Description : Increase the amount of memory allocated to a file.
- -
- --------------------------------------------------------------------------------
- */
- static int extend_mem_file (int fd, int size)
- {
- void *new_mem;
- int ret;
- if ((new_mem = realloc (buf[fd], size)) == (void *) NULL)
- ret = -1;
- else
- {
- buf[fd] = (char *) new_mem;
- ret = 0;
- }
- return (ret);
- }
- /*
- --------------------------------------------------------------------------------
- - Function : mem_init ()
- -
- - Arguments : None
- -
- - Returns : void
- -
- - Description : Initialise the library.
- -
- --------------------------------------------------------------------------------
- */
- static void mem_init ()
- {
- int i;
- for (i = 0; i < MAX_BUFFS; i++)
- {
- fds[i] = -1;
- buf[i] = (char *)NULL;
- buf_size[i] = 0;
- buf_off[i] = 0;
- }
- }
- /*
- * Local Variables:
- * mode: c
- * c-basic-offset: 8
- * fill-column: 78
- * End:
- */
|