Blame winpr/libwinpr/file/namedPipeClient.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * WinPR: Windows Portable Runtime
Packit 1fb8d4
 * File Functions
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 * Copyright 2014 Hewlett-Packard Development Company, L.P.
Packit 1fb8d4
 * Copyright 2015 Thincast Technologies GmbH
Packit 1fb8d4
 * Copyright 2015 bernhard.miklautz@thincast.com
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_CONFIG_H
Packit 1fb8d4
#include "config.h"
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/path.h>
Packit 1fb8d4
#include <winpr/file.h>
Packit 1fb8d4
Packit 1fb8d4
#ifdef HAVE_UNISTD_H
Packit 1fb8d4
#include <unistd.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include "../log.h"
Packit 1fb8d4
#define TAG WINPR_TAG("file")
Packit 1fb8d4
Packit 1fb8d4
#ifndef _WIN32
Packit 1fb8d4
Packit 1fb8d4
#ifdef ANDROID
Packit 1fb8d4
#include <sys/vfs.h>
Packit 1fb8d4
#else
Packit 1fb8d4
#include <sys/statvfs.h>
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
#include "../handle/handle.h"
Packit 1fb8d4
Packit 1fb8d4
#include "../pipe/pipe.h"
Packit 1fb8d4
Packit 1fb8d4
static HANDLE_CREATOR _NamedPipeClientHandleCreator;
Packit 1fb8d4
Packit 1fb8d4
static BOOL NamedPipeClientIsHandled(HANDLE handle)
Packit 1fb8d4
{
Packit Service 5a9772
	WINPR_NAMED_PIPE* pFile = (WINPR_NAMED_PIPE*)handle;
Packit 1fb8d4
Packit 1fb8d4
	if (!pFile || (pFile->Type != HANDLE_TYPE_NAMED_PIPE) || (pFile == INVALID_HANDLE_VALUE))
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_INVALID_HANDLE);
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL NamedPipeClientCloseHandle(HANDLE handle)
Packit 1fb8d4
{
Packit Service 5a9772
	WINPR_NAMED_PIPE* pNamedPipe = (WINPR_NAMED_PIPE*)handle;
Packit 1fb8d4
Packit 1fb8d4
	if (!NamedPipeClientIsHandled(handle))
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (pNamedPipe->clientfd != -1)
Packit 1fb8d4
	{
Packit Service 5a9772
		// WLOG_DBG(TAG, "closing clientfd %d", pNamedPipe->clientfd);
Packit 1fb8d4
		close(pNamedPipe->clientfd);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (pNamedPipe->serverfd != -1)
Packit 1fb8d4
	{
Packit Service 5a9772
		// WLOG_DBG(TAG, "closing serverfd %d", pNamedPipe->serverfd);
Packit 1fb8d4
		close(pNamedPipe->serverfd);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (pNamedPipe->pfnUnrefNamedPipe)
Packit 1fb8d4
		pNamedPipe->pfnUnrefNamedPipe(pNamedPipe);
Packit 1fb8d4
Packit 1fb8d4
	free(pNamedPipe->lpFileName);
Packit 1fb8d4
	free(pNamedPipe->lpFilePath);
Packit 1fb8d4
	free(pNamedPipe->name);
Packit 1fb8d4
	free(pNamedPipe);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int NamedPipeClientGetFd(HANDLE handle)
Packit 1fb8d4
{
Packit 1fb8d4
	WINPR_NAMED_PIPE* file = (WINPR_NAMED_PIPE*)handle;
Packit 1fb8d4
Packit 1fb8d4
	if (!NamedPipeClientIsHandled(handle))
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	if (file->ServerMode)
Packit 1fb8d4
		return file->serverfd;
Packit 1fb8d4
	else
Packit 1fb8d4
		return file->clientfd;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static HANDLE_OPS ops = {
Packit 1fb8d4
	NamedPipeClientIsHandled,
Packit 1fb8d4
	NamedPipeClientCloseHandle,
Packit 1fb8d4
	NamedPipeClientGetFd,
Packit 1fb8d4
	NULL, /* CleanupHandle */
Packit 1fb8d4
	NamedPipeRead,
Packit 1fb8d4
	NULL, /* FileReadEx */
Packit 1fb8d4
	NULL, /* FileReadScatter */
Packit 1fb8d4
	NamedPipeWrite,
Packit 1fb8d4
	NULL, /* FileWriteEx */
Packit 1fb8d4
	NULL, /* FileWriteGather */
Packit 1fb8d4
	NULL, /* FileGetFileSize */
Packit 1fb8d4
	NULL, /*  FlushFileBuffers */
Packit 1fb8d4
	NULL, /* FileSetEndOfFile */
Packit 1fb8d4
	NULL, /* FileSetFilePointer */
Packit 1fb8d4
	NULL, /* SetFilePointerEx */
Packit 1fb8d4
	NULL, /* FileLockFile */
Packit 1fb8d4
	NULL, /* FileLockFileEx */
Packit 1fb8d4
	NULL, /* FileUnlockFile */
Packit 1fb8d4
	NULL, /* FileUnlockFileEx */
Packit 1fb8d4
	NULL  /* SetFileTime */
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
static HANDLE NamedPipeClientCreateFileA(LPCSTR lpFileName, DWORD dwDesiredAccess,
Packit Service 5a9772
                                         DWORD dwShareMode,
Packit Service 5a9772
                                         LPSECURITY_ATTRIBUTES lpSecurityAttributes,
Packit Service 5a9772
                                         DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes,
Packit Service 5a9772
                                         HANDLE hTemplateFile)
Packit 1fb8d4
{
Packit 1fb8d4
	char* name;
Packit 1fb8d4
	int status;
Packit 1fb8d4
	HANDLE hNamedPipe;
Packit 1fb8d4
	struct sockaddr_un s;
Packit 1fb8d4
	WINPR_NAMED_PIPE* pNamedPipe;
Packit 1fb8d4
Packit 1fb8d4
	if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "WinPR %s does not support the FILE_FLAG_OVERLAPPED flag", __FUNCTION__);
Packit 1fb8d4
		SetLastError(ERROR_NOT_SUPPORTED);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (!lpFileName)
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	if (!IsNamedPipeFileNameA(lpFileName))
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	name = GetNamedPipeNameWithoutPrefixA(lpFileName);
Packit 1fb8d4
Packit 1fb8d4
	if (!name)
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
Packit 1fb8d4
	free(name);
Packit Service 5a9772
	pNamedPipe = (WINPR_NAMED_PIPE*)calloc(1, sizeof(WINPR_NAMED_PIPE));
Packit 1fb8d4
Packit 1fb8d4
	if (!pNamedPipe)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit Service 5a9772
	hNamedPipe = (HANDLE)pNamedPipe;
Packit 1fb8d4
	WINPR_HANDLE_SET_TYPE_AND_MODE(pNamedPipe, HANDLE_TYPE_NAMED_PIPE, WINPR_FD_READ);
Packit 1fb8d4
	pNamedPipe->name = _strdup(lpFileName);
Packit 1fb8d4
Packit 1fb8d4
	if (!pNamedPipe->name)
Packit 1fb8d4
	{
Packit 1fb8d4
		SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Packit 1fb8d4
		free(pNamedPipe);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	pNamedPipe->dwOpenMode = 0;
Packit 1fb8d4
	pNamedPipe->dwPipeMode = 0;
Packit 1fb8d4
	pNamedPipe->nMaxInstances = 0;
Packit 1fb8d4
	pNamedPipe->nOutBufferSize = 0;
Packit 1fb8d4
	pNamedPipe->nInBufferSize = 0;
Packit 1fb8d4
	pNamedPipe->nDefaultTimeOut = 0;
Packit 1fb8d4
	pNamedPipe->dwFlagsAndAttributes = dwFlagsAndAttributes;
Packit 1fb8d4
	pNamedPipe->lpFileName = GetNamedPipeNameWithoutPrefixA(lpFileName);
Packit 1fb8d4
Packit 1fb8d4
	if (!pNamedPipe->lpFileName)
Packit 1fb8d4
	{
Packit 1fb8d4
		free((void*)pNamedPipe->name);
Packit 1fb8d4
		free(pNamedPipe);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	pNamedPipe->lpFilePath = GetNamedPipeUnixDomainSocketFilePathA(lpFileName);
Packit 1fb8d4
Packit 1fb8d4
	if (!pNamedPipe->lpFilePath)
Packit 1fb8d4
	{
Packit 1fb8d4
		free((void*)pNamedPipe->lpFileName);
Packit 1fb8d4
		free((void*)pNamedPipe->name);
Packit 1fb8d4
		free(pNamedPipe);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	pNamedPipe->clientfd = socket(PF_LOCAL, SOCK_STREAM, 0);
Packit 1fb8d4
	pNamedPipe->serverfd = -1;
Packit 1fb8d4
	pNamedPipe->ServerMode = FALSE;
Packit 1fb8d4
	ZeroMemory(&s, sizeof(struct sockaddr_un));
Packit 1fb8d4
	s.sun_family = AF_UNIX;
Packit 1fb8d4
	sprintf_s(s.sun_path, ARRAYSIZE(s.sun_path), "%s", pNamedPipe->lpFilePath);
Packit Service 5a9772
	status = connect(pNamedPipe->clientfd, (struct sockaddr*)&s, sizeof(struct sockaddr_un));
Packit 1fb8d4
	pNamedPipe->ops = &ops;
Packit 1fb8d4
Packit 1fb8d4
	if (status != 0)
Packit 1fb8d4
	{
Packit 1fb8d4
		close(pNamedPipe->clientfd);
Packit Service 5a9772
		free((char*)pNamedPipe->name);
Packit Service 5a9772
		free((char*)pNamedPipe->lpFileName);
Packit Service 5a9772
		free((char*)pNamedPipe->lpFilePath);
Packit 1fb8d4
		free(pNamedPipe);
Packit 1fb8d4
		return INVALID_HANDLE_VALUE;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (dwFlagsAndAttributes & FILE_FLAG_OVERLAPPED)
Packit 1fb8d4
	{
Packit 1fb8d4
#if 0
Packit 1fb8d4
		int flags = fcntl(pNamedPipe->clientfd, F_GETFL);
Packit 1fb8d4
Packit 1fb8d4
		if (flags != -1)
Packit 1fb8d4
			fcntl(pNamedPipe->clientfd, F_SETFL, flags | O_NONBLOCK);
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return hNamedPipe;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
HANDLE_CREATOR* GetNamedPipeClientHandleCreator(void)
Packit 1fb8d4
{
Packit 1fb8d4
	_NamedPipeClientHandleCreator.IsHandled = IsNamedPipeFileNameA;
Packit 1fb8d4
	_NamedPipeClientHandleCreator.CreateFileA = NamedPipeClientCreateFileA;
Packit 1fb8d4
	return &_NamedPipeClientHandleCreator;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
#endif
Packit 1fb8d4
Packit 1fb8d4
/* Extended API */
Packit 1fb8d4
Packit Service 5a9772
#define NAMED_PIPE_PREFIX_PATH "\\\\.\\pipe\\"
Packit 1fb8d4
Packit 1fb8d4
BOOL IsNamedPipeFileNameA(LPCSTR lpName)
Packit 1fb8d4
{
Packit 1fb8d4
	if (strncmp(lpName, NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH) - 1) != 0)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
char* GetNamedPipeNameWithoutPrefixA(LPCSTR lpName)
Packit 1fb8d4
{
Packit 1fb8d4
	char* lpFileName;
Packit 1fb8d4
Packit 1fb8d4
	if (!lpName)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	if (!IsNamedPipeFileNameA(lpName))
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit Service 5a9772
	lpFileName = _strdup(&lpName[strnlen(NAMED_PIPE_PREFIX_PATH, sizeof(NAMED_PIPE_PREFIX_PATH))]);
Packit 1fb8d4
	return lpFileName;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
char* GetNamedPipeUnixDomainSocketBaseFilePathA()
Packit 1fb8d4
{
Packit 1fb8d4
	char* lpTempPath;
Packit 1fb8d4
	char* lpPipePath;
Packit 1fb8d4
	lpTempPath = GetKnownPath(KNOWN_PATH_TEMP);
Packit 1fb8d4
Packit 1fb8d4
	if (!lpTempPath)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	lpPipePath = GetCombinedPath(lpTempPath, ".pipe");
Packit 1fb8d4
	free(lpTempPath);
Packit 1fb8d4
	return lpPipePath;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
char* GetNamedPipeUnixDomainSocketFilePathA(LPCSTR lpName)
Packit 1fb8d4
{
Packit 1fb8d4
	char* lpPipePath;
Packit 1fb8d4
	char* lpFileName;
Packit 1fb8d4
	char* lpFilePath;
Packit 1fb8d4
	lpPipePath = GetNamedPipeUnixDomainSocketBaseFilePathA();
Packit 1fb8d4
	lpFileName = GetNamedPipeNameWithoutPrefixA(lpName);
Packit Service 5a9772
	lpFilePath = GetCombinedPath(lpPipePath, (char*)lpFileName);
Packit 1fb8d4
	free(lpPipePath);
Packit 1fb8d4
	free(lpFileName);
Packit 1fb8d4
	return lpFilePath;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
int GetNamePipeFileDescriptor(HANDLE hNamedPipe)
Packit 1fb8d4
{
Packit 1fb8d4
#ifndef _WIN32
Packit 1fb8d4
	int fd;
Packit 1fb8d4
	WINPR_NAMED_PIPE* pNamedPipe;
Packit Service 5a9772
	pNamedPipe = (WINPR_NAMED_PIPE*)hNamedPipe;
Packit 1fb8d4
Packit 1fb8d4
	if (!pNamedPipe || pNamedPipe->Type != HANDLE_TYPE_NAMED_PIPE)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	fd = (pNamedPipe->ServerMode) ? pNamedPipe->serverfd : pNamedPipe->clientfd;
Packit 1fb8d4
	return fd;
Packit 1fb8d4
#else
Packit 1fb8d4
	return -1;
Packit 1fb8d4
#endif
Packit 1fb8d4
}