blob: 50d416ff761aaef5668721d71b950f02e36e7c42 [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
Benny Prijono844653c2008-12-23 17:27:53 +00003 * Copyright (C) 2008-2009 Teluu Inc. (http://www.teluu.com)
4 * Copyright (C) 2003-2008 Benny Prijono <benny@prijono.org>
Benny Prijono9033e312005-11-21 02:08:39 +00005 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20#include <pj/file_io.h>
Benny Prijono37e8d332006-01-20 21:03:36 +000021#include <pj/unicode.h>
Benny Prijono9033e312005-11-21 02:08:39 +000022#include <pj/errno.h>
23#include <pj/assert.h>
24
25#include <windows.h>
26
27#ifndef INVALID_SET_FILE_POINTER
28# define INVALID_SET_FILE_POINTER ((DWORD)-1)
29#endif
30
31/**
32 * Check for end-of-file condition on the specified descriptor.
33 *
34 * @param fd The file descriptor.
35 * @param access The desired access.
36 *
37 * @return Non-zero if file is EOF.
38 */
39PJ_DECL(pj_bool_t) pj_file_eof(pj_oshandle_t fd,
40 enum pj_file_access access);
41
42
43PJ_DEF(pj_status_t) pj_file_open( pj_pool_t *pool,
44 const char *pathname,
45 unsigned flags,
46 pj_oshandle_t *fd)
47{
Benny Prijono61396412006-02-14 21:03:15 +000048 PJ_DECL_UNICODE_TEMP_BUF(wpathname,256)
Benny Prijono9033e312005-11-21 02:08:39 +000049 HANDLE hFile;
50 DWORD dwDesiredAccess = 0;
51 DWORD dwShareMode = 0;
52 DWORD dwCreationDisposition = 0;
53 DWORD dwFlagsAndAttributes = 0;
54
55 PJ_UNUSED_ARG(pool);
56
57 PJ_ASSERT_RETURN(pathname!=NULL, PJ_EINVAL);
58
59 if ((flags & PJ_O_WRONLY) == PJ_O_WRONLY) {
60 dwDesiredAccess |= GENERIC_WRITE;
61 if ((flags & PJ_O_APPEND) == PJ_O_APPEND) {
Benny Prijono53e968d2009-05-07 12:49:07 +000062#if !defined(PJ_WIN32_WINCE) || !PJ_WIN32_WINCE
63 /* FILE_APPEND_DATA is invalid on WM2003 and WM5, but it seems
64 * to be working on WM6. All are tested on emulator though.
65 * Removing this also seem to work (i.e. data is appended), so
66 * I guess this flag is "optional".
67 */
Benny Prijono9033e312005-11-21 02:08:39 +000068 dwDesiredAccess |= FILE_APPEND_DATA;
Benny Prijono53e968d2009-05-07 12:49:07 +000069#endif
Benny Prijonof5518cd2008-08-28 11:19:54 +000070 dwCreationDisposition |= OPEN_ALWAYS;
Benny Prijono9033e312005-11-21 02:08:39 +000071 } else {
72 dwDesiredAccess &= ~(FILE_APPEND_DATA);
73 dwCreationDisposition |= CREATE_ALWAYS;
74 }
75 }
76 if ((flags & PJ_O_RDONLY) == PJ_O_RDONLY) {
77 dwDesiredAccess |= GENERIC_READ;
78 if (flags == PJ_O_RDONLY)
79 dwCreationDisposition |= OPEN_EXISTING;
80 }
81
82 if (dwDesiredAccess == 0) {
83 pj_assert(!"Invalid file open flags");
84 return PJ_EINVAL;
85 }
86
87 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
88 dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
89
Benny Prijono61396412006-02-14 21:03:15 +000090 hFile = CreateFile(PJ_STRING_TO_NATIVE(pathname,wpathname,sizeof(wpathname)),
Benny Prijono9cf138e2006-01-19 03:58:29 +000091 dwDesiredAccess, dwShareMode, NULL,
Benny Prijono9033e312005-11-21 02:08:39 +000092 dwCreationDisposition, dwFlagsAndAttributes, NULL);
93 if (hFile == INVALID_HANDLE_VALUE) {
94 *fd = 0;
95 return PJ_RETURN_OS_ERROR(GetLastError());
96 }
97
Benny Prijono9bd039d2008-08-28 11:11:28 +000098 if ((flags & PJ_O_APPEND) == PJ_O_APPEND) {
99 pj_status_t status;
100
101 status = pj_file_setpos(hFile, 0, PJ_SEEK_END);
102 if (status != PJ_SUCCESS) {
103 pj_file_close(hFile);
104 return status;
105 }
106 }
107
Benny Prijono9033e312005-11-21 02:08:39 +0000108 *fd = hFile;
109 return PJ_SUCCESS;
110}
111
112PJ_DEF(pj_status_t) pj_file_close(pj_oshandle_t fd)
113{
114 if (CloseHandle(fd)==0)
115 return PJ_RETURN_OS_ERROR(GetLastError());
116 return PJ_SUCCESS;
117}
118
119PJ_DEF(pj_status_t) pj_file_write( pj_oshandle_t fd,
120 const void *data,
121 pj_ssize_t *size)
122{
123 BOOL rc;
124 DWORD bytesWritten;
125
126 rc = WriteFile(fd, data, *size, &bytesWritten, NULL);
127 if (!rc) {
128 *size = -1;
129 return PJ_RETURN_OS_ERROR(GetLastError());
130 }
131
132 *size = bytesWritten;
133 return PJ_SUCCESS;
134}
135
136PJ_DEF(pj_status_t) pj_file_read( pj_oshandle_t fd,
137 void *data,
138 pj_ssize_t *size)
139{
140 BOOL rc;
141 DWORD bytesRead;
142
143 rc = ReadFile(fd, data, *size, &bytesRead, NULL);
144 if (!rc) {
145 *size = -1;
146 return PJ_RETURN_OS_ERROR(GetLastError());
147 }
148
149 *size = bytesRead;
150 return PJ_SUCCESS;
151}
152
153/*
154PJ_DEF(pj_bool_t) pj_file_eof(pj_oshandle_t fd, enum pj_file_access access)
155{
156 BOOL rc;
157 DWORD dummy = 0, bytes;
158 DWORD dwStatus;
159
160 if ((access & PJ_O_RDONLY) == PJ_O_RDONLY) {
161 rc = ReadFile(fd, &dummy, 0, &bytes, NULL);
162 } else if ((access & PJ_O_WRONLY) == PJ_O_WRONLY) {
163 rc = WriteFile(fd, &dummy, 0, &bytes, NULL);
164 } else {
165 pj_assert(!"Invalid access");
166 return PJ_TRUE;
167 }
168
169 dwStatus = GetLastError();
170 if (dwStatus==ERROR_HANDLE_EOF)
171 return PJ_TRUE;
172
173 return 0;
174}
175*/
176
177PJ_DEF(pj_status_t) pj_file_setpos( pj_oshandle_t fd,
178 pj_off_t offset,
179 enum pj_file_seek_type whence)
180{
181 DWORD dwMoveMethod;
182 DWORD dwNewPos;
183 LONG hi32;
184
185 if (whence == PJ_SEEK_SET)
186 dwMoveMethod = FILE_BEGIN;
187 else if (whence == PJ_SEEK_CUR)
188 dwMoveMethod = FILE_CURRENT;
189 else if (whence == PJ_SEEK_END)
190 dwMoveMethod = FILE_END;
191 else {
192 pj_assert(!"Invalid whence in file_setpos");
193 return PJ_EINVAL;
194 }
195
196 hi32 = (LONG)(offset >> 32);
197 dwNewPos = SetFilePointer(fd, (long)offset, &hi32, dwMoveMethod);
198 if (dwNewPos == (DWORD)INVALID_SET_FILE_POINTER) {
199 DWORD dwStatus = GetLastError();
200 if (dwStatus != 0)
201 return PJ_RETURN_OS_ERROR(dwStatus);
202 /* dwNewPos actually is not an error. */
203 }
204
205 return PJ_SUCCESS;
206}
207
208PJ_DEF(pj_status_t) pj_file_getpos( pj_oshandle_t fd,
209 pj_off_t *pos)
210{
211 LONG hi32 = 0;
212 DWORD lo32;
213
214 lo32 = SetFilePointer(fd, 0, &hi32, FILE_CURRENT);
215 if (lo32 == (DWORD)INVALID_SET_FILE_POINTER) {
216 DWORD dwStatus = GetLastError();
217 if (dwStatus != 0)
218 return PJ_RETURN_OS_ERROR(dwStatus);
219 }
220
221 *pos = hi32;
222 *pos = (*pos << 32) + lo32;
223 return PJ_SUCCESS;
224}
225
Benny Prijonoee738712007-03-16 09:25:47 +0000226PJ_DEF(pj_status_t) pj_file_flush(pj_oshandle_t fd)
227{
228 BOOL rc;
229
230 rc = FlushFileBuffers(fd);
231
232 if (!rc) {
233 DWORD dwStatus = GetLastError();
234 if (dwStatus != 0)
235 return PJ_RETURN_OS_ERROR(dwStatus);
236 }
237
238 return PJ_SUCCESS;
239}