winpr/file: initial regular file support
authorBernhard Miklautz <bernhard.miklautz@thincast.com>
Wed, 9 Sep 2015 14:47:03 +0000 (16:47 +0200)
committerBernhard Miklautz <bernhard.miklautz@thincast.com>
Wed, 9 Sep 2015 14:47:03 +0000 (16:47 +0200)
Add initial support for "regular" files. First implemented call is
GetStdHandle to get stdin/stdout/stderr.

winpr/include/winpr/environment.h
winpr/include/winpr/file.h
winpr/libwinpr/environment/environment.c
winpr/libwinpr/file/CMakeLists.txt
winpr/libwinpr/file/file.c [new file with mode: 0644]
winpr/libwinpr/file/generic.c
winpr/libwinpr/file/namedPipeClient.c
winpr/libwinpr/file/test/CMakeLists.txt
winpr/libwinpr/file/test/TestFileGetStdHandle.c [new file with mode: 0644]

index 71bdc05..d6329d8 100644 (file)
@@ -40,10 +40,6 @@ WINPR_API BOOL SetCurrentDirectoryW(LPCWSTR lpPathName);
 WINPR_API DWORD SearchPathA(LPCSTR lpPath, LPCSTR lpFileName, LPCSTR lpExtension, DWORD nBufferLength, LPSTR lpBuffer, LPSTR* lpFilePart);
 WINPR_API DWORD SearchPathW(LPCWSTR lpPath, LPCWSTR lpFileName, LPCWSTR lpExtension, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR* lpFilePart);
 
-WINPR_API HANDLE GetStdHandle(DWORD nStdHandle);
-WINPR_API BOOL SetStdHandle(DWORD nStdHandle, HANDLE hHandle);
-WINPR_API BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle);
-
 WINPR_API LPSTR GetCommandLineA(VOID);
 WINPR_API LPWSTR GetCommandLineW(VOID);
 
index 45ec3e6..4d3a379 100644 (file)
 #define FIND_FIRST_EX_CASE_SENSITIVE           0x1
 #define FIND_FIRST_EX_LARGE_FETCH              0x2
 
+#define STD_INPUT_HANDLE  (DWORD)-10
+#define STD_OUTPUT_HANDLE (DWORD)-11
+#define STD_ERROR_HANDLE  (DWORD)-12
+
 typedef union _FILE_SEGMENT_ELEMENT
 {
        PVOID64 Buffer;
@@ -316,7 +320,6 @@ WINPR_API BOOL RemoveDirectoryW(LPCWSTR lpPathName);
 #define RemoveDirectory                RemoveDirectoryA
 #endif
 
-
 /* Extra Functions */
 
 typedef BOOL (*pcIsFileHandled)(LPCSTR lpFileName);
@@ -329,7 +332,9 @@ typedef struct _HANDLE_CREATOR
        pcCreateFileA CreateFileA;
 } HANDLE_CREATOR, *PHANDLE_CREATOR, *LPHANDLE_CREATOR;
 
-BOOL RegisterHandleCreator(PHANDLE_CREATOR pHandleCreator);
+WINPR_API HANDLE GetStdHandle(DWORD nStdHandle);
+WINPR_API BOOL SetStdHandle(DWORD nStdHandle, HANDLE hHandle);
+WINPR_API BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle);
 
 #endif /* _WIN32 */
 
index d871726..dcdb24f 100644 (file)
@@ -111,21 +111,6 @@ DWORD SearchPathW(LPCWSTR lpPath, LPCWSTR lpFileName, LPCWSTR lpExtension, DWORD
        return 0;
 }
 
