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

📄 fio.c

📁 嵌入式系统中文件系统源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
**************************************************************/
long RD_write_r(struct RD_FILE *pfile, unsigned char *buffer, unsigned long size)
{
  struct diskBlock *curBlock;
  struct diskBlock *prevBlock;
  unsigned char *des;
  int found = 0;
  long writeCount = 0;
  long freeSize = 0;
//  long curSize = 0;
  long remains;
  long i;
  sysTime now;
  
  unsigned long extraCR_num = 0;		// used to count the number of '\r' bytes
  						// needed to stuff while pfile->fileFlag == O_TEXT

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

	if (curBlock == NULL)
	{
		// no block in the file, get a new block
		pfile->currentBlock = RD_getBlock((unsigned long)RD_BLOCK_SIZE);
		if (pfile->currentBlock == NULL)
		{
			RDerrno = ERROR_ALLOC_BLOCK;
			return 0;
		}
		
		// new block is of course uncompressed
		(pfile->currentBlock)->status = BLOCK_UNCOMPRESSED;
		
		// one handle is using this block
//		(pfile->currentBlock)->userCount = 1;
		
		(pfile->currentBlock)->userCount = 0;
	#ifdef RAMDISK_COMPRESS_USE_ZLIB
		// one handle is using this block
		pfile->currentBlock->userCount++;
	#endif
		// this is the starting block of the file
		(pfile->dirEntry)->startBlock = pfile->currentBlock;
	}
	else
	{
		pfile->currentBlock = curBlock;
		found = 1;
	}
  }
