blob: 1f4d273dabb1627311c8ed8920dc892530e18a2c [file] [log] [blame]
/*-
* Copyright (c) 2003-2007 Kees Zeelenberg
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
/*
* A set of compatibility glue for building libarchive on Windows platforms.
*
* Originally created as "libarchive-nonposix.c" by Kees Zeelenberg
* for the GnuWin32 project, trimmed significantly by Tim Kientzle.
*
* Much of the original file was unnecessary for libarchive, because
* many of the features it emulated were not strictly necessary for
* libarchive. I hope for this to shrink further as libarchive
* internals are gradually reworked to sit more naturally on both
* POSIX and Windows. Any ideas for this are greatly appreciated.
*
* The biggest remaining issue is the dev/ino emulation; libarchive
* has a couple of public APIs that rely on dev/ino uniquely
* identifying a file. This doesn't match well with Windows. I'm
* considering alternative APIs.
*/
#ifdef _WIN32
#include <errno.h>
#include <stddef.h>
#include <sys/utime.h>
#include <sys/stat.h>
#include <process.h>
#include <stdlib.h>
#include <windows.h>
#include "archive_platform.h"
/* Make a link to FROM called TO. */
int link (from, to)
const char *from;
const char *to;
{
int res;
if (from == NULL || to == NULL) {
set_errno (EINVAL);
return -1;
}
if (!_access (from, F_OK))
res = CopyFile (from, to, FALSE);
else {
/* from doesn not exist; try to prepend it with the dirname of to */
char *fullfrompath, *slash, *todir;
todir = strdup (to);
if (!todir)
return -1;
slash = strrchr(todir, '/');
if (slash)
*slash = '\0';
fullfrompath = malloc (strlen (from) + strlen (todir) + 2);
if (!fullfrompath)
return -1;
strcpy (fullfrompath, todir);
strcat (fullfrompath, "/");
strcat (fullfrompath, from);
if (todir)
free (todir);
if (_access (fullfrompath, R_OK))
return -1;
res = CopyFile (fullfrompath, to, FALSE);
if (fullfrompath)
free (fullfrompath);
}
if (res == 0) {
set_errno (EINVAL);
return -1;
}
return 0;
}
/* Make a symbolic link to FROM called TO. */
int symlink (from, to)
const char *from;
const char *to;
{
return link (from, to);
}
static int get_dev_ino (HANDLE hFile, dev_t *dev, ino_t *ino)
{
/* dev_t: short (2 bytes); ino_t: unsigned int (4 bytes) */
#define LODWORD(l) ((DWORD)((DWORDLONG)(l)))
#define HIDWORD(l) ((DWORD)(((DWORDLONG)(l)>>32)&0xFFFFFFFF))
#define MAKEDWORDLONG(a,b) ((DWORDLONG)(((DWORD)(a))|(((DWORDLONG)((DWORD)(b)))<<32)))
#define INOSIZE (8*sizeof(ino_t)) /* 32 */
//#define DEVSIZE (8*sizeof(dev_t)) /* 16 */
#define SEQNUMSIZE (16)
BY_HANDLE_FILE_INFORMATION FileInformation;
uint64_t ino64, FileReferenceNumber ;
ino_t resino;
dev_t resdev;
DWORD VolumeSerialNumber;
*ino = 0;
*dev = 0;
if (hFile == INVALID_HANDLE_VALUE) /* file cannot be opened */
return 0;
ZeroMemory (&FileInformation, sizeof(FileInformation));
if (!GetFileInformationByHandle (hFile, &FileInformation)) /* cannot obtain FileInformation */
return 0;
ino64 = (uint64_t) MAKEDWORDLONG (
FileInformation.nFileIndexLow, FileInformation.nFileIndexHigh);
FileReferenceNumber = ino64 & ((~(0ULL)) >> SEQNUMSIZE); /* remove sequence number */
/* transform 64-bits ino into 32-bits by hashing */
resino = (ino_t) (
( (LODWORD(FileReferenceNumber)) ^ ((LODWORD(FileReferenceNumber)) >> INOSIZE) )
// ^
// ( (HIDWORD(FileReferenceNumber)) ^ ((HIDWORD(FileReferenceNumber)) >> INOSIZE) )
);
*ino = resino;
VolumeSerialNumber = FileInformation.dwVolumeSerialNumber;
//resdev = (unsigned short) ( (LOWORD(VolumeSerialNumber)) ^ ((HIWORD(VolumeSerialNumber)) >> DEVSIZE) );
resdev = (dev_t) VolumeSerialNumber;
*dev = resdev;
//printf ("get_dev_ino: dev = %d; ino = %u\n", resdev, resino);
return 0;
}
int get_dev_ino_fd (int fd, dev_t *dev, ino_t *ino)
{
HANDLE hFile;
hFile = (HANDLE) _get_osfhandle (fd);
return get_dev_ino (hFile, dev, ino);
}
int get_dev_ino_filename (char *path, dev_t *dev, ino_t *ino)
{
HANDLE hFile;
int res;
if (!path || !*path) /* path = NULL */
return 0;
if (_access (path, F_OK)) /* path does not exist */
return -1;
/* obtain handle to file "name"; FILE_FLAG_BACKUP_SEMANTICS is used to open directories */
hFile = CreateFile (path, 0, 0, NULL, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_ATTRIBUTE_READONLY,
NULL);
res = get_dev_ino (hFile, dev, ino);
CloseHandle (hFile);
return res;
}
int fstati64 (int fd, struct _stati64 *st)
{
int res;
res = _fstati64 (fd, st);
if (res < 0)
return -1;
if (st->st_ino == 0)
res = get_dev_ino_fd (fd, &st->st_dev, &st->st_ino);
// printf ("fstat: dev = %u; ino = %u\n", st->st_dev, st->st_ino);
return res;
}
#endif /* _WIN32 */