summaryrefslogtreecommitdiffstats
path: root/winpr/libwinpr/file/namedPipeClient.c
diff options
context:
space:
mode:
Diffstat (limited to 'winpr/libwinpr/file/namedPipeClient.c')
-rw-r--r--winpr/libwinpr/file/namedPipeClient.c305
1 files changed, 305 insertions, 0 deletions
diff --git a/winpr/libwinpr/file/namedPipeClient.c b/winpr/libwinpr/file/namedPipeClient.c
new file mode 100644
index 0000000..fbfeb35
--- /dev/null
+++ b/winpr/libwinpr/file/namedPipeClient.c
@@ -0,0 +1,305 @@
+/**
+ * WinPR: Windows Portable Runtime
+ * File Functions
+ *
+ * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2014 Hewlett-Packard Development Company, L.P.
+ * Copyright 2015 Thincast Technologies GmbH
+ * Copyright 2015 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/config.h>
+
+#include <winpr/crt.h>
+#include <winpr/path.h>
+#include <winpr/file.h>
+
+#ifdef WINPR_HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "../log.h"
+#define TAG WINPR_TAG("file")
+
+#ifndef _WIN32
+
+#ifdef ANDROID
+#include <sys/vfs.h>
+#else
+#include <sys/statvfs.h>
+#endif
+
+#include "../handle/handle.h"
+
+#include "../pipe/pipe.h"
+
+static HANDLE_CREATOR _NamedPipeClientHandleCreator;
+
+static BOOL NamedPipeClientIsHandled(HANDLE handle)
+{
+ return WINPR_HANDLE_IS_HANDLED(handle, HANDLE_TYPE_NAMED_PIPE, TRUE);
+}
+
+static BOOL NamedPipeClientCloseHandle(HANDLE handle)
+{
+ WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)handle;
+
+ if (!NamedPipeClientIsHandled(handle))
+ return FALSE;
+
+ if (pNamedPipe->clientfd != -1)
+ {
+ // WLOG_DBG(TAG, "closing clientfd %d", pNamedPipe->clientfd);
+ close(pNamedPipe->clientfd);
+ }
+
+ if (pNamedPipe->serverfd != -1)
+ {
+ // WLOG_DBG(TAG, "closing serverfd %d", pNamedPipe->serverfd);
+ close(pNamedPipe->serverfd);
+ }
+
+ if (pNamedPipe->pfnUnrefNamedPipe)
+ pNamedPipe->pfnUnrefNamedPipe(pNamedPipe);
+
+ free(pNamedPipe->lpFileName);
+ free(pNamedPipe->lpFilePath);
+ free(pNamedPipe->name);
+ free(pNamedPipe);
+ return TRUE;
+}
+
+static int NamedPipeClientGetFd(HANDLE handle)
+{
+ WINPR_NAMED_PIPE* file = (WINPR_NAMED_PIPE*)handle;
+
+ if (!NamedPipeClientIsHandled(handle))
+ return -1;
+
+ if (file->ServerMode)
+ return file->serverfd;
+ else
+ return file->clientfd;
+}
+
+static HANDLE_OPS ops = {
+ NamedPipeClientIsHandled,
+ NamedPipeClientCloseHandle,
+ NamedPipeClientGetFd,
+ NULL, /* CleanupHandle */
+ NamedPipeRead,
+ NULL, /* FileReadEx */
+ NULL, /* FileReadScatter */
+ NamedPipeWrite,
+ NULL, /* FileWriteEx */
+ NULL, /* FileWriteGather */
+ NULL, /* FileGetFileSize */
+ NULL, /* FlushFileBuffers */
+ NULL, /* FileSetEndOfFile */
+ NULL, /* FileSetFilePointer */
+ NULL, /* SetFilePointerEx */
+ NULL, /* FileLockFile */
+ NULL, /* FileLockFileEx */
+ NULL, /* FileUnlockFile */
+ NULL, /* FileUnlockFileEx */
+ NULL, /* SetFileTime */
+ NULL, /* FileGetFileInformationByHandle */
+};
+
+static HANDLE NamedPipeClientCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess,
+ DWORD dwShareMode,
+ LPSECURITY_ATTRIBUTES lpSecurityAttributes,
+ DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
+ HANDLE hTemplateFile)
+{
+ char* name = NULL;
+ int status = 0;
+ HANDLE hNamedPipe = NULL;
+ struct sockaddr_un s = { 0 };
+ WINPR_NAMED_PIPE* pNamedPipe = NULL;
+
+ if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
+ {
+ WLog_ERR(TAG, "WinPR does not support the FILE_FLAG_OVERLAPPED flag");
+ SetLastError(ERROR_NOT_SUPPORTED);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (!lpFileName)
+ return INVALID_HANDLE_VALUE;
+
+ if (!IsNamedPipeFileNameA(lpFileName))
+ return INVALID_HANDLE_VALUE;
+
+ name = GetNamedPipeNameWithoutPrefixA(lpFileName);
+
+ if (!name)
+ return INVALID_HANDLE_VALUE;
+
+ free(name);
+ pNamedPipe = (WINPR_NAMED_PIPE*)calloc(1, sizeof(WINPR_NAMED_PIPE));
+
+ if (!pNamedPipe)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ hNamedPipe = (HANDLE)pNamedPipe;
+ WINPR_HANDLE_SET_TYPE_AND_MODE(pNamedPipe, HANDLE_TYPE_NAMED_PIPE, WINPR_FD_READ);
+ pNamedPipe->name = _strdup(lpFileName);
+
+ if (!pNamedPipe->name)
+ {
+ SetLastError(ERROR_NOT_ENOUGH_MEMORY);
+ free(pNamedPipe);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ pNamedPipe->dwOpenMode = 0;
+ pNamedPipe->dwPipeMode = 0;
+ pNamedPipe->nMaxInstances = 0;
+ pNamedPipe->nOutBufferSize = 0;
+ pNamedPipe->nInBufferSize = 0;
+ pNamedPipe->nDefaultTimeOut = 0;
+ pNamedPipe->dwFlagsAndAttributes = dwFlagsAndAttributes;
+ pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpFileName);
+
+ if (!pNamedPipe->lpFileName)
+ {
+ free((void*)pNamedPipe->name);
+ free(pNamedPipe);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpFileName);
+
+ if (!pNamedPipe->lpFilePath)
+ {
+ free((void*)pNamedPipe->lpFileName);
+ free((void*)pNamedPipe->name);
+ free(pNamedPipe);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ pNamedPipe->clientfd = socket(PF_LOCAL, SOCK_STREAM, 0);
+ pNamedPipe->serverfd = -1;
+ pNamedPipe->ServerMode = FALSE;
+ s.sun_family = AF_UNIX;
+ sprintf_s(s.sun_path, ARRAYSIZE(s.sun_path), "%s", pNamedPipe->lpFilePath);
+ status = connect(pNamedPipe->clientfd, (struct sockaddr*)&s, sizeof(struct sockaddr_un));
+ pNamedPipe->common.ops = &ops;
+
+ if (status != 0)
+ {
+ close(pNamedPipe->clientfd);
+ free((char*)pNamedPipe->name);
+ free((char*)pNamedPipe->lpFileName);
+ free((char*)pNamedPipe->lpFilePath);
+ free(pNamedPipe);
+ return INVALID_HANDLE_VALUE;
+ }
+
+ if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
+ {
+#if 0
+ int flags = fcntl(pNamedPipe->clientfd, F_GETFL);
+
+ if (flags != -1)
+ fcntl(pNamedPipe->clientfd, F_SETFL, flags | O_NONBLOCK);
+
+#endif
+ }
+
+ return hNamedPipe;
+}
+
+extern HANDLE_CREATOR* GetNamedPipeClientHandleCreator(void);
+HANDLE_CREATOR* GetNamedPipeClientHandleCreator(void)
+{
+ _NamedPipeClientHandleCreator.IsHandled = IsNamedPipeFileNameA;
+ _NamedPipeClientHandleCreator.CreateFileA = NamedPipeClientCreateFileA;
+ return &_NamedPipeClientHandleCreator;
+}
+
+#endif
+
+/* Extended API */
+
+#define NAMED_PIPE_PREFIX_PATH "\\\\.\\pipe\\"
+
+BOOL IsNamedPipeFileNameA(LPCSTR lpName)
+{
+ if (strncmp(lpName, NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH) - 1) != 0)
+ return FALSE;
+
+ return TRUE;
+}
+
+char* GetNamedPipeNameWithoutPrefixA(LPCSTR lpName)
+{
+ char* lpFileName = NULL;
+
+ if (!lpName)
+ return NULL;
+
+ if (!IsNamedPipeFileNameA(lpName))
+ return NULL;
+
+ lpFileName = _strdup(&lpName[strnlen(NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH))]);
+ return lpFileName;
+}
+
+char* GetNamedPipeUnixDomainSocketBaseFilePathA(void)
+{
+ char* lpTempPath = NULL;
+ char* lpPipePath = NULL;
+ lpTempPath = GetKnownPath(KNOWN_PATH_TEMP);
+
+ if (!lpTempPath)
+ return NULL;
+
+ lpPipePath = GetCombinedPath(lpTempPath, ".pipe");
+ free(lpTempPath);
+ return lpPipePath;
+}
+
+char* GetNamedPipeUnixDomainSocketFilePathA(LPCSTR lpName)
+{
+ char* lpPipePath = NULL;
+ char* lpFileName = NULL;
+ char* lpFilePath = NULL;
+ lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA();
+ lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
+ lpFilePath = GetCombinedPath(lpPipePath, (char*)lpFileName);
+ free(lpPipePath);
+ free(lpFileName);
+ return lpFilePath;
+}
+
+int GetNamePipeFileDescriptor(HANDLE hNamedPipe)
+{
+#ifndef _WIN32
+ int fd = 0;
+ WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)hNamedPipe;
+
+ if (!NamedPipeClientIsHandled(hNamedPipe))
+ return -1;
+
+ fd = (pNamedPipe->ServerMode) ? pNamedPipe->serverfd : pNamedPipe->clientfd;
+ return fd;
+#else
+ return -1;
+#endif
+}