/*- * 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 #include #include #include #include #include #include #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 */