blob: 12f15ea3f660cda9ea87a7a0ecff4eed2173869f [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
4 *
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;
62 } else {
63 dwDesiredAccess &= ~(FILE_APPEND_DATA);
64 dwCreationDisposition |= CREATE_ALWAYS;
65 }
66 }
67 if ((flags & PJ_O_RDONLY) == PJ_O_RDONLY) {
68 dwDesiredAccess |= GENERIC_READ;
69 if (flags == PJ_O_RDONLY)
70 dwCreationDisposition |= OPEN_EXISTING;
71 }
72
73 if (dwDesiredAccess == 0) {
74 pj_assert(!"Invalid file open flags");
75 return PJ_EINVAL;
76 }
77
78 dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;
79 dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL;
80
Benny Prijono61396412006-02-14 21:03:15 +000081 hFile = CreateFile(PJ_STRING_TO_NATIVE(pathname,wpathname,sizeof(wpathname)),
Benny Prijono9cf138e2006-01-19 03:58:29 +000082 dwDesiredAccess, dwShareMode, NULL,
Benny Prijono9033e312005-11-21 02:08:39 +000083 dwCreationDisposition, dwFlagsAndAttributes, NULL);
84 if (hFile == INVALID_HANDLE_VALUE) {
85 *fd = 0;
86 return PJ_RETURN_OS_ERROR(GetLastError());
87 }
88
89 *fd = hFile;
90 return PJ_SUCCESS;
91}
92
93PJ_DEF(pj_status_t) pj_file_close(pj_oshandle_t fd)
94{
95 if (CloseHandle(fd)==0)
96 return PJ_RETURN_OS_ERROR(GetLastError());
97 return PJ_SUCCESS;
98}
99
100PJ_DEF(pj_status_t) pj_file_write( pj_oshandle_t fd,
101 const void *data,
102 pj_ssize_t *size)
103{
104 BOOL rc;
105 DWORD bytesWritten;
106
107 rc = WriteFile(fd, data, *size, &bytesWritten, NULL);
108 if (!rc) {
109 *size = -1;
110 return PJ_RETURN_OS_ERROR(GetLastError());
111 }
112
113 *size = bytesWritten;
114 return PJ_SUCCESS;
115}
116
117PJ_DEF(pj_status_t) pj_file_read( pj_oshandle_t fd,
118 void *data,
119 pj_ssize_t *size)
120{
121 BOOL rc;
122 DWORD bytesRead;
123
124 rc = ReadFile(fd, data, *size, &bytesRead, NULL);
125 if (!rc) {
126 *size = -1;
127 return PJ_RETURN_OS_ERROR(GetLastError());
128 }
129
130 *size = bytesRead;
131 return PJ_SUCCESS;
132}
133
134/*
135PJ_DEF(pj_bool_t) pj_file_eof(pj_oshandle_t fd, enum pj_file_access access)
136{
137 BOOL rc;
138 DWORD dummy = 0, bytes;
139 DWORD dwStatus;
140
141 if ((access & PJ_O_RDONLY) == PJ_O_RDONLY) {
142 rc = ReadFile(fd, &dummy, 0, &bytes, NULL);
143 } else if ((access & PJ_O_WRONLY) == PJ_O_WRONLY) {
144 rc = WriteFile(fd, &dummy, 0, &bytes, NULL);
145 } else {
146 pj_assert(!"Invalid access");
147 return PJ_TRUE;
148 }
149
150 dwStatus = GetLastError();
151 if (dwStatus==ERROR_HANDLE_EOF)
152 return PJ_TRUE;
153
154 return 0;
155}
156*/
157
158PJ_DEF(pj_status_t) pj_file_setpos( pj_oshandle_t fd,
159 pj_off_t offset,
160 enum pj_file_seek_type whence)
161{
162 DWORD dwMoveMethod;
163 DWORD dwNewPos;
164 LONG hi32;
165
166 if (whence == PJ_SEEK_SET)
167 dwMoveMethod = FILE_BEGIN;
168 else if (whence == PJ_SEEK_CUR)
169 dwMoveMethod = FILE_CURRENT;
170 else if (whence == PJ_SEEK_END)
171 dwMoveMethod = FILE_END;
172 else {
173 pj_assert(!"Invalid whence in file_setpos");
174 return PJ_EINVAL;
175 }
176
177 hi32 = (LONG)(offset >> 32);
178 dwNewPos = SetFilePointer(fd, (long)offset, &hi32, dwMoveMethod);
179 if (dwNewPos == (DWORD)INVALID_SET_FILE_POINTER) {
180 DWORD dwStatus = GetLastError();
181 if (dwStatus != 0)
182 return PJ_RETURN_OS_ERROR(dwStatus);
183 /* dwNewPos actually is not an error. */
184 }
185
186 return PJ_SUCCESS;
187}
188
189PJ_DEF(pj_status_t) pj_file_getpos( pj_oshandle_t fd,
190 pj_off_t *pos)
191{
192 LONG hi32 = 0;
193 DWORD lo32;
194
195 lo32 = SetFilePointer(fd, 0, &hi32, FILE_CURRENT);
196 if (lo32 == (DWORD)INVALID_SET_FILE_POINTER) {
197 DWORD dwStatus = GetLastError();
198 if (dwStatus != 0)
199 return PJ_RETURN_OS_ERROR(dwStatus);
200 }
201
202 *pos = hi32;
203 *pos = (*pos << 32) + lo32;
204 return PJ_SUCCESS;
205}
206