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

📄 win32_io.c

📁 一个在linux下挂载ntfs文件系统的好工具
💻 C
📖 第 1 页 / 共 3 页
字号:
 * On success returns the number of bytes read (can be < @count) and on error * returns -1 and errno set.  Read starts from position @pos. * * 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 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);}/** * ntfs_device_win32_read - read bytes from an ntfs device * @dev:	ntfs device obtained via ->open * @b:		pointer to where to put the contents * @count:	how many bytes should be read * * On success returns the number of bytes actually read (can be < @count). * On error returns -1 with errno set. */static s64 ntfs_device_win32_read(struct ntfs_device *dev, void *b, s64 count){	s64 old_pos, to_read, i, br = 0;	win32_fd *fd = (win32_fd *)dev->d_private;	BYTE *alignedbuffer;	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);	/* Impose maximum of 2GB to be on the safe side. */	if (to_read > 0x80000000) {		int delta = to_read - count;		to_read = 0x80000000;		count = to_read - delta;	}	ntfs_log_trace("fd = %p, b = %p, count = 0x%llx, pos = 0x%llx, "			"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)))		alignedbuffer = b;	else {		alignedbuffer = (BYTE *)VirtualAlloc(NULL, to_read, MEM_COMMIT,				PAGE_READWRITE);		if (!alignedbuffer) {			errno = ntfs_w32error_to_errno(GetLastError());			ntfs_log_trace("VirtualAlloc failed for read.\n");			return -1;		}	}	if (fd->vol_handle != INVALID_HANDLE_VALUE && old_pos < fd->geo_size) {		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),					ofs + vol_to_read, alignedbuffer);			if (br == -1)				goto read_error;			to_read -= br;			if (br < ofs) {				br = 0;				goto read_partial;			}			br -= ofs;			fd->pos += br;			ofs = fd->pos & (NTFS_BLOCK_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,			alignedbuffer + br);	if (i == -1) {		if (br)			goto read_partial;		goto read_error;	}	if (i < ofs)		goto read_partial;	i -= ofs;	br += i;	if (br > count)		br = count;	fd->pos = old_pos + br;read_partial:	if (alignedbuffer != b) {		memcpy((void*)b, alignedbuffer + old_ofs, br);		VirtualFree(alignedbuffer, 0, MEM_RELEASE);	}	return br;read_error:	if (alignedbuffer != b)		VirtualFree(alignedbuffer, 0, MEM_RELEASE);	return -1;}/** * ntfs_device_win32_close - close an open ntfs deivce * @dev:	ntfs device obtained via ->open * * Return 0 if o.k. *	 -1 if not, and errno set.  Note if error fd->vol_handle is trashed. */static int ntfs_device_win32_close(struct ntfs_device *dev){	win32_fd *fd = (win32_fd *)dev->d_private;	BOOL rvl;	ntfs_log_trace("Closing device %p.\n", dev);	if (!NDevOpen(dev)) {		errno = EBADF;		return -1;	}	if (fd->vol_handle != INVALID_HANDLE_VALUE) {		if (!NDevReadOnly(dev)) {			ntfs_device_win32_dismount(fd->vol_handle);			ntfs_device_win32_unlock(fd->vol_handle);		}		if (!CloseHandle(fd->vol_handle))			ntfs_log_trace("CloseHandle() failed for volume.\n");	}	rvl = CloseHandle(fd->handle);	free(fd);	if (!rvl) {		errno = ntfs_w32error_to_errno(GetLastError());		ntfs_log_trace("CloseHandle() failed.\n");		return -1;	}	return 0;}/** * ntfs_device_win32_sync - flush write buffers to disk * @dev:	ntfs device obtained via ->open * * Return 0 if o.k. *	 -1 if not, and errno set. * * Note: Volume syncing works differently in windows. *	 Disk cannot be synced in windows. */static int ntfs_device_win32_sync(struct ntfs_device *dev){	int err = 0;	BOOL to_clear = TRUE;	if (!NDevReadOnly(dev) && NDevDirty(dev)) {		win32_fd *fd = (win32_fd *)dev->d_private;		if ((fd->vol_handle != INVALID_HANDLE_VALUE) &&				!FlushFileBuffers(fd->vol_handle)) {			to_clear = FALSE;			err = ntfs_w32error_to_errno(GetLastError());		}		if (!FlushFileBuffers(fd->handle)) {			to_clear = FALSE;			if (!err)				err = ntfs_w32error_to_errno(GetLastError());		}		if (!to_clear) {			ntfs_log_trace("Could not sync.\n");			errno = err;			return -1;		}		NDevClearDirty(dev);	}	return 0;}/** * ntfs_device_win32_pwrite_simple - positioned simple write * @fd:		win32 device descriptor obtained via ->open * @pos:	at which position to write to * @count:	how many bytes should be written * @b:		a pointer to the data to write * * On success returns the number of bytes written and on error returns -1 and * errno set.  Write starts from position @pos. * * 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 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);}/** * ntfs_device_win32_write - write bytes to an ntfs device * @dev:	ntfs device obtained via ->open * @b:		pointer to the data to write * @count:	how many bytes should be written * * On success returns the number of bytes actually written. * On error returns -1 with errno set. */static s64 ntfs_device_win32_write(struct ntfs_device *dev, const void *b,		s64 count){	s64 old_pos, to_write, i, bw = 0;	win32_fd *fd = (win32_fd *)dev->d_private;	BYTE *alignedbuffer;	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);	/* Impose maximum of 2GB to be on the safe side. */	if (to_write > 0x80000000) {		int delta = to_write - count;		to_write = 0x80000000;		count = to_write - delta;	}	ntfs_log_trace("fd = %p, b = %p, count = 0x%llx, pos = 0x%llx, "			"ofs = %i, to_write = 0x%llx.\n", fd, b,			(long long)count, (long long)old_pos, ofs,			(long long)to_write);	if (NDevReadOnly(dev)) {		ntfs_log_trace("Can't write on a R/O device.\n");		errno = EROFS;		return -1;	}	if (!count)		return 0;	NDevSetDirty(dev);	if (!((unsigned long)b & (NTFS_BLOCK_SIZE - 1)) && !old_ofs &&			!(count & (NTFS_BLOCK_SIZE - 1)))		alignedbuffer = (BYTE *)b;	else {		s64 end;		alignedbuffer = (BYTE *)VirtualAlloc(NULL, to_write,				MEM_COMMIT, PAGE_READWRITE);		if (!alignedbuffer) {			errno = ntfs_w32error_to_errno(GetLastError());			ntfs_log_trace("VirtualAlloc failed for write.\n");			return -1;		}		/* 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) {				if (i >= 0)					errno = EIO;				goto write_error;			}		}		/*		 * Read last sector if end of write not sector aligned and last		 * sector is either not the same as the first sector or it is		 * the same as the first sector but this has not been read in		 * 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)) {			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) {				if (i >= 0)					errno = EIO;				goto write_error;			}		}		/* Copy the data to be written into @alignedbuffer. */		memcpy(alignedbuffer + ofs, b, count);	}	if (fd->vol_handle != INVALID_HANDLE_VALUE && old_pos < fd->geo_size) {		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),					ofs + vol_to_write, alignedbuffer);			if (bw == -1)				goto write_error;			to_write -= bw;			if (bw < ofs) {				bw = 0;				goto write_partial;			}			bw -= ofs;			fd->pos += bw;			ofs = fd->pos & (NTFS_BLOCK_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,			alignedbuffer + bw);	if (i == -1) {		if (bw)			goto write_partial;		goto write_error;	}	if (i < ofs)		goto write_partial;	i -= ofs;	bw += i;	if (bw > count)		bw = count;	fd->pos = old_pos + bw;write_partial:	if (alignedbuffer != b)		VirtualFree(alignedbuffer, 0, MEM_RELEASE);	return bw;write_error:	bw = -1;	goto write_partial;}/** * ntfs_device_win32_stat - get a unix-like stat structure for an ntfs device * @dev:	ntfs device obtained via ->open * @buf:	pointer to the stat structure to fill * * Note: Only st_mode, st_size, and st_blocks are filled. * * Return 0 if o.k. *	 -1 if not and errno set. in this case handle is trashed. */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:		st_mode = S_IFBLK;		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;	if (buf->st_size != -1)		buf->st_blocks = buf->st_size >> 9;	else		buf->st_size = 0;	return 0;}/** * ntfs_win32_hdio_getgeo - get drive geometry * @dev:	ntfs device obtained via ->open * @argp:	pointer to where to put the output * * Note: Works on windows NT/2k/XP only. * * Return 0 if o.k. *	 -1 if not, and errno set.  Note if error fd->handle is trashed. */static __inline__ int ntfs_win32_hdio_getgeo(struct ntfs_device *dev,		struct hd_geometry *argp){	win32_fd *fd = (win32_fd *)dev->d_private;	argp->heads = fd->geo_heads;	argp->sectors = fd->geo_sectors;	argp->cylinders = fd->geo_cylinders;	argp->start = fd->part_hidden_sectors;	return 0;}/** * ntfs_win32_blksszget - get block device sector size * @dev:	ntfs device obtained via ->open * @argp:	pointer to where to put the output * * Note: Works on windows NT/2k/XP only. * * Return 0 if o.k. *	 -1 if not, and errno set.  Note if error fd->handle is trashed. */static __inline__ int ntfs_win32_blksszget(struct ntfs_device *dev,int *argp){	win32_fd *fd = (win32_fd *)dev->d_private;	DWORD bytesReturned;	DISK_GEOMETRY dg;	if (DeviceIoControl(fd->handle, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0,			&dg, sizeof(DISK_GEOMETRY), &bytesReturned, NULL)) {		/* success */		*argp = dg.BytesPerSector;		return 0;	}	errno = ntfs_w32error_to_errno(GetLastError());	ntfs_log_trace("GET_DRIVE_GEOMETRY failed.\n");	return -1;}static int ntfs_device_win32_ioctl(struct ntfs_device *dev, int request,		void *argp){	win32_fd *fd = (win32_fd *)dev->d_private;	ntfs_log_trace("win32_ioctl(%d) called.\n", request);	switch (request) {#if defined(BLKGETSIZE)	case BLKGETSIZE:		ntfs_log_debug("BLKGETSIZE detected.\n");		if (fd->part_length >= 0) {			*(int *)argp = (int)(fd->part_length / 512);			return 0;		}		errno = EOPNOTSUPP;		return -1;#endif#if defined(BLKGETSIZE64)	case BLKGETSIZE64:		ntfs_log_debug("BLKGETSIZE64 detected.\n");		if (fd->part_length >= 0) {			*(s64 *)argp = fd->part_length;			return 0;		}		errno = EOPNOTSUPP;		return -1;#endif#ifdef HDIO_GETGEO	case HDIO_GETGEO:		ntfs_log_debug("HDIO_GETGEO detected.\n");		return ntfs_win32_hdio_getgeo(dev, (struct hd_geometry *)argp);#endif#ifdef BLKSSZGET	case BLKSSZGET:		ntfs_log_debug("BLKSSZGET detected.\n");		return ntfs_win32_blksszget(dev, (int *)argp);#endif#ifdef BLKBSZSET	case BLKBSZSET:		ntfs_log_debug("BLKBSZSET detected.\n");		/* Nothing to do on Windows. */		return 0;#endif	default:		ntfs_log_debug("unimplemented ioctl %d.\n", request);		errno = EOPNOTSUPP;		return -1;	}}static s64 ntfs_device_win32_pread(struct ntfs_device *dev, void *b,		s64 count, s64 offset){	return ntfs_pread(dev, offset, count, b);}static s64 ntfs_device_win32_pwrite(struct ntfs_device *dev, const void *b,		s64 count, s64 offset){	return ntfs_pwrite(dev, offset, count, b);}struct ntfs_device_operations ntfs_device_win32_io_ops = {	.open		= ntfs_device_win32_open,	.close		= ntfs_device_win32_close,	.seek		= ntfs_device_win32_seek,	.read		= ntfs_device_win32_read,	.write		= ntfs_device_win32_write,	.pread		= ntfs_device_win32_pread,	.pwrite		= ntfs_device_win32_pwrite,	.sync		= ntfs_device_win32_sync,	.stat		= ntfs_device_win32_stat,	.ioctl		= ntfs_device_win32_ioctl};

⌨️ 快捷键说明

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