Implement ntfs_device_win32_ioctl().

(Logical change 1.457)
edge.strict_endians
cantab.net!aia21 2004-07-15 09:29:13 +00:00
parent 47d78b7197
commit 3b3ac7b234
2 changed files with 182 additions and 15 deletions

View File

@ -35,6 +35,25 @@
#else /* __CYGWIN32__ */
#ifndef HDIO_GETGEO
# define HDIO_GETGEO 0x10000301
struct hd_geometry {
unsigned char heads;
unsigned char sectors;
unsigned short cylinders;
unsigned long start;
};
#endif
#ifndef BLKGETSIZE
# define BLKGETSIZE 0x10001260
#endif
#ifndef BLKSSZGET
# define BLKSSZGET 0x10001268
#endif
#ifndef BLKGETSIZE64
# define BLKGETSIZE64 0x10001272
#endif
/* On Cygwin; use Win32 low level device operations. */
#define ntfs_device_default_io_ops ntfs_device_win32_io_ops

View File

@ -55,9 +55,10 @@ typedef struct ntfs_volume ntfs_volume;
typedef struct win32_fd {
HANDLE handle;
LARGE_INTEGER part_start;
LARGE_INTEGER part_end;
s64 part_start;
s64 part_end;
LARGE_INTEGER current_pos;
int part_hidden_sectors;
} win32_fd;
#define perror(msg) win32_perror(__FILE__,__LINE__,__FUNCTION__,msg)
@ -93,6 +94,47 @@ static BOOL WINAPI SetFilePointerEx(HANDLE hFile,
}
#endif
/**
* ntfs_w32error_to_errno - Convert a win32 error code to the unix one
* @w32error The win32 error code.
*
* Limited to a reletevly small but useful number of codes
*/
static int ntfs_w32error_to_errno(DWORD w32error)
{
switch (w32error) {
case ERROR_FILE_NOT_FOUND:
case ERROR_PATH_NOT_FOUND:
return ENOENT;
case ERROR_TOO_MANY_OPEN_FILES:
return EMFILE;
case ERROR_ACCESS_DENIED:
return EACCES;
case ERROR_INVALID_HANDLE:
return EBADF;
case ERROR_NOT_ENOUGH_MEMORY:
return ENOMEM;
case ERROR_OUTOFMEMORY:
return ENOSPC;
case ERROR_INVALID_DRIVE:
case ERROR_BAD_UNIT:
return ENODEV;
case ERROR_WRITE_PROTECT:
return EROFS;
case ERROR_NOT_READY:
return EBUSY;
case ERROR_BAD_COMMAND:
return EINVAL;
case ERROR_SEEK:
return ESPIPE;
case ERROR_NOT_SUPPORTED:
return ENOTSUP;
default:
/* generic message */
return ENOMSG;
}
}
/**
* ntfs_device_win32_open - open a device
* @dev: ntfs device to open
@ -139,8 +181,8 @@ static int ntfs_device_win32_open(struct ntfs_device *dev, int flags)
if (numparams == 1) {
fd.handle = handle;
fd.part_start.QuadPart = 0;
fd.part_end.QuadPart = -1;
fd.part_start = 0;
fd.part_end = -1;
fd.current_pos.QuadPart = 0;
} else {
char buffer[10240];
@ -169,8 +211,8 @@ static int ntfs_device_win32_open(struct ntfs_device *dev, int flags)
fd.handle = handle;
fd.part_start = drive_layout->
PartitionEntry[i].
StartingOffset;
fd.part_end.QuadPart = drive_layout->
StartingOffset.QuadPart;
fd.part_end = drive_layout->
PartitionEntry[i].
StartingOffset.
QuadPart +
@ -210,8 +252,8 @@ static int ntfs_device_win32_open(struct ntfs_device *dev, int flags)
}
fd.handle = handle;
fd.part_start.QuadPart = 0;
fd.part_end.QuadPart = (((s64) info.nFileSizeHigh) << 32) +
fd.part_start = 0;
fd.part_end = (((s64) info.nFileSizeHigh) << 32) +
((s64) info.nFileSizeLow);
fd.current_pos.QuadPart = 0;
}
@ -238,7 +280,7 @@ static s64 ntfs_device_win32_seek(struct ntfs_device *dev, s64 offset,
switch (whence) {
case SEEK_SET:
disp = FILE_BEGIN;
abs_offset.QuadPart = fd->part_start.QuadPart + offset;
abs_offset.QuadPart = fd->part_start + offset;
break;
case SEEK_CUR:
disp = FILE_CURRENT;
@ -247,13 +289,13 @@ static s64 ntfs_device_win32_seek(struct ntfs_device *dev, s64 offset,
case SEEK_END:
/* end of partition != end of disk */
disp = FILE_BEGIN;
if (fd->part_end.QuadPart == -1) {
if (fd->part_end == -1) {
fprintf(stderr, "win32_seek: position relative to end "
"of disk not implemented\n");
errno = ENOTSUP;
return -1;
}
abs_offset.QuadPart = fd->part_end.QuadPart + offset;
abs_offset.QuadPart = fd->part_end + offset;
break;
default:
printf("win32_seek() wrong mode %d\n", whence);
@ -380,7 +422,7 @@ static s64 win32_bias(struct ntfs_device *dev)
{
struct win32_fd *fd = (win32_fd *)dev->d_private;
return fd->part_start.QuadPart;
return fd->part_start;
}
static s64 win32_filepos(struct ntfs_device *dev)
@ -412,12 +454,118 @@ static int ntfs_device_win32_stat(struct ntfs_device *dev, struct stat *buf)
return -1;
}
/**
* ntfs_win32_hdio_getgeo - Get drive geometry.
* @dev: An NTFS_DEVICE obtained via the open command.
* @argp: A pointer to where to put the output.
*
* Requires windows NT/2k/XP only
*
* Currently only the 'start' field is filled
*
* Return 0 if o.k.
* -errno if not, in this case handle is trashed.
*/
static __inline__ int ntfs_win32_hdio_getgeo(struct ntfs_device *dev,
struct hd_geometry *argp)
{
win32_fd *fd;
fd = (win32_fd *)dev->d_private;
if (fd->part_hidden_sectors==-1) {
/* not a partition */
Dprintf("ntfs_win32_hdio_getgeo(): error: not a partition");
fprintf(stderr, "ntfs_win32_hdio_getgeo(): unimplemented\n");
errno = ENOTSUP;
return -1;
} else {
/* only fake the 'start' value, others are unsupported */
/* heads are returned by disk_int13_info on winXP only */
argp->heads = -1;
argp->sectors = -1;
argp->cylinders = -1;
argp->start = fd->part_hidden_sectors;
return 0;
}
}
/**
* ntfs_win32_blksszget - Get block device sector size.
* @dev: An NTFS_DEVICE obtained via the open command.
* @argp: A pointer to where to put the output.
*
* Works on windows NT/2k/XP only
*
* Return 0 if o.k.
* -errno if not, in this case handle is trashed.
*/
static __inline__ int ntfs_win32_blksszget(struct ntfs_device *dev,int *argp)
{
win32_fd *fd;
DISK_GEOMETRY dg;
DWORD bytesReturned;
fd = (win32_fd *)dev->d_private;
if (DeviceIoControl(fd->handle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,
&dg, sizeof(DISK_GEOMETRY), &bytesReturned, NULL)) {
/* success */
*argp=dg.BytesPerSector;
return 0;
} else {
perror("ntfs_win32_blksszget(): FAILED!");
errno = ntfs_w32error_to_errno(GetLastError());
return -errno;
}
}
static int ntfs_device_win32_ioctl(struct ntfs_device *dev, int request,
void *argp)
{
fprintf(stderr, "win32_ioctl() unimplemented\n");
errno = ENOTSUP;
return -1;
win32_fd *fd = (win32_fd *)dev->d_private;
fprintf(stderr, "win32_ioctl(%d) called\n",request);
switch (request) {
#if defined(BLKGETSIZE)
case BLKGETSIZE:
Dprintf("win32_ioctl: BLKGETSIZE detected");
if ((fd->part_end>=0) && (fd->part_start>=0)) {
*(int *)argp = (int)((fd->part_end - fd->part_start) / 512);
return 0;
} else {
errno = ENOTSUP;
return -ENOTSUP;
}
#endif
#if defined(BLKGETSIZE64)
case BLKGETSIZE64:
Dprintf("win32_ioctl: BLKGETSIZE64 detected");
if ((fd->part_end>=0) && (fd->part_start>=0)) {
*(s64 *)argp = (s64)(fd->part_end - fd->part_start);
return 0;
} else {
errno = ENOTSUP;
return -ENOTSUP;
}
#endif
#ifdef HDIO_GETGEO
case HDIO_GETGEO:
Dprintf("win32_ioctl: HDIO_GETGEO detected");
return ntfs_win32_hdio_getgeo(dev,(struct hd_geometry *)argp);
#endif
#ifdef BLKSSZGET
case BLKSSZGET:
Dprintf("win32_ioctl: BLKSSZGET detected");
return ntfs_win32_blksszget(dev,(int *)argp);
break;
#endif
default:
fprintf(stderr, "win32_ioctl(): unimplemented ioctl %d\n",request);
errno = ENOTSUP;
return -1;
}
}
static s64 ntfs_device_win32_pread(struct ntfs_device *dev, void *buf,