⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 win32_io.c

📁 一个在linux下挂载ntfs文件系统的好工具
💻 C
📖 第 1 页 / 共 3 页
字号:
	}	errno = ntfs_w32error_to_errno(GetLastError());	ntfs_log_trace("Couldn't retrieve disk geometry.\n");	fd->geo_cylinders = -1;	fd->geo_sectors = -1;	fd->geo_size = -1;	return -1;}/** * ntfs_device_win32_open_file - open a file via win32 API * @filename:	name of the file 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_file(char *filename, win32_fd *fd,		int flags){	HANDLE handle;	if (ntfs_device_win32_simple_open_file(filename, &handle, flags,			FALSE)) {		/* open error */		return -1;	}	/* fill fd */	fd->handle = handle;	fd->part_start = 0;	fd->part_length = ntfs_device_win32_getsize(handle);	fd->pos = 0;	fd->part_hidden_sectors = -1;	fd->geo_size = -1;	/* used as a marker that this is a file */	fd->vol_handle = INVALID_HANDLE_VALUE;	return 0;}/** * ntfs_device_win32_open_drive - open a drive via 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_drive(int drive_id, win32_fd *fd,		int flags){	HANDLE handle;	int err;	char filename[MAX_PATH];	sprintf(filename, "\\\\.\\PhysicalDrive%d", drive_id);	if ((err = ntfs_device_win32_simple_open_file(filename, &handle, flags,			TRUE))) {		/* open error */		return err;	}	/* store the drive geometry */	ntfs_device_win32_getgeo(handle, fd);	/* Just to be sure */	if (fd->geo_size == -1)		fd->geo_size = ntfs_device_win32_getdisklength(handle);	/* fill fd */	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_volume_for_partition - find and open a volume * * Windows NT/2k/XP handles volumes instead of partitions. * This function gets the partition details and return an open volume handle. * That volume is the one whose only physical location on disk is the described * partition. * * The function required Windows 2k/XP, otherwise it fails (gracefully). * * Return success: a valid open volume handle. *        fail   : INVALID_HANDLE_VALUE */static HANDLE ntfs_device_win32_open_volume_for_partition(unsigned int drive_id,		s64 part_offset, s64 part_length, int flags){	HANDLE vol_find_handle;	TCHAR vol_name[MAX_PATH];	/* Make sure all the required imports exist. */	if (!fnFindFirstVolume || !fnFindNextVolume || !fnFindVolumeClose) {		ntfs_log_trace("Required dll imports not found.\n");		return INVALID_HANDLE_VALUE;	}	/* Start iterating through volumes. */	ntfs_log_trace("Entering with drive_id=%d, part_offset=%lld, "			"path_length=%lld, flags=%d.\n", drive_id,			(unsigned long long)part_offset,			(unsigned long long)part_length, flags);	vol_find_handle = fnFindFirstVolume(vol_name, MAX_PATH);	/* If a valid handle could not be aquired, reply with "don't know". */	if (vol_find_handle == INVALID_HANDLE_VALUE) {		ntfs_log_trace("FindFirstVolume failed.\n");		return INVALID_HANDLE_VALUE;	}	do {		int vol_name_length;		HANDLE handle;		/* remove trailing '/' from vol_name */#ifdef UNICODE		vol_name_length = wcslen(vol_name);#else		vol_name_length = strlen(vol_name);#endif		if (vol_name_length>0)			vol_name[vol_name_length-1]=0;		ntfs_log_debug("Processing %s.\n", vol_name);		/* open the file */		handle = CreateFile(vol_name,				ntfs_device_unix_status_flags_to_win32(flags),				FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,				OPEN_EXISTING, 0, NULL);		if (handle != INVALID_HANDLE_VALUE) {			DWORD bytesReturned;#define EXTENTS_SIZE sizeof(VOLUME_DISK_EXTENTS) + 9 * sizeof(DISK_EXTENT)			char extents[EXTENTS_SIZE];			/* Check physical locations. */			if (DeviceIoControl(handle,					IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS,					NULL, 0, extents, EXTENTS_SIZE,					&bytesReturned, NULL)) {				if (((VOLUME_DISK_EXTENTS *)extents)->						NumberOfDiskExtents == 1) {					DISK_EXTENT *extent = &((							VOLUME_DISK_EXTENTS *)							extents)->Extents[0];					if ((extent->DiskNumber==drive_id) &&							(extent->StartingOffset.							QuadPart==part_offset)							&& (extent->							ExtentLength.QuadPart							== part_length)) {						/*						 * Eureka! (Archimedes, 287 BC,						 * "I have found it!")						 */						fnFindVolumeClose(							vol_find_handle);						return handle;					}				}			}		} else			ntfs_log_trace("getExtents() Failed.\n");	} while (fnFindNextVolume(vol_find_handle, vol_name, MAX_PATH));	/* End of iteration through volumes. */	ntfs_log_trace("Closing, volume was not found.\n");	fnFindVolumeClose(vol_find_handle);	return INVALID_HANDLE_VALUE;}/** * ntfs_device_win32_find_partition - locates partition details by id. * @handle:		HANDLE to the PhysicalDrive * @partition_id:	the partition number to locate * @part_offset:	pointer to where to put the offset to the partition * @part_length:	pointer to where to put the length of the partition * @hidden_sectors:	pointer to where to put the hidden sectors * * This function requires an open PhysicalDrive handle and a partition_id. * If a partition with the required id is found on the supplied device, * the partition attributes are returned back. * * Returns: TRUE  if found, and sets the output parameters. *          FALSE if not and errno is set to the error code. */static BOOL ntfs_device_win32_find_partition(HANDLE handle, DWORD partition_id,		s64 *part_offset, s64 *part_length, int *hidden_sectors){	DRIVE_LAYOUT_INFORMATION *drive_layout;	unsigned int err, buf_size, part_count;	DWORD i;	/*	 * There is no way to know the required buffer, so if the ioctl fails,	 * try doubling the buffer size each time until the ioctl succeeds.	 */	part_count = 8;	do {		buf_size = sizeof(DRIVE_LAYOUT_INFORMATION) +				part_count * sizeof(PARTITION_INFORMATION);		drive_layout = malloc(buf_size);		if (!drive_layout) {			errno = ENOMEM;			return FALSE;		}		if (DeviceIoControl(handle, IOCTL_DISK_GET_DRIVE_LAYOUT, NULL,				0, (BYTE*)drive_layout, buf_size, &i, NULL))			break;		err = GetLastError();		free(drive_layout);		if (err != ERROR_INSUFFICIENT_BUFFER) {			ntfs_log_trace("GetDriveLayout failed.\n");			errno = ntfs_w32error_to_errno(err);			return FALSE;		}		ntfs_log_debug("More than %u partitions.\n", part_count);		part_count <<= 1;		if (part_count > 512) {			ntfs_log_trace("GetDriveLayout failed: More than 512 "					"partitions?\n");			errno = ENOBUFS;			return FALSE;		}	} while (1);	for (i = 0; i < drive_layout->PartitionCount; i++) {		if (drive_layout->PartitionEntry[i].PartitionNumber ==				partition_id) {			*part_offset = drive_layout->PartitionEntry[i].					StartingOffset.QuadPart;			*part_length = drive_layout->PartitionEntry[i].					PartitionLength.QuadPart;			*hidden_sectors = drive_layout->PartitionEntry[i].					HiddenSectors;			free(drive_layout);			return TRUE;		}	}	free(drive_layout);	errno = ENOENT;	return FALSE;}/** * ntfs_device_win32_open_partition - open a partition via win32 API * @drive_id:		drive to open * @partition_id:	partition to open * @fd:			win32 file device to return * @flags:		unix open status flags * * Return  0 if o.k. *        -1 if not, and errno set. * * When fails, fd contents may have not been preserved. */static int ntfs_device_win32_open_partition(int drive_id,		unsigned int partition_id, win32_fd *fd, int flags){	s64 part_start, part_length;	HANDLE handle;	int err, hidden_sectors;	char drive_name[MAX_PATH];	sprintf(drive_name, "\\\\.\\PhysicalDrive%d", drive_id);	/* Open the entire device without locking, ask questions later */	if ((err = ntfs_device_win32_simple_open_file(drive_name, &handle,			flags, FALSE))) {		/* error */		return err;	}	if (ntfs_device_win32_find_partition(handle, partition_id, &part_start,			&part_length, &hidden_sectors)) {		s64 tmp;		HANDLE vol_handle = ntfs_device_win32_open_volume_for_partition(			drive_id, part_start, part_length, flags);		/* Store the drive geometry. */		ntfs_device_win32_getgeo(handle, fd);		fd->handle = handle;		fd->pos = 0;		fd->part_start = part_start;		fd->part_length = part_length;		fd->part_hidden_sectors = hidden_sectors;		tmp = ntfs_device_win32_getntfssize(vol_handle);		if (tmp > 0)			fd->geo_size = tmp;		else			fd->geo_size = fd->part_length;		if (vol_handle != INVALID_HANDLE_VALUE) {			if (((flags & O_RDWR) == O_RDWR) &&					ntfs_device_win32_lock(vol_handle)) {				CloseHandle(vol_handle);				CloseHandle(handle);				return -1;			}			fd->vol_handle = vol_handle;		} else {			if ((flags & O_RDWR) == O_RDWR) {				/* Access if read-write, no volume found. */				ntfs_log_trace("Partitions containing Spanned/"						"Mirrored volumes are not "						"supported in R/W status "						"yet.\n");				CloseHandle(handle);				errno = EOPNOTSUPP;				return -1;			}			fd->vol_handle = INVALID_HANDLE_VALUE;		}		return 0;	} else {		ntfs_log_debug("Partition %u not found on drive %d.\n",				partition_id, drive_id);		CloseHandle(handle);		errno = ENODEV;		return -1;	}}/** * ntfs_device_win32_open - open a device * @dev:	a pointer to the NTFS_DEVICE to open * @flags:	unix open status flags * * @dev->d_name must hold the device name, the rest is ignored. * Supported flags are O_RDONLY, O_WRONLY and O_RDWR. * * If name is in format "(hd[0-9],[0-9])" then open a partition. * If name is in format "(hd[0-9])" then open a volume. * Otherwise open a file. */static int ntfs_device_win32_open(struct ntfs_device *dev, int flags){	int drive_id = 0, numparams;	unsigned int part = 0;	char drive_char;	win32_fd fd;	int err;	if (NDevOpen(dev)) {		errno = EBUSY;		return -1;	}	ntfs_device_win32_init_imports();	numparams = sscanf(dev->d_name, "/dev/hd%c%u", &drive_char, &part);	drive_id = toupper(drive_char) - 'A';	switch (numparams) {	case 0:		ntfs_log_debug("win32_open(%s) -> file.\n", dev->d_name);		err = ntfs_device_win32_open_file(dev->d_name, &fd, flags);		break;	case 1:		ntfs_log_debug("win32_open(%s) -> drive %d.\n", dev->d_name,				drive_id);		err = ntfs_device_win32_open_drive(drive_id, &fd, flags);		break;	case 2:		ntfs_log_debug("win32_open(%s) -> drive %d, part %u.\n",				dev->d_name, drive_id, part);		err = ntfs_device_win32_open_partition(drive_id, part, &fd,				flags);		break;	default:		ntfs_log_debug("win32_open(%s) -> unknwon file format.\n",				dev->d_name);		err = -1;	}	if (err)		return err;	ntfs_log_debug("win32_open(%s) -> %p, offset 0x%llx.\n", dev->d_name,			dev, fd.part_start);	/* Setup our read-only flag. */	if ((flags & O_RDWR) != O_RDWR)		NDevSetReadOnly(dev);	dev->d_private = malloc(sizeof(win32_fd));	memcpy(dev->d_private, &fd, sizeof(win32_fd));	NDevSetOpen(dev);	NDevClearDirty(dev);	return 0;}/** * ntfs_device_win32_seek - change current logical file position * @dev:	ntfs device obtained via ->open * @offset:	required offset from the whence anchor * @whence:	whence anchor specifying what @offset is relative to * * Return the new position on the volume on success and -1 on error with errno * set to the error code. * * @whence may be one of the following: *	SEEK_SET - Offset is relative to file start. *	SEEK_CUR - Offset is relative to current position. *	SEEK_END - Offset is relative to end of file. */static s64 ntfs_device_win32_seek(struct ntfs_device *dev, s64 offset,		int whence){	s64 abs_ofs;	win32_fd *fd = (win32_fd *)dev->d_private;	ntfs_log_trace("seek offset = 0x%llx, whence = %d.\n", offset, whence);	switch (whence) {	case SEEK_SET:		abs_ofs = offset;		break;	case SEEK_CUR:		abs_ofs = fd->pos + offset;		break;	case SEEK_END:		/* End of partition != end of disk. */		if (fd->part_length == -1) {			ntfs_log_trace("Position relative to end of disk not "					"implemented.\n");			errno = EOPNOTSUPP;			return -1;		}		abs_ofs = fd->part_length + offset;		break;	default:		ntfs_log_trace("Wrong mode %d.\n", whence);		errno = EINVAL;		return -1;	}	if (abs_ofs < 0 || abs_ofs > fd->part_length) {		ntfs_log_trace("Seeking outsize seekable area.\n");		errno = EINVAL;		return -1;	}	fd->pos = abs_ofs;	return abs_ofs;}/** * ntfs_device_win32_pio - positioned low level i/o * @fd:		win32 device descriptor obtained via ->open * @pos:	at which position to do i/o from/to * @count:	how many bytes should be transfered * @b:		source/destination buffer * @write:	TRUE if write transfer and FALSE if read transfer * * On success returns the number of bytes transfered (can be < @count) and on * 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. *	- 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){	LARGE_INTEGER li;	HANDLE handle;	DWORD bt;	BOOL res;	ntfs_log_trace("pos = 0x%llx, count = 0x%llx, direction = %s.\n",			(long long)pos, (long long)count, write ? "write" :			"read");	li.QuadPart = pos;	if (fd->vol_handle != INVALID_HANDLE_VALUE && pos < fd->geo_size) {		ntfs_log_debug("Transfering via vol_handle.\n");		handle = fd->vol_handle;	} else {		ntfs_log_debug("Transfering via handle.\n");		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;	}	return bt;}/** * ntfs_device_win32_pread_simple - positioned simple read * @fd:		win32 device descriptor obtained via ->open * @pos:	at which position to read from * @count:	how many bytes should be read * @b:		a pointer to where to put the contents *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -