Blame libarchive/archive_windows.c

Packit Service 1d0348
/*-
Packit Service 1d0348
 * Copyright (c) 2009-2011 Michihiro NAKAJIMA
Packit Service 1d0348
 * Copyright (c) 2003-2007 Kees Zeelenberg
Packit Service 1d0348
 * All rights reserved.
Packit Service 1d0348
 *
Packit Service 1d0348
 * Redistribution and use in source and binary forms, with or without
Packit Service 1d0348
 * modification, are permitted provided that the following conditions
Packit Service 1d0348
 * are met:
Packit Service 1d0348
 * 1. Redistributions of source code must retain the above copyright
Packit Service 1d0348
 *    notice, this list of conditions and the following disclaimer.
Packit Service 1d0348
 * 2. Redistributions in binary form must reproduce the above copyright
Packit Service 1d0348
 *    notice, this list of conditions and the following disclaimer in the
Packit Service 1d0348
 *    documentation and/or other materials provided with the distribution.
Packit Service 1d0348
 *
Packit Service 1d0348
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
Packit Service 1d0348
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
Packit Service 1d0348
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
Packit Service 1d0348
 * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
Packit Service 1d0348
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
Packit Service 1d0348
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
Packit Service 1d0348
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
Packit Service 1d0348
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
Packit Service 1d0348
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
Packit Service 1d0348
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Packit Service 1d0348
 *
Packit Service 1d0348
 * $FreeBSD$
Packit Service 1d0348
 */
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * A set of compatibility glue for building libarchive on Windows platforms.
Packit Service 1d0348
 *
Packit Service 1d0348
 * Originally created as "libarchive-nonposix.c" by Kees Zeelenberg
Packit Service 1d0348
 * for the GnuWin32 project, trimmed significantly by Tim Kientzle.
Packit Service 1d0348
 *
Packit Service 1d0348
 * Much of the original file was unnecessary for libarchive, because
Packit Service 1d0348
 * many of the features it emulated were not strictly necessary for
Packit Service 1d0348
 * libarchive.  I hope for this to shrink further as libarchive
Packit Service 1d0348
 * internals are gradually reworked to sit more naturally on both
Packit Service 1d0348
 * POSIX and Windows.  Any ideas for this are greatly appreciated.
Packit Service 1d0348
 *
Packit Service 1d0348
 * The biggest remaining issue is the dev/ino emulation; libarchive
Packit Service 1d0348
 * has a couple of public APIs that rely on dev/ino uniquely
Packit Service 1d0348
 * identifying a file.  This doesn't match well with Windows.  I'm
Packit Service 1d0348
 * considering alternative APIs.
Packit Service 1d0348
 */
Packit Service 1d0348
Packit Service 1d0348
#if defined(_WIN32) && !defined(__CYGWIN__)
Packit Service 1d0348
Packit Service 1d0348
#include "archive_platform.h"
Packit Service 1d0348
#include "archive_private.h"
Packit Service 1d0348
#include "archive_entry.h"
Packit Service 1d0348
#include <ctype.h>
Packit Service 1d0348
#include <errno.h>
Packit Service 1d0348
#include <stddef.h>
Packit Service 1d0348
#ifdef HAVE_SYS_UTIME_H
Packit Service 1d0348
#include <sys/utime.h>
Packit Service 1d0348
#endif
Packit Service 1d0348
#include <sys/stat.h>
Packit Service 1d0348
#include <locale.h>
Packit Service 1d0348
#include <process.h>
Packit Service 1d0348
#include <stdlib.h>
Packit Service 1d0348
#include <wchar.h>
Packit Service 1d0348
#include <windows.h>
Packit Service 1d0348
#include <share.h>
Packit Service 1d0348
Packit Service 1d0348
#define EPOC_TIME ARCHIVE_LITERAL_ULL(116444736000000000)
Packit Service 1d0348
Packit Service 1d0348
#if defined(__LA_LSEEK_NEEDED)
Packit Service 1d0348
static BOOL SetFilePointerEx_perso(HANDLE hFile,
Packit Service 1d0348
				   LARGE_INTEGER liDistanceToMove,
Packit Service 1d0348
				   PLARGE_INTEGER lpNewFilePointer,
Packit Service 1d0348
				   DWORD dwMoveMethod)
