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