forked from Mirrors/wine-wine
ntdll: Move the volume information functions to the Unix library.
Signed-off-by: Alexandre Julliard <julliard@winehq.org>feature/deterministic
parent
a0b7fb9bb2
commit
7e3d265469
|
@ -112,9 +112,6 @@
|
||||||
|
|
||||||
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
|
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
|
||||||
|
|
||||||
#define FILE_WRITE_TO_END_OF_FILE ((LONGLONG)-1)
|
|
||||||
#define FILE_USE_FILE_POINTER_POSITION ((LONGLONG)-2)
|
|
||||||
|
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* NtOpenFile [NTDLL.@]
|
* NtOpenFile [NTDLL.@]
|
||||||
|
@ -257,56 +254,6 @@ static async_data_t server_async( HANDLE handle, struct async_fileio *user, HAND
|
||||||
return async;
|
return async;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
|
||||||
* FILE_GetNtStatus(void)
|
|
||||||
*
|
|
||||||
* Retrieve the Nt Status code from errno.
|
|
||||||
* Try to be consistent with FILE_SetDosError().
|
|
||||||
*/
|
|
||||||
NTSTATUS FILE_GetNtStatus(void)
|
|
||||||
{
|
|
||||||
int err = errno;
|
|
||||||
|
|
||||||
TRACE( "errno = %d\n", errno );
|
|
||||||
switch (err)
|
|
||||||
{
|
|
||||||
case EAGAIN: return STATUS_SHARING_VIOLATION;
|
|
||||||
case EBADF: return STATUS_INVALID_HANDLE;
|
|
||||||
case EBUSY: return STATUS_DEVICE_BUSY;
|
|
||||||
case ENOSPC: return STATUS_DISK_FULL;
|
|
||||||
case EPERM:
|
|
||||||
case EROFS:
|
|
||||||
case EACCES: return STATUS_ACCESS_DENIED;
|
|
||||||
case ENOTDIR: return STATUS_OBJECT_PATH_NOT_FOUND;
|
|
||||||
case ENOENT: return STATUS_OBJECT_NAME_NOT_FOUND;
|
|
||||||
case EISDIR: return STATUS_FILE_IS_A_DIRECTORY;
|
|
||||||
case EMFILE:
|
|
||||||
case ENFILE: return STATUS_TOO_MANY_OPENED_FILES;
|
|
||||||
case EINVAL: return STATUS_INVALID_PARAMETER;
|
|
||||||
case ENOTEMPTY: return STATUS_DIRECTORY_NOT_EMPTY;
|
|
||||||
case EPIPE: return STATUS_PIPE_DISCONNECTED;
|
|
||||||
case EIO: return STATUS_DEVICE_NOT_READY;
|
|
||||||
#ifdef ENOMEDIUM
|
|
||||||
case ENOMEDIUM: return STATUS_NO_MEDIA_IN_DEVICE;
|
|
||||||
#endif
|
|
||||||
case ENXIO: return STATUS_NO_SUCH_DEVICE;
|
|
||||||
case ENOTTY:
|
|
||||||
case EOPNOTSUPP:return STATUS_NOT_SUPPORTED;
|
|
||||||
case ECONNRESET:return STATUS_PIPE_DISCONNECTED;
|
|
||||||
case EFAULT: return STATUS_ACCESS_VIOLATION;
|
|
||||||
case ESPIPE: return STATUS_ILLEGAL_FUNCTION;
|
|
||||||
case ELOOP: return STATUS_REPARSE_POINT_NOT_RESOLVED;
|
|
||||||
#ifdef ETIME /* Missing on FreeBSD */
|
|
||||||
case ETIME: return STATUS_IO_TIMEOUT;
|
|
||||||
#endif
|
|
||||||
case ENOEXEC: /* ?? */
|
|
||||||
case EEXIST: /* ?? */
|
|
||||||
default:
|
|
||||||
FIXME( "Converting errno %d to STATUS_UNSUCCESSFUL\n", err );
|
|
||||||
return STATUS_UNSUCCESSFUL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* NtReadFile [NTDLL.@]
|
* NtReadFile [NTDLL.@]
|
||||||
|
@ -599,30 +546,11 @@ NTSTATUS WINAPI NtNotifyChangeDirectoryFile( HANDLE handle, HANDLE event, PIO_AP
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* NtSetVolumeInformationFile [NTDLL.@]
|
* NtSetVolumeInformationFile [NTDLL.@]
|
||||||
* ZwSetVolumeInformationFile [NTDLL.@]
|
* ZwSetVolumeInformationFile [NTDLL.@]
|
||||||
*
|
|
||||||
* Set volume information for an open file handle.
|
|
||||||
*
|
|
||||||
* PARAMS
|
|
||||||
* FileHandle [I] Handle returned from ZwOpenFile() or ZwCreateFile()
|
|
||||||
* IoStatusBlock [O] Receives information about the operation on return
|
|
||||||
* FsInformation [I] Source for volume information
|
|
||||||
* Length [I] Size of FsInformation
|
|
||||||
* FsInformationClass [I] Type of volume information to set
|
|
||||||
*
|
|
||||||
* RETURNS
|
|
||||||
* Success: 0. IoStatusBlock is updated.
|
|
||||||
* Failure: An NTSTATUS error code describing the error.
|
|
||||||
*/
|
*/
|
||||||
NTSTATUS WINAPI NtSetVolumeInformationFile(
|
NTSTATUS WINAPI NtSetVolumeInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, void *info,
|
||||||
IN HANDLE FileHandle,
|
ULONG length, FS_INFORMATION_CLASS class )
|
||||||
PIO_STATUS_BLOCK IoStatusBlock,
|
|
||||||
PVOID FsInformation,
|
|
||||||
ULONG Length,
|
|
||||||
FS_INFORMATION_CLASS FsInformationClass)
|
|
||||||
{
|
{
|
||||||
FIXME("(%p,%p,%p,0x%08x,0x%08x) stub\n",
|
return unix_funcs->NtSetVolumeInformationFile( handle, io, info, length, class );
|
||||||
FileHandle,IoStatusBlock,FsInformation,Length,FsInformationClass);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NTSTATUS server_get_unix_name( HANDLE handle, ANSI_STRING *unix_name )
|
NTSTATUS server_get_unix_name( HANDLE handle, ANSI_STRING *unix_name )
|
||||||
|
@ -659,126 +587,6 @@ NTSTATUS server_get_unix_name( HANDLE handle, ANSI_STRING *unix_name )
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find a DOS device which can act as the root of "path".
|
|
||||||
* Similar to find_drive_root(), but returns -1 instead of crossing volumes. */
|
|
||||||
static int find_dos_device( const char *path )
|
|
||||||
{
|
|
||||||
int len = strlen(path);
|
|
||||||
int drive;
|
|
||||||
char *buffer;
|
|
||||||
struct stat st;
|
|
||||||
struct drive_info info[MAX_DOS_DRIVES];
|
|
||||||
dev_t dev_id;
|
|
||||||
|
|
||||||
if (!DIR_get_drives_info( info )) return -1;
|
|
||||||
|
|
||||||
if (stat( path, &st ) < 0) return -1;
|
|
||||||
dev_id = st.st_dev;
|
|
||||||
|
|
||||||
/* strip off trailing slashes */
|
|
||||||
while (len > 1 && path[len - 1] == '/') len--;
|
|
||||||
|
|
||||||
/* make a copy of the path */
|
|
||||||
if (!(buffer = RtlAllocateHeap( GetProcessHeap(), 0, len + 1 ))) return -1;
|
|
||||||
memcpy( buffer, path, len );
|
|
||||||
buffer[len] = 0;
|
|
||||||
|
|
||||||
for (;;)
|
|
||||||
{
|
|
||||||
if (!stat( buffer, &st ) && S_ISDIR( st.st_mode ))
|
|
||||||
{
|
|
||||||
if (st.st_dev != dev_id) break;
|
|
||||||
|
|
||||||
for (drive = 0; drive < MAX_DOS_DRIVES; drive++)
|
|
||||||
{
|
|
||||||
if ((info[drive].dev == st.st_dev) && (info[drive].ino == st.st_ino))
|
|
||||||
{
|
|
||||||
if (len == 1) len = 0; /* preserve root slash in returned path */
|
|
||||||
TRACE( "%s -> drive %c:, root=%s, name=%s\n",
|
|
||||||
debugstr_a(path), 'A' + drive, debugstr_a(buffer), debugstr_a(path + len));
|
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, buffer );
|
|
||||||
return drive;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (len <= 1) break; /* reached root */
|
|
||||||
while (path[len - 1] != '/') len--;
|
|
||||||
while (path[len - 1] == '/') len--;
|
|
||||||
buffer[len] = 0;
|
|
||||||
}
|
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, buffer );
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct mountmgr_unix_drive *get_mountmgr_fs_info( HANDLE handle, int fd )
|
|
||||||
{
|
|
||||||
struct mountmgr_unix_drive *drive;
|
|
||||||
OBJECT_ATTRIBUTES attr;
|
|
||||||
UNICODE_STRING string;
|
|
||||||
ANSI_STRING unix_name;
|
|
||||||
IO_STATUS_BLOCK io;
|
|
||||||
HANDLE mountmgr;
|
|
||||||
NTSTATUS status;
|
|
||||||
int letter;
|
|
||||||
|
|
||||||
if (server_get_unix_name( handle, &unix_name ))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
letter = find_dos_device( unix_name.Buffer );
|
|
||||||
RtlFreeAnsiString( &unix_name );
|
|
||||||
|
|
||||||
if (!(drive = RtlAllocateHeap( GetProcessHeap(), 0, 1024 )))
|
|
||||||
return NULL;
|
|
||||||
|
|
||||||
if (letter == -1)
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
if (fstat( fd, &st ) == -1)
|
|
||||||
{
|
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, drive );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
drive->unix_dev = st.st_dev;
|
|
||||||
drive->letter = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
drive->letter = 'a' + letter;
|
|
||||||
|
|
||||||
RtlInitUnicodeString( &string, MOUNTMGR_DEVICE_NAME );
|
|
||||||
InitializeObjectAttributes( &attr, &string, 0, NULL, NULL );
|
|
||||||
if (NtOpenFile( &mountmgr, GENERIC_READ | SYNCHRONIZE, &attr, &io,
|
|
||||||
FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_SYNCHRONOUS_IO_NONALERT ))
|
|
||||||
{
|
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, drive );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
status = NtDeviceIoControlFile( mountmgr, NULL, NULL, NULL, &io, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE,
|
|
||||||
drive, sizeof(*drive), drive, 1024 );
|
|
||||||
if (status == STATUS_BUFFER_OVERFLOW)
|
|
||||||
{
|
|
||||||
if (!(drive = RtlReAllocateHeap( GetProcessHeap(), 0, drive, drive->size )))
|
|
||||||
{
|
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, drive );
|
|
||||||
NtClose( mountmgr );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
status = NtDeviceIoControlFile( mountmgr, NULL, NULL, NULL, &io, IOCTL_MOUNTMGR_QUERY_UNIX_DRIVE,
|
|
||||||
drive, sizeof(*drive), drive, drive->size );
|
|
||||||
}
|
|
||||||
NtClose( mountmgr );
|
|
||||||
|
|
||||||
if (status)
|
|
||||||
{
|
|
||||||
WARN("failed to retrieve filesystem type from mountmgr, status %#x\n", status);
|
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, drive );
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
return drive;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* NtQueryInformationFile [NTDLL.@]
|
* NtQueryInformationFile [NTDLL.@]
|
||||||
|
@ -847,184 +655,6 @@ NTSTATUS WINAPI NtQueryAttributesFile( const OBJECT_ATTRIBUTES *attr, FILE_BASIC
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
|
|
||||||
/* helper for FILE_GetDeviceInfo to hide some platform differences in fstatfs */
|
|
||||||
static inline void get_device_info_fstatfs( FILE_FS_DEVICE_INFORMATION *info, const char *fstypename,
|
|
||||||
unsigned int flags )
|
|
||||||
{
|
|
||||||
if (!strcmp("cd9660", fstypename) || !strcmp("udf", fstypename))
|
|
||||||
{
|
|
||||||
info->DeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
|
|
||||||
/* Don't assume read-only, let the mount options set it below */
|
|
||||||
info->Characteristics |= FILE_REMOVABLE_MEDIA;
|
|
||||||
}
|
|
||||||
else if (!strcmp("nfs", fstypename) || !strcmp("nwfs", fstypename) ||
|
|
||||||
!strcmp("smbfs", fstypename) || !strcmp("afpfs", fstypename))
|
|
||||||
{
|
|
||||||
info->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
|
|
||||||
info->Characteristics |= FILE_REMOTE_DEVICE;
|
|
||||||
}
|
|
||||||
else if (!strcmp("procfs", fstypename))
|
|
||||||
info->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
|
|
||||||
else
|
|
||||||
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
|
||||||
|
|
||||||
if (flags & MNT_RDONLY)
|
|
||||||
info->Characteristics |= FILE_READ_ONLY_DEVICE;
|
|
||||||
|
|
||||||
if (!(flags & MNT_LOCAL))
|
|
||||||
{
|
|
||||||
info->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
|
|
||||||
info->Characteristics |= FILE_REMOTE_DEVICE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline BOOL is_device_placeholder( int fd )
|
|
||||||
{
|
|
||||||
static const char wine_placeholder[] = "Wine device placeholder";
|
|
||||||
char buffer[sizeof(wine_placeholder)-1];
|
|
||||||
|
|
||||||
if (pread( fd, buffer, sizeof(wine_placeholder) - 1, 0 ) != sizeof(wine_placeholder) - 1)
|
|
||||||
return FALSE;
|
|
||||||
return !memcmp( buffer, wine_placeholder, sizeof(wine_placeholder) - 1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
|
||||||
* get_device_info
|
|
||||||
*
|
|
||||||
* Implementation of the FileFsDeviceInformation query for NtQueryVolumeInformationFile.
|
|
||||||
*/
|
|
||||||
static NTSTATUS get_device_info( int fd, FILE_FS_DEVICE_INFORMATION *info )
|
|
||||||
{
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
info->Characteristics = 0;
|
|
||||||
if (fstat( fd, &st ) < 0) return FILE_GetNtStatus();
|
|
||||||
if (S_ISCHR( st.st_mode ))
|
|
||||||
{
|
|
||||||
info->DeviceType = FILE_DEVICE_UNKNOWN;
|
|
||||||
#ifdef linux
|
|
||||||
switch(major(st.st_rdev))
|
|
||||||
{
|
|
||||||
case MEM_MAJOR:
|
|
||||||
info->DeviceType = FILE_DEVICE_NULL;
|
|
||||||
break;
|
|
||||||
case TTY_MAJOR:
|
|
||||||
info->DeviceType = FILE_DEVICE_SERIAL_PORT;
|
|
||||||
break;
|
|
||||||
case LP_MAJOR:
|
|
||||||
info->DeviceType = FILE_DEVICE_PARALLEL_PORT;
|
|
||||||
break;
|
|
||||||
case SCSI_TAPE_MAJOR:
|
|
||||||
info->DeviceType = FILE_DEVICE_TAPE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
else if (S_ISBLK( st.st_mode ))
|
|
||||||
{
|
|
||||||
info->DeviceType = FILE_DEVICE_DISK;
|
|
||||||
}
|
|
||||||
else if (S_ISFIFO( st.st_mode ) || S_ISSOCK( st.st_mode ))
|
|
||||||
{
|
|
||||||
info->DeviceType = FILE_DEVICE_NAMED_PIPE;
|
|
||||||
}
|
|
||||||
else if (is_device_placeholder( fd ))
|
|
||||||
{
|
|
||||||
info->DeviceType = FILE_DEVICE_DISK;
|
|
||||||
}
|
|
||||||
else /* regular file or directory */
|
|
||||||
{
|
|
||||||
#if defined(linux) && defined(HAVE_FSTATFS)
|
|
||||||
struct statfs stfs;
|
|
||||||
|
|
||||||
/* check for floppy disk */
|
|
||||||
if (major(st.st_dev) == FLOPPY_MAJOR)
|
|
||||||
info->Characteristics |= FILE_REMOVABLE_MEDIA;
|
|
||||||
|
|
||||||
if (fstatfs( fd, &stfs ) < 0) stfs.f_type = 0;
|
|
||||||
switch (stfs.f_type)
|
|
||||||
{
|
|
||||||
case 0x9660: /* iso9660 */
|
|
||||||
case 0x9fa1: /* supermount */
|
|
||||||
case 0x15013346: /* udf */
|
|
||||||
info->DeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
|
|
||||||
info->Characteristics |= FILE_REMOVABLE_MEDIA|FILE_READ_ONLY_DEVICE;
|
|
||||||
break;
|
|
||||||
case 0x6969: /* nfs */
|
|
||||||
case 0xff534d42: /* cifs */
|
|
||||||
case 0xfe534d42: /* smb2 */
|
|
||||||
case 0x517b: /* smbfs */
|
|
||||||
case 0x564c: /* ncpfs */
|
|
||||||
info->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
|
|
||||||
info->Characteristics |= FILE_REMOTE_DEVICE;
|
|
||||||
break;
|
|
||||||
case 0x01021994: /* tmpfs */
|
|
||||||
case 0x28cd3d45: /* cramfs */
|
|
||||||
case 0x1373: /* devfs */
|
|
||||||
case 0x9fa0: /* procfs */
|
|
||||||
info->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
|
|
||||||
struct statfs stfs;
|
|
||||||
|
|
||||||
if (fstatfs( fd, &stfs ) < 0)
|
|
||||||
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
|
||||||
else
|
|
||||||
get_device_info_fstatfs( info, stfs.f_fstypename, stfs.f_flags );
|
|
||||||
#elif defined(__NetBSD__)
|
|
||||||
struct statvfs stfs;
|
|
||||||
|
|
||||||
if (fstatvfs( fd, &stfs) < 0)
|
|
||||||
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
|
||||||
else
|
|
||||||
get_device_info_fstatfs( info, stfs.f_fstypename, stfs.f_flag );
|
|
||||||
#elif defined(sun)
|
|
||||||
/* Use dkio to work out device types */
|
|
||||||
{
|
|
||||||
# include <sys/dkio.h>
|
|
||||||
# include <sys/vtoc.h>
|
|
||||||
struct dk_cinfo dkinf;
|
|
||||||
int retval = ioctl(fd, DKIOCINFO, &dkinf);
|
|
||||||
if(retval==-1){
|
|
||||||
WARN("Unable to get disk device type information - assuming a disk like device\n");
|
|
||||||
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
|
||||||
}
|
|
||||||
switch (dkinf.dki_ctype)
|
|
||||||
{
|
|
||||||
case DKC_CDROM:
|
|
||||||
info->DeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
|
|
||||||
info->Characteristics |= FILE_REMOVABLE_MEDIA|FILE_READ_ONLY_DEVICE;
|
|
||||||
break;
|
|
||||||
case DKC_NCRFLOPPY:
|
|
||||||
case DKC_SMSFLOPPY:
|
|
||||||
case DKC_INTEL82072:
|
|
||||||
case DKC_INTEL82077:
|
|
||||||
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
|
||||||
info->Characteristics |= FILE_REMOVABLE_MEDIA;
|
|
||||||
break;
|
|
||||||
case DKC_MD:
|
|
||||||
info->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
static int warned;
|
|
||||||
if (!warned++) FIXME( "device info not properly supported on this platform\n" );
|
|
||||||
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
|
||||||
#endif
|
|
||||||
info->Characteristics |= FILE_DEVICE_IS_MOUNTED;
|
|
||||||
}
|
|
||||||
return STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* NtQueryVolumeInformationFile [NTDLL.@]
|
* NtQueryVolumeInformationFile [NTDLL.@]
|
||||||
* ZwQueryVolumeInformationFile [NTDLL.@]
|
* ZwQueryVolumeInformationFile [NTDLL.@]
|
||||||
|
@ -1046,239 +676,7 @@ NTSTATUS WINAPI NtQueryVolumeInformationFile( HANDLE handle, PIO_STATUS_BLOCK io
|
||||||
PVOID buffer, ULONG length,
|
PVOID buffer, ULONG length,
|
||||||
FS_INFORMATION_CLASS info_class )
|
FS_INFORMATION_CLASS info_class )
|
||||||
{
|
{
|
||||||
int fd, needs_close;
|
return unix_funcs->NtQueryVolumeInformationFile( handle, io, buffer, length, info_class );
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
io->u.Status = unix_funcs->server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL );
|
|
||||||
if (io->u.Status == STATUS_BAD_DEVICE_TYPE)
|
|
||||||
{
|
|
||||||
SERVER_START_REQ( get_volume_info )
|
|
||||||
{
|
|
||||||
req->handle = wine_server_obj_handle( handle );
|
|
||||||
req->info_class = info_class;
|
|
||||||
wine_server_set_reply( req, buffer, length );
|
|
||||||
io->u.Status = wine_server_call( req );
|
|
||||||
if (!io->u.Status) io->Information = wine_server_reply_size( reply );
|
|
||||||
}
|
|
||||||
SERVER_END_REQ;
|
|
||||||
return io->u.Status;
|
|
||||||
}
|
|
||||||
else if (io->u.Status) return io->u.Status;
|
|
||||||
|
|
||||||
io->u.Status = STATUS_NOT_IMPLEMENTED;
|
|
||||||
io->Information = 0;
|
|
||||||
|
|
||||||
switch( info_class )
|
|
||||||
{
|
|
||||||
case FileFsLabelInformation:
|
|
||||||
FIXME( "%p: label info not supported\n", handle );
|
|
||||||
break;
|
|
||||||
case FileFsSizeInformation:
|
|
||||||
if (length < sizeof(FILE_FS_SIZE_INFORMATION))
|
|
||||||
io->u.Status = STATUS_BUFFER_TOO_SMALL;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FILE_FS_SIZE_INFORMATION *info = buffer;
|
|
||||||
|
|
||||||
if (fstat( fd, &st ) < 0)
|
|
||||||
{
|
|
||||||
io->u.Status = FILE_GetNtStatus();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
|
|
||||||
{
|
|
||||||
io->u.Status = STATUS_INVALID_DEVICE_REQUEST;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ULONGLONG bsize;
|
|
||||||
/* Linux's fstatvfs is buggy */
|
|
||||||
#if !defined(linux) || !defined(HAVE_FSTATFS)
|
|
||||||
struct statvfs stfs;
|
|
||||||
|
|
||||||
if (fstatvfs( fd, &stfs ) < 0)
|
|
||||||
{
|
|
||||||
io->u.Status = FILE_GetNtStatus();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
bsize = stfs.f_frsize;
|
|
||||||
#else
|
|
||||||
struct statfs stfs;
|
|
||||||
if (fstatfs( fd, &stfs ) < 0)
|
|
||||||
{
|
|
||||||
io->u.Status = FILE_GetNtStatus();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
bsize = stfs.f_bsize;
|
|
||||||
#endif
|
|
||||||
if (bsize == 2048) /* assume CD-ROM */
|
|
||||||
{
|
|
||||||
info->BytesPerSector = 2048;
|
|
||||||
info->SectorsPerAllocationUnit = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
info->BytesPerSector = 512;
|
|
||||||
info->SectorsPerAllocationUnit = 8;
|
|
||||||
}
|
|
||||||
info->TotalAllocationUnits.QuadPart = bsize * stfs.f_blocks / (info->BytesPerSector * info->SectorsPerAllocationUnit);
|
|
||||||
info->AvailableAllocationUnits.QuadPart = bsize * stfs.f_bavail / (info->BytesPerSector * info->SectorsPerAllocationUnit);
|
|
||||||
io->Information = sizeof(*info);
|
|
||||||
io->u.Status = STATUS_SUCCESS;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FileFsDeviceInformation:
|
|
||||||
if (length < sizeof(FILE_FS_DEVICE_INFORMATION))
|
|
||||||
io->u.Status = STATUS_BUFFER_TOO_SMALL;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
FILE_FS_DEVICE_INFORMATION *info = buffer;
|
|
||||||
|
|
||||||
if ((io->u.Status = get_device_info( fd, info )) == STATUS_SUCCESS)
|
|
||||||
io->Information = sizeof(*info);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case FileFsAttributeInformation:
|
|
||||||
{
|
|
||||||
static const WCHAR fatW[] = {'F','A','T'};
|
|
||||||
static const WCHAR fat32W[] = {'F','A','T','3','2'};
|
|
||||||
static const WCHAR ntfsW[] = {'N','T','F','S'};
|
|
||||||
static const WCHAR cdfsW[] = {'C','D','F','S'};
|
|
||||||
static const WCHAR udfW[] = {'U','D','F'};
|
|
||||||
|
|
||||||
FILE_FS_ATTRIBUTE_INFORMATION *info = buffer;
|
|
||||||
struct mountmgr_unix_drive *drive;
|
|
||||||
enum mountmgr_fs_type fs_type = MOUNTMGR_FS_TYPE_NTFS;
|
|
||||||
|
|
||||||
if (length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
|
|
||||||
{
|
|
||||||
io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((drive = get_mountmgr_fs_info( handle, fd )))
|
|
||||||
{
|
|
||||||
fs_type = drive->fs_type;
|
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, drive );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
struct statfs stfs;
|
|
||||||
|
|
||||||
if (!fstatfs( fd, &stfs ))
|
|
||||||
{
|
|
||||||
#if defined(linux) && defined(HAVE_FSTATFS)
|
|
||||||
switch (stfs.f_type)
|
|
||||||
{
|
|
||||||
case 0x9660:
|
|
||||||
fs_type = MOUNTMGR_FS_TYPE_ISO9660;
|
|
||||||
break;
|
|
||||||
case 0x15013346:
|
|
||||||
fs_type = MOUNTMGR_FS_TYPE_UDF;
|
|
||||||
break;
|
|
||||||
case 0x4d44:
|
|
||||||
fs_type = MOUNTMGR_FS_TYPE_FAT32;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
|
|
||||||
if (!strcmp( stfs.f_fstypename, "cd9660" ))
|
|
||||||
fs_type = MOUNTMGR_FS_TYPE_ISO9660;
|
|
||||||
else if (!strcmp( stfs.f_fstypename, "udf" ))
|
|
||||||
fs_type = MOUNTMGR_FS_TYPE_UDF;
|
|
||||||
else if (!strcmp( stfs.f_fstypename, "msdos" ))
|
|
||||||
fs_type = MOUNTMGR_FS_TYPE_FAT32;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (fs_type)
|
|
||||||
{
|
|
||||||
case MOUNTMGR_FS_TYPE_ISO9660:
|
|
||||||
info->FileSystemAttributes = FILE_READ_ONLY_VOLUME;
|
|
||||||
info->MaximumComponentNameLength = 221;
|
|
||||||
info->FileSystemNameLength = min( sizeof(cdfsW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
|
|
||||||
memcpy(info->FileSystemName, cdfsW, info->FileSystemNameLength);
|
|
||||||
break;
|
|
||||||
case MOUNTMGR_FS_TYPE_UDF:
|
|
||||||
info->FileSystemAttributes = FILE_READ_ONLY_VOLUME | FILE_UNICODE_ON_DISK | FILE_CASE_SENSITIVE_SEARCH;
|
|
||||||
info->MaximumComponentNameLength = 255;
|
|
||||||
info->FileSystemNameLength = min( sizeof(udfW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
|
|
||||||
memcpy(info->FileSystemName, udfW, info->FileSystemNameLength);
|
|
||||||
break;
|
|
||||||
case MOUNTMGR_FS_TYPE_FAT:
|
|
||||||
info->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES; /* FIXME */
|
|
||||||
info->MaximumComponentNameLength = 255;
|
|
||||||
info->FileSystemNameLength = min( sizeof(fatW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
|
|
||||||
memcpy(info->FileSystemName, fatW, info->FileSystemNameLength);
|
|
||||||
break;
|
|
||||||
case MOUNTMGR_FS_TYPE_FAT32:
|
|
||||||
info->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES; /* FIXME */
|
|
||||||
info->MaximumComponentNameLength = 255;
|
|
||||||
info->FileSystemNameLength = min( sizeof(fat32W), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
|
|
||||||
memcpy(info->FileSystemName, fat32W, info->FileSystemNameLength);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
info->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES | FILE_PERSISTENT_ACLS;
|
|
||||||
info->MaximumComponentNameLength = 255;
|
|
||||||
info->FileSystemNameLength = min( sizeof(ntfsW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
|
|
||||||
memcpy(info->FileSystemName, ntfsW, info->FileSystemNameLength);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
io->Information = offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) + info->FileSystemNameLength;
|
|
||||||
io->u.Status = STATUS_SUCCESS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FileFsVolumeInformation:
|
|
||||||
{
|
|
||||||
FILE_FS_VOLUME_INFORMATION *info = buffer;
|
|
||||||
struct mountmgr_unix_drive *drive;
|
|
||||||
const WCHAR *label;
|
|
||||||
|
|
||||||
if (length < sizeof(FILE_FS_VOLUME_INFORMATION))
|
|
||||||
{
|
|
||||||
io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(drive = get_mountmgr_fs_info( handle, fd )))
|
|
||||||
{
|
|
||||||
io->u.Status = STATUS_NOT_IMPLEMENTED;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
label = (WCHAR *)((char *)drive + drive->label_offset);
|
|
||||||
info->VolumeCreationTime.QuadPart = 0; /* FIXME */
|
|
||||||
info->VolumeSerialNumber = drive->serial;
|
|
||||||
info->VolumeLabelLength = min( wcslen( label ) * sizeof(WCHAR),
|
|
||||||
length - offsetof( FILE_FS_VOLUME_INFORMATION, VolumeLabel ) );
|
|
||||||
info->SupportsObjects = (drive->fs_type == MOUNTMGR_FS_TYPE_NTFS);
|
|
||||||
memcpy( info->VolumeLabel, label, info->VolumeLabelLength );
|
|
||||||
RtlFreeHeap( GetProcessHeap(), 0, drive );
|
|
||||||
|
|
||||||
io->Information = offsetof( FILE_FS_VOLUME_INFORMATION, VolumeLabel ) + info->VolumeLabelLength;
|
|
||||||
io->u.Status = STATUS_SUCCESS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case FileFsControlInformation:
|
|
||||||
FIXME( "%p: control info not supported\n", handle );
|
|
||||||
break;
|
|
||||||
case FileFsFullSizeInformation:
|
|
||||||
FIXME( "%p: full size info not supported\n", handle );
|
|
||||||
break;
|
|
||||||
case FileFsObjectIdInformation:
|
|
||||||
FIXME( "%p: object id info not supported\n", handle );
|
|
||||||
break;
|
|
||||||
case FileFsMaximumInformation:
|
|
||||||
FIXME( "%p: maximum info not supported\n", handle );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
io->u.Status = STATUS_INVALID_PARAMETER;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (needs_close) close( fd );
|
|
||||||
return io->u.Status;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -112,7 +112,6 @@ extern const WCHAR syswow64_dir[] DECLSPEC_HIDDEN;
|
||||||
extern const struct unix_funcs *unix_funcs DECLSPEC_HIDDEN;
|
extern const struct unix_funcs *unix_funcs DECLSPEC_HIDDEN;
|
||||||
|
|
||||||
/* file I/O */
|
/* file I/O */
|
||||||
extern NTSTATUS FILE_GetNtStatus(void) DECLSPEC_HIDDEN;
|
|
||||||
extern NTSTATUS server_get_unix_name( HANDLE handle, ANSI_STRING *unix_name ) DECLSPEC_HIDDEN;
|
extern NTSTATUS server_get_unix_name( HANDLE handle, ANSI_STRING *unix_name ) DECLSPEC_HIDDEN;
|
||||||
extern void init_directories(void) DECLSPEC_HIDDEN;
|
extern void init_directories(void) DECLSPEC_HIDDEN;
|
||||||
extern unsigned int DIR_get_drives_info( struct drive_info info[MAX_DOS_DRIVES] ) DECLSPEC_HIDDEN;
|
extern unsigned int DIR_get_drives_info( struct drive_info info[MAX_DOS_DRIVES] ) DECLSPEC_HIDDEN;
|
||||||
|
|
|
@ -46,6 +46,9 @@
|
||||||
#ifdef HAVE_SYS_STAT_H
|
#ifdef HAVE_SYS_STAT_H
|
||||||
# include <sys/stat.h>
|
# include <sys/stat.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef HAVE_SYS_STATVFS_H
|
||||||
|
# include <sys/statvfs.h>
|
||||||
|
#endif
|
||||||
#ifdef HAVE_SYS_SYSCALL_H
|
#ifdef HAVE_SYS_SYSCALL_H
|
||||||
# include <sys/syscall.h>
|
# include <sys/syscall.h>
|
||||||
#endif
|
#endif
|
||||||
|
@ -1610,7 +1613,7 @@ static NTSTATUS set_file_times( int fd, const LARGE_INTEGER *mtime, const LARGE_
|
||||||
#ifdef HAVE_FUTIMES
|
#ifdef HAVE_FUTIMES
|
||||||
if (futimes( fd, tv ) == -1) status = errno_to_status( errno );
|
if (futimes( fd, tv ) == -1) status = errno_to_status( errno );
|
||||||
#elif defined(HAVE_FUTIMESAT)
|
#elif defined(HAVE_FUTIMESAT)
|
||||||
if (futimesat( fd, NULL, tv ) == -1) status = FILE_GetNtStatus();
|
if (futimesat( fd, NULL, tv ) == -1) status = errno_to_status( errno );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else /* HAVE_FUTIMES || HAVE_FUTIMESAT */
|
#else /* HAVE_FUTIMES || HAVE_FUTIMESAT */
|
||||||
|
@ -5725,3 +5728,440 @@ NTSTATUS WINAPI NtFlushBuffersFile( HANDLE handle, IO_STATUS_BLOCK *io )
|
||||||
if (needs_close) close( fd );
|
if (needs_close) close( fd );
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
|
||||||
|
/* helper for FILE_GetDeviceInfo to hide some platform differences in fstatfs */
|
||||||
|
static inline void get_device_info_fstatfs( FILE_FS_DEVICE_INFORMATION *info, const char *fstypename,
|
||||||
|
unsigned int flags )
|
||||||
|
{
|
||||||
|
if (!strcmp("cd9660", fstypename) || !strcmp("udf", fstypename))
|
||||||
|
{
|
||||||
|
info->DeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
|
||||||
|
/* Don't assume read-only, let the mount options set it below */
|
||||||
|
info->Characteristics |= FILE_REMOVABLE_MEDIA;
|
||||||
|
}
|
||||||
|
else if (!strcmp("nfs", fstypename) || !strcmp("nwfs", fstypename) ||
|
||||||
|
!strcmp("smbfs", fstypename) || !strcmp("afpfs", fstypename))
|
||||||
|
{
|
||||||
|
info->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
|
||||||
|
info->Characteristics |= FILE_REMOTE_DEVICE;
|
||||||
|
}
|
||||||
|
else if (!strcmp("procfs", fstypename))
|
||||||
|
info->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
|
||||||
|
else
|
||||||
|
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
||||||
|
|
||||||
|
if (flags & MNT_RDONLY)
|
||||||
|
info->Characteristics |= FILE_READ_ONLY_DEVICE;
|
||||||
|
|
||||||
|
if (!(flags & MNT_LOCAL))
|
||||||
|
{
|
||||||
|
info->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
|
||||||
|
info->Characteristics |= FILE_REMOTE_DEVICE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline BOOL is_device_placeholder( int fd )
|
||||||
|
{
|
||||||
|
static const char wine_placeholder[] = "Wine device placeholder";
|
||||||
|
char buffer[sizeof(wine_placeholder)-1];
|
||||||
|
|
||||||
|
if (pread( fd, buffer, sizeof(wine_placeholder) - 1, 0 ) != sizeof(wine_placeholder) - 1)
|
||||||
|
return FALSE;
|
||||||
|
return !memcmp( buffer, wine_placeholder, sizeof(wine_placeholder) - 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
static NTSTATUS get_device_info( int fd, FILE_FS_DEVICE_INFORMATION *info )
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
info->Characteristics = 0;
|
||||||
|
if (fstat( fd, &st ) < 0) return errno_to_status( errno );
|
||||||
|
if (S_ISCHR( st.st_mode ))
|
||||||
|
{
|
||||||
|
info->DeviceType = FILE_DEVICE_UNKNOWN;
|
||||||
|
#ifdef linux
|
||||||
|
switch(major(st.st_rdev))
|
||||||
|
{
|
||||||
|
case MEM_MAJOR:
|
||||||
|
info->DeviceType = FILE_DEVICE_NULL;
|
||||||
|
break;
|
||||||
|
case TTY_MAJOR:
|
||||||
|
info->DeviceType = FILE_DEVICE_SERIAL_PORT;
|
||||||
|
break;
|
||||||
|
case LP_MAJOR:
|
||||||
|
info->DeviceType = FILE_DEVICE_PARALLEL_PORT;
|
||||||
|
break;
|
||||||
|
case SCSI_TAPE_MAJOR:
|
||||||
|
info->DeviceType = FILE_DEVICE_TAPE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (S_ISBLK( st.st_mode ))
|
||||||
|
{
|
||||||
|
info->DeviceType = FILE_DEVICE_DISK;
|
||||||
|
}
|
||||||
|
else if (S_ISFIFO( st.st_mode ) || S_ISSOCK( st.st_mode ))
|
||||||
|
{
|
||||||
|
info->DeviceType = FILE_DEVICE_NAMED_PIPE;
|
||||||
|
}
|
||||||
|
else if (is_device_placeholder( fd ))
|
||||||
|
{
|
||||||
|
info->DeviceType = FILE_DEVICE_DISK;
|
||||||
|
}
|
||||||
|
else /* regular file or directory */
|
||||||
|
{
|
||||||
|
#if defined(linux) && defined(HAVE_FSTATFS)
|
||||||
|
struct statfs stfs;
|
||||||
|
|
||||||
|
/* check for floppy disk */
|
||||||
|
if (major(st.st_dev) == FLOPPY_MAJOR)
|
||||||
|
info->Characteristics |= FILE_REMOVABLE_MEDIA;
|
||||||
|
|
||||||
|
if (fstatfs( fd, &stfs ) < 0) stfs.f_type = 0;
|
||||||
|
switch (stfs.f_type)
|
||||||
|
{
|
||||||
|
case 0x9660: /* iso9660 */
|
||||||
|
case 0x9fa1: /* supermount */
|
||||||
|
case 0x15013346: /* udf */
|
||||||
|
info->DeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
|
||||||
|
info->Characteristics |= FILE_REMOVABLE_MEDIA|FILE_READ_ONLY_DEVICE;
|
||||||
|
break;
|
||||||
|
case 0x6969: /* nfs */
|
||||||
|
case 0xff534d42: /* cifs */
|
||||||
|
case 0xfe534d42: /* smb2 */
|
||||||
|
case 0x517b: /* smbfs */
|
||||||
|
case 0x564c: /* ncpfs */
|
||||||
|
info->DeviceType = FILE_DEVICE_NETWORK_FILE_SYSTEM;
|
||||||
|
info->Characteristics |= FILE_REMOTE_DEVICE;
|
||||||
|
break;
|
||||||
|
case 0x01021994: /* tmpfs */
|
||||||
|
case 0x28cd3d45: /* cramfs */
|
||||||
|
case 0x1373: /* devfs */
|
||||||
|
case 0x9fa0: /* procfs */
|
||||||
|
info->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
|
||||||
|
struct statfs stfs;
|
||||||
|
|
||||||
|
if (fstatfs( fd, &stfs ) < 0)
|
||||||
|
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
||||||
|
else
|
||||||
|
get_device_info_fstatfs( info, stfs.f_fstypename, stfs.f_flags );
|
||||||
|
#elif defined(__NetBSD__)
|
||||||
|
struct statvfs stfs;
|
||||||
|
|
||||||
|
if (fstatvfs( fd, &stfs) < 0)
|
||||||
|
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
||||||
|
else
|
||||||
|
get_device_info_fstatfs( info, stfs.f_fstypename, stfs.f_flag );
|
||||||
|
#elif defined(sun)
|
||||||
|
/* Use dkio to work out device types */
|
||||||
|
{
|
||||||
|
# include <sys/dkio.h>
|
||||||
|
# include <sys/vtoc.h>
|
||||||
|
struct dk_cinfo dkinf;
|
||||||
|
int retval = ioctl(fd, DKIOCINFO, &dkinf);
|
||||||
|
if(retval==-1){
|
||||||
|
WARN("Unable to get disk device type information - assuming a disk like device\n");
|
||||||
|
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
||||||
|
}
|
||||||
|
switch (dkinf.dki_ctype)
|
||||||
|
{
|
||||||
|
case DKC_CDROM:
|
||||||
|
info->DeviceType = FILE_DEVICE_CD_ROM_FILE_SYSTEM;
|
||||||
|
info->Characteristics |= FILE_REMOVABLE_MEDIA|FILE_READ_ONLY_DEVICE;
|
||||||
|
break;
|
||||||
|
case DKC_NCRFLOPPY:
|
||||||
|
case DKC_SMSFLOPPY:
|
||||||
|
case DKC_INTEL82072:
|
||||||
|
case DKC_INTEL82077:
|
||||||
|
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
||||||
|
info->Characteristics |= FILE_REMOVABLE_MEDIA;
|
||||||
|
break;
|
||||||
|
case DKC_MD:
|
||||||
|
info->DeviceType = FILE_DEVICE_VIRTUAL_DISK;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int warned;
|
||||||
|
if (!warned++) FIXME( "device info not properly supported on this platform\n" );
|
||||||
|
info->DeviceType = FILE_DEVICE_DISK_FILE_SYSTEM;
|
||||||
|
#endif
|
||||||
|
info->Characteristics |= FILE_DEVICE_IS_MOUNTED;
|
||||||
|
}
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* NtQueryVolumeInformationFile (NTDLL.@)
|
||||||
|
*/
|
||||||
|
NTSTATUS WINAPI NtQueryVolumeInformationFile( HANDLE handle, IO_STATUS_BLOCK *io,
|
||||||
|
void *buffer, ULONG length,
|
||||||
|
FS_INFORMATION_CLASS info_class )
|
||||||
|
{
|
||||||
|
int fd, needs_close;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
|
io->u.Status = server_get_unix_fd( handle, 0, &fd, &needs_close, NULL, NULL );
|
||||||
|
if (io->u.Status == STATUS_BAD_DEVICE_TYPE)
|
||||||
|
{
|
||||||
|
SERVER_START_REQ( get_volume_info )
|
||||||
|
{
|
||||||
|
req->handle = wine_server_obj_handle( handle );
|
||||||
|
req->info_class = info_class;
|
||||||
|
wine_server_set_reply( req, buffer, length );
|
||||||
|
io->u.Status = wine_server_call( req );
|
||||||
|
if (!io->u.Status) io->Information = wine_server_reply_size( reply );
|
||||||
|
}
|
||||||
|
SERVER_END_REQ;
|
||||||
|
return io->u.Status;
|
||||||
|
}
|
||||||
|
else if (io->u.Status) return io->u.Status;
|
||||||
|
|
||||||
|
io->u.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
io->Information = 0;
|
||||||
|
|
||||||
|
switch( info_class )
|
||||||
|
{
|
||||||
|
case FileFsLabelInformation:
|
||||||
|
FIXME( "%p: label info not supported\n", handle );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileFsSizeInformation:
|
||||||
|
if (length < sizeof(FILE_FS_SIZE_INFORMATION))
|
||||||
|
io->u.Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FILE_FS_SIZE_INFORMATION *info = buffer;
|
||||||
|
|
||||||
|
if (fstat( fd, &st ) < 0)
|
||||||
|
{
|
||||||
|
io->u.Status = errno_to_status( errno );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode))
|
||||||
|
{
|
||||||
|
io->u.Status = STATUS_INVALID_DEVICE_REQUEST;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ULONGLONG bsize;
|
||||||
|
/* Linux's fstatvfs is buggy */
|
||||||
|
#if !defined(linux) || !defined(HAVE_FSTATFS)
|
||||||
|
struct statvfs stfs;
|
||||||
|
|
||||||
|
if (fstatvfs( fd, &stfs ) < 0)
|
||||||
|
{
|
||||||
|
io->u.Status = errno_to_status( errno );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bsize = stfs.f_frsize;
|
||||||
|
#else
|
||||||
|
struct statfs stfs;
|
||||||
|
if (fstatfs( fd, &stfs ) < 0)
|
||||||
|
{
|
||||||
|
io->u.Status = errno_to_status( errno );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
bsize = stfs.f_bsize;
|
||||||
|
#endif
|
||||||
|
if (bsize == 2048) /* assume CD-ROM */
|
||||||
|
{
|
||||||
|
info->BytesPerSector = 2048;
|
||||||
|
info->SectorsPerAllocationUnit = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
info->BytesPerSector = 512;
|
||||||
|
info->SectorsPerAllocationUnit = 8;
|
||||||
|
}
|
||||||
|
info->TotalAllocationUnits.QuadPart = bsize * stfs.f_blocks / (info->BytesPerSector * info->SectorsPerAllocationUnit);
|
||||||
|
info->AvailableAllocationUnits.QuadPart = bsize * stfs.f_bavail / (info->BytesPerSector * info->SectorsPerAllocationUnit);
|
||||||
|
io->Information = sizeof(*info);
|
||||||
|
io->u.Status = STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileFsDeviceInformation:
|
||||||
|
if (length < sizeof(FILE_FS_DEVICE_INFORMATION))
|
||||||
|
io->u.Status = STATUS_BUFFER_TOO_SMALL;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FILE_FS_DEVICE_INFORMATION *info = buffer;
|
||||||
|
|
||||||
|
if ((io->u.Status = get_device_info( fd, info )) == STATUS_SUCCESS)
|
||||||
|
io->Information = sizeof(*info);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileFsAttributeInformation:
|
||||||
|
{
|
||||||
|
static const WCHAR fatW[] = {'F','A','T'};
|
||||||
|
static const WCHAR fat32W[] = {'F','A','T','3','2'};
|
||||||
|
static const WCHAR ntfsW[] = {'N','T','F','S'};
|
||||||
|
static const WCHAR cdfsW[] = {'C','D','F','S'};
|
||||||
|
static const WCHAR udfW[] = {'U','D','F'};
|
||||||
|
|
||||||
|
FILE_FS_ATTRIBUTE_INFORMATION *info = buffer;
|
||||||
|
struct mountmgr_unix_drive *drive;
|
||||||
|
enum mountmgr_fs_type fs_type = MOUNTMGR_FS_TYPE_NTFS;
|
||||||
|
|
||||||
|
if (length < sizeof(FILE_FS_ATTRIBUTE_INFORMATION))
|
||||||
|
{
|
||||||
|
io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((drive = get_mountmgr_fs_info( handle, fd )))
|
||||||
|
{
|
||||||
|
fs_type = drive->fs_type;
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, drive );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
struct statfs stfs;
|
||||||
|
|
||||||
|
if (!fstatfs( fd, &stfs ))
|
||||||
|
{
|
||||||
|
#if defined(linux) && defined(HAVE_FSTATFS)
|
||||||
|
switch (stfs.f_type)
|
||||||
|
{
|
||||||
|
case 0x9660:
|
||||||
|
fs_type = MOUNTMGR_FS_TYPE_ISO9660;
|
||||||
|
break;
|
||||||
|
case 0x15013346:
|
||||||
|
fs_type = MOUNTMGR_FS_TYPE_UDF;
|
||||||
|
break;
|
||||||
|
case 0x4d44:
|
||||||
|
fs_type = MOUNTMGR_FS_TYPE_FAT32;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__OpenBSD__) || defined(__DragonFly__) || defined(__APPLE__)
|
||||||
|
if (!strcmp( stfs.f_fstypename, "cd9660" ))
|
||||||
|
fs_type = MOUNTMGR_FS_TYPE_ISO9660;
|
||||||
|
else if (!strcmp( stfs.f_fstypename, "udf" ))
|
||||||
|
fs_type = MOUNTMGR_FS_TYPE_UDF;
|
||||||
|
else if (!strcmp( stfs.f_fstypename, "msdos" ))
|
||||||
|
fs_type = MOUNTMGR_FS_TYPE_FAT32;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (fs_type)
|
||||||
|
{
|
||||||
|
case MOUNTMGR_FS_TYPE_ISO9660:
|
||||||
|
info->FileSystemAttributes = FILE_READ_ONLY_VOLUME;
|
||||||
|
info->MaximumComponentNameLength = 221;
|
||||||
|
info->FileSystemNameLength = min( sizeof(cdfsW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
|
||||||
|
memcpy(info->FileSystemName, cdfsW, info->FileSystemNameLength);
|
||||||
|
break;
|
||||||
|
case MOUNTMGR_FS_TYPE_UDF:
|
||||||
|
info->FileSystemAttributes = FILE_READ_ONLY_VOLUME | FILE_UNICODE_ON_DISK | FILE_CASE_SENSITIVE_SEARCH;
|
||||||
|
info->MaximumComponentNameLength = 255;
|
||||||
|
info->FileSystemNameLength = min( sizeof(udfW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
|
||||||
|
memcpy(info->FileSystemName, udfW, info->FileSystemNameLength);
|
||||||
|
break;
|
||||||
|
case MOUNTMGR_FS_TYPE_FAT:
|
||||||
|
info->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES; /* FIXME */
|
||||||
|
info->MaximumComponentNameLength = 255;
|
||||||
|
info->FileSystemNameLength = min( sizeof(fatW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
|
||||||
|
memcpy(info->FileSystemName, fatW, info->FileSystemNameLength);
|
||||||
|
break;
|
||||||
|
case MOUNTMGR_FS_TYPE_FAT32:
|
||||||
|
info->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES; /* FIXME */
|
||||||
|
info->MaximumComponentNameLength = 255;
|
||||||
|
info->FileSystemNameLength = min( sizeof(fat32W), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
|
||||||
|
memcpy(info->FileSystemName, fat32W, info->FileSystemNameLength);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
info->FileSystemAttributes = FILE_CASE_PRESERVED_NAMES | FILE_PERSISTENT_ACLS;
|
||||||
|
info->MaximumComponentNameLength = 255;
|
||||||
|
info->FileSystemNameLength = min( sizeof(ntfsW), length - offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) );
|
||||||
|
memcpy(info->FileSystemName, ntfsW, info->FileSystemNameLength);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
io->Information = offsetof( FILE_FS_ATTRIBUTE_INFORMATION, FileSystemName ) + info->FileSystemNameLength;
|
||||||
|
io->u.Status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case FileFsVolumeInformation:
|
||||||
|
{
|
||||||
|
FILE_FS_VOLUME_INFORMATION *info = buffer;
|
||||||
|
struct mountmgr_unix_drive *drive;
|
||||||
|
const WCHAR *label;
|
||||||
|
|
||||||
|
if (length < sizeof(FILE_FS_VOLUME_INFORMATION))
|
||||||
|
{
|
||||||
|
io->u.Status = STATUS_INFO_LENGTH_MISMATCH;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(drive = get_mountmgr_fs_info( handle, fd )))
|
||||||
|
{
|
||||||
|
io->u.Status = STATUS_NOT_IMPLEMENTED;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
label = (WCHAR *)((char *)drive + drive->label_offset);
|
||||||
|
info->VolumeCreationTime.QuadPart = 0; /* FIXME */
|
||||||
|
info->VolumeSerialNumber = drive->serial;
|
||||||
|
info->VolumeLabelLength = min( wcslen( label ) * sizeof(WCHAR),
|
||||||
|
length - offsetof( FILE_FS_VOLUME_INFORMATION, VolumeLabel ) );
|
||||||
|
info->SupportsObjects = (drive->fs_type == MOUNTMGR_FS_TYPE_NTFS);
|
||||||
|
memcpy( info->VolumeLabel, label, info->VolumeLabelLength );
|
||||||
|
RtlFreeHeap( GetProcessHeap(), 0, drive );
|
||||||
|
|
||||||
|
io->Information = offsetof( FILE_FS_VOLUME_INFORMATION, VolumeLabel ) + info->VolumeLabelLength;
|
||||||
|
io->u.Status = STATUS_SUCCESS;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case FileFsControlInformation:
|
||||||
|
FIXME( "%p: control info not supported\n", handle );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileFsFullSizeInformation:
|
||||||
|
FIXME( "%p: full size info not supported\n", handle );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileFsObjectIdInformation:
|
||||||
|
FIXME( "%p: object id info not supported\n", handle );
|
||||||
|
break;
|
||||||
|
|
||||||
|
case FileFsMaximumInformation:
|
||||||
|
FIXME( "%p: maximum info not supported\n", handle );
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
io->u.Status = STATUS_INVALID_PARAMETER;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (needs_close) close( fd );
|
||||||
|
return io->u.Status;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************
|
||||||
|
* NtSetVolumeInformationFile (NTDLL.@)
|
||||||
|
*/
|
||||||
|
NTSTATUS WINAPI NtSetVolumeInformationFile( HANDLE handle, IO_STATUS_BLOCK *io, void *info,
|
||||||
|
ULONG length, FS_INFORMATION_CLASS class )
|
||||||
|
{
|
||||||
|
FIXME( "(%p,%p,%p,0x%08x,0x%08x) stub\n", handle, io, info, length, class );
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
|
@ -942,6 +942,7 @@ static struct unix_funcs unix_funcs =
|
||||||
NtQuerySystemTime,
|
NtQuerySystemTime,
|
||||||
NtQueryTimer,
|
NtQueryTimer,
|
||||||
NtQueryVirtualMemory,
|
NtQueryVirtualMemory,
|
||||||
|
NtQueryVolumeInformationFile,
|
||||||
NtQueueApcThread,
|
NtQueueApcThread,
|
||||||
NtRaiseException,
|
NtRaiseException,
|
||||||
NtReadFile,
|
NtReadFile,
|
||||||
|
@ -966,6 +967,7 @@ static struct unix_funcs unix_funcs =
|
||||||
NtSetLdtEntries,
|
NtSetLdtEntries,
|
||||||
NtSetSystemTime,
|
NtSetSystemTime,
|
||||||
NtSetTimer,
|
NtSetTimer,
|
||||||
|
NtSetVolumeInformationFile,
|
||||||
NtSignalAndWaitForSingleObject,
|
NtSignalAndWaitForSingleObject,
|
||||||
NtSuspendProcess,
|
NtSuspendProcess,
|
||||||
NtSuspendThread,
|
NtSuspendThread,
|
||||||
|
|
|
@ -28,7 +28,7 @@ struct ldt_copy;
|
||||||
struct msghdr;
|
struct msghdr;
|
||||||
|
|
||||||
/* increment this when you change the function table */
|
/* increment this when you change the function table */
|
||||||
#define NTDLL_UNIXLIB_VERSION 54
|
#define NTDLL_UNIXLIB_VERSION 55
|
||||||
|
|
||||||
struct unix_funcs
|
struct unix_funcs
|
||||||
{
|
{
|
||||||
|
@ -172,6 +172,9 @@ struct unix_funcs
|
||||||
NTSTATUS (WINAPI *NtQueryVirtualMemory)( HANDLE process, LPCVOID addr,
|
NTSTATUS (WINAPI *NtQueryVirtualMemory)( HANDLE process, LPCVOID addr,
|
||||||
MEMORY_INFORMATION_CLASS info_class,
|
MEMORY_INFORMATION_CLASS info_class,
|
||||||
PVOID buffer, SIZE_T len, SIZE_T *res_len );
|
PVOID buffer, SIZE_T len, SIZE_T *res_len );
|
||||||
|
NTSTATUS (WINAPI *NtQueryVolumeInformationFile)( HANDLE handle, IO_STATUS_BLOCK *io,
|
||||||
|
void *buffer, ULONG length,
|
||||||
|
FS_INFORMATION_CLASS info_class );
|
||||||
NTSTATUS (WINAPI *NtQueueApcThread)( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1,
|
NTSTATUS (WINAPI *NtQueueApcThread)( HANDLE handle, PNTAPCFUNC func, ULONG_PTR arg1,
|
||||||
ULONG_PTR arg2, ULONG_PTR arg3 );
|
ULONG_PTR arg2, ULONG_PTR arg3 );
|
||||||
NTSTATUS (WINAPI *NtRaiseException)( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance );
|
NTSTATUS (WINAPI *NtRaiseException)( EXCEPTION_RECORD *rec, CONTEXT *context, BOOL first_chance );
|
||||||
|
@ -214,6 +217,8 @@ struct unix_funcs
|
||||||
NTSTATUS (WINAPI *NtSetTimer)( HANDLE handle, const LARGE_INTEGER *when,
|
NTSTATUS (WINAPI *NtSetTimer)( HANDLE handle, const LARGE_INTEGER *when,
|
||||||
PTIMER_APC_ROUTINE callback, void *arg,
|
PTIMER_APC_ROUTINE callback, void *arg,
|
||||||
BOOLEAN resume, ULONG period, BOOLEAN *state );
|
BOOLEAN resume, ULONG period, BOOLEAN *state );
|
||||||
|
NTSTATUS (WINAPI *NtSetVolumeInformationFile)( HANDLE handle, IO_STATUS_BLOCK *io, void *info,
|
||||||
|
ULONG length, FS_INFORMATION_CLASS class );
|
||||||
NTSTATUS (WINAPI *NtSignalAndWaitForSingleObject)( HANDLE signal, HANDLE wait,
|
NTSTATUS (WINAPI *NtSignalAndWaitForSingleObject)( HANDLE signal, HANDLE wait,
|
||||||
BOOLEAN alertable, const LARGE_INTEGER *timeout );
|
BOOLEAN alertable, const LARGE_INTEGER *timeout );
|
||||||
NTSTATUS (WINAPI *NtSuspendProcess)( HANDLE handle );
|
NTSTATUS (WINAPI *NtSuspendProcess)( HANDLE handle );
|
||||||
|
|
Loading…
Reference in New Issue