winpr/file: refactoring
The used method for initalizing and registering the handle creators had certain disadvantages like that it was necessary to have the creators initialized before the first call to CreateFile. In case of comm it wouldn't have been possible to open an comm port without calling any other call related function first. Now the handle creators are initialized the first time CreateFile is called. This way it is also possible to ensure a certain order of the handler invocations. This commit also splits out the client side named pipe code from the generic file handling (now called generic.c instead of file.c) and uses the new handle creator infrastructure to register.
This commit is contained in:
parent
4626f17cf2
commit
204ae5462a
@ -71,7 +71,7 @@ typedef struct comm_device COMM_DEVICE;
|
||||
static COMM_DEVICE **_CommDevices = NULL;
|
||||
static CRITICAL_SECTION _CommDevicesLock;
|
||||
|
||||
static HANDLE_CREATOR *_CommHandleCreator = NULL;
|
||||
static HANDLE_CREATOR _CommHandleCreator;
|
||||
|
||||
static pthread_once_t _CommInitialized = PTHREAD_ONCE_INIT;
|
||||
|
||||
@ -85,14 +85,19 @@ static int CommGetFd(HANDLE handle)
|
||||
return comm->fd;
|
||||
}
|
||||
|
||||
static void _CommInit()
|
||||
HANDLE_CREATOR *GetCommHandleCreator(void)
|
||||
{
|
||||
_CommHandleCreator.IsHandled = IsCommDevice;
|
||||
_CommHandleCreator.CreateFileA = CommCreateFileA;
|
||||
return &_CommHandleCreator;
|
||||
}
|
||||
|
||||
static void _CommInit(void)
|
||||
{
|
||||
/* NB: error management to be done outside of this function */
|
||||
|
||||
assert(_Log == NULL);
|
||||
assert(_CommDevices == NULL);
|
||||
assert(_CommHandleCreator == NULL);
|
||||
|
||||
|
||||
_CommDevices = (COMM_DEVICE**)calloc(COMM_DEVICE_MAX+1, sizeof(COMM_DEVICE*));
|
||||
if (!_CommDevices)
|
||||
@ -105,32 +110,10 @@ static void _CommInit()
|
||||
return;
|
||||
}
|
||||
|
||||
_CommHandleCreator = (HANDLE_CREATOR*)malloc(sizeof(HANDLE_CREATOR));
|
||||
if (!_CommHandleCreator)
|
||||
{
|
||||
DeleteCriticalSection(&_CommDevicesLock);
|
||||
free(_CommDevices);
|
||||
_CommDevices = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
_CommHandleCreator->IsHandled = IsCommDevice;
|
||||
_CommHandleCreator->CreateFileA = CommCreateFileA;
|
||||
|
||||
if (!RegisterHandleCreator(_CommHandleCreator))
|
||||
{
|
||||
DeleteCriticalSection(&_CommDevicesLock);
|
||||
free(_CommDevices);
|
||||
free(_CommHandleCreator);
|
||||
_CommDevices = NULL;
|
||||
_CommHandleCreator = NULL;
|
||||
return;
|
||||
}
|
||||
_Log = WLog_Get("com.winpr.comm");
|
||||
assert(_Log != NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns TRUE when the comm module is correctly intialized, FALSE otherwise
|
||||
* with ERROR_DLL_INIT_FAILED set as the last error.
|
||||
@ -143,12 +126,6 @@ static BOOL CommInitialized()
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (_CommHandleCreator == NULL)
|
||||
{
|
||||
SetLastError(ERROR_DLL_INIT_FAILED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
winpr_module_add(file.c pattern.c)
|
||||
winpr_module_add(generic.c namedPipeClient.c pattern.c)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
|
@ -25,11 +25,6 @@
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/synch.h>
|
||||
#include <winpr/error.h>
|
||||
#include <winpr/handle.h>
|
||||
#include <winpr/platform.h>
|
||||
#include <winpr/collections.h>
|
||||
|
||||
#include <winpr/file.h>
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
@ -42,7 +37,34 @@
|
||||
|
||||
#include "../log.h"
|
||||
#define TAG WINPR_TAG("file")
|
||||
#include <winpr/handle.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <sys/un.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#ifdef HAVE_AIO_H
|
||||
#undef HAVE_AIO_H /* disable for now, incomplete */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_AIO_H
|
||||
#include <aio.h>
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <sys/vfs.h>
|
||||
#else
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
|
||||
#include "../handle/handle.h"
|
||||
|
||||
#include "../pipe/pipe.h"
|
||||
|
||||
/**
|
||||
* api-ms-win-core-file-l1-2-0.dll:
|
||||
@ -148,172 +170,27 @@
|
||||
* http://code.google.com/p/kernel/wiki/AIOUserGuide
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <time.h>
|
||||
#include <errno.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#ifdef HAVE_AIO_H
|
||||
#undef HAVE_AIO_H /* disable for now, incomplete */
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_AIO_H
|
||||
#include <aio.h>
|
||||
#endif
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <signal.h>
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <sys/vfs.h>
|
||||
#else
|
||||
#include <sys/statvfs.h>
|
||||
#endif
|
||||
|
||||
#include "../handle/handle.h"
|
||||
|
||||
#include "../pipe/pipe.h"
|
||||
|
||||
/* TODO: FIXME: use of a wArrayList and split winpr-utils with
|
||||
* winpr-collections to avoid a circular dependency
|
||||
* _HandleCreators = ArrayList_New(TRUE);
|
||||
*/
|
||||
/* _HandleCreators is a NULL-terminated array with a maximun of HANDLE_CREATOR_MAX HANDLE_CREATOR */
|
||||
#define HANDLE_CREATOR_MAX 128
|
||||
static HANDLE_CREATOR** _HandleCreators = NULL;
|
||||
static CRITICAL_SECTION _HandleCreatorsLock;
|
||||
static wArrayList *_HandleCreators;
|
||||
|
||||
static pthread_once_t _HandleCreatorsInitialized = PTHREAD_ONCE_INIT;
|
||||
|
||||
static BOOL FileCloseHandle(HANDLE handle);
|
||||
|
||||
static BOOL FileIsHandled(HANDLE handle)
|
||||
{
|
||||
WINPR_NAMED_PIPE* pFile = (WINPR_NAMED_PIPE*) handle;
|
||||
|
||||
if (!pFile || (pFile->Type != HANDLE_TYPE_NAMED_PIPE) || (pFile == INVALID_HANDLE_VALUE))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOL FileCloseHandle(HANDLE handle) {
|
||||
WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*) handle;
|
||||
|
||||
|
||||
if (!FileIsHandled(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 FileGetFd(HANDLE handle)
|
||||
{
|
||||
WINPR_NAMED_PIPE *file = (WINPR_NAMED_PIPE *)handle;
|
||||
|
||||
if (!FileIsHandled(handle))
|
||||
return -1;
|
||||
|
||||
if (file->ServerMode)
|
||||
return file->serverfd;
|
||||
else
|
||||
return file->clientfd;
|
||||
}
|
||||
HANDLE_CREATOR *GetNamedPipeClientHandleCreator(void);
|
||||
HANDLE_CREATOR *GetCommHandleCreator(void);
|
||||
|
||||
static void _HandleCreatorsInit()
|
||||
{
|
||||
/* NB: error management to be done outside of this function */
|
||||
|
||||
assert(_HandleCreators == NULL);
|
||||
_HandleCreators = (HANDLE_CREATOR**)calloc(HANDLE_CREATOR_MAX+1, sizeof(HANDLE_CREATOR*));
|
||||
_HandleCreators = ArrayList_New(TRUE);
|
||||
if (!_HandleCreators)
|
||||
return;
|
||||
|
||||
if (!InitializeCriticalSectionEx(&_HandleCreatorsLock, 0, 0))
|
||||
{
|
||||
free(_HandleCreators);
|
||||
_HandleCreators = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns TRUE on success, FALSE otherwise.
|
||||
*
|
||||
* ERRORS:
|
||||
* ERROR_DLL_INIT_FAILED
|
||||
* ERROR_INSUFFICIENT_BUFFER _HandleCreators full
|
||||
*/
|
||||
BOOL RegisterHandleCreator(PHANDLE_CREATOR pHandleCreator)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (pthread_once(&_HandleCreatorsInitialized, _HandleCreatorsInit) != 0)
|
||||
{
|
||||
SetLastError(ERROR_DLL_INIT_FAILED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (_HandleCreators == NULL)
|
||||
{
|
||||
SetLastError(ERROR_DLL_INIT_FAILED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&_HandleCreatorsLock);
|
||||
|
||||
for (i=0; i<HANDLE_CREATOR_MAX; i++)
|
||||
{
|
||||
if (_HandleCreators[i] == NULL)
|
||||
{
|
||||
_HandleCreators[i] = pHandleCreator;
|
||||
LeaveCriticalSection(&_HandleCreatorsLock);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
SetLastError(ERROR_INSUFFICIENT_BUFFER);
|
||||
LeaveCriticalSection(&_HandleCreatorsLock);
|
||||
return FALSE;
|
||||
/*
|
||||
* Register all file handle creators.
|
||||
*/
|
||||
ArrayList_Add(_HandleCreators, GetNamedPipeClientHandleCreator());
|
||||
ArrayList_Add(_HandleCreators, GetCommHandleCreator());
|
||||
}
|
||||
|
||||
|
||||
@ -344,25 +221,10 @@ int InstallAioSignalHandler()
|
||||
|
||||
#endif /* HAVE_AIO_H */
|
||||
|
||||
|
||||
static HANDLE_OPS ops = {
|
||||
FileIsHandled,
|
||||
FileCloseHandle,
|
||||
FileGetFd,
|
||||
NULL, /* CleanupHandle */
|
||||
NamedPipeRead,
|
||||
NamedPipeWrite
|
||||
};
|
||||
|
||||
HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
|
||||
{
|
||||
int i;
|
||||
char* name;
|
||||
int status;
|
||||
HANDLE hNamedPipe;
|
||||
struct sockaddr_un s;
|
||||
WINPR_NAMED_PIPE* pNamedPipe;
|
||||
|
||||
if (!lpFileName)
|
||||
return INVALID_HANDLE_VALUE;
|
||||
@ -379,106 +241,23 @@ HANDLE CreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
EnterCriticalSection(&_HandleCreatorsLock);
|
||||
ArrayList_Lock(_HandleCreators);
|
||||
|
||||
for (i=0; _HandleCreators[i] != NULL; i++)
|
||||
for (i=0; i <= ArrayList_Count(_HandleCreators); i++)
|
||||
{
|
||||
HANDLE_CREATOR* creator = (HANDLE_CREATOR*)_HandleCreators[i];
|
||||
HANDLE_CREATOR* creator = ArrayList_GetItem(_HandleCreators, i);
|
||||
|
||||
if (creator && creator->IsHandled(lpFileName))
|
||||
{
|
||||
HANDLE newHandle = creator->CreateFileA(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes,
|
||||
dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile);
|
||||
LeaveCriticalSection(&_HandleCreatorsLock);
|
||||
ArrayList_Unlock(_HandleCreators);
|
||||
return newHandle;
|
||||
}
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&_HandleCreatorsLock);
|
||||
|
||||
/* TODO: use of a HANDLE_CREATOR for named pipes as well */
|
||||
|
||||
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;
|
||||
ZeroMemory(&s, sizeof(struct sockaddr_un));
|
||||
s.sun_family = AF_UNIX;
|
||||
strcpy(s.sun_path, pNamedPipe->lpFilePath);
|
||||
status = connect(pNamedPipe->clientfd, (struct sockaddr*) &s, sizeof(struct sockaddr_un));
|
||||
|
||||
pNamedPipe->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;
|
||||
ArrayList_Unlock(_HandleCreators);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
HANDLE CreateFileW(LPCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
@ -807,72 +586,6 @@ BOOL RemoveDirectoryW(LPCWSTR lpPathName)
|
||||
|
||||
/* 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;
|
||||
|
||||
if (!lpName)
|
||||
return NULL;
|
||||
|
||||
if (!IsNamedPipeFileNameA(lpName))
|
||||
return NULL;
|
||||
|
||||
lpFileName = _strdup(&lpName[strlen(NAMED_PIPE_PREFIX_PATH)]);
|
||||
return lpFileName;
|
||||
}
|
||||
|
||||
char* GetNamedPipeUnixDomainSocketBaseFilePathA()
|
||||
{
|
||||
char* lpTempPath;
|
||||
char* lpPipePath;
|
||||
lpTempPath = GetKnownPath(KNOWN_PATH_TEMP);
|
||||
if (!lpTempPath)
|
||||
return NULL;
|
||||
lpPipePath = GetCombinedPath(lpTempPath, ".pipe");
|
||||
free(lpTempPath);
|
||||
return lpPipePath;
|
||||
}
|
||||
|
||||
char* GetNamedPipeUnixDomainSocketFilePathA(LPCSTR lpName)
|
||||
{
|
||||
char* lpPipePath;
|
||||
char* lpFileName;
|
||||
char* lpFilePath;
|
||||
lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA();
|
||||
lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
|
||||
lpFilePath = GetCombinedPath(lpPipePath, (char*) lpFileName);
|
||||
free(lpPipePath);
|
||||
free(lpFileName);
|
||||
return lpFilePath;
|
||||
}
|
||||
|
||||
int GetNamePipeFileDescriptor(HANDLE hNamedPipe)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
int fd;
|
||||
WINPR_NAMED_PIPE* pNamedPipe;
|
||||
pNamedPipe = (WINPR_NAMED_PIPE*) hNamedPipe;
|
||||
|
||||
if (!pNamedPipe || pNamedPipe->Type != HANDLE_TYPE_NAMED_PIPE)
|
||||
return -1;
|
||||
|
||||
fd = (pNamedPipe->ServerMode) ? pNamedPipe->serverfd : pNamedPipe->clientfd;
|
||||
return fd;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int UnixChangeFileMode(const char* filename, int flags)
|
||||
{
|
||||
#ifndef _WIN32
|
287
winpr/libwinpr/file/namedPipeClient.c
Normal file
287
winpr/libwinpr/file/namedPipeClient.c
Normal file
@ -0,0 +1,287 @@
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <winpr/crt.h>
|
||||
#include <winpr/path.h>
|
||||
#include <winpr/file.h>
|
||||
|
||||
#ifdef 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)
|
||||
{
|
||||
WINPR_NAMED_PIPE* pFile = (WINPR_NAMED_PIPE*) handle;
|
||||
|
||||
if (!pFile || (pFile->Type != HANDLE_TYPE_NAMED_PIPE) || (pFile == INVALID_HANDLE_VALUE))
|
||||
{
|
||||
SetLastError(ERROR_INVALID_HANDLE);
|
||||
return FALSE;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
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,
|
||||
NamedPipeWrite
|
||||
};
|
||||
|
||||
static HANDLE NamedPipeClientCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes,
|
||||
DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
|
||||
{
|
||||
char* name;
|
||||
int status;
|
||||
HANDLE hNamedPipe;
|
||||
struct sockaddr_un s;
|
||||
WINPR_NAMED_PIPE* pNamedPipe;
|
||||
|
||||
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;
|
||||
ZeroMemory(&s, sizeof(struct sockaddr_un));
|
||||
s.sun_family = AF_UNIX;
|
||||
strcpy(s.sun_path, pNamedPipe->lpFilePath);
|
||||
status = connect(pNamedPipe->clientfd, (struct sockaddr*) &s, sizeof(struct sockaddr_un));
|
||||
|
||||
pNamedPipe->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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (!lpName)
|
||||
return NULL;
|
||||
|
||||
if (!IsNamedPipeFileNameA(lpName))
|
||||
return NULL;
|
||||
|
||||
lpFileName = _strdup(&lpName[strlen(NAMED_PIPE_PREFIX_PATH)]);
|
||||
return lpFileName;
|
||||
}
|
||||
|
||||
char* GetNamedPipeUnixDomainSocketBaseFilePathA()
|
||||
{
|
||||
char* lpTempPath;
|
||||
char* lpPipePath;
|
||||
lpTempPath = GetKnownPath(KNOWN_PATH_TEMP);
|
||||
if (!lpTempPath)
|
||||
return NULL;
|
||||
lpPipePath = GetCombinedPath(lpTempPath, ".pipe");
|
||||
free(lpTempPath);
|
||||
return lpPipePath;
|
||||
}
|
||||
|
||||
char* GetNamedPipeUnixDomainSocketFilePathA(LPCSTR lpName)
|
||||
{
|
||||
char* lpPipePath;
|
||||
char* lpFileName;
|
||||
char* lpFilePath;
|
||||
lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA();
|
||||
lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
|
||||
lpFilePath = GetCombinedPath(lpPipePath, (char*) lpFileName);
|
||||
free(lpPipePath);
|
||||
free(lpFileName);
|
||||
return lpFilePath;
|
||||
}
|
||||
|
||||
int GetNamePipeFileDescriptor(HANDLE hNamedPipe)
|
||||
{
|
||||
#ifndef _WIN32
|
||||
int fd;
|
||||
WINPR_NAMED_PIPE* pNamedPipe;
|
||||
pNamedPipe = (WINPR_NAMED_PIPE*) hNamedPipe;
|
||||
|
||||
if (!pNamedPipe || pNamedPipe->Type != HANDLE_TYPE_NAMED_PIPE)
|
||||
return -1;
|
||||
|
||||
fd = (pNamedPipe->ServerMode) ? pNamedPipe->serverfd : pNamedPipe->clientfd;
|
||||
return fd;
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
@ -102,7 +102,7 @@ static INLINE int winpr_Handle_getFd(HANDLE handle)
|
||||
if (!winpr_Handle_GetInfo(handle, &type, &hdl))
|
||||
return -1;
|
||||
|
||||
if (!hdl || !hdl->ops->GetFd)
|
||||
if (!hdl || !hdl->ops || !hdl->ops->GetFd)
|
||||
return -1;
|
||||
|
||||
return hdl->ops->GetFd(handle);
|
||||
@ -116,7 +116,7 @@ static INLINE DWORD winpr_Handle_cleanup(HANDLE handle)
|
||||
if (!winpr_Handle_GetInfo(handle, &type, &hdl))
|
||||
return WAIT_FAILED;
|
||||
|
||||
if (!hdl)
|
||||
if (!hdl || !hdl->ops)
|
||||
return WAIT_FAILED;
|
||||
|
||||
/* If there is no cleanup function, assume all ok. */
|
||||
|
@ -36,12 +36,6 @@ static void* named_pipe_client_thread(void* arg)
|
||||
WaitForSingleObject(ReadyEvent, INFINITE);
|
||||
hNamedPipe = CreateFile(lpszPipeNameMt, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
if (!hNamedPipe)
|
||||
{
|
||||
printf("%s:Named Pipe CreateFile failure: NULL handle\n", __FUNCTION__);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (hNamedPipe == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf("%s: Named Pipe CreateFile failure: INVALID_HANDLE_VALUE\n", __FUNCTION__);
|
||||
@ -252,8 +246,8 @@ static void* named_pipe_single_thread(void* arg)
|
||||
|
||||
for (i = 0; i < numPipes; i++)
|
||||
{
|
||||
if (!(clients[i] = CreateFile(lpszPipeNameSt, GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, OPEN_EXISTING, 0, NULL)))
|
||||
if ((clients[i] = CreateFile(lpszPipeNameSt, GENERIC_READ | GENERIC_WRITE,
|
||||
0, NULL, OPEN_EXISTING, 0, NULL)) == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
printf("%s: CreateFile #%d failed\n", __FUNCTION__, i);
|
||||
goto out;
|
||||
|
Loading…
Reference in New Issue
Block a user