-HANDLE GetStdHandle(DWORD nStdHandle)
-{
-       return NULL;
-}
-
-BOOL SetStdHandle(DWORD nStdHandle, HANDLE hHandle)
-{
-       return TRUE;
-}
-
-BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle)
-{
-       return TRUE;
-}
-
 LPSTR GetCommandLineA(VOID)
 {
        return NULL;
index 55a8e84..986c873 100644 (file)
@@ -15,7 +15,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-winpr_module_add(generic.c namedPipeClient.c pattern.c)
+winpr_module_add(generic.c namedPipeClient.c pattern.c file.c)
 
 if(BUILD_TESTING)
        add_subdirectory(test)
diff --git a/winpr/libwinpr/file/file.c b/winpr/libwinpr/file/file.c
new file mode 100644 (file)
index 0000000..b46ee4f
--- /dev/null
@@ -0,0 +1,222 @@
+/**
+ * WinPR: Windows Portable Runtime
+ * File Functions
+ *
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 Bernhard Miklautz <bernhard.miklautz@thincast.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _WIN32
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif /* HAVE_CONFIG_H */
+
+
+#include "../log.h"
+#define TAG WINPR_TAG("file")
+
+#include <winpr/file.h>
+#include <winpr/wlog.h>
+
+#include "../handle/handle.h"
+#include <errno.h>
+
+struct winpr_file
+{
+       WINPR_HANDLE_DEF();
+
+       int fd;
+};
+
+typedef struct winpr_file WINPR_FILE;
+
+static BOOL FileIsHandled(HANDLE handle)
+{
+       WINPR_FILE* pFile = (WINPR_FILE*) handle;
+
+       if (!pFile || (pFile->Type != HANDLE_TYPE_FILE))
+       {
+               SetLastError(ERROR_INVALID_HANDLE);
+               return FALSE;
+       }
+
+       return TRUE;
+}
+
+static int FileGetFd(HANDLE handle)
+{
+       WINPR_FILE *file= (WINPR_FILE*)handle;
+
+       if (!FileIsHandled(handle))
+               return -1;
+
+       return file->fd;
+}
+
+static BOOL FileCloseHandle(HANDLE handle) {
+       WINPR_FILE* file = (WINPR_FILE *)handle;
+
+       if (!FileIsHandled(handle))
+               return FALSE;
+
+       if (file->fd != -1)
+       {
+               close(file->fd);
+               file->fd = -1;
+       }
+
+       free(handle);
+       return TRUE;
+}
+
+static BOOL FileRead(PVOID Object, LPVOID lpBuffer, DWORD nNumberOfBytesToRead,
+                                       LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped)
+{
+       int io_status;
+       WINPR_FILE* file;
+       BOOL status = TRUE;
+
+       if (!Object)
+               return FALSE;
+
+       if (lpOverlapped)
+       {
+               WLog_ERR(TAG, "Overlapping write not supported.");
+               return FALSE;
+       }
+
+       file = (WINPR_FILE *)Object;
+       do
+       {
+               io_status = read(file->fd, lpBuffer, nNumberOfBytesToRead);
+       }
+       while ((io_status < 0) && (errno == EINTR));
+
+       if (io_status < 0)
+       {
+               status = FALSE;
+
+               switch (errno)
+               {
+                       case EWOULDBLOCK:
+                               SetLastError(ERROR_NO_DATA);
+                               break;
+               }
+       }
+
+       if (lpNumberOfBytesRead)
+               *lpNumberOfBytesRead = io_status;
+
+       return status;
+}
+
+static BOOL FileWrite(PVOID Object, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,
+                                               LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped)
+{
+       int io_status;
+       WINPR_FILE* file;
+
+       if (!Object)
+               return FALSE;
+
+       if (lpOverlapped)
+       {
+               WLog_ERR(TAG, "Overlapping write not supported.");
+               return FALSE;
+       }
+
+       file = (WINPR_FILE *)Object;
+
+       do
+       {
+               io_status = write(file->fd, lpBuffer, nNumberOfBytesToWrite);
+       }
+       while ((io_status < 0) && (errno == EINTR));
+
+       if ((io_status < 0) && (errno == EWOULDBLOCK))
+               io_status = 0;
+
+       *lpNumberOfBytesWritten = io_status;
+       return TRUE;
+}
+
+
+static HANDLE_OPS ops = {
+               FileIsHandled,
+               FileCloseHandle,
+               FileGetFd,
+               NULL, /* CleanupHandle */
+               FileRead,
+               FileWrite
+};
+
+static WINPR_FILE *FileHandle_New()
+{
+       WINPR_FILE *pFile;
+       HANDLE hFile;
+
+       pFile = (WINPR_FILE*) calloc(1, sizeof(WINPR_FILE));
+       if (!pFile)
+       {
+               SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+               return NULL;
+       }
+       pFile->fd = -1;
+       pFile->ops = &ops;
+
+       hFile = (HANDLE) pFile;
+       WINPR_HANDLE_SET_TYPE_AND_MODE(pFile, HANDLE_TYPE_FILE, WINPR_FD_READ);
+       return pFile;
+}
+
+HANDLE GetStdHandle(DWORD nStdHandle)
+{
+       int fd;
+       WINPR_FILE *pFile;
+       switch (nStdHandle)
+       {
+               case STD_INPUT_HANDLE:
+                       fd = STDIN_FILENO;
+                       break;
+               case STD_OUTPUT_HANDLE:
+                       fd = STDOUT_FILENO;
+                       break;
+               case STD_ERROR_HANDLE:
+                       fd = STDERR_FILENO;
+                       break;
+               default:
+                       return INVALID_HANDLE_VALUE;
+       }
+       pFile = FileHandle_New();
+       if (!pFile)
+               return INVALID_HANDLE_VALUE;
+
+       pFile->fd = fd;
+       return (HANDLE)pFile;
+}
+
+BOOL SetStdHandle(DWORD nStdHandle, HANDLE hHandle)
+{
+       return TRUE;
+}
+
+BOOL SetStdHandleEx(DWORD dwStdHandle, HANDLE hNewHandle, HANDLE* phOldHandle)
+{
+       return TRUE;
+}
+
+#endif /* _WIN32 */
+
index c71d17a..9eac8e1 100644 (file)
@@ -24,7 +24,6 @@
 
 #include <winpr/crt.h>
 #include <winpr/path.h>
-#include <winpr/synch.h>
 #include <winpr/file.h>
 
 #ifdef HAVE_UNISTD_H
index 2941d31..d2aed74 100644 (file)
@@ -61,7 +61,8 @@ static BOOL NamedPipeClientIsHandled(HANDLE handle)
        return TRUE;
 }
 