#ifdef RAMDISK_COMPRESS_USE_ZLIB
  else
  {
	if ((pfile->fpos < pfile->blockfpos) || (pfile->fpos >= pfile->blockfpos + RD_BLOCK_SIZE))
	{
		// 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;
  }

  prevBlock = NULL;
  // 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)
	{
		// bad file structure
		found = 0;
	}
  }
  else if (pfile->fpos >= pfile->blockfpos + RD_BLOCK_SIZE)
  {
	// file position is behind the current block
	// find the block that is pointed by the file position by going forward
	while (curBlock != NULL)
	{
		prevBlock = curBlock;
		curBlock = curBlock->nextBlock;
		pfile->blockfpos += RD_BLOCK_SIZE;
		if ((pfile->fpos >= pfile->blockfpos) && (pfile->fpos < pfile->blockfpos + RD_BLOCK_SIZE))
		{
			found = 1;
			break;
		}
	}
	   
	if (curBlock == NULL && found == 1)
	{
		// the file position is just beyond the last block
		// add a new block to the file
		curBlock = RD_getBlock((unsigned long)RD_BLOCK_SIZE);
		if (curBlock == NULL)
		{
			pfile->currentBlock = NULL;
			pfile->blockfpos = 0;
			RDerrno = ERROR_ALLOC_BLOCK;
			return 0;
		}

		// set up the block links
		curBlock->prevBlock = prevBlock;
		if (prevBlock != NULL)
		{
			prevBlock->nextBlock = curBlock;

  			RD_writeBlockChecksum(prevBlock);
		}
		else
			(pfile->dirEntry)->startBlock = curBlock;
		// new block is of course uncompressed
		curBlock->status = BLOCK_UNCOMPRESSED;
		// no handle is originally using this block
		curBlock->userCount = 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;
	
	// !!Note: we don't write the checksum here because
	//	it'll be written later
#endif
  }
  else
  {
	// no block other than the current block is found
	//   either the required block is not found or the required block
	//   is the currnet block
	if (curBlock == NULL)
	{
		// the required block is not found
		pfile->currentBlock = NULL;
		pfile->blockfpos = 0;
		RDerrno = ERROR_FILE_STRUCTURE;
		return 0;
	}

	// the required block is already the current block
  }

  // the block to be written is now in pfile->currentBlock and uncompressed
  curBlock = pfile->currentBlock;
  remains = size;
  // part 1: copy the data from the user-provided buffer to handle buffer
  //   the handle buffer is dirty afterwards

  // the size of data from the file position to the end of the block
  freeSize = RD_BLOCK_SIZE - (pfile->fpos - pfile->blockfpos);
  if (remains <= freeSize)
  {
	// the current block has enough data to satisfy the read operation
	freeSize = remains;
  }

  des = (unsigned char *)((unsigned long)curBlock + B_HEADER + (pfile->fpos - pfile->blockfpos));
  prevBlock = curBlock;
  if ((pfile->fileFlag & O_TEXT) == O_TEXT)
  {
  	for (i = 0; i < freeSize; i++)
  	{
  		if (des >= ((unsigned char*)curBlock + B_HEADER + RD_BLOCK_SIZE))
  		{
  			curBlock = curBlock->nextBlock;
	  		des = (unsigned char *)((unsigned long)curBlock + B_HEADER);
  		}
  	
		if (*buffer == '\n')
		{
  			// stuff a '\r' in the file
	 		*des++ = '\r';
	  		extraCR_num++;
  		}

		// when there are less equal one empty byte in the current block
	  	if ((des+1) >= ((unsigned char*)curBlock + B_HEADER + RD_BLOCK_SIZE))
  		{
  			// Note: curBlock could move to the next only once because 
	  		//	the maximum value of freeSize is RD_BLOCK_SIZE
  		
  			// we'll create a new block when
  			// (1) the capacity of the current block is already full
	  		//    or
  			// (2) there are only one empty byte left in the current block and
  			//	this loop will still go on at least 1 time
  			
	  		if (des >= ((unsigned char*)curBlock + B_HEADER + RD_BLOCK_SIZE) || \
  				(i+1) < freeSize)
  			{
	 			// move on to the next block
	  			curBlock = curBlock->nextBlock;
  				if (curBlock == NULL)
	  			{
					// a new block is needed, go get it
					curBlock = RD_getBlock((unsigned long)RD_BLOCK_SIZE);
					if (curBlock == NULL)
					{
						pfile->currentBlock = NULL;
						pfile->blockfpos = 0;
						RDerrno = ERROR_ALLOC_BLOCK;

						sc_getTime(&now);
						(pfile->dirEntry)->time = now.hour * 2048 + now.minute * 32 + \
							now.second / 2;
						(pfile->dirEntry)->date = (now.year-1980) * 512 + now.month * 32 + now.day;

						pfile->fpos += (i + extraCR_num);

						RD_writeBlockChecksum(prevBlock);
						
						return i;
					}
					
					// link the new block to the file block link
					curBlock->prevBlock = prevBlock;
					prevBlock->nextBlock = curBlock;
				
					// new block is of course uncompressed
					curBlock->status = BLOCK_UNCOMPRESSED;
					
					curBlock->userCount = 0;
			#ifdef RAMDISK_COMPRESS_USE_ZLIB
					// one handle is using this block
					curBlock->userCount++;
			#endif
  				}
  				else
  				{
					// 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;

						sc_getTime(&now);
						(pfile->dirEntry)->time = now.hour * 2048 + now.minute * 32 + now.second / 2;
						(pfile->dirEntry)->date = (now.year-1980) * 512 + now.month * 32 + now.day;

						RD_writeBlockChecksum(prevBlock);
						
						return i;
					}
					curBlock = pfile->currentBlock;
				#endif
  					
	  			}

  				if (des >= ((unsigned char*)curBlock + B_HEADER + RD_BLOCK_SIZE))
  					des = (unsigned char *)((unsigned long)curBlock + B_HEADER);
	  			else
  				{
  					// there is still one byte left in the previous block, so go back!
  					curBlock = prevBlock;
	  			}
  			}
		}
		*des++ = *buffer++;
  	}
  }
  else // binary mode
  {
	// if both buffers are 4 byte-aligned
	if ((long)des % 4 == 0 && (long)buffer % 4 == 0)
	{
		for (i = 0; i < freeSize / 4; i++)
		{
			*((int*)des) = *((int*)buffer);
			des += 4;
			buffer += 4;
		}
			
		for (i = 0; i < freeSize % 4; i++)
			*des++ = *buffer++;
	}
	else if ((long)des % 2 == 0 && (long)buffer % 2 == 0)// if both buffers are 2 byte-aligned
	{
		for (i = 0; i < freeSize / 2; i++)
		{
			*((short*)des) = *((short*)buffer);
			des += 2;
			buffer += 2;
		}
			
		for (i = 0; i < freeSize % 2; i++)
			*des++ = *buffer++;
	}
	else if ((long) des % 2 == 1 && (long) buffer % 2 == 1)
	{
		// move 1 byte first to make both des & buffer located on even addresses
		*des++ = *buffer++;
		
		if ((long)des % 4 == 0 && (long)buffer % 4 == 0)
		{
			for (i = 0; i < (freeSize-1) / 4; i++)
			{
				*((int*)des) = *((int*)buffer);
				des += 4;
				buffer += 4;
			}
		
			for (i = 0; i < (freeSize-1) % 4; i++)
				*des++ = *buffer++;
		}
		else
		{
			for (i = 0; i < (freeSize-1) / 2; i++)
			{
				*((short*)des) = *((short*)buffer);
				des += 2;
				buffer += 2;
			}
		
			for (i = 0; i < (freeSize-1) % 2; i++)
				*des++ = *buffer++;
		}
	}
	else
	{
  		for (i = 0; i < freeSize; i++)
			*des++ = *buffer++;
	}
	   
  }
  
  // update the positions
  remains -= freeSize;

