blob: 35742798eaffcbd7922a3f1f1ce4c106e7c33983 [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) {
62 dwDesiredAccess |= FILE_APPEND_DATA;
Benny Prijonof5518cd2008-08-28 11:19:54 +000063 dwCreationDisposition |= OPEN_ALWAYS;
Benny Prijono9033e312005-11-21 02:08:39 +000064 } else {
65 dwDesiredAccess &= ~(FILE_APPEND_DATA);
66 dwCreationDisposition |= CREATE_ALWAYS;
67 }
68 }
69 if ((flags & PJ_O_RDONLY) == PJ_O_RDONLY) {
70 dwDesiredAccess |= GENERIC_READ;
71 if (flags == PJ_O_RDONLY)
72 dwCreationDisposition |= OPEN_EXISTING;
73 }
74
75 if (dwDesiredAccess == 0) {
76 pj_assert(!"Invalid file open flags");
77 return PJ_EINVAL;
78 }
79
80 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
81 dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
82
Benny Prijono61396412006-02-14 21:03:15 +000083 hFile = CreateFile(PJ_STRING_TO_NATIVE(pathname,wpathname,sizeof(wpathname)),
Benny Prijono9cf138e2006-01-19 03:58:29 +000084 dwDesiredAccess, dwShareMode, NULL,
Benny Prijono9033e312005-11-21 02:08:39 +000085 dwCreationDisposition, dwFlagsAndAttributes, NULL);
86 if (hFile == INVALID_HANDLE_VALUE) {
87 *fd = 0;
88 return PJ_RETURN_OS_ERROR(GetLastError());
89 }
90
Benny Prijono9bd039d2008-08-28 11:11:28 +000091 if ((flags & PJ_O_APPEND) == PJ_O_APPEND) {
92 pj_status_t status;
93
94 status = pj_file_setpos(hFile, 0, PJ_SEEK_END);
95 if (status != PJ_SUCCESS) {
96 pj_file_close(hFile);
97 return status;
98 }
99 }
100
Benny Prijono9033e312005-11-21 02:08:39 +0000101 *fd = hFile;
102 return PJ_SUCCESS;
103}
104
105PJ_DEF(pj_status_t) pj_file_close(pj_oshandle_t fd)
106{
107 if (CloseHandle(fd)==0)
108 return PJ_RETURN_OS_ERROR(GetLastError());
109 return PJ_SUCCESS;
110}
111
112PJ_DEF(pj_status_t) pj_file_write( pj_oshandle_t fd,
113 const void *data,
114 pj_ssize_t *size)
115{
116 BOOL rc;
117 DWORD bytesWritten;
118
119 rc = WriteFile(fd, data, *size, &bytesWritten, NULL);
120 if (!rc) {
121 *size = -1;
122 return PJ_RETURN_OS_ERROR(GetLastError());
123 }
124
125 *size = bytesWritten;
126 return PJ_SUCCESS;
127}
128
129PJ_DEF(pj_status_t) pj_file_read( pj_oshandle_t fd,
130 void *data,
131 pj_ssize_t *size)
132{
133 BOOL rc;
134 DWORD bytesRead;
135
136 rc = ReadFile(fd, data, *size, &bytesRead, NULL);
137 if (!rc) {
138 *size = -1;
139 return PJ_RETURN_OS_ERROR(GetLastError());
140 }
141
142 *size = bytesRead;
143 return PJ_SUCCESS;
144}
145
146/*
147PJ_DEF(pj_bool_t) pj_file_eof(pj_oshandle_t fd, enum pj_file_access access)
148{
149 BOOL rc;
150 DWORD dummy = 0, bytes;
151 DWORD dwStatus;
152
153 if ((access & PJ_O_RDONLY) == PJ_O_RDONLY) {
154 rc = ReadFile(fd, &dummy, 0, &bytes, NULL);
155 } else if ((access & PJ_O_WRONLY) == PJ_O_WRONLY) {
156 rc = WriteFile(fd, &dummy, 0, &bytes, NULL);
157 } else {
158 pj_assert(!"Invalid access");
159 return PJ_TRUE;
160 }
161
162 dwStatus = GetLastError();
163 if (dwStatus==ERROR_HANDLE_EOF)
164 return PJ_TRUE;
165
166 return 0;
167}
168*/
169
170PJ_DEF(pj_status_t) pj_file_setpos( pj_oshandle_t fd,
171 pj_off_t offset,
172 enum pj_file_seek_type whence)
173{
174 DWORD dwMoveMethod;
175 DWORD dwNewPos;
176 LONG hi32;
177
178 if (whence == PJ_SEEK_SET)
179 dwMoveMethod = FILE_BEGIN;
180 else if (whence == PJ_SEEK_CUR)
181 dwMoveMethod = FILE_CURRENT;
182 else if (whence == PJ_SEEK_END)
183 dwMoveMethod = FILE_END;
184 else {
185 pj_assert(!"Invalid whence in file_setpos");
186 return PJ_EINVAL;
187 }
188
189 hi32 = (LONG)(offset >> 32);
190 dwNewPos = SetFilePointer(fd, (long)offset, &hi32, dwMoveMethod);
191 if (dwNewPos == (DWORD)INVALID_SET_FILE_POINTER) {
192 DWORD dwStatus = GetLastError();
193 if (dwStatus != 0)
194 return PJ_RETURN_OS_ERROR(dwStatus);
195 /* dwNewPos actually is not an error. */
196 }
197
198 return PJ_SUCCESS;
199}
200
201PJ_DEF(pj_status_t) pj_file_getpos( pj_oshandle_t fd,
202 pj_off_t *pos)
203{
204 LONG hi32 = 0;
205 DWORD lo32;
206
207 lo32 = SetFilePointer(fd, 0, &hi32, FILE_CURRENT);
208 if (lo32 == (DWORD)INVALID_SET_FILE_POINTER) {
209 DWORD dwStatus = GetLastError();
210 if (dwStatus != 0)
211 return PJ_RETURN_OS_ERROR(dwStatus);
212 }
213
214 *pos = hi32;
215 *pos = (*pos << 32) + lo32;
216 return PJ_SUCCESS;
217}
218
Benny Prijonoee738712007-03-16 09:25:47 +0000219PJ_DEF(pj_status_t) pj_file_flush(pj_oshandle_t fd)
220{
221 BOOL rc;
222
223 rc = FlushFileBuffers(fd);
224
225 if (!rc) {
226 DWORD dwStatus = GetLastError();
227 if (dwStatus != 0)
228 return PJ_RETURN_OS_ERROR(dwStatus);
229 }
230
231 return PJ_SUCCESS;
232}