-BOOL NamedPipeClientCloseHandle(HANDLE handle) {
+BOOL NamedPipeClientCloseHandle(HANDLE handle)
+{
        WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*) handle;
 
 
index f23bde6..c7015c6 100644 (file)
@@ -12,7 +12,9 @@ set(${MODULE_PREFIX}_TESTS
        TestFilePatternMatch.c
        TestFileFindFirstFile.c
        TestFileFindFirstFileEx.c
-       TestFileFindNextFile.c)
+       TestFileFindNextFile.c
+       TestFileGetStdHandle.c
+)
 
 create_test_sourcelist(${MODULE_PREFIX}_SRCS
        ${${MODULE_PREFIX}_DRIVER}
diff --git a/winpr/libwinpr/file/test/TestFileGetStdHandle.c b/winpr/libwinpr/file/test/TestFileGetStdHandle.c
new file mode 100644 (file)
index 0000000..e37dd8c
--- /dev/null
@@ -0,0 +1,46 @@
+
+/**
+ * WinPR: Windows Portable Runtime
+ * File Functions
+ *
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 Bernhard Miklautz <bernhard.miklautz@thincast.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <winpr/file.h>
+#include <string.h>
+#include <stdio.h>
+
+int TestFileGetStdHandle(int argc, char* argv[])
+{
+       HANDLE stdout;
+       char *buf = "happy happy";
+       DWORD bytesWritten;
+
+       stdout = GetStdHandle(STD_OUTPUT_HANDLE);
+       if (stdout == INVALID_HANDLE_VALUE)
+       {
+               fprintf(stderr, "GetStdHandle failed ;(\n");
+               return -1;
+       }
+       WriteFile(stdout, buf, strlen(buf), &bytesWritten, FALSE);
+       if (bytesWritten != strlen(buf))
+       {
+               fprintf(stderr, "write failed\n");
+               return -1;
+       }
+
+       return 0;
+}
\ No newline at end of file