summaryrefslogtreecommitdiff
Diffstat
-rwxr-xr-xAndroid.mk138
-rwxr-xr-xAndroid.mk.bak89
-rwxr-xr-xCREDITS20
-rwxr-xr-xINSTALL200
-rwxr-xr-xMakefile715
-rwxr-xr-xMakefile.am106
-rwxr-xr-xMakefile.in955
-rwxr-xr-xNEWS4
-rwxr-xr-xREADME80
-rwxr-xr-xTODO.ntfsprogs126
-rwxr-xr-xaclocal.m47091
-rwxr-xr-xcompile21
-rwxr-xr-xconfig.guess292
-rw-r--r--[-rwxr-xr-x]config.h165
-rwxr-xr-xconfig.h.in110
-rwxr-xr-xconfig.log3290
-rwxr-xr-xconfig.status1220
-rwxr-xr-xconfig.sub104
-rwxr-xr-xconfigure26448
-rwxr-xr-xconfigure.ac291
-rwxr-xr-xdepcomp87
-rwxr-xr-xinclude/Makefile.in181
-rwxr-xr-xinclude/fuse-lite/Makefile.in112
-rwxr-xr-xinclude/fuse-lite/fuse.h61
-rwxr-xr-xinclude/fuse-lite/fuse_common.h49
-rwxr-xr-xinclude/fuse-lite/fuse_kernel.h6
-rwxr-xr-xinclude/fuse-lite/fuse_lowlevel.h20
-rwxr-xr-xinclude/ntfs-3g/Makefile.am4
-rwxr-xr-xinclude/ntfs-3g/Makefile.in163
-rwxr-xr-xinclude/ntfs-3g/acls.h3
-rwxr-xr-xinclude/ntfs-3g/attrib.h50
-rwxr-xr-xinclude/ntfs-3g/cache.h7
-rwxr-xr-xinclude/ntfs-3g/compat.h6
-rwxr-xr-xinclude/ntfs-3g/compress.h6
-rwxr-xr-xinclude/ntfs-3g/debug.h4
-rwxr-xr-xinclude/ntfs-3g/device.h18
-rwxr-xr-xinclude/ntfs-3g/device_io.h21
-rwxr-xr-xinclude/ntfs-3g/dir.h11
-rwxr-xr-xinclude/ntfs-3g/layout.h32
-rwxr-xr-xinclude/ntfs-3g/lcnalloc.h1
-rwxr-xr-xinclude/ntfs-3g/logging.h3
-rwxr-xr-xinclude/ntfs-3g/mst.h3
-rwxr-xr-xinclude/ntfs-3g/ntfstime.h12
-rwxr-xr-xinclude/ntfs-3g/param.h72
-rwxr-xr-xinclude/ntfs-3g/realpath.h24
-rwxr-xr-xinclude/ntfs-3g/runlist.h3
-rwxr-xr-xinclude/ntfs-3g/security.h20
-rwxr-xr-xinclude/ntfs-3g/types.h8
-rwxr-xr-xinclude/ntfs-3g/unistr.h13
-rwxr-xr-xinclude/ntfs-3g/volume.h78
-rwxr-xr-xinclude/ntfs-3g/xattrs.h75
-rwxr-xr-xinstall-sh5
-rwxr-xr-xlibfuse-lite/Makefile.am3
-rwxr-xr-xlibfuse-lite/Makefile.in188
-rwxr-xr-xlibfuse-lite/fuse.c418
-rwxr-xr-xlibfuse-lite/fuse_kern_chan.c2
-rwxr-xr-xlibfuse-lite/fuse_lowlevel.c53
-rwxr-xr-xlibfuse-lite/fuse_opt.c20
-rwxr-xr-xlibfuse-lite/fuse_session.c12
-rwxr-xr-xlibfuse-lite/fusermount.c97
-rwxr-xr-xlibfuse-lite/helper.c21
-rwxr-xr-xlibfuse-lite/mount.c486
-rwxr-xr-xlibfuse-lite/mount_util.c246
-rwxr-xr-xlibfuse-lite/mount_util.h11
-rwxr-xr-xlibntfs-3g/Makefile.am15
-rwxr-xr-xlibntfs-3g/Makefile.in420
-rwxr-xr-xlibntfs-3g/acls.c219
-rwxr-xr-xlibntfs-3g/attrib.c1205
-rwxr-xr-xlibntfs-3g/bootsect.c4
-rwxr-xr-xlibntfs-3g/cache.c7
-rwxr-xr-xlibntfs-3g/compress.c962
-rwxr-xr-xlibntfs-3g/device.c252
-rwxr-xr-xlibntfs-3g/dir.c374
-rwxr-xr-xlibntfs-3g/efs.c217
-rwxr-xr-xlibntfs-3g/index.c30
-rwxr-xr-xlibntfs-3g/inode.c46
-rwxr-xr-xlibntfs-3g/lcnalloc.c36
-rw-r--r--libntfs-3g/libntfs-3g.pc10
-rw-r--r--libntfs-3g/libntfs-3g.script.so2
-rwxr-xr-xlibntfs-3g/logfile.c23
-rwxr-xr-xlibntfs-3g/logging.c24
-rwxr-xr-xlibntfs-3g/mft.c12
-rwxr-xr-xlibntfs-3g/mst.c24
-rwxr-xr-xlibntfs-3g/object_id.c9
-rwxr-xr-xlibntfs-3g/realpath.c103
-rwxr-xr-xlibntfs-3g/reparse.c67
-rwxr-xr-xlibntfs-3g/runlist.c62
-rwxr-xr-xlibntfs-3g/security.c345
-rwxr-xr-xlibntfs-3g/unistr.c244
-rwxr-xr-xlibntfs-3g/unix_io.c19
-rwxr-xr-xlibntfs-3g/volume.c365
-rwxr-xr-xlibntfs-3g/win32_io.c708
-rwxr-xr-xlibntfs-3g/xattrs.c791
-rwxr-xr-xlibtool9301
-rwxr-xr-xltmain.sh8439
-rwxr-xr-xm4/libtool.m47377
-rwxr-xr-xm4/ltoptions.m4368
-rwxr-xr-xm4/ltsugar.m4123
-rwxr-xr-xm4/ltversion.m423
-rwxr-xr-xm4/lt~obsolete.m492
-rwxr-xr-xmissing49
-rwxr-xr-xntfsprogs/Makefile.am154
-rwxr-xr-xntfsprogs/Makefile.in1199
-rwxr-xr-xntfsprogs/attrdef.c168
-rwxr-xr-xntfsprogs/attrdef.h7
-rwxr-xr-xntfsprogs/boot.c268
-rwxr-xr-xntfsprogs/boot.h7
-rwxr-xr-xntfsprogs/cluster.c118
-rwxr-xr-xntfsprogs/cluster.h39
-rwxr-xr-xntfsprogs/list.h194
-rw-r--r--ntfsprogs/mkntfs.8290
-rwxr-xr-xntfsprogs/mkntfs.8.in290
-rwxr-xr-xntfsprogs/mkntfs.c5177
-rw-r--r--ntfsprogs/ntfscat.8136
-rwxr-xr-xntfsprogs/ntfscat.8.in136
-rwxr-xr-xntfsprogs/ntfscat.c440
-rwxr-xr-xntfsprogs/ntfscat.h46
-rwxr-xr-xntfsprogs/ntfsck.c883
-rw-r--r--ntfsprogs/ntfsclone.8391
-rwxr-xr-xntfsprogs/ntfsclone.8.in391
-rwxr-xr-xntfsprogs/ntfsclone.c2701
-rw-r--r--ntfsprogs/ntfscluster.8124
-rwxr-xr-xntfsprogs/ntfscluster.8.in124
-rwxr-xr-xntfsprogs/ntfscluster.c563
-rwxr-xr-xntfsprogs/ntfscluster.h63
-rw-r--r--ntfsprogs/ntfscmp.877
-rwxr-xr-xntfsprogs/ntfscmp.8.in77
-rwxr-xr-xntfsprogs/ntfscmp.c1012
-rw-r--r--ntfsprogs/ntfscp.8111
-rwxr-xr-xntfsprogs/ntfscp.8.in111
-rwxr-xr-xntfsprogs/ntfscp.c590
-rwxr-xr-xntfsprogs/ntfsdecrypt.c1436
-rwxr-xr-xntfsprogs/ntfsdump_logfile.c779
-rw-r--r--ntfsprogs/ntfsfix.881
-rwxr-xr-xntfsprogs/ntfsfix.8.in81
-rwxr-xr-xntfsprogs/ntfsfix.c1657
-rw-r--r--ntfsprogs/ntfsinfo.889
-rwxr-xr-xntfsprogs/ntfsinfo.8.in89
-rwxr-xr-xntfsprogs/ntfsinfo.c2384
-rw-r--r--ntfsprogs/ntfslabel.8118
-rwxr-xr-xntfsprogs/ntfslabel.8.in118
-rwxr-xr-xntfsprogs/ntfslabel.c458
-rw-r--r--ntfsprogs/ntfsls.8172
-rwxr-xr-xntfsprogs/ntfsls.8.in172
-rwxr-xr-xntfsprogs/ntfsls.c717
-rwxr-xr-xntfsprogs/ntfsmftalloc.c368
-rwxr-xr-xntfsprogs/ntfsmove.c923
-rwxr-xr-xntfsprogs/ntfsmove.h46
-rw-r--r--ntfsprogs/ntfsprogs.869
-rwxr-xr-xntfsprogs/ntfsprogs.8.in69
-rw-r--r--ntfsprogs/ntfsresize.8326
-rwxr-xr-xntfsprogs/ntfsresize.8.in326
-rwxr-xr-xntfsprogs/ntfsresize.c4497
-rwxr-xr-xntfsprogs/ntfstruncate.c809
-rw-r--r--ntfsprogs/ntfsundelete.8324
-rwxr-xr-xntfsprogs/ntfsundelete.8.in324
-rwxr-xr-xntfsprogs/ntfsundelete.c2490
-rwxr-xr-xntfsprogs/ntfsundelete.h112
-rwxr-xr-xntfsprogs/ntfswipe.c2131
-rwxr-xr-xntfsprogs/ntfswipe.h54
-rwxr-xr-xntfsprogs/sd.c607
-rwxr-xr-xntfsprogs/sd.h11
-rwxr-xr-xntfsprogs/utils.c1184
-rwxr-xr-xntfsprogs/utils.h137
-rwxr-xr-xprog.IAB1071
-rwxr-xr-xprog.IAD5
-rwxr-xr-xprog.IMB466
-rwxr-xr-xprog.IMD2
-rwxr-xr-xprog.PFI2
-rwxr-xr-xprog.PO1
-rwxr-xr-xprog.PR14
-rwxr-xr-xprog.PRI219
-rwxr-xr-xprog.PS979
-rwxr-xr-xprog.SearchResults3
-rwxr-xr-xprog.WK39
-rwxr-xr-xsrc/Makefile.am86
-rwxr-xr-xsrc/Makefile.in938
-rwxr-xr-xsrc/lowntfs-3g.c1538
-rw-r--r--src/ntfs-3g.8448
-rwxr-xr-xsrc/ntfs-3g.8.in217
-rwxr-xr-xsrc/ntfs-3g.c1357
-rw-r--r--src/ntfs-3g.probe.881
-rwxr-xr-xsrc/ntfs-3g.probe.8.in4
-rwxr-xr-xsrc/ntfs-3g.probe.c9
-rw-r--r--src/ntfs-3g.secaudit.8184
-rwxr-xr-xsrc/ntfs-3g.secaudit.8.in15
-rw-r--r--src/ntfs-3g.usermap.896
-rwxr-xr-xsrc/ntfs-3g_common.c745
-rwxr-xr-xsrc/ntfs-3g_common.h185
-rwxr-xr-xsrc/secaudit.c673
-rwxr-xr-xsrc/secaudit.h32
-rwxr-xr-xsrc/usermap.c3
-rw-r--r--[-rwxr-xr-x]stamp-h10
193 files changed, 80411 insertions, 44563 deletions
diff --git a/libntfs-3g/win32_io.c b/libntfs-3g/win32_io.c
index ed9fa52..437a3fc 100755
--- a/libntfs-3g/win32_io.c
+++ b/libntfs-3g/win32_io.c
@@ -6,6 +6,7 @@
* Copyright (c) 2003-2004 Lode Leroy
* Copyright (c) 2003-2006 Anton Altaparmakov
* Copyright (c) 2004-2005 Yuval Fledel
+ * Copyright (c) 2012-2013 Jean-Pierre Andre
*
* This program/include file is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as published
@@ -26,8 +27,33 @@
#include "config.h"
#ifdef HAVE_WINDOWS_H
+#define BOOL WINBOOL /* avoid conflicting definitions of BOOL */
#include <windows.h>
+#undef BOOL
#endif
+
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+/*
+ * Definitions needed for <winioctl.h>
+ */
+#ifndef _ANONYMOUS_UNION
+#define _ANONYMOUS_UNION
+#define _ANONYMOUS_STRUCT
+typedef unsigned long long DWORD64;
+#endif
+
+typedef struct {
+ DWORD data1; /* The first eight hexadecimal digits of the GUID. */
+ WORD data2; /* The first group of four hexadecimal digits. */
+ WORD data3; /* The second group of four hexadecimal digits. */
+ char data4[8]; /* The first two bytes are the third group of four
+ hexadecimal digits. The remaining six bytes are the
+ final 12 hexadecimal digits. */
+} GUID;
+
#include <winioctl.h>
#ifdef HAVE_STDIO_H
@@ -42,6 +68,11 @@
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif
+#ifdef HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#define stat stat64
+#define st_blocks st_rdev /* emulate st_blocks, missing in Windows */
+#endif
/* Prevent volume.h from being be loaded, as it conflicts with winnt.h. */
#define _NTFS_VOLUME_H
@@ -51,6 +82,10 @@ typedef struct ntfs_volume ntfs_volume;
#include "debug.h"
#include "types.h"
#include "device.h"
+#include "misc.h"
+
+#define cpu_to_le16(x) (x)
+#define const_cpu_to_le16(x) (x)
#ifndef MAX_PATH
#define MAX_PATH 1024
@@ -61,10 +96,26 @@ typedef struct ntfs_volume ntfs_volume;
#define NTFS_BLOCK_SIZE_BITS 9
#endif
+#ifndef INVALID_SET_FILE_POINTER
+#define INVALID_SET_FILE_POINTER ((DWORD)-1)
+#endif
+
#ifndef IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS
#define IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS 5636096
#endif
+#ifndef IOCTL_DISK_GET_DRIVE_GEOMETRY
+#define IOCTL_DISK_GET_DRIVE_GEOMETRY 0x70000
+#endif
+
+#ifndef IOCTL_GET_DISK_LENGTH_INFO
+#define IOCTL_GET_DISK_LENGTH_INFO 0x7405c
+#endif
+
+#ifndef FSCTL_ALLOW_EXTENDED_DASD_IO
+#define FSCTL_ALLOW_EXTENDED_DASD_IO 0x90083
+#endif
+
/* Windows 2k+ imports. */
typedef HANDLE (WINAPI *LPFN_FINDFIRSTVOLUME)(LPTSTR, DWORD);
typedef BOOL (WINAPI *LPFN_FINDNEXTVOLUME)(HANDLE, LPTSTR, DWORD);
@@ -83,6 +134,146 @@ static LPFN_SETFILEPOINTEREX fnSetFilePointerEx = NULL;
#define FNPOSTFIX "A"
#endif
+enum { /* see http://msdn.microsoft.com/en-us/library/cc704588(v=prot.10).aspx */
+ STATUS_UNKNOWN = -1,
+ STATUS_SUCCESS = 0x00000000,
+ STATUS_BUFFER_OVERFLOW = 0x80000005,
+ STATUS_INVALID_HANDLE = 0xC0000008,
+ STATUS_INVALID_PARAMETER = 0xC000000D,
+ STATUS_INVALID_DEVICE_REQUEST = 0xC0000010,
+ STATUS_END_OF_FILE = 0xC0000011,
+ STATUS_CONFLICTING_ADDRESSES = 0xC0000018,
+ STATUS_NO_MATCH = 0xC000001E,
+ STATUS_ACCESS_DENIED = 0xC0000022,
+ STATUS_BUFFER_TOO_SMALL = 0xC0000023,
+ STATUS_OBJECT_TYPE_MISMATCH = 0xC0000024,
+ STATUS_FILE_NOT_FOUND = 0xC0000028,
+ STATUS_OBJECT_NAME_INVALID = 0xC0000033,
+ STATUS_OBJECT_NAME_NOT_FOUND = 0xC0000034,
+ STATUS_INVALID_PARAMETER_1 = 0xC00000EF,
+ STATUS_IO_DEVICE_ERROR = 0xC0000185,
+ STATUS_GUARD_PAGE_VIOLATION = 0x80000001
+ } ;
+
+typedef u32 NTSTATUS; /* do not let the compiler choose the size */
+#ifdef __x86_64__
+typedef unsigned long long ULONG_PTR; /* an integer the same size as a pointer */
+#else
+typedef unsigned long ULONG_PTR; /* an integer the same size as a pointer */
+#endif
+
+HANDLE get_osfhandle(int); /* from msvcrt.dll */
+
+/*
+ * A few needed definitions not included in <windows.h>
+ */
+
+typedef struct _IO_STATUS_BLOCK {
+ union {
+ NTSTATUS Status;
+ PVOID Pointer;
+ };
+ ULONG_PTR Information;
+} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;
+
+typedef struct _UNICODE_STRING {
+ USHORT Length;
+ USHORT MaximumLength;
+#ifdef __x86_64__
+ u32 padding;
+#endif
+ PWSTR Buffer;
+} UNICODE_STRING, *PUNICODE_STRING;
+
+typedef struct _OBJECT_ATTRIBUTES {
+ ULONG Length;
+#ifdef __x86_64__
+ u32 padding1;
+ HANDLE RootDirectory;
+ PUNICODE_STRING ObjectName;
+ ULONG Attributes;
+ u32 padding2;
+#else
+ HANDLE RootDirectory;
+ PUNICODE_STRING ObjectName;
+ ULONG Attributes;
+#endif
+ PVOID SecurityDescriptor;
+ PVOID SecurityQualityOfService;
+} OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
+
+#define FILE_OPEN 1
+#define FILE_CREATE 2
+#define FILE_OVERWRITE 4
+#define FILE_SYNCHRONOUS_IO_ALERT 0x10
+#define FILE_SYNCHRONOUS_IO_NONALERT 0x20
+#define OBJ_CASE_INSENSITIVE 0x40
+
+typedef void (WINAPI *PIO_APC_ROUTINE)(void*, PIO_STATUS_BLOCK, ULONG);
+
+extern WINAPI NTSTATUS NtOpenFile(
+ PHANDLE FileHandle,
+ ACCESS_MASK DesiredAccess,
+ POBJECT_ATTRIBUTES ObjectAttributes,
+ PIO_STATUS_BLOCK IoStatusBlock,
+ ULONG ShareAccess,
+ ULONG OpenOptions
+);
+
+extern WINAPI NTSTATUS NtReadFile(
+ HANDLE FileHandle,
+ HANDLE Event,
+ PIO_APC_ROUTINE ApcRoutine,
+ PVOID ApcContext,
+ PIO_STATUS_BLOCK IoStatusBlock,
+ PVOID Buffer,
+ ULONG Length,
+ PLARGE_INTEGER ByteOffset,
+ PULONG Key
+);
+
+extern WINAPI NTSTATUS NtWriteFile(
+ HANDLE FileHandle,
+ HANDLE Event,
+ PIO_APC_ROUTINE ApcRoutine,
+ PVOID ApcContext,
+ PIO_STATUS_BLOCK IoStatusBlock,
+ LPCVOID Buffer,
+ ULONG Length,
+ PLARGE_INTEGER ByteOffset,
+ PULONG Key
+);
+
+extern NTSTATUS WINAPI NtClose(
+ HANDLE Handle
+);
+
+extern NTSTATUS WINAPI NtDeviceIoControlFile(
+ HANDLE FileHandle,
+ HANDLE Event,
+ PIO_APC_ROUTINE ApcRoutine,
+ PVOID ApcContext,
+ PIO_STATUS_BLOCK IoStatusBlock,
+ ULONG IoControlCode,
+ PVOID InputBuffer,
+ ULONG InputBufferLength,
+ PVOID OutputBuffer,
+ ULONG OutputBufferLength
+);
+
+extern NTSTATUS WINAPI NtFsControlFile(
+ HANDLE FileHandle,
+ HANDLE Event,
+ PIO_APC_ROUTINE ApcRoutine,
+ PVOID ApcContext,
+ PIO_STATUS_BLOCK IoStatusBlock,
+ ULONG FsControlCode,
+ PVOID InputBuffer,
+ ULONG InputBufferLength,
+ PVOID OutputBuffer,
+ ULONG OutputBufferLength
+);
+
/**
* struct win32_fd -
*/
@@ -93,8 +284,11 @@ typedef struct {
s64 part_length;
int part_hidden_sectors;
s64 geo_size, geo_cylinders;
+ s32 geo_sector_size;
+ s64 volume_size;
DWORD geo_sectors, geo_heads;
HANDLE vol_handle;
+ BOOL ntdll;
} win32_fd;
/**
@@ -146,6 +340,26 @@ static int ntfs_w32error_to_errno(unsigned int w32error)
}
}
+static int ntfs_ntstatus_to_errno(NTSTATUS status)
+{
+ ntfs_log_trace("Converting w32error 0x%x.\n",w32error);
+ switch (status) {
+ case STATUS_INVALID_HANDLE :
+ case STATUS_INVALID_PARAMETER :
+ case STATUS_OBJECT_NAME_INVALID :
+ case STATUS_INVALID_DEVICE_REQUEST :
+ return (EINVAL);
+ case STATUS_ACCESS_DENIED :
+ return (EACCES);
+ case STATUS_IO_DEVICE_ERROR :
+ case STATUS_END_OF_FILE :
+ return (EIO);
+ default:
+ /* generic message */
+ return ENOMSG;
+ }
+}
+
/**
* libntfs_SetFilePointerEx - emulation for SetFilePointerEx()
*
@@ -156,10 +370,11 @@ static BOOL WINAPI libntfs_SetFilePointerEx(HANDLE hFile,
LARGE_INTEGER liDistanceToMove,
PLARGE_INTEGER lpNewFilePointer, DWORD dwMoveMethod)
{
- liDistanceToMove.LowPart = SetFilePointer(hFile,
- liDistanceToMove.LowPart, &liDistanceToMove.HighPart,
- dwMoveMethod);
- if (liDistanceToMove.LowPart == INVALID_SET_FILE_POINTER &&
+ liDistanceToMove.u.LowPart = SetFilePointer(hFile,
+ liDistanceToMove.u.LowPart,
+ &liDistanceToMove.u.HighPart, dwMoveMethod);
+ SetLastError(NO_ERROR);
+ if (liDistanceToMove.u.LowPart == INVALID_SET_FILE_POINTER &&
GetLastError() != NO_ERROR) {
if (lpNewFilePointer)
lpNewFilePointer->QuadPart = -1;
@@ -199,7 +414,7 @@ static void ntfs_device_win32_init_imports(void)
* SetFilePointerEx().
*/
if (!fnSetFilePointerEx) {
- ntfs_log_debug("SetFilePonterEx() not found in "
+ ntfs_log_debug("SetFilePointerEx() not found in "
"kernel32.dll: Enabling emulation.\n");
fnSetFilePointerEx = libntfs_SetFilePointerEx;
}
@@ -232,13 +447,13 @@ static __inline__ int ntfs_device_unix_status_flags_to_win32(int flags)
switch (flags & O_ACCMODE) {
case O_RDONLY:
- win_mode = FILE_READ_DATA;
+ win_mode = GENERIC_READ;
break;
case O_WRONLY:
- win_mode = FILE_WRITE_DATA;
+ win_mode = GENERIC_WRITE;
break;
case O_RDWR:
- win_mode = FILE_READ_DATA | FILE_WRITE_DATA;
+ win_mode = GENERIC_READ | GENERIC_WRITE;
break;
default:
/* error */
@@ -267,7 +482,8 @@ static int ntfs_device_win32_simple_open_file(const char *filename,
*handle = CreateFile(filename,
ntfs_device_unix_status_flags_to_win32(flags),
locking ? 0 : (FILE_SHARE_WRITE | FILE_SHARE_READ),
- NULL, OPEN_EXISTING, 0, NULL);
+ NULL, (flags & O_CREAT ? OPEN_ALWAYS : OPEN_EXISTING),
+ 0, NULL);
if (*handle == INVALID_HANDLE_VALUE) {
errno = ntfs_w32error_to_errno(GetLastError());
ntfs_log_trace("CreateFile(%s) failed.\n", filename);
@@ -321,6 +537,22 @@ static int ntfs_device_win32_unlock(HANDLE handle)
return 0;
}
+static int ntfs_device_win32_setlock(HANDLE handle, ULONG code)
+{
+ IO_STATUS_BLOCK io_status;
+ NTSTATUS res;
+
+ io_status.Status = STATUS_SUCCESS;
+ io_status.Information = 0;
+ res = NtFsControlFile(handle,(HANDLE)NULL,
+ (PIO_APC_ROUTINE)NULL,(void*)NULL,
+ &io_status, code,
+ (char*)NULL,0,(char*)NULL,0);
+ if (res != STATUS_SUCCESS)
+ errno = ntfs_ntstatus_to_errno(res);
+ return (res == STATUS_SUCCESS ? 0 : -1);
+}
+
/**
* ntfs_device_win32_dismount - dismount a volume
* @handle: a win32 HANDLE for a volume to dismount
@@ -359,15 +591,18 @@ static int ntfs_device_win32_dismount(HANDLE handle)
*/
static s64 ntfs_device_win32_getsize(HANDLE handle)
{
- DWORD loword, hiword;
+ LONG loword, hiword;
- loword = GetFileSize(handle, &hiword);
- if (loword == INVALID_FILE_SIZE) {
+ SetLastError(NO_ERROR);
+ hiword = 0;
+ loword = SetFilePointer(handle, 0, &hiword, 2);
+ if ((loword == INVALID_SET_FILE_POINTER)
+ && (GetLastError() != NO_ERROR)) {
errno = ntfs_w32error_to_errno(GetLastError());
ntfs_log_trace("Couldn't get file size.\n");
return -1;
}
- return ((s64)hiword << 32) + loword;
+ return ((s64)hiword << 32) + (ULONG)loword;
}
/**
@@ -467,6 +702,7 @@ static int ntfs_device_win32_getgeo(HANDLE handle, win32_fd *fd)
fd->geo_cylinders = ((DISK_GEOMETRY*)&b)->Cylinders.QuadPart;
fd->geo_sectors = ((DISK_GEOMETRY*)&b)->SectorsPerTrack;
fd->geo_size = ((DISK_GEOMETRY_EX*)&b)->DiskSize.QuadPart;
+ fd->geo_sector_size = NTFS_BLOCK_SIZE;
switch (ddi->DetectionType) {
case DetectInt13:
fd->geo_cylinders = ddi->Int13.MaxCylinders;
@@ -493,6 +729,7 @@ static int ntfs_device_win32_getgeo(HANDLE handle, win32_fd *fd)
fd->geo_size = fd->geo_cylinders * fd->geo_sectors *
((DISK_GEOMETRY*)&b)->TracksPerCylinder *
((DISK_GEOMETRY*)&b)->BytesPerSector;
+ fd->geo_sector_size = ((DISK_GEOMETRY*)&b)->BytesPerSector;
return 0;
}
errno = ntfs_w32error_to_errno(GetLastError());
@@ -500,9 +737,51 @@ static int ntfs_device_win32_getgeo(HANDLE handle, win32_fd *fd)
fd->geo_cylinders = -1;
fd->geo_sectors = -1;
fd->geo_size = -1;
+ fd->geo_sector_size = NTFS_BLOCK_SIZE;
return -1;
}
+static int ntfs_device_win32_getntgeo(HANDLE handle, win32_fd *fd)
+{
+ DISK_GEOMETRY geo;
+ NTSTATUS st;
+ IO_STATUS_BLOCK status;
+ u64 bytes;
+ int res;
+
+ res = -1;
+ fd->geo_cylinders = 0;
+ fd->geo_sectors = 0;
+ fd->geo_size = 1073741824;
+ fd->geo_sectors = fd->geo_size >> 9;
+ fd->geo_sector_size = NTFS_BLOCK_SIZE;
+
+ st = NtDeviceIoControlFile(handle, (HANDLE)NULL,
+ (PIO_APC_ROUTINE)NULL, (void*)NULL,
+ &status, IOCTL_DISK_GET_DRIVE_GEOMETRY, (void*)NULL, 0,
+ (void*)&geo, sizeof(geo));
+ if (st == STATUS_SUCCESS) {
+ /* over-estimate the (rounded) number of cylinders */
+ fd->geo_cylinders = geo.Cylinders.QuadPart + 1;
+ fd->geo_sectors = fd->geo_cylinders
+ *geo.TracksPerCylinder*geo.SectorsPerTrack;
+ fd->geo_size = fd->geo_sectors*geo.BytesPerSector;
+ fd->geo_sector_size = geo.BytesPerSector;
+ res = 0;
+ /* try to get the exact sector count */
+ st = NtDeviceIoControlFile(handle, (HANDLE)NULL,
+ (PIO_APC_ROUTINE)NULL, (void*)NULL,
+ &status, IOCTL_GET_DISK_LENGTH_INFO,
+ (void*)NULL, 0,
+ (void*)&bytes, sizeof(bytes));
+ if (st == STATUS_SUCCESS) {
+ fd->geo_size = bytes;
+ fd->geo_sectors = bytes/geo.BytesPerSector;
+ }
+ }
+ return (res);
+}
+
/**
* ntfs_device_win32_open_file - open a file via win32 API
* @filename: name of the file to open
@@ -516,12 +795,22 @@ static __inline__ int ntfs_device_win32_open_file(char *filename, win32_fd *fd,
int flags)
{
HANDLE handle;
+ int mode;
if (ntfs_device_win32_simple_open_file(filename, &handle, flags,
FALSE)) {
/* open error */
return -1;
}
+ mode = flags & O_ACCMODE;
+ if ((mode == O_RDWR) || (mode == O_WRONLY)) {
+ DWORD bytes;
+
+ /* try making sparse (but ignore errors) */
+ DeviceIoControl(handle, FSCTL_SET_SPARSE,
+ (void*)NULL, 0, (void*)NULL, 0,
+ &bytes, (LPOVERLAPPED)NULL);
+ }
/* fill fd */
fd->handle = handle;
fd->part_start = 0;
@@ -530,6 +819,8 @@ static __inline__ int ntfs_device_win32_open_file(char *filename, win32_fd *fd,
fd->part_hidden_sectors = -1;
fd->geo_size = -1; /* used as a marker that this is a file */
fd->vol_handle = INVALID_HANDLE_VALUE;
+ fd->geo_sector_size = 512; /* will be adjusted from the boot sector */
+ fd->ntdll = FALSE;
return 0;
}
@@ -561,6 +852,90 @@ static __inline__ int ntfs_device_win32_open_drive(int drive_id, win32_fd *fd,
if (fd->geo_size == -1)
fd->geo_size = ntfs_device_win32_getdisklength(handle);
/* fill fd */
+ fd->ntdll = FALSE;
+ fd->handle = handle;
+ fd->part_start = 0;
+ fd->part_length = fd->geo_size;
+ fd->pos = 0;
+ fd->part_hidden_sectors = -1;
+ fd->vol_handle = INVALID_HANDLE_VALUE;
+ return 0;
+}
+
+/**
+ * ntfs_device_win32_open_lowlevel - open a drive via low level win32 API
+ * @drive_id: drive to open
+ * @fd: pointer to win32 file device in which to put the result
+ * @flags: unix open status flags
+ *
+ * return 0 if o.k.
+ * -1 if not, and errno set.
+ */
+static __inline__ int ntfs_device_win32_open_lowlevel(int drive_id,
+ win32_fd *fd, int flags)
+{
+ HANDLE handle;
+ NTSTATUS st;
+ ACCESS_MASK access;
+ ULONG share;
+ OBJECT_ATTRIBUTES attr;
+ IO_STATUS_BLOCK io_status;
+ UNICODE_STRING unicode_name;
+ ntfschar unicode_buffer[7];
+ int mode;
+ static const ntfschar unicode_init[] = {
+ const_cpu_to_le16('\\'), const_cpu_to_le16('?'),
+ const_cpu_to_le16('?'), const_cpu_to_le16('\\'),
+ const_cpu_to_le16(' '), const_cpu_to_le16(':'),
+ const_cpu_to_le16(0)
+ };
+
+ memcpy(unicode_buffer, unicode_init, sizeof(unicode_buffer));
+ unicode_buffer[4] = cpu_to_le16(drive_id + 'A');
+ unicode_name.Buffer = unicode_buffer;
+ unicode_name.Length = 6*sizeof(ntfschar);
+ unicode_name.MaximumLength = 6*sizeof(ntfschar);
+
+ attr.Length = sizeof(OBJECT_ATTRIBUTES);
+ attr.RootDirectory = (HANDLE*)NULL;
+ attr.ObjectName = &unicode_name;
+ attr.Attributes = OBJ_CASE_INSENSITIVE;
+ attr.SecurityDescriptor = (void*)NULL;
+ attr.SecurityQualityOfService = (void*)NULL;
+
+ io_status.Status = 0;
+ io_status.Information = 0;
+ mode = flags & O_ACCMODE;
+ share = (mode == O_RDWR ?
+ 0 : FILE_SHARE_READ | FILE_SHARE_WRITE);
+ access = (mode == O_RDWR ?
+ FILE_READ_DATA | FILE_WRITE_DATA | SYNCHRONIZE
+ : FILE_READ_DATA | SYNCHRONIZE);
+
+ st = NtOpenFile(&handle, access,
+ &attr, &io_status,
+ share,
+ FILE_SYNCHRONOUS_IO_ALERT);
+ if (st != STATUS_SUCCESS) {
+ errno = ntfs_ntstatus_to_errno(st);
+ return (-1);
+ }
+ ntfs_device_win32_setlock(handle,FSCTL_LOCK_VOLUME);
+ /* store the drive geometry */
+ ntfs_device_win32_getntgeo(handle, fd);
+ fd->ntdll = TRUE;
+ /* allow accessing the full partition */
+ st = NtFsControlFile(handle, (HANDLE)NULL,
+ (PIO_APC_ROUTINE)NULL,
+ (PVOID)NULL, &io_status,
+ FSCTL_ALLOW_EXTENDED_DASD_IO,
+ NULL, 0, NULL, 0);
+ if (st != STATUS_SUCCESS) {
+ errno = ntfs_ntstatus_to_errno(st);
+ NtClose(handle);
+ return (-1);
+ }
+ /* fill fd */
fd->handle = handle;
fd->part_start = 0;
fd->part_length = fd->geo_size;
@@ -694,7 +1069,7 @@ static BOOL ntfs_device_win32_find_partition(HANDLE handle, DWORD partition_id,
do {
buf_size = sizeof(DRIVE_LAYOUT_INFORMATION) +
part_count * sizeof(PARTITION_INFORMATION);
- drive_layout = malloc(buf_size);
+ drive_layout = (DRIVE_LAYOUT_INFORMATION*)ntfs_malloc(buf_size);
if (!drive_layout) {
errno = ENOMEM;
return FALSE;
@@ -775,6 +1150,8 @@ static int ntfs_device_win32_open_partition(int drive_id,
fd->part_start = part_start;
fd->part_length = part_length;
fd->part_hidden_sectors = hidden_sectors;
+ fd->geo_sector_size = 512;
+ fd->ntdll = FALSE;
tmp = ntfs_device_win32_getntfssize(vol_handle);
if (tmp > 0)
fd->geo_size = tmp;
@@ -837,7 +1214,13 @@ static int ntfs_device_win32_open(struct ntfs_device *dev, int flags)
}
ntfs_device_win32_init_imports();
numparams = sscanf(dev->d_name, "/dev/hd%c%u", &drive_char, &part);
- drive_id = toupper(drive_char) - 'A';
+ if (!numparams
+ && (dev->d_name[1] == ':')
+ && (dev->d_name[2] == '\0')) {
+ drive_char = dev->d_name[0];
+ numparams = 3;
+ drive_id = toupper(drive_char) - 'A';
+ }
switch (numparams) {
case 0:
ntfs_log_debug("win32_open(%s) -> file.\n", dev->d_name);
@@ -854,6 +1237,12 @@ static int ntfs_device_win32_open(struct ntfs_device *dev, int flags)
err = ntfs_device_win32_open_partition(drive_id, part, &fd,
flags);
break;
+ case 3:
+ ntfs_log_debug("win32_open(%s) -> drive %c:\n",
+ dev->d_name, drive_char);
+ err = ntfs_device_win32_open_lowlevel(drive_id, &fd,
+ flags);
+ break;
default:
ntfs_log_debug("win32_open(%s) -> unknwon file format.\n",
dev->d_name);
@@ -866,7 +1255,7 @@ static int ntfs_device_win32_open(struct ntfs_device *dev, int flags)
/* Setup our read-only flag. */
if ((flags & O_RDWR) != O_RDWR)
NDevSetReadOnly(dev);
- dev->d_private = malloc(sizeof(win32_fd));
+ dev->d_private = (win32_fd*)ntfs_malloc(sizeof(win32_fd));
memcpy(dev->d_private, &fd, sizeof(win32_fd));
NDevSetOpen(dev);
NDevClearDirty(dev);
@@ -916,7 +1305,8 @@ static s64 ntfs_device_win32_seek(struct ntfs_device *dev, s64 offset,
errno = EINVAL;
return -1;
}
- if (abs_ofs < 0 || abs_ofs > fd->part_length) {
+ if ((abs_ofs < 0)
+ || (fd->ntdll && (abs_ofs > fd->part_length))) {
ntfs_log_trace("Seeking outsize seekable area.\n");
errno = EINVAL;
return -1;
@@ -937,18 +1327,19 @@ static s64 ntfs_device_win32_seek(struct ntfs_device *dev, s64 offset,
* error returns -1 and errno set. Transfer starts from position @pos on @fd.
*
* Notes:
- * - @pos, @buf, and @count must be aligned to NTFS_BLOCK_SIZE.
+ * - @pos, @buf, and @count must be aligned to geo_sector_size
* - When dealing with volumes, a single call must not span both volume
* and disk extents.
* - Does not use/set @fd->pos.
*/
static s64 ntfs_device_win32_pio(win32_fd *fd, const s64 pos,
- const s64 count, void *b, const BOOL write)
+ const s64 count, void *rbuf, const void *wbuf)
{
LARGE_INTEGER li;
HANDLE handle;
DWORD bt;
BOOL res;
+ s64 bytes;
ntfs_log_trace("pos = 0x%llx, count = 0x%llx, direction = %s.\n",
(long long)pos, (long long)count, write ? "write" :
@@ -962,21 +1353,57 @@ static s64 ntfs_device_win32_pio(win32_fd *fd, const s64 pos,
handle = fd->handle;
li.QuadPart += fd->part_start;
}
- if (!fnSetFilePointerEx(handle, li, NULL, FILE_BEGIN)) {
- errno = ntfs_w32error_to_errno(GetLastError());
- ntfs_log_trace("SetFilePointer failed.\n");
- return -1;
- }
- if (write)
- res = WriteFile(handle, b, count, &bt, NULL);
- else
- res = ReadFile(handle, b, count, &bt, NULL);
- if (!res) {
- errno = ntfs_w32error_to_errno(GetLastError());
- ntfs_log_trace("%sFile() failed.\n", write ? "Write" : "Read");
- return -1;
+
+ if (fd->ntdll) {
+ IO_STATUS_BLOCK io_status;
+ NTSTATUS res;
+ LARGE_INTEGER offset;
+
+ io_status.Status = STATUS_SUCCESS;
+ io_status.Information = 0;
+ offset.QuadPart = pos;
+ if (wbuf) {
+ res = NtWriteFile(fd->handle,(HANDLE)NULL,
+ (PIO_APC_ROUTINE)NULL,(void*)NULL,
+ &io_status, wbuf, count,
+ &offset, (PULONG)NULL);
+ } else {
+ res = NtReadFile(fd->handle,(HANDLE)NULL,
+ (PIO_APC_ROUTINE)NULL,(void*)NULL,
+ &io_status, rbuf, count,
+ &offset, (PULONG)NULL);
+ }
+ if (res == STATUS_SUCCESS) {
+ bytes = io_status.Information;
+ } else {
+ bytes = -1;
+ errno = ntfs_ntstatus_to_errno(res);
+ }
+ } else {
+ if (!fnSetFilePointerEx(handle, li, NULL, FILE_BEGIN)) {
+ errno = ntfs_w32error_to_errno(GetLastError());
+ ntfs_log_trace("SetFilePointer failed.\n");
+ return -1;
+ }
+ if (wbuf)
+ res = WriteFile(handle, wbuf, count, &bt, NULL);
+ else
+ res = ReadFile(handle, rbuf, count, &bt, NULL);
+ bytes = bt;
+ if (!res) {
+ errno = ntfs_w32error_to_errno(GetLastError());
+ ntfs_log_trace("%sFile() failed.\n", write ?
+ "Write" : "Read");
+ return -1;
+ }
+ if (rbuf && !pos) {
+ /* get the sector size from the boot sector */
+ char *boot = (char*)rbuf;
+ fd->geo_sector_size = (boot[11] & 255)
+ + ((boot[12] & 255) << 8);
+ }
}
- return bt;
+ return bytes;
}
/**
@@ -990,7 +1417,7 @@ static s64 ntfs_device_win32_pio(win32_fd *fd, const s64 pos,
* returns -1 and errno set. Read starts from position @pos.
*
* Notes:
- * - @pos, @buf, and @count must be aligned to NTFS_BLOCK_SIZE.
+ * - @pos, @buf, and @count must be aligned to geo_sector_size.
* - When dealing with volumes, a single call must not span both volume
* and disk extents.
* - Does not use/set @fd->pos.
@@ -998,7 +1425,7 @@ static s64 ntfs_device_win32_pio(win32_fd *fd, const s64 pos,
static inline s64 ntfs_device_win32_pread_simple(win32_fd *fd, const s64 pos,
const s64 count, void *b)
{
- return ntfs_device_win32_pio(fd, pos, count, b, FALSE);
+ return ntfs_device_win32_pio(fd, pos, count, b, (void*)NULL);
}
/**
@@ -1018,9 +1445,9 @@ static s64 ntfs_device_win32_read(struct ntfs_device *dev, void *b, s64 count)
int old_ofs, ofs;
old_pos = fd->pos;
- old_ofs = ofs = old_pos & (NTFS_BLOCK_SIZE - 1);
- to_read = (ofs + count + NTFS_BLOCK_SIZE - 1) &
- ~(s64)(NTFS_BLOCK_SIZE - 1);
+ old_ofs = ofs = old_pos & (fd->geo_sector_size - 1);
+ to_read = (ofs + count + fd->geo_sector_size - 1) &
+ ~(s64)(fd->geo_sector_size - 1);
/* Impose maximum of 2GB to be on the safe side. */
if (to_read > 0x80000000) {
int delta = to_read - count;
@@ -1031,8 +1458,8 @@ static s64 ntfs_device_win32_read(struct ntfs_device *dev, void *b, s64 count)
"ofs = %i, to_read = 0x%llx.\n", fd, b,
(long long)count, (long long)old_pos, ofs,
(long long)to_read);
- if (!((unsigned long)b & (NTFS_BLOCK_SIZE - 1)) && !old_ofs &&
- !(count & (NTFS_BLOCK_SIZE - 1)))
+ if (!((unsigned long)b & (fd->geo_sector_size - 1)) && !old_ofs &&
+ !(count & (fd->geo_sector_size - 1)))
alignedbuffer = b;
else {
alignedbuffer = (BYTE *)VirtualAlloc(NULL, to_read, MEM_COMMIT,
@@ -1047,7 +1474,7 @@ static s64 ntfs_device_win32_read(struct ntfs_device *dev, void *b, s64 count)
s64 vol_to_read = fd->geo_size - old_pos;
if (count > vol_to_read) {
br = ntfs_device_win32_pread_simple(fd,
- old_pos & ~(s64)(NTFS_BLOCK_SIZE - 1),
+ old_pos & ~(s64)(fd->geo_sector_size - 1),
ofs + vol_to_read, alignedbuffer);
if (br == -1)
goto read_error;
@@ -1058,13 +1485,13 @@ static s64 ntfs_device_win32_read(struct ntfs_device *dev, void *b, s64 count)
}
br -= ofs;
fd->pos += br;
- ofs = fd->pos & (NTFS_BLOCK_SIZE - 1);
+ ofs = fd->pos & (fd->geo_sector_size - 1);
if (br != vol_to_read)
goto read_partial;
}
}
i = ntfs_device_win32_pread_simple(fd,
- fd->pos & ~(s64)(NTFS_BLOCK_SIZE - 1), to_read,
+ fd->pos & ~(s64)(fd->geo_sector_size - 1), to_read,
alignedbuffer + br);
if (i == -1) {
if (br)
@@ -1115,11 +1542,18 @@ static int ntfs_device_win32_close(struct ntfs_device *dev)
if (!CloseHandle(fd->vol_handle))
ntfs_log_trace("CloseHandle() failed for volume.\n");
}
- rvl = CloseHandle(fd->handle);
+ if (fd->ntdll) {
+ ntfs_device_win32_setlock(fd->handle,FSCTL_UNLOCK_VOLUME);
+ rvl = NtClose(fd->handle) == STATUS_SUCCESS;
+ } else
+ rvl = CloseHandle(fd->handle);
free(fd);
if (!rvl) {
errno = ntfs_w32error_to_errno(GetLastError());
- ntfs_log_trace("CloseHandle() failed.\n");
+ if (fd->ntdll)
+ ntfs_log_trace("NtClose() failed.\n");
+ else
+ ntfs_log_trace("CloseHandle() failed.\n");
return -1;
}
return 0;
@@ -1174,7 +1608,7 @@ static int ntfs_device_win32_sync(struct ntfs_device *dev)
* errno set. Write starts from position @pos.
*
* Notes:
- * - @pos, @buf, and @count must be aligned to NTFS_BLOCK_SIZE.
+ * - @pos, @buf, and @count must be aligned to geo_sector_size.
* - When dealing with volumes, a single call must not span both volume
* and disk extents.
* - Does not use/set @fd->pos.
@@ -1182,7 +1616,7 @@ static int ntfs_device_win32_sync(struct ntfs_device *dev)
static inline s64 ntfs_device_win32_pwrite_simple(win32_fd *fd, const s64 pos,
const s64 count, const void *b)
{
- return ntfs_device_win32_pio(fd, pos, count, (void *)b, TRUE);
+ return ntfs_device_win32_pio(fd, pos, count, (void*)NULL, b);
}
/**
@@ -1203,9 +1637,9 @@ static s64 ntfs_device_win32_write(struct ntfs_device *dev, const void *b,
int old_ofs, ofs;
old_pos = fd->pos;
- old_ofs = ofs = old_pos & (NTFS_BLOCK_SIZE - 1);
- to_write = (ofs + count + NTFS_BLOCK_SIZE - 1) &
- ~(s64)(NTFS_BLOCK_SIZE - 1);
+ old_ofs = ofs = old_pos & (fd->geo_sector_size - 1);
+ to_write = (ofs + count + fd->geo_sector_size - 1) &
+ ~(s64)(fd->geo_sector_size - 1);
/* Impose maximum of 2GB to be on the safe side. */
if (to_write > 0x80000000) {
int delta = to_write - count;
@@ -1224,8 +1658,8 @@ static s64 ntfs_device_win32_write(struct ntfs_device *dev, const void *b,
if (!count)
return 0;
NDevSetDirty(dev);
- if (!((unsigned long)b & (NTFS_BLOCK_SIZE - 1)) && !old_ofs &&
- !(count & (NTFS_BLOCK_SIZE - 1)))
+ if (!((unsigned long)b & (fd->geo_sector_size - 1)) && !old_ofs &&
+ !(count & (fd->geo_sector_size - 1)))
alignedbuffer = (BYTE *)b;
else {
s64 end;
@@ -1240,9 +1674,9 @@ static s64 ntfs_device_win32_write(struct ntfs_device *dev, const void *b,
/* Read first sector if start of write not sector aligned. */
if (ofs) {
i = ntfs_device_win32_pread_simple(fd,
- old_pos & ~(s64)(NTFS_BLOCK_SIZE - 1),
- NTFS_BLOCK_SIZE, alignedbuffer);
- if (i != NTFS_BLOCK_SIZE) {
+ old_pos & ~(s64)(fd->geo_sector_size - 1),
+ fd->geo_sector_size, alignedbuffer);
+ if (i != fd->geo_sector_size) {
if (i >= 0)
errno = EIO;
goto write_error;
@@ -1255,13 +1689,13 @@ static s64 ntfs_device_win32_write(struct ntfs_device *dev, const void *b,
* yet, i.e. the start of the write is sector aligned.
*/
end = old_pos + count;
- if ((end & (NTFS_BLOCK_SIZE - 1)) &&
- ((to_write > NTFS_BLOCK_SIZE) || !ofs)) {
+ if ((end & (fd->geo_sector_size - 1)) &&
+ ((to_write > fd->geo_sector_size) || !ofs)) {
i = ntfs_device_win32_pread_simple(fd,
- end & ~(s64)(NTFS_BLOCK_SIZE - 1),
- NTFS_BLOCK_SIZE, alignedbuffer +
- to_write - NTFS_BLOCK_SIZE);
- if (i != NTFS_BLOCK_SIZE) {
+ end & ~(s64)(fd->geo_sector_size - 1),
+ fd->geo_sector_size, alignedbuffer +
+ to_write - fd->geo_sector_size);
+ if (i != fd->geo_sector_size) {
if (i >= 0)
errno = EIO;
goto write_error;
@@ -1274,7 +1708,7 @@ static s64 ntfs_device_win32_write(struct ntfs_device *dev, const void *b,
s64 vol_to_write = fd->geo_size - old_pos;
if (count > vol_to_write) {
bw = ntfs_device_win32_pwrite_simple(fd,
- old_pos & ~(s64)(NTFS_BLOCK_SIZE - 1),
+ old_pos & ~(s64)(fd->geo_sector_size - 1),
ofs + vol_to_write, alignedbuffer);
if (bw == -1)
goto write_error;
@@ -1285,13 +1719,13 @@ static s64 ntfs_device_win32_write(struct ntfs_device *dev, const void *b,
}
bw -= ofs;
fd->pos += bw;
- ofs = fd->pos & (NTFS_BLOCK_SIZE - 1);
+ ofs = fd->pos & (fd->geo_sector_size - 1);
if (bw != vol_to_write)
goto write_partial;
}
}
i = ntfs_device_win32_pwrite_simple(fd,
- fd->pos & ~(s64)(NTFS_BLOCK_SIZE - 1), to_write,
+ fd->pos & ~(s64)(fd->geo_sector_size - 1), to_write,
alignedbuffer + bw);
if (i == -1) {
if (bw)
@@ -1329,19 +1763,22 @@ static int ntfs_device_win32_stat(struct ntfs_device *dev, struct stat *buf)
win32_fd *fd = (win32_fd *)dev->d_private;
mode_t st_mode;
- switch (GetFileType(fd->handle)) {
- case FILE_TYPE_CHAR:
- st_mode = S_IFCHR;
- break;
- case FILE_TYPE_DISK:
+ if ((dev->d_name[1] == ':') && (dev->d_name[2] == '\0'))
st_mode = S_IFBLK;
- break;
- case FILE_TYPE_PIPE:
- st_mode = S_IFIFO;
- break;
- default:
- st_mode = 0;
- }
+ else
+ switch (GetFileType(fd->handle)) {
+ case FILE_TYPE_CHAR:
+ st_mode = S_IFCHR;
+ break;
+ case FILE_TYPE_DISK:
+ st_mode = S_IFREG;
+ break;
+ case FILE_TYPE_PIPE:
+ st_mode = S_IFIFO;
+ break;
+ default:
+ st_mode = 0;
+ }
memset(buf, 0, sizeof(struct stat));
buf->st_mode = st_mode;
buf->st_size = fd->part_length;
@@ -1352,6 +1789,7 @@ static int ntfs_device_win32_stat(struct ntfs_device *dev, struct stat *buf)
return 0;
}
+#ifdef HDIO_GETGEO
/**
* ntfs_win32_hdio_getgeo - get drive geometry
* @dev: ntfs device obtained via ->open
@@ -1373,6 +1811,7 @@ static __inline__ int ntfs_win32_hdio_getgeo(struct ntfs_device *dev,
argp->start = fd->part_hidden_sectors;
return 0;
}
+#endif
/**
* ntfs_win32_blksszget - get block device sector size
@@ -1404,7 +1843,9 @@ static __inline__ int ntfs_win32_blksszget(struct ntfs_device *dev,int *argp)
static int ntfs_device_win32_ioctl(struct ntfs_device *dev, int request,
void *argp)
{
+#if defined(BLKGETSIZE) | defined(BLKGETSIZE64)
win32_fd *fd = (win32_fd *)dev->d_private;
+#endif
ntfs_log_trace("win32_ioctl(%d) called.\n", request);
switch (request) {
@@ -1454,13 +1895,40 @@ static int ntfs_device_win32_ioctl(struct ntfs_device *dev, int request,
static s64 ntfs_device_win32_pread(struct ntfs_device *dev, void *b,
s64 count, s64 offset)
{
- return ntfs_pread(dev, offset, count, b);
+ s64 got;
+ win32_fd *fd;
+
+ /* read the fast way if sector aligned */
+ fd = (win32_fd*)dev->d_private;
+ if (!((count | offset) & (fd->geo_sector_size - 1))) {
+ got = ntfs_device_win32_pio(fd, offset, count, b, (void*)NULL);
+ } else {
+ if (ntfs_device_win32_seek(dev, offset, 0) == -1)
+ got = 0;
+ else
+ got = ntfs_device_win32_read(dev, b, count);
+ }
+
+ return (got);
}
static s64 ntfs_device_win32_pwrite(struct ntfs_device *dev, const void *b,
s64 count, s64 offset)
{
- return ntfs_pwrite(dev, offset, count, b);
+ s64 put;
+ win32_fd *fd;
+
+ /* write the fast way if sector aligned */
+ fd = (win32_fd*)dev->d_private;
+ if (!((count | offset) & (fd->geo_sector_size - 1))) {
+ put = ntfs_device_win32_pio(fd, offset, count, (void*)NULL, b);
+ } else {
+ if (ntfs_device_win32_seek(dev, offset, 0) == -1)
+ put = 0;
+ else
+ put = ntfs_device_win32_write(dev, b, count);
+ }
+ return (put);
}
struct ntfs_device_operations ntfs_device_win32_io_ops = {
@@ -1475,3 +1943,87 @@ struct ntfs_device_operations ntfs_device_win32_io_ops = {
.stat = ntfs_device_win32_stat,
.ioctl = ntfs_device_win32_ioctl
};
+
+/*
+ * Mark an open file as sparse
+ *
+ * This is only called by ntfsclone when cloning a volume to a file.
+ * The argument is the target file, not a volume.
+ *
+ * Returns 0 if successful.
+ */
+
+int ntfs_win32_set_sparse(int fd)
+{
+ BOOL ok;
+ HANDLE handle;
+ DWORD bytes;
+
+ handle = get_osfhandle(fd);
+ if (handle == INVALID_HANDLE_VALUE)
+ ok = FALSE;
+ else
+ ok = DeviceIoControl(handle, FSCTL_SET_SPARSE,
+ (void*)NULL, 0, (void*)NULL, 0,
+ &bytes, (LPOVERLAPPED)NULL);
+ return (!ok);
+}
+
+/*
+ * Resize an open file
+ *
+ * This is only called by ntfsclone when cloning a volume to a file.
+ * The argument must designate a file, not a volume.
+ *
+ * Returns 0 if successful.
+ */
+
+static int win32_ftruncate(HANDLE handle, s64 size)
+{
+ BOOL ok;
+ LONG hsize, lsize;
+ LONG ohsize, olsize;
+
+ if (handle == INVALID_HANDLE_VALUE)
+ ok = FALSE;
+ else {
+ SetLastError(NO_ERROR);
+ /* save original position */
+ ohsize = 0;
+ olsize = SetFilePointer(handle, 0, &ohsize, 1);
+ hsize = size >> 32;
+ lsize = size & 0xffffffff;
+ ok = (SetFilePointer(handle, lsize, &hsize, 0) == (DWORD)lsize)
+ && (GetLastError() == NO_ERROR)
+ && SetEndOfFile(handle);
+ /* restore original position, even if above failed */
+ SetFilePointer(handle, olsize, &ohsize, 0);
+ if (GetLastError() != NO_ERROR)
+ ok = FALSE;
+ }
+ if (!ok)
+ errno = EINVAL;
+ return (ok ? 0 : -1);
+}
+
+int ntfs_device_win32_ftruncate(struct ntfs_device *dev, s64 size)
+{
+ win32_fd *fd;
+ int ret;
+
+ ret = -1;
+ fd = (win32_fd*)dev->d_private;
+ if (fd && !fd->ntdll)
+ ret = win32_ftruncate(fd->handle, size);
+ return (ret);
+}
+
+int ntfs_win32_ftruncate(int fd, s64 size)
+{
+ int ret;
+ HANDLE handle;
+
+ handle = get_osfhandle(fd);
+ ret = win32_ftruncate(handle, size);
+ return (ret);
+}