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

📄 fio.c

📁 嵌入式系统中文件系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  if (curBlock != NULL)
  {
	if (RD_checkBlockLocation(curBlock) == -1)
	{
		RDerrno = ERROR_FILE_SYSTEM;
		return -1;
	}

	// there is a current block, compress the block if (1) compression for
	//   this file is enabled, (2) the block is uncompressed, and (3) the block
	//   is the current block of only one file handle
	if ((((pfile->dirEntry)->attribute & DA_COMPRESS) == DA_COMPRESS) && \
	    (curBlock->status == BLOCK_UNCOMPRESSED) && \
	    (curBlock->userCount == 1))
	{
		// compression enabled and the block is uncompressed, compress the block

		// get a buffer
		buf = (int *)ap_malloc(RD_BLOCK_SIZE);
		if (buf == NULL)
		{
			RDerrno = ERROR_ALLOC_MEM;
			return -1;
		}

		// copy the content of the original block to the buffer
		// this copying is used instead of directly compress the 
		//   data in the target block so that RAMDisk can recover
		//   the disk content in case the compression failed.
		src = (int*)((unsigned long)curBlock + B_HEADER);
		loop = curBlock->size / sizeof(int);
		for (i = 0; i < loop; i++)
			buf[i] = src[i];

		newSize = rd_compress_zlib((unsigned char *)src, curBlock->actualSize);
		if (newSize == -1 || newSize >= curBlock->actualSize)
		{
			// compression failed, recover the original content
			loop = curBlock->size / sizeof(int);
			for (i = 0; i < loop; i++)
				src[i] = buf[i];

			RDerrno = ERROR_BLOCK_COMPRESS;
			returnValue = -1;
		}
		else
		{
			// compression done

//			// copy the compressed data from the head to the tail of the block
//			loop = ((newSize - 1) / sizeof(int)) + 1;
//			src = (int*)((unsigned long)curBlock + B_HEADER + (loop * sizeof(int)) - sizeof(int));
//			des = (int*)((unsigned long)curBlock + B_HEADER + curBlock->size - sizeof(int));
//			for (i = 0; i < loop; i++)
//				*des-- = *src--;

			// truncate the block so that only the compressed data region is left
			newBlock = RD_truncateBlock(curBlock, newSize);
/*
			if (newBlock != curBlock)
			{
				// update the link to the next block
				if (newBlock->nextBlock != NULL)
					((struct diskBlock *)(newBlock->nextBlock))->prevBlock = newBlock;

				// update the link to the previous block
				//   If there is no previous block, then the current block
				//   is the starting block and the directory entry must be
				//   updated.
				if (newBlock->prevBlock == NULL)
					(pfile->dirEntry)->startBlock = newBlock;
				else
					((struct diskBlock *)(newBlock->prevBlock))->nextBlock = newBlock;

				newBlock->status = BLOCK_COMPRESSED;
				pfile->currentBlock = newBlock;
			}
*/
			newBlock->status = BLOCK_COMPRESSED;
			pfile->currentBlock = newBlock;
		}

		ap_free(buf);
	}
  }

  // !!Note: in RD_truncate_r(), we've done RD_writeBlockChecksum() once.
  //	But because newBlock->status is changned here, we have to
  //	write it again. This might lead to a bit slow performance. Watch Out!!
  RD_writeBlockChecksum(newBlock);
  
  return returnValue;
}
#endif	// #ifdef RAMDISK_COMPRESS_USE_ZLIB



