📄 fio.c
字号:
**************************************************************/
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 + -