diff options
Diffstat (limited to 'pjlib/src/pj')
-rw-r--r-- | pjlib/src/pj/file_access_win32.c | 172 | ||||
-rw-r--r-- | pjlib/src/pj/file_io_ansi.c | 138 | ||||
-rw-r--r-- | pjlib/src/pj/file_io_win32.c | 186 | ||||
-rw-r--r-- | pjlib/src/pj/ioqueue_winnt.c | 29 |
4 files changed, 517 insertions, 8 deletions
diff --git a/pjlib/src/pj/file_access_win32.c b/pjlib/src/pj/file_access_win32.c new file mode 100644 index 00000000..36405658 --- /dev/null +++ b/pjlib/src/pj/file_access_win32.c @@ -0,0 +1,172 @@ +/* $Id$ */
+#include <pj/file_access.h>
+#include <pj/assert.h>
+#include <pj/errno.h>
+#include <windows.h>
+#include <time.h>
+
+/*
+ * pj_file_exists()
+ */
+PJ_DEF(pj_bool_t) pj_file_exists(const char *filename)
+{
+ HANDLE hFile;
+
+ PJ_ASSERT_RETURN(filename != NULL, 0);
+
+ hFile = CreateFile(filename, READ_CONTROL, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return 0;
+
+ CloseHandle(hFile);
+ return PJ_TRUE;
+}
+
+
+/*
+ * pj_file_size()
+ */
+PJ_DEF(pj_off_t) pj_file_size(const char *filename)
+{
+ HANDLE hFile;
+ DWORD sizeLo, sizeHi;
+ pj_off_t size;
+
+ PJ_ASSERT_RETURN(filename != NULL, -1);
+
+ hFile = CreateFile(filename, READ_CONTROL,
+ FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return -1;
+
+ sizeLo = GetFileSize(hFile, &sizeHi);
+ if (sizeLo == INVALID_FILE_SIZE) {
+ DWORD dwStatus = GetLastError();
+ if (dwStatus != NO_ERROR) {
+ CloseHandle(hFile);
+ return -1;
+ }
+ }
+
+ size = sizeHi;
+ size = (size << 32) + sizeLo;
+
+ CloseHandle(hFile);
+ return size;
+}
+
+
+/*
+ * pj_file_delete()
+ */
+PJ_DEF(pj_status_t) pj_file_delete(const char *filename)
+{
+ PJ_ASSERT_RETURN(filename != NULL, PJ_EINVAL);
+
+ if (DeleteFile(filename) == FALSE)
+ return PJ_RETURN_OS_ERROR(GetLastError());
+
+ return PJ_SUCCESS;
+}
+
+
+/*
+ * pj_file_move()
+ */
+PJ_DEF(pj_status_t) pj_file_move( const char *oldname, const char *newname)
+{
+ BOOL rc;
+
+ PJ_ASSERT_RETURN(oldname!=NULL && newname!=NULL, PJ_EINVAL);
+
+#if PJ_WIN32_WINNT >= 0x0400
+ rc = MoveFileEx(oldname, newname,
+ MOVEFILE_COPY_ALLOWED|MOVEFILE_REPLACE_EXISTING);
+#else
+ rc = MoveFile(oldname, newname);
+#endif
+
+ if (!rc)
+ return PJ_RETURN_OS_ERROR(GetLastError());
+
+ return PJ_SUCCESS;
+}
+
+
+static pj_status_t file_time_to_time_val(const FILETIME *file_time,
+ pj_time_val *time_val)
+{
+ SYSTEMTIME systemTime, localTime;
+ struct tm tm;
+
+ if (!FileTimeToSystemTime(file_time, &systemTime))
+ return -1;
+
+ if (!SystemTimeToTzSpecificLocalTime(NULL, &systemTime, &localTime))
+ return -1;
+
+ memset(&tm, 0, sizeof(struct tm));
+ tm.tm_year = localTime.wYear - 1900;
+ tm.tm_mon = localTime.wMonth - 1;
+ tm.tm_mday = localTime.wDay;
+ tm.tm_hour = localTime.wHour;
+ tm.tm_min = localTime.wMinute;
+ tm.tm_sec = localTime.wSecond;
+ tm.tm_isdst = 0;
+
+ time_val->sec = mktime(&tm);
+ if (time_val->sec == (time_t)-1)
+ return -1;
+
+ time_val->msec = localTime.wMilliseconds;
+
+ return PJ_SUCCESS;
+}
+
+/*
+ * pj_file_getstat()
+ */
+PJ_DEF(pj_status_t) pj_file_getstat(const char *filename, pj_file_stat *stat)
+{
+ HANDLE hFile;
+ DWORD sizeLo, sizeHi;
+ FILETIME creationTime, accessTime, writeTime;
+
+ PJ_ASSERT_RETURN(filename!=NULL && stat!=NULL, PJ_EINVAL);
+
+ hFile = CreateFile(filename, READ_CONTROL, FILE_SHARE_READ, NULL,
+ OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+ if (hFile == INVALID_HANDLE_VALUE)
+ return PJ_RETURN_OS_ERROR(GetLastError());
+
+ sizeLo = GetFileSize(hFile, &sizeHi);
+ if (sizeLo == INVALID_FILE_SIZE) {
+ DWORD dwStatus = GetLastError();
+ if (dwStatus != NO_ERROR) {
+ CloseHandle(hFile);
+ return PJ_RETURN_OS_ERROR(dwStatus);
+ }
+ }
+
+ stat->size = sizeHi;
+ stat->size = (stat->size << 32) + sizeLo;
+
+ if (GetFileTime(hFile, &creationTime, &accessTime, &writeTime)==FALSE) {
+ DWORD dwStatus = GetLastError();
+ CloseHandle(hFile);
+ return PJ_RETURN_OS_ERROR(dwStatus);
+ }
+
+ CloseHandle(hFile);
+
+ if (file_time_to_time_val(&creationTime, &stat->ctime) != PJ_SUCCESS)
+ return PJ_RETURN_OS_ERROR(GetLastError());
+
+ file_time_to_time_val(&accessTime, &stat->atime);
+ file_time_to_time_val(&writeTime, &stat->mtime);
+
+ return PJ_SUCCESS;
+}
+
diff --git a/pjlib/src/pj/file_io_ansi.c b/pjlib/src/pj/file_io_ansi.c new file mode 100644 index 00000000..f95c74a9 --- /dev/null +++ b/pjlib/src/pj/file_io_ansi.c @@ -0,0 +1,138 @@ +/* $Id$ */ +#include <pj/file_io.h> +#include <pj/assert.h> +#include <pj/errno.h> +#include <stdio.h> +#include <errno.h> + +PJ_DEF(pj_status_t) pj_file_open( pj_pool_t *pool, + const char *pathname, + unsigned flags, + pj_oshandle_t *fd) +{ + char mode[8]; + char *p = mode; + + PJ_ASSERT_RETURN(pathname && fd, PJ_EINVAL); + PJ_UNUSED_ARG(pool); + + if ((flags & PJ_O_APPEND) == PJ_O_APPEND) { + if ((flags & PJ_O_WRONLY) == PJ_O_WRONLY) { + *p++ = 'a'; + if ((flags & PJ_O_RDONLY) == PJ_O_RDONLY) + *p++ = '+'; + } else { + /* This is invalid. + * Can not specify PJ_O_RDONLY with PJ_O_APPEND! + */ + } + } else { + if ((flags & PJ_O_RDONLY) == PJ_O_RDONLY) { + *p++ = 'r'; + if ((flags & PJ_O_WRONLY) == PJ_O_WRONLY) + *p++ = '+'; + } else { + *p++ = 'w'; + } + } + + if (p==mode) + return PJ_EINVAL; + + *p++ = 'b'; + *p++ = '\0'; + + *fd = fopen(pathname, mode); + if (*fd == NULL) + return PJ_RETURN_OS_ERROR(errno); + + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) pj_file_close(pj_oshandle_t fd) +{ + PJ_ASSERT_RETURN(fd, PJ_EINVAL); + if (fclose((FILE*)fd) != 0) + return PJ_RETURN_OS_ERROR(errno); + + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) pj_file_write( pj_oshandle_t fd, + const void *data, + pj_ssize_t *size) +{ + size_t written; + + clearerr((FILE*)fd); + written = fwrite(data, 1, *size, (FILE*)fd); + if (ferror((FILE*)fd)) { + return PJ_RETURN_OS_ERROR(errno); + } + + *size = written; + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) pj_file_read( pj_oshandle_t fd, + void *data, + pj_ssize_t *size) +{ + size_t bytes; + + clearerr((FILE*)fd); + bytes = fread(data, 1, *size, (FILE*)fd); + if (ferror((FILE*)fd)) { + return PJ_RETURN_OS_ERROR(errno); + } + + *size = bytes; + return PJ_SUCCESS; +} +
+PJ_DEF(pj_bool_t) pj_file_eof(pj_oshandle_t fd, enum pj_file_access access)
+{
+ PJ_UNUSED_ARG(access);
+ return feof((FILE*)fd) ? PJ_TRUE : 0;
+}
+ +PJ_DEF(pj_status_t) pj_file_setpos( pj_oshandle_t fd, + pj_off_t offset, + enum pj_file_seek_type whence) +{ + int mode; + + switch (whence) { + case PJ_SEEK_SET: + mode = SEEK_SET; break; + case PJ_SEEK_CUR: + mode = SEEK_CUR; break; + case PJ_SEEK_END: + mode = SEEK_END; break; + default: + pj_assert(!"Invalid whence in file_setpos"); + return PJ_EINVAL; + } + + if (fseek((FILE*)fd, (long)offset, mode) != 0) + return PJ_RETURN_OS_ERROR(errno); + + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) pj_file_getpos( pj_oshandle_t fd, + pj_off_t *pos) +{ + long offset; + + offset = ftell((FILE*)fd); + if (offset == -1) { + *pos = -1; + return PJ_RETURN_OS_ERROR(errno); + } + + *pos = offset; + return PJ_SUCCESS; +} + + diff --git a/pjlib/src/pj/file_io_win32.c b/pjlib/src/pj/file_io_win32.c new file mode 100644 index 00000000..d9908410 --- /dev/null +++ b/pjlib/src/pj/file_io_win32.c @@ -0,0 +1,186 @@ +/* $Id$ */ +#include <pj/file_io.h> +#include <pj/errno.h> +#include <pj/assert.h> + +#include <windows.h> + +#ifndef INVALID_SET_FILE_POINTER +# define INVALID_SET_FILE_POINTER ((DWORD)-1) +#endif +
+/**
+ * Check for end-of-file condition on the specified descriptor.
+ *
+ * @param fd The file descriptor.
+ * @param access The desired access.
+ *
+ * @return Non-zero if file is EOF.
+ */
+PJ_DECL(pj_bool_t) pj_file_eof(pj_oshandle_t fd,
+ enum pj_file_access access);
+ + +PJ_DEF(pj_status_t) pj_file_open( pj_pool_t *pool, + const char *pathname, + unsigned flags, + pj_oshandle_t *fd) +{ + HANDLE hFile; + DWORD dwDesiredAccess = 0; + DWORD dwShareMode = 0; + DWORD dwCreationDisposition = 0; + DWORD dwFlagsAndAttributes = 0; + + PJ_UNUSED_ARG(pool); + + PJ_ASSERT_RETURN(pathname!=NULL, PJ_EINVAL); + + if ((flags & PJ_O_WRONLY) == PJ_O_WRONLY) { + dwDesiredAccess |= GENERIC_WRITE; + if ((flags & PJ_O_APPEND) == PJ_O_APPEND) { + dwDesiredAccess |= FILE_APPEND_DATA; + } else { + dwDesiredAccess &= ~(FILE_APPEND_DATA);
+ dwCreationDisposition |= CREATE_ALWAYS;
+ } + } + if ((flags & PJ_O_RDONLY) == PJ_O_RDONLY) {
+ dwDesiredAccess |= GENERIC_READ;
+ if (flags == PJ_O_RDONLY)
+ dwCreationDisposition |= OPEN_EXISTING;
+ }
+ + if (dwDesiredAccess == 0) { + pj_assert(!"Invalid file open flags"); + return PJ_EINVAL; + } + + dwShareMode = FILE_SHARE_READ | FILE_SHARE_WRITE; + dwFlagsAndAttributes = FILE_ATTRIBUTE_NORMAL; +
+ hFile = CreateFile(pathname, dwDesiredAccess, dwShareMode, NULL, + dwCreationDisposition, dwFlagsAndAttributes, NULL); + if (hFile == INVALID_HANDLE_VALUE) { + *fd = 0; + return PJ_RETURN_OS_ERROR(GetLastError()); + } + + *fd = hFile; + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) pj_file_close(pj_oshandle_t fd) +{ + if (CloseHandle(fd)==0) + return PJ_RETURN_OS_ERROR(GetLastError()); + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) pj_file_write( pj_oshandle_t fd, + const void *data, + pj_ssize_t *size) +{ + BOOL rc; + DWORD bytesWritten; + + rc = WriteFile(fd, data, *size, &bytesWritten, NULL); + if (!rc) { + *size = -1; + return PJ_RETURN_OS_ERROR(GetLastError()); + } + + *size = bytesWritten; + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) pj_file_read( pj_oshandle_t fd, + void *data, + pj_ssize_t *size) +{ + BOOL rc; + DWORD bytesRead; + + rc = ReadFile(fd, data, *size, &bytesRead, NULL); + if (!rc) { + *size = -1; + return PJ_RETURN_OS_ERROR(GetLastError()); + } + + *size = bytesRead; + return PJ_SUCCESS; +} +
+/*
+PJ_DEF(pj_bool_t) pj_file_eof(pj_oshandle_t fd, enum pj_file_access access)
+{
+ BOOL rc;
+ DWORD dummy = 0, bytes;
+ DWORD dwStatus;
+
+ if ((access & PJ_O_RDONLY) == PJ_O_RDONLY) {
+ rc = ReadFile(fd, &dummy, 0, &bytes, NULL);
+ } else if ((access & PJ_O_WRONLY) == PJ_O_WRONLY) {
+ rc = WriteFile(fd, &dummy, 0, &bytes, NULL);
+ } else {
+ pj_assert(!"Invalid access");
+ return PJ_TRUE;
+ }
+
+ dwStatus = GetLastError();
+ if (dwStatus==ERROR_HANDLE_EOF)
+ return PJ_TRUE;
+
+ return 0;
+}
+*/
+ +PJ_DEF(pj_status_t) pj_file_setpos( pj_oshandle_t fd, + pj_off_t offset, + enum pj_file_seek_type whence) +{ + DWORD dwMoveMethod; + DWORD dwNewPos; + LONG hi32; + + if (whence == PJ_SEEK_SET) + dwMoveMethod = FILE_BEGIN; + else if (whence == PJ_SEEK_CUR) + dwMoveMethod = FILE_CURRENT; + else if (whence == PJ_SEEK_END) + dwMoveMethod = FILE_END; + else { + pj_assert(!"Invalid whence in file_setpos"); + return PJ_EINVAL; + } + + hi32 = (LONG)(offset >> 32); + dwNewPos = SetFilePointer(fd, (long)offset, &hi32, dwMoveMethod); + if (dwNewPos == (DWORD)INVALID_SET_FILE_POINTER) { + DWORD dwStatus = GetLastError(); + if (dwStatus != 0) + return PJ_RETURN_OS_ERROR(dwStatus); + /* dwNewPos actually is not an error. */ + } + + return PJ_SUCCESS; +} + +PJ_DEF(pj_status_t) pj_file_getpos( pj_oshandle_t fd, + pj_off_t *pos) +{ + LONG hi32 = 0; + DWORD lo32; + + lo32 = SetFilePointer(fd, 0, &hi32, FILE_CURRENT); + if (lo32 == (DWORD)INVALID_SET_FILE_POINTER) { + DWORD dwStatus = GetLastError(); + if (dwStatus != 0) + return PJ_RETURN_OS_ERROR(dwStatus); + } + + *pos = hi32; + *pos = (*pos << 32) + lo32; + return PJ_SUCCESS; +} + diff --git a/pjlib/src/pj/ioqueue_winnt.c b/pjlib/src/pj/ioqueue_winnt.c index afb75c54..32a74666 100644 --- a/pjlib/src/pj/ioqueue_winnt.c +++ b/pjlib/src/pj/ioqueue_winnt.c @@ -33,9 +33,9 @@ typedef struct generic_overlapped WSAOVERLAPPED overlapped;
pj_ioqueue_operation_e operation;
} generic_overlapped;
- +
/* - * OVERLAP structure for send and receive. + * OVERLAPPPED structure for send and receive. */ typedef struct ioqueue_overlapped { @@ -74,6 +74,14 @@ union operation_key ioqueue_accept_rec accept;
#endif
};
+
+/* Type of handle in the key. */
+enum handle_type
+{
+ HND_IS_UNKNOWN,
+ HND_IS_FILE,
+ HND_IS_SOCKET,
+};
/* * Structure for individual socket. @@ -82,7 +90,8 @@ struct pj_ioqueue_key_t {
pj_ioqueue_t *ioqueue; HANDLE hnd; - void *user_data; + void *user_data;
+ enum handle_type hnd_type; #if PJ_HAS_TCP int connecting; #endif @@ -316,7 +325,8 @@ PJ_DEF(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool, /* Build the key for this socket. */ rec = pj_pool_zalloc(pool, sizeof(pj_ioqueue_key_t));
rec->ioqueue = ioqueue; - rec->hnd = (HANDLE)sock; + rec->hnd = (HANDLE)sock;
+ rec->hnd_type = HND_IS_SOCKET; rec->user_data = user_data; pj_memcpy(&rec->cb, cb, sizeof(pj_ioqueue_callback)); @@ -336,7 +346,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_register_sock( pj_pool_t *pool, *key = rec; return PJ_SUCCESS; } - +
/* * pj_ioqueue_unregister()
*/ @@ -362,7 +372,10 @@ PJ_DEF(pj_status_t) pj_ioqueue_unregister( pj_ioqueue_key_t *key ) key->connecting = 0;
pj_lock_release(ioqueue->lock); } -#endif +#endif
+ if (key->hnd_type == HND_IS_FILE) {
+ CloseHandle(key->hnd);
+ } return PJ_SUCCESS; } @@ -482,7 +495,7 @@ PJ_DEF(int) pj_ioqueue_poll( pj_ioqueue_t *ioqueue, const pj_time_val *timeout) } return -1; } - +
/* * pj_ioqueue_recv() * @@ -505,7 +518,7 @@ PJ_DEF(pj_status_t) pj_ioqueue_recv( pj_ioqueue_key_t *key, union operation_key *op_key_rec;
PJ_CHECK_STACK();
- PJ_ASSERT_RETURN(key && op_key && buffer, PJ_EINVAL);
+ PJ_ASSERT_RETURN(key && op_key && buffer && length, PJ_EINVAL);
op_key_rec = (union operation_key*)op_key->internal__;
op_key_rec->overlapped.wsabuf.buf = buffer;
|