//  pfile->fpos += freeSize;
  pfile->fpos += (freeSize + extraCR_num);
  
  if (pfile->fpos > (pfile->dirEntry)->fsize)
  {
	// file size grows
	(pfile->dirEntry)->fsize = pfile->fpos;
  }

  if (curBlock->actualSize < (pfile->fpos - pfile->blockfpos))
  {
   	// if we didn't advance curBlock while writing in part1
   	if (prevBlock == curBlock)
   	{
		curBlock->actualSize = (pfile->fpos - pfile->blockfpos);
		curBlock->dataSize = (pfile->fpos - pfile->blockfpos);
   	}
   	else
   	{
   		prevBlock->actualSize = RD_BLOCK_SIZE;
   		prevBlock->dataSize = RD_BLOCK_SIZE;
   		
  		RD_writeBlockChecksum(prevBlock);
  	
		curBlock->actualSize = (pfile->fpos - pfile->blockfpos - RD_BLOCK_SIZE);
		curBlock->dataSize = (pfile->fpos - pfile->blockfpos - RD_BLOCK_SIZE);

		// if the capacity of curBlock is full, we compress the prevBlock( = pfile->currentBlock)
		if (curBlock->actualSize >= RD_BLOCK_SIZE)
		{
			// compress the previous block if necessary
		#ifdef RAMDISK_COMPRESS_USE_ZLIB
			pfile->currentBlock = prevBlock;
			compressCurrentBlock(pfile);
//			prevBlock = pfile->currentBlock;
			// one less file handle is using this block
			(pfile->currentBlock)->userCount--;

		#endif
			// move pfile->currentBlock to the new block we just created in the last data-copy loop
			pfile->currentBlock = curBlock;
			pfile->blockfpos += RD_BLOCK_SIZE;
			extraCR_num = 0;
		}
		else
		{
			// restore curBlock for part2 processing
			pfile->currentBlock = curBlock = prevBlock;
		}
		
   	}
  }

  if (remains == 0)
  {
	sc_getTime(&now);
	(pfile->dirEntry)->time = now.hour * 2048 + now.minute * 32 + now.second / 2;
	(pfile->dirEntry)->date = (now.year-1980) * 512 + now.month * 32 + now.day;

  	RD_writeBlockChecksum(curBlock);

	return freeSize;
  }

  writeCount += freeSize;

  // part 2: write not done yet

  // continue with next block till the last block
  while (remains > RD_BLOCK_SIZE)
  {
	// update the file position of the 1st byte of the current block
	pfile->blockfpos += RD_BLOCK_SIZE;

	// get next block
	prevBlock = curBlock;
	curBlock = curBlock->nextBlock;

	// compress the previous block if necessary
#ifdef RAMDISK_COMPRESS_USE_ZLIB
	compressCurrentBlock(pfile);
	prevBlock = pfile->currentBlock;
	// one less file handle is using this block
	(pfile->currentBlock)->userCount--;
#endif

	if (curBlock == NULL)
	{
		// a new block is needed, go get it
		curBlock = RD_getBlock((unsigned long)RD_BLOCK_SIZE);
		if (curBlock == NULL)
		{
			pfile->currentBlock = NULL;
			pfile->blockfpos = 0;
			RDerrno = ERROR_ALLOC_BLOCK;

			sc_getTime(&now);
			(pfile->dirEntry)->time = now.hour * 2048 + now.minute * 32 + now.second / 2;
			(pfile->dirEntry)->date = (now.year-1980) * 512 + now.month * 32 + now.day;

 			RD_writeBlockChecksum(prevBlock);
  			
			return writeCount;
		}
		
		// link the new block to the file block link
		curBlock->prevBlock = prevBlock;
		if (prevBlock != NULL)
			prevBlock->nextBlock = curBlock;
			
		// new block is of course uncompressed
		curBlock->status = BLOCK_UNCOMPRESSED;
		// no handle is originally using this block
		curBlock->userCount = 0;
	}
	
  	RD_writeBlockChecksum(prevBlock);

	// the current block is the new block
	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;

		sc_getTime(&now);
		(pfile->dirEntry)->time = now.hour * 2048 + now.minute * 32 + now.second / 2;
		(pfile->dirEntry)->date = (now.year-1980) * 512 + now.month * 32 + now.day;

  		RD_writeBlockChecksum(curBlock);
		
		return writeCount;
	}
	curBlock = pfile->currentBlock;
#endif

   	// store the original curBlock temporarily
	prevBlock = curBlock;
	
	des = (unsigned char *)((unsigned long)curBlock + B_HEADER + extraCR_num);
	extraCR_num = 0;
	
	if ((pfile->fileFlag & O_TEXT) == O_TEXT)
	{
		for (i = 0; i < RD_BLOCK_SIZE; i++)
		{
  			if (des >= ((unsigned char*)curBlock + B_HEADER + RD_BLOCK_SIZE))
	  		{
  				curBlock = curBlock->nextBlock;
  				des = (unsigned char *)((unsigned long)curBlock + B_HEADER);
	  		}

  			if (*buffer == '\n')
	  		{
  				// stuff a '\r' in the file

⌨️ 快捷键说明

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