xref: /plan9/sys/src/cmd/gs/jpeg/jmemname.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
17dd7cddfSDavid du Colombier /*
27dd7cddfSDavid du Colombier  * jmemname.c
37dd7cddfSDavid du Colombier  *
4*593dc095SDavid du Colombier  * Copyright (C) 1992-1997, Thomas G. Lane.
57dd7cddfSDavid du Colombier  * This file is part of the Independent JPEG Group's software.
67dd7cddfSDavid du Colombier  * For conditions of distribution and use, see the accompanying README file.
77dd7cddfSDavid du Colombier  *
87dd7cddfSDavid du Colombier  * This file provides a generic implementation of the system-dependent
97dd7cddfSDavid du Colombier  * portion of the JPEG memory manager.  This implementation assumes that
107dd7cddfSDavid du Colombier  * you must explicitly construct a name for each temp file.
117dd7cddfSDavid du Colombier  * Also, the problem of determining the amount of memory available
127dd7cddfSDavid du Colombier  * is shoved onto the user.
137dd7cddfSDavid du Colombier  */
147dd7cddfSDavid du Colombier 
157dd7cddfSDavid du Colombier #define JPEG_INTERNALS
167dd7cddfSDavid du Colombier #include "jinclude.h"
177dd7cddfSDavid du Colombier #include "jpeglib.h"
187dd7cddfSDavid du Colombier #include "jmemsys.h"		/* import the system-dependent declarations */
197dd7cddfSDavid du Colombier 
207dd7cddfSDavid du Colombier #ifndef HAVE_STDLIB_H		/* <stdlib.h> should declare malloc(),free() */
217dd7cddfSDavid du Colombier extern void * malloc JPP((size_t size));
227dd7cddfSDavid du Colombier extern void free JPP((void *ptr));
237dd7cddfSDavid du Colombier #endif
247dd7cddfSDavid du Colombier 
257dd7cddfSDavid du Colombier #ifndef SEEK_SET		/* pre-ANSI systems may not define this; */
267dd7cddfSDavid du Colombier #define SEEK_SET  0		/* if not, assume 0 is correct */
277dd7cddfSDavid du Colombier #endif
287dd7cddfSDavid du Colombier 
297dd7cddfSDavid du Colombier #ifdef DONT_USE_B_MODE		/* define mode parameters for fopen() */
307dd7cddfSDavid du Colombier #define READ_BINARY	"r"
317dd7cddfSDavid du Colombier #define RW_BINARY	"w+"
327dd7cddfSDavid du Colombier #else
33*593dc095SDavid du Colombier #ifdef VMS			/* VMS is very nonstandard */
34*593dc095SDavid du Colombier #define READ_BINARY	"rb", "ctx=stm"
35*593dc095SDavid du Colombier #define RW_BINARY	"w+b", "ctx=stm"
36*593dc095SDavid du Colombier #else				/* standard ANSI-compliant case */
377dd7cddfSDavid du Colombier #define READ_BINARY	"rb"
387dd7cddfSDavid du Colombier #define RW_BINARY	"w+b"
397dd7cddfSDavid du Colombier #endif
40*593dc095SDavid du Colombier #endif
417dd7cddfSDavid du Colombier 
427dd7cddfSDavid du Colombier 
437dd7cddfSDavid du Colombier /*
447dd7cddfSDavid du Colombier  * Selection of a file name for a temporary file.
457dd7cddfSDavid du Colombier  * This is system-dependent!
467dd7cddfSDavid du Colombier  *
477dd7cddfSDavid du Colombier  * The code as given is suitable for most Unix systems, and it is easily
487dd7cddfSDavid du Colombier  * modified for most non-Unix systems.  Some notes:
497dd7cddfSDavid du Colombier  *  1.  The temp file is created in the directory named by TEMP_DIRECTORY.
507dd7cddfSDavid du Colombier  *      The default value is /usr/tmp, which is the conventional place for
517dd7cddfSDavid du Colombier  *      creating large temp files on Unix.  On other systems you'll probably
527dd7cddfSDavid du Colombier  *      want to change the file location.  You can do this by editing the
537dd7cddfSDavid du Colombier  *      #define, or (preferred) by defining TEMP_DIRECTORY in jconfig.h.
547dd7cddfSDavid du Colombier  *
557dd7cddfSDavid du Colombier  *  2.  If you need to change the file name as well as its location,
567dd7cddfSDavid du Colombier  *      you can override the TEMP_FILE_NAME macro.  (Note that this is
577dd7cddfSDavid du Colombier  *      actually a printf format string; it must contain %s and %d.)
587dd7cddfSDavid du Colombier  *      Few people should need to do this.
597dd7cddfSDavid du Colombier  *
607dd7cddfSDavid du Colombier  *  3.  mktemp() is used to ensure that multiple processes running
617dd7cddfSDavid du Colombier  *      simultaneously won't select the same file names.  If your system
627dd7cddfSDavid du Colombier  *      doesn't have mktemp(), define NO_MKTEMP to do it the hard way.
637dd7cddfSDavid du Colombier  *      (If you don't have <errno.h>, also define NO_ERRNO_H.)
647dd7cddfSDavid du Colombier  *
657dd7cddfSDavid du Colombier  *  4.  You probably want to define NEED_SIGNAL_CATCHER so that cjpeg.c/djpeg.c
667dd7cddfSDavid du Colombier  *      will cause the temp files to be removed if you stop the program early.
677dd7cddfSDavid du Colombier  */
687dd7cddfSDavid du Colombier 
697dd7cddfSDavid du Colombier #ifndef TEMP_DIRECTORY		/* can override from jconfig.h or Makefile */
707dd7cddfSDavid du Colombier #define TEMP_DIRECTORY  "/usr/tmp/" /* recommended setting for Unix */
717dd7cddfSDavid du Colombier #endif
727dd7cddfSDavid du Colombier 
737dd7cddfSDavid du Colombier static int next_file_num;	/* to distinguish among several temp files */
747dd7cddfSDavid du Colombier 
757dd7cddfSDavid du Colombier #ifdef NO_MKTEMP
767dd7cddfSDavid du Colombier 
777dd7cddfSDavid du Colombier #ifndef TEMP_FILE_NAME		/* can override from jconfig.h or Makefile */
787dd7cddfSDavid du Colombier #define TEMP_FILE_NAME  "%sJPG%03d.TMP"
797dd7cddfSDavid du Colombier #endif
807dd7cddfSDavid du Colombier 
817dd7cddfSDavid du Colombier #ifndef NO_ERRNO_H
827dd7cddfSDavid du Colombier #include <errno.h>		/* to define ENOENT */
837dd7cddfSDavid du Colombier #endif
847dd7cddfSDavid du Colombier 
857dd7cddfSDavid du Colombier /* ANSI C specifies that errno is a macro, but on older systems it's more
867dd7cddfSDavid du Colombier  * likely to be a plain int variable.  And not all versions of errno.h
877dd7cddfSDavid du Colombier  * bother to declare it, so we have to in order to be most portable.  Thus:
887dd7cddfSDavid du Colombier  */
897dd7cddfSDavid du Colombier #ifndef errno
907dd7cddfSDavid du Colombier extern int errno;
917dd7cddfSDavid du Colombier #endif
927dd7cddfSDavid du Colombier 
937dd7cddfSDavid du Colombier 
947dd7cddfSDavid du Colombier LOCAL(void)
select_file_name(char * fname)957dd7cddfSDavid du Colombier select_file_name (char * fname)
967dd7cddfSDavid du Colombier {
977dd7cddfSDavid du Colombier   FILE * tfile;
987dd7cddfSDavid du Colombier 
997dd7cddfSDavid du Colombier   /* Keep generating file names till we find one that's not in use */
1007dd7cddfSDavid du Colombier   for (;;) {
1017dd7cddfSDavid du Colombier     next_file_num++;		/* advance counter */
1027dd7cddfSDavid du Colombier     sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num);
1037dd7cddfSDavid du Colombier     if ((tfile = fopen(fname, READ_BINARY)) == NULL) {
1047dd7cddfSDavid du Colombier       /* fopen could have failed for a reason other than the file not
1057dd7cddfSDavid du Colombier        * being there; for example, file there but unreadable.
1067dd7cddfSDavid du Colombier        * If <errno.h> isn't available, then we cannot test the cause.
1077dd7cddfSDavid du Colombier        */
1087dd7cddfSDavid du Colombier #ifdef ENOENT
1097dd7cddfSDavid du Colombier       if (errno != ENOENT)
1107dd7cddfSDavid du Colombier 	continue;
1117dd7cddfSDavid du Colombier #endif
1127dd7cddfSDavid du Colombier       break;
1137dd7cddfSDavid du Colombier     }
1147dd7cddfSDavid du Colombier     fclose(tfile);		/* oops, it's there; close tfile & try again */
1157dd7cddfSDavid du Colombier   }
1167dd7cddfSDavid du Colombier }
1177dd7cddfSDavid du Colombier 
1187dd7cddfSDavid du Colombier #else /* ! NO_MKTEMP */
1197dd7cddfSDavid du Colombier 
1207dd7cddfSDavid du Colombier /* Note that mktemp() requires the initial filename to end in six X's */
1217dd7cddfSDavid du Colombier #ifndef TEMP_FILE_NAME		/* can override from jconfig.h or Makefile */
1227dd7cddfSDavid du Colombier #define TEMP_FILE_NAME  "%sJPG%dXXXXXX"
1237dd7cddfSDavid du Colombier #endif
1247dd7cddfSDavid du Colombier 
1257dd7cddfSDavid du Colombier LOCAL(void)
select_file_name(char * fname)1267dd7cddfSDavid du Colombier select_file_name (char * fname)
1277dd7cddfSDavid du Colombier {
1287dd7cddfSDavid du Colombier   next_file_num++;		/* advance counter */
1297dd7cddfSDavid du Colombier   sprintf(fname, TEMP_FILE_NAME, TEMP_DIRECTORY, next_file_num);
1307dd7cddfSDavid du Colombier   mktemp(fname);		/* make sure file name is unique */
1317dd7cddfSDavid du Colombier   /* mktemp replaces the trailing XXXXXX with a unique string of characters */
1327dd7cddfSDavid du Colombier }
1337dd7cddfSDavid du Colombier 
1347dd7cddfSDavid du Colombier #endif /* NO_MKTEMP */
1357dd7cddfSDavid du Colombier 
1367dd7cddfSDavid du Colombier 
1377dd7cddfSDavid du Colombier /*
1387dd7cddfSDavid du Colombier  * Memory allocation and freeing are controlled by the regular library
1397dd7cddfSDavid du Colombier  * routines malloc() and free().
1407dd7cddfSDavid du Colombier  */
1417dd7cddfSDavid du Colombier 
1427dd7cddfSDavid du Colombier GLOBAL(void *)
jpeg_get_small(j_common_ptr cinfo,size_t sizeofobject)1437dd7cddfSDavid du Colombier jpeg_get_small (j_common_ptr cinfo, size_t sizeofobject)
1447dd7cddfSDavid du Colombier {
1457dd7cddfSDavid du Colombier   return (void *) malloc(sizeofobject);
1467dd7cddfSDavid du Colombier }
1477dd7cddfSDavid du Colombier 
1487dd7cddfSDavid du Colombier GLOBAL(void)
jpeg_free_small(j_common_ptr cinfo,void * object,size_t sizeofobject)1497dd7cddfSDavid du Colombier jpeg_free_small (j_common_ptr cinfo, void * object, size_t sizeofobject)
1507dd7cddfSDavid du Colombier {
1517dd7cddfSDavid du Colombier   free(object);
1527dd7cddfSDavid du Colombier }
1537dd7cddfSDavid du Colombier 
1547dd7cddfSDavid du Colombier 
1557dd7cddfSDavid du Colombier /*
1567dd7cddfSDavid du Colombier  * "Large" objects are treated the same as "small" ones.
1577dd7cddfSDavid du Colombier  * NB: although we include FAR keywords in the routine declarations,
1587dd7cddfSDavid du Colombier  * this file won't actually work in 80x86 small/medium model; at least,
1597dd7cddfSDavid du Colombier  * you probably won't be able to process useful-size images in only 64KB.
1607dd7cddfSDavid du Colombier  */
1617dd7cddfSDavid du Colombier 
1627dd7cddfSDavid du Colombier GLOBAL(void FAR *)
jpeg_get_large(j_common_ptr cinfo,size_t sizeofobject)1637dd7cddfSDavid du Colombier jpeg_get_large (j_common_ptr cinfo, size_t sizeofobject)
1647dd7cddfSDavid du Colombier {
1657dd7cddfSDavid du Colombier   return (void FAR *) malloc(sizeofobject);
1667dd7cddfSDavid du Colombier }
1677dd7cddfSDavid du Colombier 
1687dd7cddfSDavid du Colombier GLOBAL(void)
jpeg_free_large(j_common_ptr cinfo,void FAR * object,size_t sizeofobject)1697dd7cddfSDavid du Colombier jpeg_free_large (j_common_ptr cinfo, void FAR * object, size_t sizeofobject)
1707dd7cddfSDavid du Colombier {
1717dd7cddfSDavid du Colombier   free(object);
1727dd7cddfSDavid du Colombier }
1737dd7cddfSDavid du Colombier 
1747dd7cddfSDavid du Colombier 
1757dd7cddfSDavid du Colombier /*
1767dd7cddfSDavid du Colombier  * This routine computes the total memory space available for allocation.
1777dd7cddfSDavid du Colombier  * It's impossible to do this in a portable way; our current solution is
1787dd7cddfSDavid du Colombier  * to make the user tell us (with a default value set at compile time).
1797dd7cddfSDavid du Colombier  * If you can actually get the available space, it's a good idea to subtract
1807dd7cddfSDavid du Colombier  * a slop factor of 5% or so.
1817dd7cddfSDavid du Colombier  */
1827dd7cddfSDavid du Colombier 
1837dd7cddfSDavid du Colombier #ifndef DEFAULT_MAX_MEM		/* so can override from makefile */
1847dd7cddfSDavid du Colombier #define DEFAULT_MAX_MEM		1000000L /* default: one megabyte */
1857dd7cddfSDavid du Colombier #endif
1867dd7cddfSDavid du Colombier 
1877dd7cddfSDavid du Colombier GLOBAL(long)
jpeg_mem_available(j_common_ptr cinfo,long min_bytes_needed,long max_bytes_needed,long already_allocated)1887dd7cddfSDavid du Colombier jpeg_mem_available (j_common_ptr cinfo, long min_bytes_needed,
1897dd7cddfSDavid du Colombier 		    long max_bytes_needed, long already_allocated)
1907dd7cddfSDavid du Colombier {
1917dd7cddfSDavid du Colombier   return cinfo->mem->max_memory_to_use - already_allocated;
1927dd7cddfSDavid du Colombier }
1937dd7cddfSDavid du Colombier 
1947dd7cddfSDavid du Colombier 
1957dd7cddfSDavid du Colombier /*
1967dd7cddfSDavid du Colombier  * Backing store (temporary file) management.
1977dd7cddfSDavid du Colombier  * Backing store objects are only used when the value returned by
1987dd7cddfSDavid du Colombier  * jpeg_mem_available is less than the total space needed.  You can dispense
1997dd7cddfSDavid du Colombier  * with these routines if you have plenty of virtual memory; see jmemnobs.c.
2007dd7cddfSDavid du Colombier  */
2017dd7cddfSDavid du Colombier 
2027dd7cddfSDavid du Colombier 
2037dd7cddfSDavid du Colombier METHODDEF(void)
read_backing_store(j_common_ptr cinfo,backing_store_ptr info,void FAR * buffer_address,long file_offset,long byte_count)2047dd7cddfSDavid du Colombier read_backing_store (j_common_ptr cinfo, backing_store_ptr info,
2057dd7cddfSDavid du Colombier 		    void FAR * buffer_address,
2067dd7cddfSDavid du Colombier 		    long file_offset, long byte_count)
2077dd7cddfSDavid du Colombier {
2087dd7cddfSDavid du Colombier   if (fseek(info->temp_file, file_offset, SEEK_SET))
2097dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_TFILE_SEEK);
2107dd7cddfSDavid du Colombier   if (JFREAD(info->temp_file, buffer_address, byte_count)
2117dd7cddfSDavid du Colombier       != (size_t) byte_count)
2127dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_TFILE_READ);
2137dd7cddfSDavid du Colombier }
2147dd7cddfSDavid du Colombier 
2157dd7cddfSDavid du Colombier 
2167dd7cddfSDavid du Colombier METHODDEF(void)
write_backing_store(j_common_ptr cinfo,backing_store_ptr info,void FAR * buffer_address,long file_offset,long byte_count)2177dd7cddfSDavid du Colombier write_backing_store (j_common_ptr cinfo, backing_store_ptr info,
2187dd7cddfSDavid du Colombier 		     void FAR * buffer_address,
2197dd7cddfSDavid du Colombier 		     long file_offset, long byte_count)
2207dd7cddfSDavid du Colombier {
2217dd7cddfSDavid du Colombier   if (fseek(info->temp_file, file_offset, SEEK_SET))
2227dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_TFILE_SEEK);
2237dd7cddfSDavid du Colombier   if (JFWRITE(info->temp_file, buffer_address, byte_count)
2247dd7cddfSDavid du Colombier       != (size_t) byte_count)
2257dd7cddfSDavid du Colombier     ERREXIT(cinfo, JERR_TFILE_WRITE);
2267dd7cddfSDavid du Colombier }
2277dd7cddfSDavid du Colombier 
2287dd7cddfSDavid du Colombier 
2297dd7cddfSDavid du Colombier METHODDEF(void)
close_backing_store(j_common_ptr cinfo,backing_store_ptr info)2307dd7cddfSDavid du Colombier close_backing_store (j_common_ptr cinfo, backing_store_ptr info)
2317dd7cddfSDavid du Colombier {
2327dd7cddfSDavid du Colombier   fclose(info->temp_file);	/* close the file */
2337dd7cddfSDavid du Colombier   unlink(info->temp_name);	/* delete the file */
2347dd7cddfSDavid du Colombier /* If your system doesn't have unlink(), use remove() instead.
2357dd7cddfSDavid du Colombier  * remove() is the ANSI-standard name for this function, but if
2367dd7cddfSDavid du Colombier  * your system was ANSI you'd be using jmemansi.c, right?
2377dd7cddfSDavid du Colombier  */
2387dd7cddfSDavid du Colombier   TRACEMSS(cinfo, 1, JTRC_TFILE_CLOSE, info->temp_name);
2397dd7cddfSDavid du Colombier }
2407dd7cddfSDavid du Colombier 
2417dd7cddfSDavid du Colombier 
2427dd7cddfSDavid du Colombier /*
2437dd7cddfSDavid du Colombier  * Initial opening of a backing-store object.
2447dd7cddfSDavid du Colombier  */
2457dd7cddfSDavid du Colombier 
2467dd7cddfSDavid du Colombier GLOBAL(void)
jpeg_open_backing_store(j_common_ptr cinfo,backing_store_ptr info,long total_bytes_needed)2477dd7cddfSDavid du Colombier jpeg_open_backing_store (j_common_ptr cinfo, backing_store_ptr info,
2487dd7cddfSDavid du Colombier 			 long total_bytes_needed)
2497dd7cddfSDavid du Colombier {
2507dd7cddfSDavid du Colombier   select_file_name(info->temp_name);
2517dd7cddfSDavid du Colombier   if ((info->temp_file = fopen(info->temp_name, RW_BINARY)) == NULL)
2527dd7cddfSDavid du Colombier     ERREXITS(cinfo, JERR_TFILE_CREATE, info->temp_name);
2537dd7cddfSDavid du Colombier   info->read_backing_store = read_backing_store;
2547dd7cddfSDavid du Colombier   info->write_backing_store = write_backing_store;
2557dd7cddfSDavid du Colombier   info->close_backing_store = close_backing_store;
2567dd7cddfSDavid du Colombier   TRACEMSS(cinfo, 1, JTRC_TFILE_OPEN, info->temp_name);
2577dd7cddfSDavid du Colombier }
2587dd7cddfSDavid du Colombier 
2597dd7cddfSDavid du Colombier 
2607dd7cddfSDavid du Colombier /*
2617dd7cddfSDavid du Colombier  * These routines take care of any system-dependent initialization and
2627dd7cddfSDavid du Colombier  * cleanup required.
2637dd7cddfSDavid du Colombier  */
2647dd7cddfSDavid du Colombier 
2657dd7cddfSDavid du Colombier GLOBAL(long)
jpeg_mem_init(j_common_ptr cinfo)2667dd7cddfSDavid du Colombier jpeg_mem_init (j_common_ptr cinfo)
2677dd7cddfSDavid du Colombier {
2687dd7cddfSDavid du Colombier   next_file_num = 0;		/* initialize temp file name generator */
2697dd7cddfSDavid du Colombier   return DEFAULT_MAX_MEM;	/* default for max_memory_to_use */
2707dd7cddfSDavid du Colombier }
2717dd7cddfSDavid du Colombier 
2727dd7cddfSDavid du Colombier GLOBAL(void)
jpeg_mem_term(j_common_ptr cinfo)2737dd7cddfSDavid du Colombier jpeg_mem_term (j_common_ptr cinfo)
2747dd7cddfSDavid du Colombier {
2757dd7cddfSDavid du Colombier   /* no work */
2767dd7cddfSDavid du Colombier }
277