summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gs/base/gp.h18
-rw-r--r--gs/base/gp_macio.c28
-rw-r--r--gs/base/gp_mswin.c100
-rw-r--r--gs/base/gp_os2fs.c28
-rw-r--r--gs/base/gp_unifs.c40
-rw-r--r--gs/base/gp_vms.c28
-rw-r--r--gs/base/gxclfile.c297
7 files changed, 465 insertions, 74 deletions
diff --git a/gs/base/gp.h b/gs/base/gp.h
index 829a782fd..1cdf34754 100644
--- a/gs/base/gp.h
+++ b/gs/base/gp.h
@@ -232,6 +232,24 @@ FILE *gp_open_scratch_file(const gs_memory_t *mem,
232/* Open a file with the given name, as a stream of uninterpreted bytes. */ 232/* Open a file with the given name, as a stream of uninterpreted bytes. */
233FILE *gp_fopen(const char *fname, const char *mode); 233FILE *gp_fopen(const char *fname, const char *mode);
234 234
235/* Test whether this platform supports the sharing of file descriptors */
236int gp_can_share_fdesc(void);
237
238/* Create a self-deleting scratch file */
239FILE *gp_open_scratch_file_rm(const gs_memory_t *mem,
240 const char *prefix,
241 char fname[gp_file_name_sizeof],
242 const char *mode);
243
244/* Create a second open FILE on the basis of a given one */
245FILE *gp_fdup(FILE *f, const char *mode);
246
247/* Read from a specified offset within a FILE into a buffer */
248int gp_fpread(char *buf, uint count, int64_t offset, FILE *f);
249
250/* Write to a specified offset within a FILE from a buffer */
251int gp_fpwrite(char *buf, uint count, int64_t offset, FILE *f);
252
235/* Force given file into binary mode (no eol translations, etc) */ 253/* Force given file into binary mode (no eol translations, etc) */
236/* if 2nd param true, text mode if 2nd param false */ 254/* if 2nd param true, text mode if 2nd param false */
237int gp_setmode_binary(FILE * pfile, bool mode); 255int gp_setmode_binary(FILE * pfile, bool mode);
diff --git a/gs/base/gp_macio.c b/gs/base/gp_macio.c
index c5190d561..8452312f0 100644
--- a/gs/base/gp_macio.c
+++ b/gs/base/gp_macio.c
@@ -549,6 +549,34 @@ gp_fopen (const char * fname, const char * mode) {
549 549
550} 550}
551 551
552int gp_can_share_fdesc(void)
553{
554 return 0;
555}
556
557FILE *gp_open_scratch_file_rm(const gs_memory_t *mem,
558 const char *prefix,
559 char fname[gp_file_name_sizeof],
560 const char *mode)
561{
562 return NULL;
563}
564
565FILE *gp_fdup(FILE *f, const char *mode)
566{
567 return NULL;
568}
569
570int gp_fpread(char *buf, uint count, int64_t offset, FILE *f)
571{
572 return -1;
573}
574
575int gp_fpwrite(char *buf, uint count, int64_t offset, FILE *f)
576{
577 return -1;
578}
579
552FILE * 580FILE *
553popen (const char * fname, const char * mode ) { 581popen (const char * fname, const char * mode ) {
554 return gp_fopen (fname, mode); 582 return gp_fopen (fname, mode);
diff --git a/gs/base/gp_mswin.c b/gs/base/gp_mswin.c
index b7f5a8166..d4e33af9b 100644
--- a/gs/base/gp_mswin.c
+++ b/gs/base/gp_mswin.c
@@ -612,11 +612,12 @@ FILE *mswin_popen(const char *cmd, const char *mode)
612 612
613/* Create and open a scratch file with a given name prefix. */ 613/* Create and open a scratch file with a given name prefix. */
614/* Write the actual file name at fname. */ 614/* Write the actual file name at fname. */
615FILE * 615static FILE *
616gp_open_scratch_file(const gs_memory_t *mem, 616gp_open_scratch_file_generic(const gs_memory_t *mem,
617 const char *prefix, 617 const char *prefix,
618 char *fname, 618 char *fname,
619 const char *mode) 619 const char *mode,
620 int remove)
620{ 621{
621 UINT n; 622 UINT n;
622 DWORD l; 623 DWORD l;
@@ -721,26 +722,19 @@ gp_open_scratch_file(const gs_memory_t *mem,
721 hfile = CreateFile2(uni, 722 hfile = CreateFile2(uni,
722 GENERIC_READ | GENERIC_WRITE | DELETE, 723 GENERIC_READ | GENERIC_WRITE | DELETE,
723 FILE_SHARE_READ | FILE_SHARE_WRITE, 724 FILE_SHARE_READ | FILE_SHARE_WRITE,
724 CREATE_ALWAYS, 725 CREATE_ALWAYS | (remove ? FILE_FLAG_DELETE_ON_CLOSE : 0),
725 NULL); 726 NULL);
726#else 727#else
727 hfile = CreateFileW(uni, 728 hfile = CreateFileW(uni,
728 GENERIC_READ | GENERIC_WRITE | DELETE, 729 GENERIC_READ | GENERIC_WRITE | DELETE,
729 FILE_SHARE_READ | FILE_SHARE_WRITE, 730 FILE_SHARE_READ | FILE_SHARE_WRITE,
730 NULL, CREATE_ALWAYS, 731 NULL, CREATE_ALWAYS,
731 FILE_ATTRIBUTE_NORMAL /* | FILE_FLAG_DELETE_ON_CLOSE */, 732 FILE_ATTRIBUTE_NORMAL | (remove ? FILE_FLAG_DELETE_ON_CLOSE : 0),
732 NULL); 733 NULL);
733#endif 734#endif
734 free(uni); 735 free(uni);
735 } 736 }
736#endif 737#endif
737 /*
738 * Can't apply FILE_FLAG_DELETE_ON_CLOSE due to
739 * the logics of clist_fclose. Also note that
740 * gdev_prn_render_pages requires multiple temporary files
741 * to exist simultaneousely, so that keeping all them opened
742 * may exceed available CRTL file handles.
743 */
744 } 738 }
745 } 739 }
746 if (hfile != INVALID_HANDLE_VALUE) { 740 if (hfile != INVALID_HANDLE_VALUE) {
@@ -769,6 +763,24 @@ gp_open_scratch_file(const gs_memory_t *mem,
769 return f; 763 return f;
770} 764}
771 765
766FILE *
767gp_open_scratch_file(const gs_memory_t *mem,
768 const char *prefix,
769 char *fname,
770 const char *mode)
771{
772 return gp_open_scratch_file_generic(mem, prefix, fname, mode, 0);
773}
774
775FILE *
776gp_open_scratch_file_rm(const gs_memory_t *mem,
777 const char *prefix,
778 char *fname,
779 const char *mode)
780{
781 return gp_open_scratch_file_generic(mem, prefix, fname, mode, 1);
782}
783
772/* Open a file with the given name, as a stream of uninterpreted bytes. */ 784/* Open a file with the given name, as a stream of uninterpreted bytes. */
773FILE * 785FILE *
774gp_fopen(const char *fname, const char *mode) 786gp_fopen(const char *fname, const char *mode)
@@ -794,6 +806,66 @@ gp_fopen(const char *fname, const char *mode)
794#endif 806#endif
795} 807}
796 808
809/* test whether gp_fdup is supported on this platform */
810int gp_can_share_fdesc(void)
811{
812 return 1;
813}
814
815/* Create a second open FILE on the basis of a given one */
816FILE *gp_fdup(FILE *f, const char *mode)
817{
818 int fd = fileno(f);
819 if (fd < 0)
820 return NULL;
821
822 fd = dup(fd);
823 if (fd < 0)
824 return NULL;
825
826 return fdopen(fd, mode);
827}
828
829/* Read from a specified offset within a FILE into a buffer */
830int gp_fpread(char *buf, uint count, int64_t offset, FILE *f)
831{
832 OVERLAPPED overlapped;
833 DWORD ret;
834 HANDLE hnd = _get_osfhandle(fileno(f));
835
836 if (hnd == INVALID_HANDLE_VALUE)
837 return -1;
838
839 memset(&overlapped, 0, sizeof(OVERLAPPED));
840 overlapped.Offset = (DWORD)offset;
841 overlapped.OffsetHigh = (DWORD)(offset >> 32);
842
843 if (!ReadFile((HANDLE)hnd, buf, count, &ret, &overlapped))
844 return -1;
845
846 return ret;
847}
848
849/* Write to a specified offset within a FILE from a buffer */
850int gp_fpwrite(char *buf, uint count, int64_t offset, FILE *f)
851{
852 OVERLAPPED overlapped;
853 DWORD ret;
854 HANDLE hnd = _get_osfhandle(fileno(f));
855
856 if (hnd == INVALID_HANDLE_VALUE)
857 return -1;
858
859 memset(&overlapped, 0, sizeof(OVERLAPPED));
860 overlapped.Offset = (DWORD)offset;
861 overlapped.OffsetHigh = (DWORD)(offset >> 32);
862
863 if (!WriteFile((HANDLE)hnd, buf, count, &ret, &overlapped))
864 return -1;
865
866 return ret;
867}
868
797/* ------ Font enumeration ------ */ 869/* ------ Font enumeration ------ */
798 870
799 /* This is used to query the native os for a list of font names and 871 /* This is used to query the native os for a list of font names and
diff --git a/gs/base/gp_os2fs.c b/gs/base/gp_os2fs.c
index 1de5a3336..fd033bcc2 100644
--- a/gs/base/gp_os2fs.c
+++ b/gs/base/gp_os2fs.c
@@ -262,6 +262,34 @@ gp_fopen(const char *fname, const char *mode)
262 return fopen(fname, mode); 262 return fopen(fname, mode);
263} 263}
264 264
265int gp_can_share_fdesc(void)
266{
267 return 0;
268}
269
270FILE *gp_open_scratch_file_rm(const gs_memory_t *mem,
271 const char *prefix,
272 char fname[gp_file_name_sizeof],
273 const char *mode)
274{
275 return NULL;
276}
277
278FILE *gp_fdup(FILE *f, const char *mode)
279{
280 return NULL;
281}
282
283int gp_fpread(char *buf, uint count, int64_t offset, FILE *f)
284{
285 return -1;
286}
287
288int gp_fpwrite(char *buf, uint count, int64_t offset, FILE *f)
289{
290 return -1;
291}
292
265/* -------------- Helpers for gp_file_name_combine_generic ------------- */ 293/* -------------- Helpers for gp_file_name_combine_generic ------------- */
266 294
267uint gp_file_name_root(const char *fname, uint len) 295uint gp_file_name_root(const char *fname, uint len)
diff --git a/gs/base/gp_unifs.c b/gs/base/gp_unifs.c
index f44b3d2bc..59fc86c3d 100644
--- a/gs/base/gp_unifs.c
+++ b/gs/base/gp_unifs.c
@@ -151,6 +151,46 @@ gp_fopen(const char *fname, const char *mode)
151 return fopen(fname, mode); 151 return fopen(fname, mode);
152} 152}
153 153
154int gp_can_share_fdesc(void)
155{
156 return 1;
157}
158
159FILE *gp_open_scratch_file_rm(const gs_memory_t *mem,
160 const char *prefix,
161 char fname[gp_file_name_sizeof],
162 const char *mode)
163{
164 FILE *f = gp_open_scratch_file_generic(mem, prefix, fname, mode, false);
165 /* Unlink file immediately to avoid it being left around if the program
166 * is killed. On this platform readers access temp files by cloning the
167 * FILE pointer and without accessing the file by name */
168 if (f)
169 unlink(fname);
170 return f;
171}
172
173FILE *gp_fdup(FILE *f, const char *mode)
174{
175 int fd = fileno(f);
176 if (fd < 0)
177 return NULL;
178 fd = dup(fd);
179 if (fd < 0)
180 return NULL;
181 return fdopen(fd, mode);
182}
183
184int gp_fpread(char *buf, uint count, int64_t offset, FILE *f)
185{
186 return pread(fileno(f), buf, count, offset);
187}
188
189int gp_fpwrite(char *buf, uint count, int64_t offset, FILE *f)
190{
191 return pwrite(fileno(f), buf, count, offset);
192}
193
154/* Set a file into binary or text mode. */ 194/* Set a file into binary or text mode. */
155int 195int
156gp_setmode_binary(FILE * pfile, bool mode) 196gp_setmode_binary(FILE * pfile, bool mode)
diff --git a/gs/base/gp_vms.c b/gs/base/gp_vms.c
index 689f4ca88..f3b5f6f31 100644
--- a/gs/base/gp_vms.c
+++ b/gs/base/gp_vms.c
@@ -287,6 +287,34 @@ gp_fopen(const char *fname, const char *mode)
287 return fopen(fname, mode); 287 return fopen(fname, mode);
288} 288}
289 289
290int gp_can_share_fdesc(void)
291{
292 return 0;
293}
294
295FILE *gp_open_scratch_file_rm(const gs_memory_t *mem,
296 const char *prefix,
297 char fname[gp_file_name_sizeof],
298 const char *mode)
299{
300 return NULL;
301}
302
303FILE *gp_fdup(FILE *f, const char *mode)
304{
305 return NULL;
306}
307
308int gp_fpread(char *buf, uint count, int64_t offset, FILE *f)
309{
310 return -1;
311}
312
313int gp_fpwrite(char *buf, uint count, int64_t offset, FILE *f)
314{
315 return -1;
316}
317
290/* Set a file into binary or text mode. */ 318/* Set a file into binary or text mode. */
291int 319int
292gp_setmode_binary(FILE * pfile, bool binary) 320gp_setmode_binary(FILE * pfile, bool binary)
diff --git a/gs/base/gxclfile.c b/gs/base/gxclfile.c
index 2ca35b60d..18ab29d45 100644
--- a/gs/base/gxclfile.c
+++ b/gs/base/gxclfile.c
@@ -15,6 +15,7 @@
15 15
16 16
17/* File-based command list implementation */ 17/* File-based command list implementation */
18#include "assert.h"
18#include "stdio_.h" 19#include "stdio_.h"
19#include "string_.h" 20#include "string_.h"
20#include "unistd_.h" 21#include "unistd_.h"
@@ -32,38 +33,149 @@
32 33
33/* ------ Open/close/unlink ------ */ 34/* ------ Open/close/unlink ------ */
34 35
36#define ENC_FILE_STR ("encoded_file_ptr_%p")
37#define ENC_FILE_STRX ("encoded_file_ptr_0x%p")
38
39static void
40file_to_fake_path(clist_file_ptr file, char fname[gp_file_name_sizeof])
41{
42 gs_sprintf(fname, ENC_FILE_STR, file);
43}
44
45static clist_file_ptr
46fake_path_to_file(const char *fname)
47{
48 clist_file_ptr i1, i2;
49
50 int r1 = sscanf(fname, ENC_FILE_STR, &i1);
51 int r2 = sscanf(fname, ENC_FILE_STRX, &i2);
52 return r2 == 1 ? i2 : (r1 == 1 ? i1 : NULL);
53}
54
55/* Use our own FILE structure so that, on some platforms, we write and read
56 * tmp files via a single file descriptor. That allows cleaning of tmp files
57 * to be addressed via DELETE_ON_CLOSE under Windows, and immediate unlink
58 * after opening under Linux. When running in this mode, we keep our own
59 * record of position within the file for the sake of thread safety
60 */
61typedef struct
62{
63 gs_memory_t *mem;
64 FILE *f;
65 int64_t pos;
66} IFILE;
67
68static IFILE *wrap_file(gs_memory_t *mem, FILE *f)
69{
70 IFILE *ifile;
71
72 if (!f) return NULL;
73 ifile = (IFILE *)gs_alloc_bytes(mem->non_gc_memory, sizeof(*ifile), "Allocate wrapped IFILE");
74 if (!ifile)
75 {
76 fclose(f);
77 return NULL;
78 }
79 ifile->mem = mem->non_gc_memory;
80 ifile->f = f;
81 ifile->pos = 0;
82 return ifile;
83}
84
85int close_file(IFILE *ifile)
86{
87 int res = 0;
88 if (ifile)
89 {
90 res = fclose(ifile->f);
91 gs_free_object(ifile->mem, ifile, "Free wrapped IFILE");
92 }
93 return res;
94}
95
35static int 96static int
36clist_fopen(char fname[gp_file_name_sizeof], const char *fmode, 97clist_fopen(char fname[gp_file_name_sizeof], const char *fmode,
37 clist_file_ptr * pcf, gs_memory_t * mem, gs_memory_t *data_mem, 98 clist_file_ptr * pcf, gs_memory_t * mem, gs_memory_t *data_mem,
38 bool ok_to_compress) 99 bool ok_to_compress)
39{ 100{
40 if (*fname == 0) { 101 if (*fname == 0)
102 {
41 if (fmode[0] == 'r') 103 if (fmode[0] == 'r')
42 return_error(gs_error_invalidfileaccess); 104 return_error(gs_error_invalidfileaccess);
43 *pcf = (clist_file_ptr)gp_open_scratch_file_64(mem, 105 if (gp_can_share_fdesc())
44 gp_scratch_file_name_prefix, 106 {
45 fname, fmode); 107 *pcf = (clist_file_ptr)wrap_file(mem, gp_open_scratch_file_rm(mem,
46 } else 108 gp_scratch_file_name_prefix,
47 *pcf = gp_fopen(fname, fmode); 109 fname, fmode));
48 if (*pcf == NULL) { 110 /* If the platform supports FILE duplication then we overwrite the
111 * file name with an encoded form of the FILE pointer */
112 file_to_fake_path(*pcf, fname);
113 }
114 else
115 {
116 *pcf = (clist_file_ptr)wrap_file(mem, gp_open_scratch_file_64(mem,
117 gp_scratch_file_name_prefix,
118 fname, fmode));
119 }
120 }
121 else
122 {
123 // Check if a special path is passed in. If so, clone the FILE handle
124 clist_file_ptr ocf = fake_path_to_file(fname);
125 if (ocf)
126 {
127 *pcf = wrap_file(mem, gp_fdup(((IFILE *)ocf)->f, fmode));
128 }
129 else
130 {
131 *pcf = wrap_file(mem, gp_fopen(fname, fmode));
132 }
133 }
134
135 if (*pcf == NULL)
136 {
49 emprintf1(mem, "Could not open the scratch file %s.\n", fname); 137 emprintf1(mem, "Could not open the scratch file %s.\n", fname);
50 return_error(gs_error_invalidfileaccess); 138 return_error(gs_error_invalidfileaccess);
51 } 139 }
140
52 return 0; 141 return 0;
53} 142}
54 143
55static int 144static int
56clist_unlink(const char *fname) 145clist_unlink(const char *fname)
57{ 146{
58 return (unlink(fname) != 0 ? gs_note_error(gs_error_ioerror) : 0); 147 clist_file_ptr ocf = fake_path_to_file(fname);
148 if (ocf)
149 {
150 /* fname is an encoded file pointer. The file will either have been
151 * created with the delete-on-close option, or already have been
152 * unlinked. We need only close the FILE */
153 return close_file((IFILE *)ocf) != 0 ? gs_note_error(gs_error_ioerror) : 0;
154 }
155 else
156 {
157 return (unlink(fname) != 0 ? gs_note_error(gs_error_ioerror) : 0);
158 }
59} 159}
60 160
61static int 161static int
62clist_fclose(clist_file_ptr cf, const char *fname, bool delete) 162clist_fclose(clist_file_ptr cf, const char *fname, bool delete)
63{ 163{
64 return (fclose((FILE *) cf) != 0 ? gs_note_error(gs_error_ioerror) : 164 clist_file_ptr ocf = fake_path_to_file(fname);
65 delete ? clist_unlink(fname) : 165 if (ocf == cf)
66 0); 166 {
167 /* fname is an encoded file pointer, and cf is the FILE used to create it.
168 * We shouldn't close it unless we have been asked to delete it, in which
169 * case closing it will delete it */
170 if (delete)
171 close_file((IFILE *)ocf);
172 }
173 else
174 {
175 return (close_file((IFILE *) cf) != 0 ? gs_note_error(gs_error_ioerror) :
176 delete ? clist_unlink(fname) :
177 0);
178 }
67} 179}
68 180
69/* ------ Writing ------ */ 181/* ------ Writing ------ */
@@ -71,7 +183,16 @@ clist_fclose(clist_file_ptr cf, const char *fname, bool delete)
71static int 183static int
72clist_fwrite_chars(const void *data, uint len, clist_file_ptr cf) 184clist_fwrite_chars(const void *data, uint len, clist_file_ptr cf)
73{ 185{
74 return fwrite(data, 1, len, (FILE *) cf); 186 if (gp_can_share_fdesc())
187 {
188 int res = gp_fpwrite(data, len, ((IFILE *)cf)->pos, ((IFILE *)cf)->f);
189 if (res >= 0)
190 ((IFILE *)cf)->pos += len; return res;
191 }
192 else
193 {
194 return fwrite(data, 1, len, ((IFILE *)cf)->f);
195 }
75} 196}
76 197
77/* ------ Reading ------ */ 198/* ------ Reading ------ */
@@ -79,33 +200,45 @@ clist_fwrite_chars(const void *data, uint len, clist_file_ptr cf)
79static int 200static int
80clist_fread_chars(void *data, uint len, clist_file_ptr cf) 201clist_fread_chars(void *data, uint len, clist_file_ptr cf)
81{ 202{
82 FILE *f = (FILE *) cf; 203 if (gp_can_share_fdesc())
83 byte *str = data; 204 {
84 205 int res = gp_fpread(data, len, ((IFILE *)cf)->pos, ((IFILE *)cf)->f);
85 /* The typical implementation of fread */ 206 if (res >= 0)
86 /* is extremely inefficient for small counts, */ 207 ((IFILE *)cf)->pos += res;
87 /* so we just use straight-line code instead. */ 208
88 switch (len) { 209 return res;
89 default: 210 }
90 return fread(str, 1, len, f); 211 else
91 case 8: 212 {
92 *str++ = (byte) getc(f); 213 FILE *f = ((IFILE *)cf)->f;
93 case 7: 214 byte *str = data;
94 *str++ = (byte) getc(f); 215
95 case 6: 216 /* The typical implementation of fread */
96 *str++ = (byte) getc(f); 217 /* is extremely inefficient for small counts, */
97 case 5: 218 /* so we just use straight-line code instead. */
98 *str++ = (byte) getc(f); 219 switch (len) {
99 case 4: 220 default:
100 *str++ = (byte) getc(f); 221 return fread(str, 1, len, f);
101 case 3: 222 case 8:
102 *str++ = (byte) getc(f); 223 *str++ = (byte) getc(f);
103 case 2: 224 case 7:
104 *str++ = (byte) getc(f); 225 *str++ = (byte) getc(f);
105 case 1: 226 case 6:
106 *str = (byte) getc(f); 227 *str++ = (byte) getc(f);
107 } 228 case 5:
108 return len; 229 *str++ = (byte) getc(f);
230 case 4:
231 *str++ = (byte) getc(f);
232 case 3:
233 *str++ = (byte) getc(f);
234 case 2:
235 *str++ = (byte) getc(f);
236 case 1:
237 *str = (byte) getc(f);
238 }
239
240 return len;
241 }
109} 242}
110 243
111/* ------ Position/status ------ */ 244/* ------ Position/status ------ */
@@ -119,43 +252,87 @@ clist_set_memory_warning(clist_file_ptr cf, int bytes_left)
119static int 252static int
120clist_ferror_code(clist_file_ptr cf) 253clist_ferror_code(clist_file_ptr cf)
121{ 254{
122 return (ferror((FILE *) cf) ? gs_error_ioerror : 0); 255 return (ferror(((IFILE *)cf)->f) ? gs_error_ioerror : 0);
123} 256}
124 257
125static int64_t 258static int64_t
126clist_ftell(clist_file_ptr cf) 259clist_ftell(clist_file_ptr cf)
127{ 260{
128 return gp_ftell_64((FILE *) cf); 261 IFILE *ifile = (IFILE *)cf;
262
263 return gp_can_share_fdesc() ? ifile->pos : ftell(ifile->f);
129} 264}
130 265
131static void 266static void
132clist_rewind(clist_file_ptr cf, bool discard_data, const char *fname) 267clist_rewind(clist_file_ptr cf, bool discard_data, const char *fname)
133{ 268{
134 FILE *f = (FILE *) cf; 269 FILE *f = ((IFILE *)cf)->f;
135 270 IFILE *ocf = fake_path_to_file(fname);
136 if (discard_data) { 271 char fmode[4];
137 /* 272
138 * The ANSI C stdio specification provides no operation for 273 strcpy(fmode, "w+");
139 * truncating a file at a given position, or even just for 274 strcat(fmode, gp_fmode_binary_suffix);
140 * deleting its contents; we have to use a bizarre workaround to 275
141 * get the same effect. 276 if (ocf)
142 */ 277 {
143 char fmode[4]; 278 if (discard_data)
144 279 {
145 /* Opening with "w" mode deletes the contents when closing. */ 280 /* fname is an encoded ifile pointer. We can use an entirely
146 (void)freopen(fname, gp_fmode_wb, f); 281 * new scratch file. */
147 strcpy(fmode, "w+"); 282 char tfname[gp_file_name_sizeof];
148 strcat(fmode, gp_fmode_binary_suffix); 283 fclose(ocf->f);
149 (void)freopen(fname, fmode, f); 284 ocf->f = gp_open_scratch_file_rm(NULL, gp_scratch_file_name_prefix, tfname, fmode);
150 } else { 285 }
151 rewind(f); 286 else
287 {
288 ((IFILE *)cf)->pos = 0;
289 }
290 }
291 else
292 {
293 if (discard_data) {
294 /*
295 * The ANSI C stdio specification provides no operation for
296 * truncating a file at a given position, or even just for
297 * deleting its contents; we have to use a bizarre workaround to
298 * get the same effect.
299 */
300
301 /* Opening with "w" mode deletes the contents when closing. */
302 (void)freopen(fname, gp_fmode_wb, f);
303 (void)freopen(fname, fmode, f);
304 } else {
305 rewind(f);
306 }
152 } 307 }
153} 308}
154 309
155static int 310static int
156clist_fseek(clist_file_ptr cf, int64_t offset, int mode, const char *ignore_fname) 311clist_fseek(clist_file_ptr cf, int64_t offset, int mode, const char *ignore_fname)
157{ 312{
158 return gp_fseek_64((FILE *) cf, offset, mode); 313 IFILE *ifile = (IFILE *)cf;
314
315 if (gp_can_share_fdesc())
316 {
317 switch (mode)
318 {
319 case SEEK_SET:
320 ifile->pos = offset;
321 break;
322 case SEEK_CUR:
323 ifile->pos += offset;
324 break;
325 case SEEK_END:
326 gp_fseek_64(ifile->f, 0, SEEK_END);
327 ifile->pos = ftell(ifile->f);
328 break;
329 }
330 return 0;
331 }
332 else
333 {
334 return gp_fseek_64(ifile->f, offset, mode);
335 }
159} 336}
160 337
161static clist_io_procs_t clist_io_procs_file = { 338static clist_io_procs_t clist_io_procs_file = {