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