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

📄 devices.c

📁 jfs 源码
💻 C
字号:
/* *   Copyright (c) International Business Machines Corp., 2000-2003 * *   This program is free software;  you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or  *   (at your option) any later version. *  *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY;  without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See *   the GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program;  if not, write to the Free Software  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#include <fcntl.h>#include <unistd.h>#include <sys/types.h>#include <sys/stat.h>#include "jfs_types.h"#include "jfs_filsys.h"#include <string.h>#include <stdio.h>#include <stdlib.h>#include "devices.h"#include "debug.h"#include <sys/ioctl.h>#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE64)#define BLKGETSIZE64 _IOR(0x12, 114, size_t)#endif#if defined(__linux__) && defined(_IO) && !defined(BLKGETSIZE)#define BLKGETSIZE _IO(0x12,96)	/* return device size (sectors) */#endif/* * NAME: ujfs_get_dev_size * * FUNCTION: Uses the device driver interface to determine the raw capacity of *      the specified device. * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: *      device  - device *      size    - filled in with size of device; not modified if failure occurs * * NOTES: * * DATA STRUCTURES: * * RETURNS: 0 if successful; anything else indicates failures */int ujfs_get_dev_size(HFILE device, int64_t *size){	off_t Starting_Position;	/* position within file/device upon					 * entry to this function. */	off_t Current_Position = 16777215;	/* position we are attempting						 * to read from. */	off_t Last_Valid_Position = 0;	/* Last position we could successfully					 * read from. */	off_t First_Invalid_Position;	/* first invalid position we attempted					 * to read from/seek to. */	off_t Seek_Result;	/* value returned by lseek. */	size_t Read_Result = 0;	/* value returned by read. */	char Test_Byte;		/* used to validate a position that we				 * successfully lseek'ed to. */	int rc;	struct stat stat_data;	rc = fstat(device, &stat_data);	if (!rc && S_ISREG(stat_data.st_mode)) {		/* This is a regular file.  */		*size = (int64_t) ((stat_data.st_size / 1024) * 1024);		return NO_ERROR;	}#ifdef BLKGETSIZE64	{		uint64_t sz;		if (ioctl(device, BLKGETSIZE64, &sz) >= 0) {			*size = sz;			return 0;		}	}#endif#ifdef BLKGETSIZE	{		unsigned long num_sectors = 0;		if (ioctl(device, BLKGETSIZE, &num_sectors) >= 0) {			/* for now, keep size as multiple of 1024, *			 * not 512, so eliminate any odd sector.   */			*size = PBSIZE * (int64_t) ((num_sectors / 2) * 2);			return NO_ERROR;		}	}#endif	/*	 * If the ioctl above fails or is undefined, use a binary search to	 * find the last byte in the partition.  This works because an lseek to	 * a position within the partition does not return an error while an	 * lseek to a position beyond the end of the partition does.  Note that	 * some SCSI drivers may log an 'access beyond end of device' error	 * message.	 */	/* Save the starting position so that we can restore it when we are	 * done! */	Starting_Position = lseek(device, 0, SEEK_CUR);	if (Starting_Position < 0)		return ERROR_SEEK;	/*	 * Find a position beyond the end of the partition.  We will start by	 * attempting to seek to and read the 16777216th byte in the partition.	 * We start here because a JFS partition must be at least this big.  If	 * it is not, then we can not format it as JFS.	 */	do {		/* Seek to the location we wish to test. */		Seek_Result = lseek(device, Current_Position, SEEK_SET);		if (Seek_Result == Current_Position) {			/* Can we read from this location? */			Read_Result = read(device, &Test_Byte, 1);			if (Read_Result == 1) {				/* The current test position is valid.  Save it				 * for future reference. */				Last_Valid_Position = Current_Position;				/* Lets calculate the next location to test. */				Current_Position = ((Current_Position + 1) * 2)						   - 1;			}		}	} while ((Seek_Result == Last_Valid_Position) && (Read_Result == 1));	/*	 * We have exited the while loop, which means that Current Position is	 * beyond the end of the partition or is unreadable due to a hardware	 * problem (bad block).  Since the odds of hitting a bad block are very	 * low, we will ignore that condition for now.  If time becomes	 * available, then this issue can be revisited.	 */	/* Is the drive greater than 16MB? */	if (Last_Valid_Position == 0) {		/*		 * Determine if drive is readable at all.  If it is, the drive		 * is too small.  If not, it could be a newly created partion,		 * so we need to issue a different error message		 */		*size = 0;	/* Indicates not readable at all */		Seek_Result = lseek(device, Last_Valid_Position, SEEK_SET);		if (Seek_Result == Last_Valid_Position) {			/* Can we read from this location? */			Read_Result = read(device, &Test_Byte, 1);			if (Read_Result == 1)				/* non-zero indicates readable, but too small */				*size = 1;		}		goto restore;	}	/*	 * The drive is larger than 16MB.  Now we must find out exactly how	 * large.	 *	 * We now have a point within the partition and one beyond it.  The end	 * of the partition must lie between the two.  We will use a binary	 * search to find it.	 */	/* Setup for the binary search. */	First_Invalid_Position = Current_Position;	Current_Position = Last_Valid_Position +			   ((Current_Position - Last_Valid_Position) / 2);	/*	 * Iterate until the difference between the last valid position and the	 * first invalid position is 2 or less.	 */	while ((First_Invalid_Position - Last_Valid_Position) > 2) {		/* Seek to the location we wish to test. */		Seek_Result = lseek(device, Current_Position, SEEK_SET);		if (Seek_Result == Current_Position) {			/* Can we read from this location? */			Read_Result = read(device, &Test_Byte, 1);			if (Read_Result == 1) {				/* The current test position is valid.				 * Save it for future reference. */				Last_Valid_Position = Current_Position;				/*				 * Lets calculate the next location to test. It				 * should be half way between the current test				 * position and the first invalid position that				 * we know of.				 */				Current_Position = Current_Position +						   ((First_Invalid_Position -						     Last_Valid_Position) / 2);			}		} else			Read_Result = 0;		if (Read_Result != 1) {			/* Out test position is beyond the end of the partition.			 * It becomes our first known invalid position. */			First_Invalid_Position = Current_Position;			/* Our new test position should be half way between our			 * last known valid position and our current test			 * position. */			Current_Position =			    Last_Valid_Position +			    ((Current_Position - Last_Valid_Position) / 2);		}	}	/*	 * The size of the drive should be Last_Valid_Position + 1 as	 * Last_Valid_Position is an offset from the beginning of the partition.	 */	*size = Last_Valid_Position + 1;restore:	/* Restore the original position. */	if (Starting_Position != lseek(device, Starting_Position, SEEK_SET))		return ERROR_SEEK;	return NO_ERROR;}/* * NAME: ujfs_rw_diskblocks * * FUNCTION: Read/Write specific number of bytes for an opened device. * * PRE CONDITIONS: * * POST CONDITIONS: * * PARAMETERS: *      dev_ptr         - file handle of an opened device to read/write *      disk_offset     - byte offset from beginning of device for start of disk *                        block read/write *      disk_count      - number of bytes to read/write *      data_buffer     - On read this will be filled in with data read from *                        disk; on write this contains data to be written *      mode            - GET: read; PUT: write; VRFY: verify * * NOTES: A disk address is formed by {#cylinder, #head, #sector} * *      Also the DSK_READTRACK and DSK_WRITETRACK is a track based *      function. If it needs to read/write crossing track boundary, *      additional calls are used. * * DATA STRUCTURES: * * RETURNS: */int ujfs_rw_diskblocks(HFILE dev_ptr,		       int64_t disk_offset, 		       int32_t disk_count, 		       void *data_buffer, 		       int32_t mode){	off_t Actual_Location;	size_t Bytes_Transferred;	Actual_Location = lseek(dev_ptr, disk_offset, SEEK_SET);	if ((Actual_Location < 0) || (Actual_Location != disk_offset))		return ERROR_SEEK;	switch (mode) {	case GET:		Bytes_Transferred = read(dev_ptr, data_buffer, disk_count);		break;	case PUT:		Bytes_Transferred = write(dev_ptr, data_buffer, disk_count);		break;	default:		DBG_ERROR(("Internal error: %s(%d): bad mode: %d\n", __FILE__,			   __LINE__, mode))		    return ERROR_INVALID_HANDLE;		break;		/* Keep the compiler happy. */	}	if (Bytes_Transferred != disk_count) {		if (mode == GET)			return ERROR_READ_FAULT;		else			return ERROR_WRITE_FAULT;	}	return NO_ERROR;}

⌨️ 快捷键说明

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