Packit Service 1d0348
{
Packit Service 1d0348
	LARGE_INTEGER li;
Packit Service 1d0348
	li.QuadPart = liDistanceToMove.QuadPart;
Packit Service 1d0348
	li.LowPart = SetFilePointer(
Packit Service 1d0348
		hFile, li.LowPart, &li.HighPart, dwMoveMethod);
Packit Service 1d0348
	if(lpNewFilePointer) {
Packit Service 1d0348
		lpNewFilePointer->QuadPart = li.QuadPart;
Packit Service 1d0348
	}
Packit Service 1d0348
	return li.LowPart != -1 || GetLastError() == NO_ERROR;
Packit Service 1d0348
}
Packit Service 1d0348
#endif
Packit Service 1d0348
Packit Service 1d0348
struct ustat {
Packit Service 1d0348
	int64_t		st_atime;
Packit Service 1d0348
	uint32_t	st_atime_nsec;
Packit Service 1d0348
	int64_t		st_ctime;
Packit Service 1d0348
	uint32_t	st_ctime_nsec;
Packit Service 1d0348
	int64_t		st_mtime;
Packit Service 1d0348
	uint32_t	st_mtime_nsec;
Packit Service 1d0348
	gid_t		st_gid;
Packit Service 1d0348
	/* 64bits ino */
Packit Service 1d0348
	int64_t		st_ino;
Packit Service 1d0348
	mode_t		st_mode;
Packit Service 1d0348
	uint32_t	st_nlink;
Packit Service 1d0348
	uint64_t	st_size;
Packit Service 1d0348
	uid_t		st_uid;
Packit Service 1d0348
	dev_t		st_dev;
Packit Service 1d0348
	dev_t		st_rdev;
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
/* Transform 64-bits ino into 32-bits by hashing.
Packit Service 1d0348
 * You do not forget that really unique number size is 64-bits.
Packit Service 1d0348
 */
Packit Service 1d0348
#define INOSIZE (8*sizeof(ino_t)) /* 32 */
Packit Service 1d0348
static __inline ino_t
Packit Service 1d0348
getino(struct ustat *ub)
Packit Service 1d0348
{
Packit Service 1d0348
	ULARGE_INTEGER ino64;
Packit Service 1d0348
	ino64.QuadPart = ub->st_ino;
Packit Service 1d0348
	/* I don't know this hashing is correct way */
Packit Service 1d0348
	return ((ino_t)(ino64.LowPart ^ (ino64.LowPart >> INOSIZE)));
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * Prepend "\\?\" to the path name and convert it to unicode to permit
Packit Service 1d0348
 * an extended-length path for a maximum total path length of 32767
Packit Service 1d0348
 * characters.
Packit Service 1d0348
 * see also http://msdn.microsoft.com/en-us/library/aa365247.aspx
Packit Service 1d0348
 */
Packit Service 1d0348
wchar_t *
Packit Service 1d0348
__la_win_permissive_name(const char *name)
Packit Service 1d0348
{
Packit Service 1d0348
	wchar_t *wn;
Packit Service 1d0348
	wchar_t *ws;
Packit Service 1d0348
	size_t ll;
Packit Service 1d0348
Packit Service 1d0348
	ll = strlen(name);
Packit Service 1d0348
	wn = malloc((ll + 1) * sizeof(wchar_t));
Packit Service 1d0348
	if (wn == NULL)
Packit Service 1d0348
		return (NULL);
Packit Service 1d0348
	ll = mbstowcs(wn, name, ll);
Packit Service 1d0348
	if (ll == (size_t)-1) {
Packit Service 1d0348
		free(wn);
Packit Service 1d0348
		return (NULL);
Packit Service 1d0348
	}
Packit Service 1d0348
	wn[ll] = L'\0';
Packit Service 1d0348
	ws = __la_win_permissive_name_w(wn);
Packit Service 1d0348
	free(wn);
Packit Service 1d0348
	return (ws);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
wchar_t *
Packit Service 1d0348
__la_win_permissive_name_w(const wchar_t *wname)
Packit Service 1d0348
{
Packit Service 1d0348
	wchar_t *wn, *wnp;
Packit Service 1d0348
	wchar_t *ws, *wsp;
Packit Service 1d0348
	DWORD l, len, slen;
Packit Service 1d0348
	int unc;
Packit Service 1d0348
Packit Service 1d0348
	/* Get a full-pathname. */
Packit Service 1d0348
	l = GetFullPathNameW(wname, 0, NULL, NULL);
Packit Service 1d0348
	if (l == 0)
Packit Service 1d0348
		return (NULL);
Packit Service 1d0348
	/* NOTE: GetFullPathNameW has a bug that if the length of the file
Packit Service 1d0348
	 * name is just 1 then it returns incomplete buffer size. Thus, we
Packit Service 1d0348
	 * have to add three to the size to allocate a sufficient buffer
Packit Service 1d0348
	 * size for the full-pathname of the file name. */
Packit Service 1d0348
	l += 3;
Packit Service 1d0348
	wnp = malloc(l * sizeof(wchar_t));
Packit Service 1d0348
	if (wnp == NULL)
Packit Service 1d0348
		return (NULL);
Packit Service 1d0348
	len = GetFullPathNameW(wname, l, wnp, NULL);
Packit Service 1d0348
	wn = wnp;
Packit Service 1d0348
Packit Service 1d0348
	if (wnp[0] == L'\\' && wnp[1] == L'\\' &&
Packit Service 1d0348
	    wnp[2] == L'?' && wnp[3] == L'\\')
Packit Service 1d0348
		/* We have already a permissive name. */
Packit Service 1d0348
		return (wn);
Packit Service 1d0348
Packit Service 1d0348
	if (wnp[0] == L'\\' && wnp[1] == L'\\' &&
Packit Service 1d0348
		wnp[2] == L'.' && wnp[3] == L'\\') {
Packit Service 1d0348
		/* This is a device name */
Packit Service 1d0348
		if (((wnp[4] >= L'a' && wnp[4] <= L'z') ||
Packit Service 1d0348
		     (wnp[4] >= L'A' && wnp[4] <= L'Z')) &&
Packit Service 1d0348
		    wnp[5] == L':' && wnp[6] == L'\\')
Packit Service 1d0348
			wnp[2] = L'?';/* Not device name. */
Packit Service 1d0348
		return (wn);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	unc = 0;
Packit Service 1d0348
	if (wnp[0] == L'\\' && wnp[1] == L'\\' && wnp[2] != L'\\') {
Packit Service 1d0348
		wchar_t *p = &wnp[2];
Packit Service 1d0348
Packit Service 1d0348
		/* Skip server-name letters. */
Packit Service 1d0348
		while (*p != L'\\' && *p != L'\0')
Packit Service 1d0348
			++p;
Packit Service 1d0348
		if (*p == L'\\') {
Packit Service 1d0348
			wchar_t *rp = ++p;
Packit Service 1d0348
			/* Skip share-name letters. */
Packit Service 1d0348
			while (*p != L'\\' && *p != L'\0')
Packit Service 1d0348
				++p;
Packit Service 1d0348
			if (*p == L'\\' && p != rp) {
Packit Service 1d0348
				/* Now, match patterns such as
Packit Service 1d0348
				 * "\\server-name\share-name\" */
Packit Service 1d0348
				wnp += 2;
Packit Service 1d0348
				len -= 2;
Packit Service 1d0348
				unc = 1;
Packit Service 1d0348
			}
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	slen = 4 + (unc * 4) + len + 1;
Packit Service 1d0348
	ws = wsp = malloc(slen * sizeof(wchar_t));
Packit Service 1d0348
	if (ws == NULL) {
Packit Service 1d0348
		free(wn);
Packit Service 1d0348
		return (NULL);
Packit Service 1d0348
	}
Packit Service 1d0348
	/* prepend "\\?\" */
Packit Service 1d0348
	wcsncpy(wsp, L"\\\\?\\", 4);
Packit Service 1d0348
	wsp += 4;
Packit Service 1d0348
	slen -= 4;
Packit Service 1d0348
	if (unc) {
Packit Service 1d0348
		/* append "UNC\" ---> "\\?\UNC\" */
Packit Service 1d0348
		wcsncpy(wsp, L"UNC\\", 4);
Packit Service 1d0348
		wsp += 4;
Packit Service 1d0348
		slen -= 4;
Packit Service 1d0348
	}
Packit Service 1d0348
	wcsncpy(wsp, wnp, slen);
Packit Service 1d0348
	wsp[slen - 1] = L'\0'; /* Ensure null termination. */
Packit Service 1d0348
	free(wn);
Packit Service 1d0348
	return (ws);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * Create a file handle.
Packit Service 1d0348
 * This can exceed MAX_PATH limitation.
Packit Service 1d0348
 */
Packit Service 1d0348
static HANDLE
Packit Service 1d0348
la_CreateFile(const char *path, DWORD dwDesiredAccess, DWORD dwShareMode,
Packit Service 1d0348
    LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition,
Packit Service 1d0348
    DWORD dwFlagsAndAttributes, HANDLE hTemplateFile)
Packit Service 1d0348
{
Packit Service 1d0348
	wchar_t *wpath;
Packit Service 1d0348
	HANDLE handle;
Packit Service 1d0348
Packit Service 1d0348
	handle = CreateFileA(path, dwDesiredAccess, dwShareMode,
Packit Service 1d0348
	    lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
Packit Service 1d0348
	    hTemplateFile);
Packit Service 1d0348
	if (handle != INVALID_HANDLE_VALUE)
Packit Service 1d0348
		return (handle);
Packit Service 1d0348
	if (GetLastError() != ERROR_PATH_NOT_FOUND)
Packit Service 1d0348
		return (handle);
Packit Service 1d0348
	wpath = __la_win_permissive_name(path);
Packit Service 1d0348
	if (wpath == NULL)
Packit Service 1d0348
		return (handle);
Packit Service 1d0348
	handle = CreateFileW(wpath, dwDesiredAccess, dwShareMode,
Packit Service 1d0348
	    lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes,
Packit Service 1d0348
	    hTemplateFile);
Packit Service 1d0348
	free(wpath);
Packit Service 1d0348
	return (handle);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
#if defined(__LA_LSEEK_NEEDED)
Packit Service 1d0348
__int64
Packit Service 1d0348
__la_lseek(int fd, __int64 offset, int whence)
Packit Service 1d0348
{
Packit Service 1d0348
	LARGE_INTEGER distance;
Packit Service 1d0348
	LARGE_INTEGER newpointer;
Packit Service 1d0348
	HANDLE handle;
Packit Service 1d0348
Packit Service 1d0348
	if (fd < 0) {
Packit Service 1d0348
		errno = EBADF;
Packit Service 1d0348
		return (-1);
Packit Service 1d0348
	}
Packit Service 1d0348
	handle = (HANDLE)_get_osfhandle(fd);
Packit Service 1d0348
	if (GetFileType(handle) != FILE_TYPE_DISK) {
Packit Service 1d0348
		errno = EBADF;
Packit Service 1d0348
		return (-1);
Packit Service 1d0348
	}
Packit Service 1d0348
	distance.QuadPart = offset;
Packit Service 1d0348
	if (!SetFilePointerEx_perso(handle, distance, &newpointer, whence)) {
Packit Service 1d0348
		DWORD lasterr;
Packit Service 1d0348
Packit Service 1d0348
		lasterr = GetLastError();
Packit Service 1d0348
		if (lasterr == ERROR_BROKEN_PIPE)
Packit Service 1d0348
			return (0);
Packit Service 1d0348
		if (lasterr == ERROR_ACCESS_DENIED)
Packit Service 1d0348
			errno = EBADF;
Packit Service 1d0348
		else
Packit Service 1d0348
			la_dosmaperr(lasterr);
Packit Service 1d0348
		return (-1);
Packit Service 1d0348
	}
Packit Service 1d0348
	return (newpointer.QuadPart);
Packit Service 1d0348
}
Packit Service 1d0348
#endif
Packit Service 1d0348
Packit Service 1d0348
/* This can exceed MAX_PATH limitation. */
Packit Service 1d0348
int
Packit Service 1d0348
__la_open(const char *path, int flags, ...)
Packit Service 1d0348
{
Packit Service 1d0348
	va_list ap;
Packit Service 1d0348
	wchar_t *ws;
Packit Service 1d0348
	int r, pmode;
Packit Service 1d0348
	DWORD attr;
Packit Service 1d0348
Packit Service 1d0348
	va_start(ap, flags);
Packit Service 1d0348
	pmode = va_arg(ap, int);
Packit Service 1d0348
	va_end(ap);
Packit Service 1d0348
	ws = NULL;
Packit Service 1d0348
	if ((flags & ~O_BINARY) == O_RDONLY) {
Packit Service 1d0348
		/*
Packit Service 1d0348
		 * When we open a directory, _open function returns
Packit Service 1d0348
		 * "Permission denied" error.
Packit Service 1d0348
		 */
Packit Service 1d0348
		attr = GetFileAttributesA(path);
Packit Service 1d0348
		if (attr == (DWORD)-1 && GetLastError() == ERROR_PATH_NOT_FOUND) {
Packit Service 1d0348
			ws = __la_win_permissive_name(path);
Packit Service 1d0348
			if (ws == NULL) {
Packit Service 1d0348
				errno = EINVAL;
Packit Service 1d0348
				return (-1);
Packit Service 1d0348
			}
Packit Service 1d0348
			attr = GetFileAttributesW(ws);
Packit Service 1d0348
		}
Packit Service 1d0348
		if (attr == (DWORD)-1) {
Packit Service 1d0348
			la_dosmaperr(GetLastError());
Packit Service 1d0348
			free(ws);
Packit Service 1d0348
			return (-1);
Packit Service 1d0348
		}
Packit Service 1d0348
		if (attr & FILE_ATTRIBUTE_DIRECTORY) {
Packit Service 1d0348
			HANDLE handle;
Packit Service 1d0348
Packit Service 1d0348
			if (ws != NULL)
Packit Service 1d0348
				handle = CreateFileW(ws, 0, 0, NULL,
Packit Service 1d0348
				    OPEN_EXISTING,
Packit Service 1d0348
				    FILE_FLAG_BACKUP_SEMANTICS |
Packit Service 1d0348
				    FILE_ATTRIBUTE_READONLY,
Packit Service 1d0348
					NULL);
Packit Service 1d0348
			else
Packit Service 1d0348
				handle = CreateFileA(path, 0, 0, NULL,
Packit Service 1d0348
				    OPEN_EXISTING,
Packit Service 1d0348
				    FILE_FLAG_BACKUP_SEMANTICS |
Packit Service 1d0348
				    FILE_ATTRIBUTE_READONLY,
Packit Service 1d0348
					NULL);
Packit Service 1d0348
			free(ws);
Packit Service 1d0348
			if (handle == INVALID_HANDLE_VALUE) {
Packit Service 1d0348
				la_dosmaperr(GetLastError());
Packit Service 1d0348
				return (-1);
Packit Service 1d0348
			}
Packit Service 1d0348
			r = _open_osfhandle((intptr_t)handle, _O_RDONLY);
Packit Service 1d0348
			return (r);
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
	if (ws == NULL) {
Packit Service 1d0348
#if defined(__BORLANDC__)
Packit Service 1d0348
		/* Borland has no mode argument.
Packit Service 1d0348
		   TODO: Fix mode of new file.  */
Packit Service 1d0348
		r = _open(path, flags);
Packit Service 1d0348
#else
Packit Service 1d0348
		r = _open(path, flags, pmode);
Packit Service 1d0348
#endif
Packit Service 1d0348
		if (r < 0 && errno == EACCES && (flags & O_CREAT) != 0) {
Packit Service 1d0348
			/* Simulate other POSIX system action to pass our test suite. */
Packit Service 1d0348
			attr = GetFileAttributesA(path);
Packit Service 1d0348
			if (attr == (DWORD)-1)
Packit Service 1d0348
				la_dosmaperr(GetLastError());
Packit Service 1d0348
			else if (attr & FILE_ATTRIBUTE_DIRECTORY)
Packit Service 1d0348
				errno = EISDIR;
Packit Service 1d0348
			else
Packit Service 1d0348
				errno = EACCES;
Packit Service 1d0348
			return (-1);
Packit Service 1d0348
		}
Packit Service 1d0348
		if (r >= 0 || errno != ENOENT)
Packit Service 1d0348
			return (r);
Packit Service 1d0348
		ws = __la_win_permissive_name(path);
Packit Service 1d0348
		if (ws == NULL) {
Packit Service 1d0348
			errno = EINVAL;
Packit Service 1d0348
			return (-1);
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
	r = _wopen(ws, flags, pmode);
Packit Service 1d0348
	if (r < 0 && errno == EACCES && (flags & O_CREAT) != 0) {
Packit Service 1d0348
		/* Simulate other POSIX system action to pass our test suite. */
Packit Service 1d0348
		attr = GetFileAttributesW(ws);
Packit Service 1d0348
		if (attr == (DWORD)-1)
Packit Service 1d0348
			la_dosmaperr(GetLastError());
Packit Service 1d0348
		else if (attr & FILE_ATTRIBUTE_DIRECTORY)
Packit Service 1d0348
			errno = EISDIR;
Packit Service 1d0348
		else
Packit Service 1d0348
			errno = EACCES;
Packit Service 1d0348
	}
Packit Service 1d0348
	free(ws);
Packit Service 1d0348
	return (r);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
ssize_t
Packit Service 1d0348
__la_read(int fd, void *buf, size_t nbytes)
Packit Service 1d0348
{
Packit Service 1d0348
	HANDLE handle;
Packit Service 1d0348
	DWORD bytes_read, lasterr;
Packit Service 1d0348
	int r;
Packit Service 1d0348
Packit Service 1d0348
#ifdef _WIN64
Packit Service 1d0348
	if (nbytes > UINT32_MAX)
Packit Service 1d0348
		nbytes = UINT32_MAX;
Packit Service 1d0348
#endif
Packit Service 1d0348
	if (fd < 0) {
Packit Service 1d0348
		errno = EBADF;
Packit Service 1d0348
		return (-1);
Packit Service 1d0348
	}
Packit Service 1d0348
	/* Do not pass 0 to third parameter of ReadFile(), read bytes.
Packit Service 1d0348
	 * This will not return to application side. */
Packit Service 1d0348
	if (nbytes == 0)
Packit Service 1d0348
		return (0);
Packit Service 1d0348
	handle = (HANDLE)_get_osfhandle(fd);
Packit Service 1d0348
	r = ReadFile(handle, buf, (uint32_t)nbytes,
Packit Service 1d0348
	    &bytes_read, NULL);
Packit Service 1d0348
	if (r == 0) {
Packit Service 1d0348
		lasterr = GetLastError();
Packit Service 1d0348
		if (lasterr == ERROR_NO_DATA) {
Packit Service 1d0348
			errno = EAGAIN;
Packit Service 1d0348
			return (-1);
Packit Service 1d0348
		}
Packit Service 1d0348
		if (lasterr == ERROR_BROKEN_PIPE)
Packit Service 1d0348
			return (0);
Packit Service 1d0348
		if (lasterr == ERROR_ACCESS_DENIED)
Packit Service 1d0348
			errno = EBADF;
Packit Service 1d0348
		else
Packit Service 1d0348
			la_dosmaperr(lasterr);
Packit Service 1d0348
		return (-1);
Packit Service 1d0348
	}
Packit Service 1d0348
	return ((ssize_t)bytes_read);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
/* Convert Windows FILETIME to UTC */
Packit Service 1d0348
__inline static void
Packit Service 1d0348
fileTimeToUTC(const FILETIME *filetime, time_t *t, long *ns)
Packit Service 1d0348
{
Packit Service 1d0348
	ULARGE_INTEGER utc;
Packit Service 1d0348
Packit Service 1d0348
	utc.HighPart = filetime->dwHighDateTime;
Packit Service 1d0348
	utc.LowPart  = filetime->dwLowDateTime;
Packit Service 1d0348
	if (utc.QuadPart >= EPOC_TIME) {
Packit Service 1d0348
		utc.QuadPart -= EPOC_TIME;
Packit Service 1d0348
		*t = (time_t)(utc.QuadPart / 10000000);	/* milli seconds base */
Packit Service 1d0348
		*ns = (long)(utc.QuadPart % 10000000) * 100;/* nano seconds base */
Packit Service 1d0348
	} else {
Packit Service 1d0348
		*t = 0;
Packit Service 1d0348
		*ns = 0;
Packit Service 1d0348
	}
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
/* Stat by handle
Packit Service 1d0348
 * Windows' stat() does not accept the path added "\\?\" especially "?"
Packit Service 1d0348
 * character.
Packit Service 1d0348
 * It means we cannot access the long name path longer than MAX_PATH.
Packit Service 1d0348
 * So I've implemented simular Windows' stat() to access the long name path.
Packit Service 1d0348
 * And I've added some feature.
Packit Service 1d0348
 * 1. set st_ino by nFileIndexHigh and nFileIndexLow of
Packit Service 1d0348
 *    BY_HANDLE_FILE_INFORMATION.
Packit Service 1d0348
 * 2. set st_nlink by nNumberOfLinks of BY_HANDLE_FILE_INFORMATION.
Packit Service 1d0348
 * 3. set st_dev by dwVolumeSerialNumber by BY_HANDLE_FILE_INFORMATION.
Packit Service 1d0348
 */
Packit Service 1d0348
static int
Packit Service 1d0348
__hstat(HANDLE handle, struct ustat *st)
Packit Service 1d0348
{
Packit Service 1d0348
	BY_HANDLE_FILE_INFORMATION info;
Packit Service 1d0348
	ULARGE_INTEGER ino64;
Packit Service 1d0348
	DWORD ftype;
Packit Service 1d0348
	mode_t mode;
Packit Service 1d0348
	time_t t;
Packit Service 1d0348
	long ns;
Packit Service 1d0348
Packit Service 1d0348
	switch (ftype = GetFileType(handle)) {
Packit Service 1d0348
	case FILE_TYPE_UNKNOWN:
Packit Service 1d0348
		errno = EBADF;
Packit Service 1d0348
		return (-1);
Packit Service 1d0348
	case FILE_TYPE_CHAR:
Packit Service 1d0348
	case FILE_TYPE_PIPE:
Packit Service 1d0348
		if (ftype == FILE_TYPE_CHAR) {
Packit Service 1d0348
			st->st_mode = S_IFCHR;
Packit Service 1d0348
			st->st_size = 0;
Packit Service 1d0348
		} else {
Packit Service 1d0348
			DWORD avail;
Packit Service 1d0348
Packit Service 1d0348
			st->st_mode = S_IFIFO;
Packit Service 1d0348
			if (PeekNamedPipe(handle, NULL, 0, NULL, &avail, NULL))
Packit Service 1d0348
				st->st_size = avail;
Packit Service 1d0348
			else
Packit Service 1d0348
				st->st_size = 0;
Packit Service 1d0348
		}
Packit Service 1d0348
		st->st_atime = 0;
Packit Service 1d0348
		st->st_atime_nsec = 0;
Packit Service 1d0348
		st->st_mtime = 0;
Packit Service 1d0348
		st->st_mtime_nsec = 0;
Packit Service 1d0348
		st->st_ctime = 0;
Packit Service 1d0348
		st->st_ctime_nsec = 0;
Packit Service 1d0348
		st->st_ino = 0;
Packit Service 1d0348
		st->st_nlink = 1;
Packit Service 1d0348
		st->st_uid = 0;
Packit Service 1d0348
		st->st_gid = 0;
Packit Service 1d0348
		st->st_rdev = 0;
Packit Service 1d0348
		st->st_dev = 0;
Packit Service 1d0348
		return (0);
Packit Service 1d0348
	case FILE_TYPE_DISK:
Packit Service 1d0348
		break;
Packit Service 1d0348
	default:
Packit Service 1d0348
		/* This ftype is undocumented type. */
Packit Service 1d0348
		la_dosmaperr(GetLastError());
Packit Service 1d0348
		return (-1);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	ZeroMemory(&info, sizeof(info));
Packit Service 1d0348
	if (!GetFileInformationByHandle (handle, &info)) {
Packit Service 1d0348
		la_dosmaperr(GetLastError());
Packit Service 1d0348
		return (-1);
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	mode = S_IRUSR | S_IRGRP | S_IROTH;
Packit Service 1d0348
	if ((info.dwFileAttributes & FILE_ATTRIBUTE_READONLY) == 0)
Packit Service 1d0348
		mode |= S_IWUSR | S_IWGRP | S_IWOTH;
Packit Service 1d0348
	if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
Packit Service 1d0348
		mode |= S_IFDIR | S_IXUSR | S_IXGRP | S_IXOTH;
Packit Service 1d0348
	else
Packit Service 1d0348
		mode |= S_IFREG;
Packit Service 1d0348
	st->st_mode = mode;
Packit Service 1d0348
Packit Service 1d0348
	fileTimeToUTC(&info.ftLastAccessTime, &t, &ns);
Packit Service 1d0348
	st->st_atime = t;
Packit Service 1d0348
	st->st_atime_nsec = ns;
Packit Service 1d0348
	fileTimeToUTC(&info.ftLastWriteTime, &t, &ns);
Packit Service 1d0348
	st->st_mtime = t;
Packit Service 1d0348
	st->st_mtime_nsec = ns;
Packit Service 1d0348
	fileTimeToUTC(&info.ftCreationTime, &t, &ns);
Packit Service 1d0348
	st->st_ctime = t;
Packit Service 1d0348
	st->st_ctime_nsec = ns;
Packit Service 1d0348
	st->st_size =
Packit Service 1d0348
	    ((int64_t)(info.nFileSizeHigh) * ((int64_t)MAXDWORD + 1))
Packit Service 1d0348
		+ (int64_t)(info.nFileSizeLow);
Packit Service 1d0348
#ifdef SIMULATE_WIN_STAT
Packit Service 1d0348
	st->st_ino = 0;
Packit Service 1d0348
	st->st_nlink = 1;
Packit Service 1d0348
	st->st_dev = 0;
Packit Service 1d0348
#else
Packit Service 1d0348
	/* Getting FileIndex as i-node. We should remove a sequence which
Packit Service 1d0348
	 * is high-16-bits of nFileIndexHigh. */
Packit Service 1d0348
	ino64.HighPart = info.nFileIndexHigh & 0x0000FFFFUL;
Packit Service 1d0348
	ino64.LowPart  = info.nFileIndexLow;
Packit Service 1d0348
	st->st_ino = ino64.QuadPart;
Packit Service 1d0348
	st->st_nlink = info.nNumberOfLinks;
Packit Service 1d0348
	if (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
Packit Service 1d0348
		++st->st_nlink;/* Add parent directory. */
Packit Service 1d0348
	st->st_dev = info.dwVolumeSerialNumber;
Packit Service 1d0348
#endif
Packit Service 1d0348
	st->st_uid = 0;
Packit Service 1d0348
	st->st_gid = 0;
Packit Service 1d0348
	st->st_rdev = 0;
Packit Service 1d0348
	return (0);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static void
Packit Service 1d0348
copy_stat(struct stat *st, struct ustat *us)
Packit Service 1d0348
{
Packit Service 1d0348
	st->st_atime = us->st_atime;
Packit Service 1d0348
	st->st_ctime = us->st_ctime;
Packit Service 1d0348
	st->st_mtime = us->st_mtime;
Packit Service 1d0348
	st->st_gid = us->st_gid;
Packit Service 1d0348
	st->st_ino = getino(us);
Packit Service 1d0348
	st->st_mode = us->st_mode;
Packit Service 1d0348
	st->st_nlink = us->st_nlink;
Packit Service 1d0348
	st->st_size = (off_t)us->st_size;
Packit Service 1d0348
	st->st_uid = us->st_uid;
Packit Service 1d0348
	st->st_dev = us->st_dev;
Packit Service 1d0348
	st->st_rdev = us->st_rdev;
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * TODO: Remove a use of __la_fstat and __la_stat.
Packit Service 1d0348
 * We should use GetFileInformationByHandle in place
Packit Service 1d0348
 * where We still use the *stat functions.
Packit Service 1d0348
 */
Packit Service 1d0348
int
Packit Service 1d0348
__la_fstat(int fd, struct stat *st)
Packit Service 1d0348
{
Packit Service 1d0348
	struct ustat u;
Packit Service 1d0348
	int ret;
Packit Service 1d0348
Packit Service 1d0348
	if (fd < 0) {
Packit Service 1d0348
		errno = EBADF;
Packit Service 1d0348
		return (-1);
Packit Service 1d0348
	}
Packit Service 1d0348
	ret = __hstat((HANDLE)_get_osfhandle(fd), &u);
Packit Service 1d0348
	if (ret >= 0) {
Packit Service 1d0348
		copy_stat(st, &u);
Packit Service 1d0348
		if (u.st_mode & (S_IFCHR | S_IFIFO)) {
Packit Service 1d0348
			st->st_dev = fd;
Packit Service 1d0348
			st->st_rdev = fd;
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
	return (ret);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
/* This can exceed MAX_PATH limitation. */
Packit Service 1d0348
int
Packit Service 1d0348
__la_stat(const char *path, struct stat *st)
Packit Service 1d0348
{
Packit Service 1d0348
	HANDLE handle;
Packit Service 1d0348
	struct ustat u;
Packit Service 1d0348
	int ret;
Packit Service 1d0348
Packit Service 1d0348
	handle = la_CreateFile(path, 0, FILE_SHARE_READ, NULL, OPEN_EXISTING,
Packit Service 1d0348
		FILE_FLAG_BACKUP_SEMANTICS,
Packit Service 1d0348
		NULL);
Packit Service 1d0348
	if (handle == INVALID_HANDLE_VALUE) {
Packit Service 1d0348
		la_dosmaperr(GetLastError());
Packit Service 1d0348
		return (-1);
Packit Service 1d0348
	}
Packit Service 1d0348
	ret = __hstat(handle, &u);
Packit Service 1d0348
	CloseHandle(handle);
Packit Service 1d0348
	if (ret >= 0) {
Packit Service 1d0348
		char *p;
Packit Service 1d0348
Packit Service 1d0348
		copy_stat(st, &u);
Packit Service 1d0348
		p = strrchr(path, '.');
Packit Service 1d0348
		if (p != NULL && strlen(p) == 4) {
Packit Service 1d0348
			char exttype[4];
Packit Service 1d0348
Packit Service 1d0348
			++ p;
Packit Service 1d0348
			exttype[0] = toupper(*p++);
Packit Service 1d0348
			exttype[1] = toupper(*p++);
Packit Service 1d0348
			exttype[2] = toupper(*p++);
Packit Service 1d0348
			exttype[3] = '\0';
Packit Service 1d0348
			if (!strcmp(exttype, "EXE") || !strcmp(exttype, "CMD") ||
Packit Service 1d0348
				!strcmp(exttype, "BAT") || !strcmp(exttype, "COM"))
Packit Service 1d0348
				st->st_mode |= S_IXUSR | S_IXGRP | S_IXOTH;
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
	return (ret);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * This waitpid is limited implementation.
Packit Service 1d0348
 */
Packit Service 1d0348
pid_t
Packit Service 1d0348
__la_waitpid(HANDLE child, int *status, int option)
Packit Service 1d0348
{
Packit Service 1d0348
	DWORD cs;
Packit Service 1d0348
Packit Service 1d0348
	(void)option;/* UNUSED */
Packit Service 1d0348
	do {
Packit Service 1d0348
		if (GetExitCodeProcess(child, &cs) == 0) {
Packit Service 1d0348
			CloseHandle(child);
Packit Service 1d0348
			la_dosmaperr(GetLastError());
Packit Service 1d0348
			*status = 0;
Packit Service 1d0348
			return (-1);
Packit Service 1d0348
		}
Packit Service 1d0348
	} while (cs == STILL_ACTIVE);
Packit Service 1d0348
Packit Service 1d0348
	*status = (int)(cs & 0xff);
Packit Service 1d0348
	return (0);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
ssize_t
Packit Service 1d0348
__la_write(int fd, const void *buf, size_t nbytes)
Packit Service 1d0348
{
Packit Service 1d0348
	DWORD bytes_written;
Packit Service 1d0348
Packit Service 1d0348
#ifdef _WIN64
Packit Service 1d0348
	if (nbytes > UINT32_MAX)
Packit Service 1d0348
		nbytes = UINT32_MAX;
Packit Service 1d0348
#endif
Packit Service 1d0348
	if (fd < 0) {
Packit Service 1d0348
		errno = EBADF;
Packit Service 1d0348
		return (-1);
Packit Service 1d0348
	}
Packit Service 1d0348
	if (!WriteFile((HANDLE)_get_osfhandle(fd), buf, (uint32_t)nbytes,
Packit Service 1d0348
	    &bytes_written, NULL)) {
Packit Service 1d0348
		DWORD lasterr;
Packit Service 1d0348
Packit Service 1d0348
		lasterr = GetLastError();
Packit Service 1d0348
		if (lasterr == ERROR_ACCESS_DENIED)
Packit Service 1d0348
			errno = EBADF;
Packit Service 1d0348
		else
Packit Service 1d0348
			la_dosmaperr(lasterr);
Packit Service 1d0348
		return (-1);
Packit Service 1d0348
	}
Packit Service 1d0348
	return (bytes_written);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * Replace the Windows path separator '\' with '/'.
Packit Service 1d0348
 */
Packit Service 1d0348
static int
Packit Service 1d0348
replace_pathseparator(struct archive_wstring *ws, const wchar_t *wp)
Packit Service 1d0348
{
Packit Service 1d0348
	wchar_t *w;
Packit Service 1d0348
	size_t path_length;
Packit Service 1d0348
Packit Service 1d0348
	if (wp == NULL)
Packit Service 1d0348
		return(0);
Packit Service 1d0348
	if (wcschr(wp, L'\\') == NULL)
Packit Service 1d0348
		return(0);
Packit Service 1d0348
	path_length = wcslen(wp);
Packit Service 1d0348
	if (archive_wstring_ensure(ws, path_length) == NULL)
Packit Service 1d0348
		return(-1);
Packit Service 1d0348
	archive_wstrncpy(ws, wp, path_length);
Packit Service 1d0348
	for (w = ws->s; *w; w++) {
Packit Service 1d0348
		if (*w == L'\\')
Packit Service 1d0348
			*w = L'/';
Packit Service 1d0348
	}
Packit Service 1d0348
	return(1);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
static int
Packit Service 1d0348
fix_pathseparator(struct archive_entry *entry)
Packit Service 1d0348
{
Packit Service 1d0348
	struct archive_wstring ws;
Packit Service 1d0348
	const wchar_t *wp;
Packit Service 1d0348
	int ret = ARCHIVE_OK;
Packit Service 1d0348
Packit Service 1d0348
	archive_string_init(&ws);
Packit Service 1d0348
	wp = archive_entry_pathname_w(entry);
Packit Service 1d0348
	switch (replace_pathseparator(&ws, wp)) {
Packit Service 1d0348
	case 0: /* Not replaced. */
Packit Service 1d0348
		break;
Packit Service 1d0348
	case 1: /* Replaced. */
Packit Service 1d0348
		archive_entry_copy_pathname_w(entry, ws.s);
Packit Service 1d0348
		break;
Packit Service 1d0348
	default:
Packit Service 1d0348
		ret = ARCHIVE_FAILED;
Packit Service 1d0348
	}
Packit Service 1d0348
	wp = archive_entry_hardlink_w(entry);
Packit Service 1d0348
	switch (replace_pathseparator(&ws, wp)) {
Packit Service 1d0348
	case 0: /* Not replaced. */
Packit Service 1d0348
		break;
Packit Service 1d0348
	case 1: /* Replaced. */
Packit Service 1d0348
		archive_entry_copy_hardlink_w(entry, ws.s);
Packit Service 1d0348
		break;
Packit Service 1d0348
	default:
Packit Service 1d0348
		ret = ARCHIVE_FAILED;
Packit Service 1d0348
	}
Packit Service 1d0348
	wp = archive_entry_symlink_w(entry);
Packit Service 1d0348
	switch (replace_pathseparator(&ws, wp)) {
Packit Service 1d0348
	case 0: /* Not replaced. */
Packit Service 1d0348
		break;
Packit Service 1d0348
	case 1: /* Replaced. */
Packit Service 1d0348
		archive_entry_copy_symlink_w(entry, ws.s);
Packit Service 1d0348
		break;
Packit Service 1d0348
	default:
Packit Service 1d0348
		ret = ARCHIVE_FAILED;
Packit Service 1d0348
	}
Packit Service 1d0348
	archive_wstring_free(&ws);
Packit Service 1d0348
	return(ret);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
struct archive_entry *
Packit Service 1d0348
__la_win_entry_in_posix_pathseparator(struct archive_entry *entry)
Packit Service 1d0348
{
Packit Service 1d0348
	struct archive_entry *entry_main;
Packit Service 1d0348
	const wchar_t *wp;
Packit Service 1d0348
	int has_backslash = 0;
Packit Service 1d0348
	int ret;
Packit Service 1d0348
Packit Service 1d0348
	wp = archive_entry_pathname_w(entry);
Packit Service 1d0348
	if (wp != NULL && wcschr(wp, L'\\') != NULL)
Packit Service 1d0348
		has_backslash = 1;
Packit Service 1d0348
	if (!has_backslash) {
Packit Service 1d0348
		wp = archive_entry_hardlink_w(entry);
Packit Service 1d0348
		if (wp != NULL && wcschr(wp, L'\\') != NULL)
Packit Service 1d0348
			has_backslash = 1;
Packit Service 1d0348
	}
Packit Service 1d0348
	if (!has_backslash) {
Packit Service 1d0348
		wp = archive_entry_symlink_w(entry);
Packit Service 1d0348
		if (wp != NULL && wcschr(wp, L'\\') != NULL)
Packit Service 1d0348
			has_backslash = 1;
Packit Service 1d0348
	}
Packit Service 1d0348
	/*
Packit Service 1d0348
	 * If there is no backslash chars, return the original.
Packit Service 1d0348
	 */
Packit Service 1d0348
	if (!has_backslash)
Packit Service 1d0348
		return (entry);
Packit Service 1d0348
Packit Service 1d0348
	/* Copy entry so we can modify it as needed. */
Packit Service 1d0348
	entry_main = archive_entry_clone(entry);
Packit Service 1d0348
	if (entry_main == NULL)
Packit Service 1d0348
		return (NULL);
Packit Service 1d0348
	/* Replace the Windows path-separator '\' with '/'. */
Packit Service 1d0348
	ret = fix_pathseparator(entry_main);
Packit Service 1d0348
	if (ret < ARCHIVE_WARN) {
Packit Service 1d0348
		archive_entry_free(entry_main);
Packit Service 1d0348
		return (NULL);
Packit Service 1d0348
	}
Packit Service 1d0348
	return (entry_main);
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
Packit Service 1d0348
/*
Packit Service 1d0348
 * The following function was modified from PostgreSQL sources and is
Packit Service 1d0348
 * subject to the copyright below.
Packit Service 1d0348
 */
Packit Service 1d0348
/*-------------------------------------------------------------------------
Packit Service 1d0348
 *
Packit Service 1d0348
 * win32error.c
Packit Service 1d0348
 *	  Map win32 error codes to errno values
Packit Service 1d0348
 *
Packit Service 1d0348
 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
Packit Service 1d0348
 *
Packit Service 1d0348
 * IDENTIFICATION
Packit Service 1d0348
 *	  $PostgreSQL: pgsql/src/port/win32error.c,v 1.4 2008/01/01 19:46:00 momjian Exp $
Packit Service 1d0348
 *
Packit Service 1d0348
 *-------------------------------------------------------------------------
Packit Service 1d0348
 */
Packit Service 1d0348
/*
Packit Service 1d0348
PostgreSQL Database Management System
Packit Service 1d0348
(formerly known as Postgres, then as Postgres95)
Packit Service 1d0348
Packit Service 1d0348
Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
Packit Service 1d0348
Packit Service 1d0348
Portions Copyright (c) 1994, The Regents of the University of California
Packit Service 1d0348
Packit Service 1d0348
Permission to use, copy, modify, and distribute this software and its
Packit Service 1d0348
documentation for any purpose, without fee, and without a written agreement
Packit Service 1d0348
is hereby granted, provided that the above copyright notice and this
Packit Service 1d0348
paragraph and the following two paragraphs appear in all copies.
Packit Service 1d0348
Packit Service 1d0348
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
Packit Service 1d0348
DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
Packit Service 1d0348
LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
Packit Service 1d0348
DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
Packit Service 1d0348
POSSIBILITY OF SUCH DAMAGE.
Packit Service 1d0348
Packit Service 1d0348
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
Packit Service 1d0348
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
Packit Service 1d0348
AND FITNESS FOR A PARTICULAR PURPOSE.  THE SOFTWARE PROVIDED HEREUNDER IS
Packit Service 1d0348
ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
Packit Service 1d0348
PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
Packit Service 1d0348
*/
Packit Service 1d0348
Packit Service 1d0348
static const struct {
Packit Service 1d0348
	DWORD		winerr;
Packit Service 1d0348
	int		doserr;
Packit Service 1d0348
} doserrors[] =
Packit Service 1d0348
{
Packit Service 1d0348
	{	ERROR_INVALID_FUNCTION, EINVAL	},
Packit Service 1d0348
	{	ERROR_FILE_NOT_FOUND, ENOENT	},
Packit Service 1d0348
	{	ERROR_PATH_NOT_FOUND, ENOENT	},
Packit Service 1d0348
	{	ERROR_TOO_MANY_OPEN_FILES, EMFILE	},
Packit Service 1d0348
	{	ERROR_ACCESS_DENIED, EACCES	},
Packit Service 1d0348
	{	ERROR_INVALID_HANDLE, EBADF	},
Packit Service 1d0348
	{	ERROR_ARENA_TRASHED, ENOMEM	},
Packit Service 1d0348
	{	ERROR_NOT_ENOUGH_MEMORY, ENOMEM	},
Packit Service 1d0348
	{	ERROR_INVALID_BLOCK, ENOMEM	},
Packit Service 1d0348
	{	ERROR_BAD_ENVIRONMENT, E2BIG	},
Packit Service 1d0348
	{	ERROR_BAD_FORMAT, ENOEXEC	},
Packit Service 1d0348
	{	ERROR_INVALID_ACCESS, EINVAL	},
Packit Service 1d0348
	{	ERROR_INVALID_DATA, EINVAL	},
Packit Service 1d0348
	{	ERROR_INVALID_DRIVE, ENOENT	},
Packit Service 1d0348
	{	ERROR_CURRENT_DIRECTORY, EACCES	},
Packit Service 1d0348
	{	ERROR_NOT_SAME_DEVICE, EXDEV	},
Packit Service 1d0348
	{	ERROR_NO_MORE_FILES, ENOENT	},
Packit Service 1d0348
	{	ERROR_LOCK_VIOLATION, EACCES	},
Packit Service 1d0348
	{	ERROR_SHARING_VIOLATION, EACCES	},
Packit Service 1d0348
	{	ERROR_BAD_NETPATH, ENOENT	},
Packit Service 1d0348
	{	ERROR_NETWORK_ACCESS_DENIED, EACCES	},
Packit Service 1d0348
	{	ERROR_BAD_NET_NAME, ENOENT	},
Packit Service 1d0348
	{	ERROR_FILE_EXISTS, EEXIST	},
Packit Service 1d0348
	{	ERROR_CANNOT_MAKE, EACCES	},
Packit Service 1d0348
	{	ERROR_FAIL_I24, EACCES	},
Packit Service 1d0348
	{	ERROR_INVALID_PARAMETER, EINVAL	},
Packit Service 1d0348
	{	ERROR_NO_PROC_SLOTS, EAGAIN	},
Packit Service 1d0348
	{	ERROR_DRIVE_LOCKED, EACCES	},
Packit Service 1d0348
	{	ERROR_BROKEN_PIPE, EPIPE	},
Packit Service 1d0348
	{	ERROR_DISK_FULL, ENOSPC	},
Packit Service 1d0348
	{	ERROR_INVALID_TARGET_HANDLE, EBADF	},
Packit Service 1d0348
	{	ERROR_INVALID_HANDLE, EINVAL	},
Packit Service 1d0348
	{	ERROR_WAIT_NO_CHILDREN, ECHILD	},
Packit Service 1d0348
	{	ERROR_CHILD_NOT_COMPLETE, ECHILD	},
Packit Service 1d0348
	{	ERROR_DIRECT_ACCESS_HANDLE, EBADF	},
Packit Service 1d0348
	{	ERROR_NEGATIVE_SEEK, EINVAL	},
Packit Service 1d0348
	{	ERROR_SEEK_ON_DEVICE, EACCES	},
Packit Service 1d0348
	{	ERROR_DIR_NOT_EMPTY, ENOTEMPTY	},
Packit Service 1d0348
	{	ERROR_NOT_LOCKED, EACCES	},
Packit Service 1d0348
	{	ERROR_BAD_PATHNAME, ENOENT	},
Packit Service 1d0348
	{	ERROR_MAX_THRDS_REACHED, EAGAIN	},
Packit Service 1d0348
	{	ERROR_LOCK_FAILED, EACCES	},
Packit Service 1d0348
	{	ERROR_ALREADY_EXISTS, EEXIST	},
Packit Service 1d0348
	{	ERROR_FILENAME_EXCED_RANGE, ENOENT	},
Packit Service 1d0348
	{	ERROR_NESTING_NOT_ALLOWED, EAGAIN	},
Packit Service 1d0348
	{	ERROR_NOT_ENOUGH_QUOTA, ENOMEM	}
Packit Service 1d0348
};
Packit Service 1d0348
Packit Service 1d0348
void
Packit Service 1d0348
__la_dosmaperr(unsigned long e)
Packit Service 1d0348
{
Packit Service 1d0348
	int			i;
Packit Service 1d0348
Packit Service 1d0348
	if (e == 0)
Packit Service 1d0348
	{
Packit Service 1d0348
		errno = 0;
Packit Service 1d0348
		return;
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	for (i = 0; i < (int)(sizeof(doserrors)/sizeof(doserrors[0])); i++)
Packit Service 1d0348
	{
Packit Service 1d0348
		if (doserrors[i].winerr == e)
Packit Service 1d0348
		{
Packit Service 1d0348
			errno = doserrors[i].doserr;
Packit Service 1d0348
			return;
Packit Service 1d0348
		}
Packit Service 1d0348
	}
Packit Service 1d0348
Packit Service 1d0348
	/* fprintf(stderr, "unrecognized win32 error code: %lu", e); */
Packit Service 1d0348
	errno = EINVAL;
Packit Service 1d0348
	return;
Packit Service 1d0348
}
Packit Service 1d0348
Packit Service 1d0348
#endif /* _WIN32 && !__CYGWIN__ */