1 /* Copyright (C) 2001-2019 Artifex Software, Inc.
2 All Rights Reserved.
3
4 This software is provided AS-IS with no warranty, either express or
5 implied.
6
7 This software is distributed under license and may not be copied,
8 modified or distributed except as expressly authorized under the terms
9 of the license contained in the file LICENSE in this distribution.
10
11 Refer to licensing information at http://www.artifex.com or contact
12 Artifex Software, Inc., 1305 Grant Avenue - Suite 200, Novato,
13 CA 94945, U.S.A., +1(415)492-9861, for further information.
14 */
15
16 /* prevent gp.h from defining fopen */
17 #define fopen fopen
18
19 #include "windows_.h"
20 #include "stdio_.h"
21 #include "gp.h"
22 #include "memory_.h"
23 #include "stat_.h"
24
25 #include "gp_mswin.h"
26
27 /* Open a file with the given name, as a stream of uninterpreted bytes. */
28 FILE *
gp_fopen_impl(gs_memory_t * mem,const char * fname,const char * mode)29 gp_fopen_impl(gs_memory_t *mem, const char *fname, const char *mode)
30 {
31 int len = utf8_to_wchar(NULL, fname);
32 wchar_t *uni;
33 wchar_t wmode[4];
34 FILE *file;
35
36 if (len <= 0)
37 return NULL;
38
39 uni = (wchar_t *)gs_alloc_bytes(mem, len*sizeof(wchar_t), "gp_fopen_impl");
40 if (uni == NULL)
41 return NULL;
42 utf8_to_wchar(uni, fname);
43 utf8_to_wchar(wmode, mode);
44 file = _wfopen(uni, wmode);
45 gs_free_object(mem, uni, "gs_fopen_impl");
46
47 return file;
48 }
49
50 /* Create a second open FILE on the basis of a given one */
gp_fdup_impl(FILE * f,const char * mode)51 FILE *gp_fdup_impl(FILE *f, const char *mode)
52 {
53 int fd = fileno(f);
54 if (fd < 0)
55 return NULL;
56
57 fd = dup(fd);
58 if (fd < 0)
59 return NULL;
60
61 return fdopen(fd, mode);
62 }
63
64 /* Read from a specified offset within a FILE into a buffer */
gp_pread_impl(char * buf,size_t count,gs_offset_t offset,FILE * f)65 int gp_pread_impl(char *buf, size_t count, gs_offset_t offset, FILE *f)
66 {
67 OVERLAPPED overlapped;
68 DWORD ret;
69 HANDLE hnd = (HANDLE)_get_osfhandle(fileno(f));
70
71 if (hnd == INVALID_HANDLE_VALUE)
72 return -1;
73
74 memset(&overlapped, 0, sizeof(OVERLAPPED));
75 overlapped.Offset = (DWORD)offset;
76 overlapped.OffsetHigh = (DWORD)(offset >> 32);
77
78 if (!ReadFile((HANDLE)hnd, buf, count, &ret, &overlapped))
79 return -1;
80
81 return ret;
82 }
83
84 /* Write to a specified offset within a FILE from a buffer */
gp_pwrite_impl(const char * buf,size_t count,gs_offset_t offset,FILE * f)85 int gp_pwrite_impl(const char *buf, size_t count, gs_offset_t offset, FILE *f)
86 {
87 OVERLAPPED overlapped;
88 DWORD ret;
89 HANDLE hnd = (HANDLE)_get_osfhandle(fileno(f));
90
91 if (hnd == INVALID_HANDLE_VALUE)
92 return -1;
93
94 memset(&overlapped, 0, sizeof(OVERLAPPED));
95 overlapped.Offset = (DWORD)offset;
96 overlapped.OffsetHigh = (DWORD)(offset >> 32);
97
98 if (!WriteFile((HANDLE)hnd, buf, count, &ret, &overlapped))
99 return -1;
100
101 return ret;
102 }
103
104 /* --------- 64 bit file access ----------- */
105 /* MSVC versions before 8 doen't provide big files.
106 MSVC 8 doesn't distinguish big and small files,
107 but provide special positioning functions
108 to access data behind 4GB.
109 Currently we support 64 bits file access with MSVC only.
110 */
111
112 #if defined(_MSC_VER) && _MSC_VER < 1400
113 int64_t _ftelli64( FILE *);
114 int _fseeki64( FILE *, int64_t, int);
115 #endif
116
gp_ftell_impl(FILE * strm)117 gs_offset_t gp_ftell_impl(FILE *strm)
118 {
119 #if !defined(_MSC_VER)
120 return ftell(strm);
121 #elif _MSC_VER < 1200
122 return ftell(strm);
123 #else
124 return (int64_t)_ftelli64(strm);
125 #endif
126 }
127
gp_fseek_impl(FILE * strm,gs_offset_t offset,int origin)128 int gp_fseek_impl(FILE *strm, gs_offset_t offset, int origin)
129 {
130 #if !defined(_MSC_VER)
131 return fseek(strm, offset, origin);
132 #elif _MSC_VER < 1200
133 long offset1 = (long)offset;
134
135 if (offset != offset1)
136 return -1;
137 return fseek(strm, offset1, origin);
138 #else
139 return _fseeki64(strm, offset, origin);
140 #endif
141 }
142
gp_fseekable_impl(FILE * f)143 bool gp_fseekable_impl(FILE *f)
144 {
145 struct __stat64 s;
146 int fno;
147
148 fno = fileno(f);
149 if (fno < 0)
150 return(false);
151
152 if (_fstat64(fno, &s) < 0)
153 return(false);
154
155 return((bool)S_ISREG(s.st_mode));
156 }
157