#ifdef RAMDISK_COMPRESS_USE_ZLIB
/*************************************************************
Function: uncompressCurrentBlock
Description:
	Uncompress the current block of a file handle
Input:
	file handle
Output:
	0:  Success
	-1: Failure
**************************************************************/
int uncompressCurrentBlock(struct RD_FILE *pfile)
{
  int *des;
  long expandedSize;
  struct diskBlock *curBlock;
  struct diskBlock *theBlock;

  curBlock = pfile->currentBlock;

  // check if the current block should be uncompressed
  if (curBlock != NULL)
  {
	if (RD_checkBlockLocation(curBlock) == -1)
	{
		RDerrno = ERROR_FILE_SYSTEM;
		return -1;
	}

	// there is a current block, uncompress the block if the block is compressed
	if (curBlock->status == BLOCK_COMPRESSED)
	{
		// the block is compressed, uncompress the block
		if (curBlock->userCount > 1)
		{
			// there are more than 1 handles using this block
			//   it is impossible that this block is still uncompressed
			RDerrno = ERROR_FILE_STRUCTURE;
			return -1;
		}

		// get a block for uncompression
		theBlock = RD_getBlock(RD_BLOCK_SIZE);
		if (theBlock == NULL)
		{
			RDerrno = ERROR_ALLOC_BLOCK;
			return -1;
		}

		// copy the content of the original block to the buffer
		// this copying is used instead of directly compress the 
		//   data in the target block so that RAMDisk can recover
		//   the disk content in case the compression failed.
		des = (int*)((unsigned long)theBlock + B_HEADER);

		expandedSize = rd_uncompress_zlib(curBlock, des);
		if (expandedSize == -1 || expandedSize != curBlock->actualSize)
		{
			// uncompression failed
			RD_freeBlock(theBlock);
			RDerrno = ERROR_BLOCK_UNCOMPRESS;
			return -1;
		}
		else
		{
			// uncompression done
			// replace the compressed block by the uncompressed block in
			//   the file's block link
			theBlock->dataSize = expandedSize;
			theBlock->actualSize = expandedSize;
			theBlock->status = BLOCK_UNCOMPRESSED;
			theBlock->userCount = curBlock->userCount;
			theBlock->prevBlock = curBlock->prevBlock;
			theBlock->nextBlock = curBlock->nextBlock;

			// update the link to the next block
			if (theBlock->nextBlock != NULL)
				((struct diskBlock *)(theBlock->nextBlock))->prevBlock = theBlock;

			// update the link to the previous block
			//   If there is no previous block, then the current block
			//   is the starting block and the directory entry must be
			//   updated.
			if (theBlock->prevBlock == NULL)
				(pfile->dirEntry)->startBlock = theBlock;
			else
				((struct diskBlock *)(theBlock->prevBlock))->nextBlock = theBlock;

			pfile->currentBlock = theBlock;

			RD_freeBlock(curBlock);
		}
	}
  }

  RD_writeBlockChecksum(theBlock);
  
  return 0;
}
#endif	// #ifdef RAMDISK_COMPRESS_USE_ZLIB



/*************************************************************
Function : RD_read
Description:
	read data from file to user buffer
Inputs :
	fhandle - file handle
	buffer - user specified buffer
	size - size of data to be read
Outputs :
	the size of data read from disk
**************************************************************/
long RD_read(int fhandle, void *buffer, unsigned long size)
{
  long result;
#ifdef RAMDISK_STAT_LOG
  unsigned long startTime, endTime;
  struct signature *boot = (struct signature *)RD_BootBegin;
#endif

  if (InitRD == FALSE)
  {
	RDerrno = ERROR_FILE_SYSTEM_NOT_INIT;
	return 0;
  }

  if ((fhandle < 0) || (fhandle >= MAX_OPEN_FILE) || (RD_HandleTable[fhandle] == NULL))
  {
	RDerrno = ERROR_INVALID_HANDLE;
	return 0;
  }

  if (RD_HandleTable[fhandle]->deviceID != RAMDISK_ID)
  {
	RDerrno = ERROR_INVALID_DEVICE;
	return 0;
  }

  RDerrno = 0;

  if (size == 0)
	return 0;

  if (sc_waitSemaphore(RD_SemaphoreID) == -1)
  {
	RDerrno = ERROR_WAIT_SEMAPHORE;
	return 0;
  }

#ifdef RAMDISK_STAT_LOG
  startTime = sc_getTimeStamp();
#endif

  result = RD_read_r(RD_HandleTable[fhandle], buffer, size);
  
  RD_updateFileHandleTable(RD_HandleTable[fhandle]);
  
#ifdef RAMDISK_STAT_LOG
  endTime = sc_getTimeStamp();
  if (endTime > startTime)
  {
	boot->readTime += (endTime - startTime);
  }

  boot->readCount += result;
#endif

  if (sc_signalSemaphore(RD_SemaphoreID) == -1)
  {
	RDerrno = ERROR_SIGNAL_SEMAPHORE;
	return 0;
  }

  return result;
}



/*************************************************************
Function : RD_write
Description:
	write data from user buffer to file
Inputs :
	fhandle - file handle
	buffer - user specified buffer
	size - size of data to be written
Outputs :
	the size of data written to disk
**************************************************************/
long RD_write(int fhandle, void *buffer, unsigned long size)
{
  long result;
  
#ifdef RAMDISK_STAT_LOG
  unsigned long startTime, endTime;
  struct signature *boot = (struct signature *)RD_BootBegin;
#endif

  if (InitRD == FALSE)
  {
	RDerrno = ERROR_FILE_SYSTEM_NOT_INIT;
	return 0;
  }

  if ((fhandle < 0) || (fhandle >= MAX_OPEN_FILE) || (RD_HandleTable[fhandle] == NULL))
  {
	RDerrno = ERROR_INVALID_HANDLE;
	return 0;
  }

  if (RD_HandleTable[fhandle]->deviceID != RAMDISK_ID)
  {
	RDerrno = ERROR_INVALID_DEVICE;
	return 0;
  }
  
  if ((RD_HandleTable[fhandle]->fileFlag & O_RDWR) == 0)
  {
  	RDerrno = ERROR_FILE_FLAG;
  	return 0;
  }

  RDerrno = 0;

  if (size == 0)
	return 0;

  if (sc_waitSemaphore(RD_SemaphoreID) == -1)
  {
	RDerrno = ERROR_WAIT_SEMAPHORE;
	return 0;
  }

#ifdef RAMDISK_STAT_LOG
  startTime = sc_getTimeStamp();
#endif

  result = RD_write_r(RD_HandleTable[fhandle], buffer, size);
  RD_updateFileHandleTable(RD_HandleTable[fhandle]);
 
#ifdef RAMDISK_STAT_LOG
  endTime = sc_getTimeStamp();
  if (endTime > startTime)
  {
	boot->writeTime += (endTime - startTime);
  }

  boot->writeCount += result;
#endif

  if (sc_signalSemaphore(RD_SemaphoreID) == -1)
  {
	RDerrno = ERROR_SIGNAL_SEMAPHORE;
	return 0;
  }

  return result;
}



