xref: /plan9/sys/src/cmd/gs/src/gxclfile.c (revision 593dc095aefb2a85c828727bbfa9da139a49bdf4)
1 /* Copyright (C) 1995, 1997, 1998 Aladdin Enterprises.  All rights reserved.
2 
3   This software is provided AS-IS with no warranty, either express or
4   implied.
5 
6   This software is distributed under license and may not be copied,
7   modified or distributed except as expressly authorized under the terms
8   of the license contained in the file LICENSE in this distribution.
9 
10   For more information about licensing, please refer to
11   http://www.ghostscript.com/licensing/. For information on
12   commercial licensing, go to http://www.artifex.com/licensing/ or
13   contact Artifex Software, Inc., 101 Lucas Valley Road #110,
14   San Rafael, CA  94903, U.S.A., +1(415)492-9861.
15 */
16 
17 /* $Id: gxclfile.c,v 1.5 2002/02/21 22:24:53 giles Exp $ */
18 /* File-based command list implementation */
19 #include "stdio_.h"
20 #include "string_.h"
21 #include "unistd_.h"
22 #include "gserror.h"
23 #include "gserrors.h"
24 #include "gsmemory.h"
25 #include "gp.h"
26 #include "gxclio.h"
27 
28 /* This is an implementation of the command list I/O interface */
29 /* that uses the file system for storage. */
30 
31 /* ------ Open/close/unlink ------ */
32 
33 int
clist_fopen(char fname[gp_file_name_sizeof],const char * fmode,clist_file_ptr * pcf,gs_memory_t * mem,gs_memory_t * data_mem,bool ok_to_compress)34 clist_fopen(char fname[gp_file_name_sizeof], const char *fmode,
35 	    clist_file_ptr * pcf, gs_memory_t * mem, gs_memory_t *data_mem,
36 	    bool ok_to_compress)
37 {
38     if (*fname == 0) {
39 	if (fmode[0] == 'r')
40 	    return_error(gs_error_invalidfileaccess);
41 	*pcf =
42 	    (clist_file_ptr) gp_open_scratch_file(gp_scratch_file_name_prefix,
43 						  fname, fmode);
44     } else
45 	*pcf = gp_fopen(fname, fmode);
46     if (*pcf == NULL) {
47 	eprintf1("Could not open the scratch file %s.\n", fname);
48 	return_error(gs_error_invalidfileaccess);
49     }
50     return 0;
51 }
52 
53 int
clist_fclose(clist_file_ptr cf,const char * fname,bool delete)54 clist_fclose(clist_file_ptr cf, const char *fname, bool delete)
55 {
56     return (fclose((FILE *) cf) != 0 ? gs_note_error(gs_error_ioerror) :
57 	    delete ? clist_unlink(fname) :
58 	    0);
59 }
60 
61 int
clist_unlink(const char * fname)62 clist_unlink(const char *fname)
63 {
64     return (unlink(fname) != 0 ? gs_note_error(gs_error_ioerror) : 0);
65 }
66 
67 /* ------ Writing ------ */
68 
69 long
clist_space_available(long requested)70 clist_space_available(long requested)
71 {
72     return requested;
73 }
74 
75 int
clist_fwrite_chars(const void * data,uint len,clist_file_ptr cf)76 clist_fwrite_chars(const void *data, uint len, clist_file_ptr cf)
77 {
78     return fwrite(data, 1, len, (FILE *) cf);
79 }
80 
81 /* ------ Reading ------ */
82 
83 int
clist_fread_chars(void * data,uint len,clist_file_ptr cf)84 clist_fread_chars(void *data, uint len, clist_file_ptr cf)
85 {
86     FILE *f = (FILE *) cf;
87     byte *str = data;
88 
89     /* The typical implementation of fread */
90     /* is extremely inefficient for small counts, */
91     /* so we just use straight-line code instead. */
92     switch (len) {
93 	default:
94 	    return fread(str, 1, len, f);
95 	case 8:
96 	    *str++ = (byte) getc(f);
97 	case 7:
98 	    *str++ = (byte) getc(f);
99 	case 6:
100 	    *str++ = (byte) getc(f);
101 	case 5:
102 	    *str++ = (byte) getc(f);
103 	case 4:
104 	    *str++ = (byte) getc(f);
105 	case 3:
106 	    *str++ = (byte) getc(f);
107 	case 2:
108 	    *str++ = (byte) getc(f);
109 	case 1:
110 	    *str = (byte) getc(f);
111     }
112     return len;
113 }
114 
115 /* ------ Position/status ------ */
116 
117 int
clist_set_memory_warning(clist_file_ptr cf,int bytes_left)118 clist_set_memory_warning(clist_file_ptr cf, int bytes_left)
119 {
120     return 0;			/* no-op */
121 }
122 
123 int
clist_ferror_code(clist_file_ptr cf)124 clist_ferror_code(clist_file_ptr cf)
125 {
126     return (ferror((FILE *) cf) ? gs_error_ioerror : 0);
127 }
128 
129 long
clist_ftell(clist_file_ptr cf)130 clist_ftell(clist_file_ptr cf)
131 {
132     return ftell((FILE *) cf);
133 }
134 
135 void
clist_rewind(clist_file_ptr cf,bool discard_data,const char * fname)136 clist_rewind(clist_file_ptr cf, bool discard_data, const char *fname)
137 {
138     FILE *f = (FILE *) cf;
139 
140     if (discard_data) {
141 	/*
142 	 * The ANSI C stdio specification provides no operation for
143 	 * truncating a file at a given position, or even just for
144 	 * deleting its contents; we have to use a bizarre workaround to
145 	 * get the same effect.
146 	 */
147 	char fmode[4];
148 
149 	/* Opening with "w" mode deletes the contents when closing. */
150 	freopen(fname, gp_fmode_wb, f);
151 	strcpy(fmode, "w+");
152 	strcat(fmode, gp_fmode_binary_suffix);
153 	freopen(fname, fmode, f);
154     } else {
155 	rewind(f);
156     }
157 }
158 
159 int
clist_fseek(clist_file_ptr cf,long offset,int mode,const char * ignore_fname)160 clist_fseek(clist_file_ptr cf, long offset, int mode, const char *ignore_fname)
161 {
162     return fseek((FILE *) cf, offset, mode);
163 }
164