/*************************************************************
Function: RD_flush
Description:
	clear the buffer in file handle
Input:
	fhandle - the target file handle
Output:
	0	SUCCESS
	-1	FAILURE
Note:
**************************************************************/
int RD_flush(int fhandle)
{
  RDerrno = 0;

  return 0;
}



/*************************************************************
Function: RD_flushAll
Description:
	clear the buffers in all file handles
Input:
	NONE
Output:
	0	SUCCESS
	-1	FAILURE
Note:
**************************************************************/
int RD_flushAll(void)
{
  RDerrno = 0;

  return 0;
}



/*************************************************************
Function: RD_read_r
Description:
	read data from file to user buffer
Input:
	pfile - the target file structure
	buffer - the user buffer
	size - the size of data to be read
Output:
	size of data read from the disk
**************************************************************/
long RD_read_r(struct RD_FILE *pfile, unsigned char *buffer, unsigned long size)
{
  struct diskBlock *curBlock;
  unsigned char *src;
  int found = 0;
  long readCount = 0;
  long remains;
  long curSize;
  long i;

  struct diskBlock *prevBlock;
  
  // check if the end of the file has already been reached
  if (pfile->fpos >= (pfile->dirEntry)->fsize)
  {
	RDerrno = ERROR_EOF;
	return 0;
  }

  if (pfile->currentBlock == NULL)
  {
	// there is no current block
	curBlock = (pfile->dirEntry)->startBlock;
	pfile->blockfpos = 0;

	if (curBlock == NULL)
	{
		// block not found, must be error in file structure
		pfile->currentBlock = NULL;
		return 0;
	}
	else
	{
		pfile->currentBlock = curBlock;
		found = 1;
	}
  }
#ifdef RAMDISK_COMPRESS_USE_ZLIB
  else
  {
	if ((pfile->fpos < pfile->blockfpos) || (pfile->fpos >= pfile->blockfpos + (pfile->currentBlock)->actualSize))
	{
		// file position will move to another block, compress the current block if necessary
		compressCurrentBlock(pfile);
		// one less file handle is using this block
		(pfile->currentBlock)->userCount--;
	}
  }
#endif

  // there is a current block
  curBlock = pfile->currentBlock;


  if (RD_checkBlockLocation(curBlock) == -1)
  {
	// invalid block location
	RDerrno = ERROR_FILE_SYSTEM;
	return 0;
  }

  // check if the file position matches this block
  if (pfile->fpos < pfile->blockfpos)
  {
	// file position is before the beginning of the current block
	// find the block that is pointed by the file position by going backward
	while (curBlock != NULL)
	{
		curBlock = curBlock->prevBlock;
		pfile->blockfpos -= RD_BLOCK_SIZE;
		
		if ((pfile->fpos >= pfile->blockfpos) && (pfile->fpos < pfile->blockfpos + RD_BLOCK_SIZE))
		{
			found = 1;
			break;
		}
	}

	if (curBlock == NULL)
		found = 0;
	
  }
  else if (pfile->fpos >= pfile->blockfpos + curBlock->actualSize)
  {
	// file position is behind the current block
	// find the block that is pointed by the file position by going forward
	
	while (curBlock != NULL)
	{
		pfile->blockfpos += RD_BLOCK_SIZE;
		curBlock = curBlock->nextBlock;

		if ((pfile->fpos >= pfile->blockfpos) && (pfile->fpos < pfile->blockfpos + RD_BLOCK_SIZE))
		{
			found = 1;
			break;
		}
	}
	
	if (curBlock == NULL)
		found = 0;
	   
  }
  
  if (found == 1)
  {
	// a block other than the current block is found
	pfile->currentBlock = curBlock;

#ifdef RAMDISK_COMPRESS_USE_ZLIB
	// one more file handle is using this block
	(pfile->currentBlock)->userCount++;
	// uncompress the block if necessary
	if (uncompressCurrentBlock(pfile) == -1)
	{
		pfile->currentBlock = NULL;
		pfile->blockfpos = 0;

		return 0;
	}
	curBlock = pfile->currentBlock;
#endif
  }
  else
  {
	// no block other than the current block is found

⌨️ 快捷键说明

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