📄 file.c
字号:
if (NULL != FileHandleTable[Handle].Read.Buffer) { Tmp = stavfs_DiscardRWBuffer(FileHandleTable[Handle].Device_p, &(FileHandleTable[Handle].Read.Buffer)); if (Tmp != ST_NO_ERROR) Error = Tmp; } if (NULL != FileHandleTable[Handle].Write.Buffer) { Tmp = stavfs_DiscardRWBuffer(FileHandleTable[Handle].Device_p, &(FileHandleTable[Handle].Write.Buffer)); if (Tmp != ST_NO_ERROR) Error = Tmp; } /* Mark the handle as closed */ FileHandleTable[Handle].Device_p = CLOSED_FILE; /* Marking the handle released */ FileHandleTable[Handle].DirEntry_p = NULL; /* If the file is open for write */ if (DirEntry_p->Flags & FILE_FLAG_OPEN_FOR_WRITE) { /* Look for other handles that are open for write */ for (Handle = 0; (Handle < MAX_OPEN_FILES); Handle++) { if ((FileHandleTable[Handle].Device_p == Device_p) && (FileHandleTable[Handle].DirEntry_p == DirEntry_p) && (FileHandleTable[Handle].Mode & STAVFS_WRITE_MODE)) { /* We have a write handle on this file */ break; } } if (Handle >= MAX_OPEN_FILES) { /* Closing the final writing handle - must flush MCAT first incase we have allocated clusters */ if (ST_NO_ERROR != (Tmp = stavfs_FlushCat(Device_p))) { Error = Tmp; } DirEntry_p->Flags &= ~FILE_FLAG_OPEN_FOR_WRITE; stavfs_ModifyDirEntry(Device_p, DirEntry_p); } /* Flush directory entry in all cases where we wrote data, like a sync */ if (ST_NO_ERROR != (Tmp = stavfs_FlushDir(Device_p, NULL))) { Error = Tmp; } } /* Free the directory reference */ if (DirEntry_p != NULL) { stavfs_ReleaseFileEntry (Device_p, DirEntry_p); } } return (Error);}/******************************************************************************Function Name : stavfs_DeleteFile Description : Delete the named file. The files must be closed to delete. Parameters :******************************************************************************/static ST_ErrorCode_t stavfs_DeleteFile (stavfs_Device_t * Device_p, char *Name){ ST_ErrorCode_t Error = ST_NO_ERROR; ST_ErrorCode_t TmpErr = ST_NO_ERROR; stavfs_DirEntry_t *DirEntry_p = NULL; int i; assert (Device_p != NULL); assert (Name != NULL); /* Find the directory entry */ Error = stavfs_FindFileEntry(Device_p, NULL, Name, &DirEntry_p); if (DirEntry_p == NULL) { /* No such file */ STTBX_Print(("No such file\n")); Error = STAVFS_ERROR_NO_SUCH_FILE; } /* Check to see if it is open */ for (i = 0; (Error == ST_NO_ERROR) && (i < MAX_OPEN_FILES); i++) { if ((FileHandleTable[i].DirEntry_p == DirEntry_p) && (FileHandleTable[i].Device_p == Device_p)) { STTBX_Print(("File in use\n")); Error = STAVFS_ERROR_FILE_IN_USE; } } /* Delete the file */ if (Error == ST_NO_ERROR) { Error = stavfs_DeleteFileEntry(Device_p, DirEntry_p); } /* Update the MCAT and then the directory (which finally marks the file as deleted) */ if (ST_NO_ERROR != (TmpErr = stavfs_FlushCat(Device_p))) { Error = TmpErr; } if (ST_NO_ERROR != (TmpErr = stavfs_FlushDir(Device_p, NULL))) { Error = TmpErr; } /* Release our temporary reference */ if (DirEntry_p != NULL) { /* Release the reference */ stavfs_ReleaseFileEntry (Device_p, DirEntry_p); } return (Error);}/******************************************************************************Function Name : stavfs_DeleteFileEntry Description : Delete the file entry. Parameters :******************************************************************************/ST_ErrorCode_t stavfs_DeleteFileEntry (stavfs_Device_t * Device_p, stavfs_DirEntry_t *DirEntry_p){ ST_ErrorCode_t Error = ST_NO_ERROR; U64 EndLBA = NullLBA; assert (Device_p != NULL); assert (DirEntry_p != NULL); /* Mark the entry as being deleted */ DirEntry_p->Flags |= FILE_FLAG_BEING_DELETED; EndLBA = DirEntry_p->EndLBA; DirEntry_p->EndLBA = DirEntry_p->StartLBA; stavfs_ModifyDirEntry(Device_p, DirEntry_p); Error = stavfs_FlushDir(Device_p, NULL); /* Free up the allocated space */ if (Error == ST_NO_ERROR) { U32 FreeClusters = stavfs_FreeClusterChain(Device_p, &EndLBA); /* Correct the allocated size */ stavfs_ModifyDirEntry(Device_p, DirEntry_p); INT_I64_SubLit(DirEntry_p->AllocSize, FreeClusters, DirEntry_p->AllocSize); if (INT_I64_AreNotEqual(EndLBA, NullLBA)) { /* We have failed to release the chain */ Error = ST_ERROR_BAD_PARAMETER; } } /* Free up the directory entry */ if (Error == ST_NO_ERROR) { /* Mark the entry as unused */ DirEntry_p->Flags = FILE_FLAG_ENTRY_UNUSED; stavfs_ModifyDirEntry(Device_p, DirEntry_p); } else { stavfs_RootSector_t RootSector; /* Failed to delete properly - flag partition as bad */ if (ST_NO_ERROR != stavfs_ReadRootSector (Device_p, &RootSector)) { STTBX_Print (("Error reading the root sector\n")); Error = STAVFS_ERROR_UNREADABLE_DISK; } else { RootSector.StateFlags |= ROOT_PARTITION_FLAG_BAD; if (ST_NO_ERROR != stavfs_WriteRootSector (Device_p, &RootSector)) { STTBX_Print (("Error writing the root sector\n")); Error = STAVFS_ERROR_UNWRITABLE_DISK; } } } return (Error);}/******************************************************************************Function Name : stavfs_WriteFile Description : Parameters :******************************************************************************/static ST_ErrorCode_t stavfs_WriteFile (int Handle, U32 Size, char const *Address, U32 *BytesWritten){ ST_ErrorCode_t Error = ST_NO_ERROR; stavfs_OpenFileHandle_t *FileHandle_p = FileHandleTable+Handle; stavfs_Device_t *Device_p = FileHandle_p->Device_p; stavfs_DirEntry_t *DirEntry_p = FileHandle_p->DirEntry_p; stavfs_FilePos_t *Pos_p = &(FileHandle_p->Write); U32 Offset = 0; U32 WrittenData = 0; U64 FilePos; BOOL StreamFile = (DirEntry_p->Flags & FILE_FLAG_STREAM_MODE); BOOL ReachedEOF = FALSE; /* Check for file overflow */ assert(Device_p != NULL); assert(DirEntry_p != NULL); assert(Pos_p != NULL); /* Check for file overflow */ if (DirEntry_p->Flags & FILE_FLAG_CYCLIC_FILE) { /* Cyclic file */ U32 TopDiff = 0; U64 TopPos; U32 ReadDiff = 0; U64 ReadPos; /* Get the distance to the top of file */ stavfs_GetPos(Device_p, Pos_p, &TopPos); if (TopPos.LSW > DirEntry_p->Size.Cyclic.TopOffset) { TopDiff = DirEntry_p->AllocSize.LSW * Device_p->ClusterSize * DISK_SECTOR_SIZE; TopDiff -= TopPos.LSW; TopDiff += DirEntry_p->Size.Cyclic.TopOffset; } else { TopDiff = DirEntry_p->Size.Cyclic.TopOffset; TopDiff -= TopPos.LSW; } /* Get the distance from the top of file to the read position */ stavfs_GetPos(Device_p, &(FileHandle_p->Read), &ReadPos); if (ReadPos.LSW <= DirEntry_p->Size.Cyclic.TopOffset) { ReadDiff = DirEntry_p->AllocSize.LSW * Device_p->ClusterSize * DISK_SECTOR_SIZE; ReadDiff -= DirEntry_p->Size.Cyclic.TopOffset; ReadDiff += ReadPos.LSW; } else { ReadDiff = ReadPos.LSW; ReadDiff -= DirEntry_p->Size.Cyclic.TopOffset; } /* The vailable space is the sum of TopDiff and ReadDiff -1 */ /* But this may be > 2^32 and therefore wrap */ /* Check that we have space for the read */ if ((ReadDiff <= Size) && (TopDiff <= (Size - ReadDiff))) { /* We have overflowed */ ReachedEOF = TRUE; } } /* If there is any data to write then write it to disk */ if ((Size > 0) && (Error == ST_NO_ERROR)) { U32 WriteSectors = 0; U32 ThisSize; U64 LBA; /* Write within the first sector */ if (0 != (Offset = Pos_p->Offset%DISK_SECTOR_SIZE)) { /* Get the Sectors LBA */ INT_I64_AddLit(Pos_p->BlockLBA, Pos_p->Offset/DISK_SECTOR_SIZE, LBA); /* Are we reading only part of the sector */ ThisSize = DISK_SECTOR_SIZE - Pos_p->Offset%DISK_SECTOR_SIZE; if (Size < ThisSize) { ThisSize = Size; } /* Read the data */ if (ST_NO_ERROR != stavfs_SetRWBuffer(Device_p, &LBA, &(Pos_p->Buffer), StreamFile)) { Error = STAVFS_ERROR_UNREADABLE_DISK; } else if (ST_NO_ERROR != stavfs_RWBufferWrite(Device_p, Pos_p->Buffer, Offset, ThisSize, Address, FALSE)) { Error = STAVFS_ERROR_UNWRITABLE_DISK; } else { Size -= ThisSize; Address += ThisSize; Pos_p->Offset += ThisSize; WrittenData += ThisSize; } } /* Write Blocks */ WriteSectors = Size/DISK_SECTOR_SIZE; if ((WriteSectors > 0) && (Error == ST_NO_ERROR)) { /* We no longer need the buffer */ if (ST_NO_ERROR != stavfs_DiscardRWBuffer(Device_p, &(Pos_p->Buffer))) { Error = STAVFS_ERROR_UNWRITABLE_DISK; } } while ((WriteSectors > 0) && (Error == ST_NO_ERROR)) { U32 ThisSectors; /* Ensure that we have space to write to */ Error = stavfs_MoreDiskSpace(FileHandle_p, Pos_p, TRUE, Size); if (Error == ST_NO_ERROR) { /* Get the Sectors LBA */ ThisSectors = Pos_p->BlockSize*Device_p->ClusterSize - Pos_p->Offset/DISK_SECTOR_SIZE; INT_I64_AddLit(Pos_p->BlockLBA, Pos_p->Offset/DISK_SECTOR_SIZE, LBA); /* Are we reading only part of the sectors */ if (WriteSectors < ThisSectors) { ThisSectors = WriteSectors; } /* Read the data */ if (ST_NO_ERROR != stavfs_RWCacheBlockWrite (Device_p, &LBA, ThisSectors, Address, StreamFile)) { Error = STAVFS_ERROR_UNWRITABLE_DISK; } else { WriteSectors -= ThisSectors; Size -= ThisSectors*DISK_SECTOR_SIZE; Address += ThisSectors*DISK_SECTOR_SIZE; Pos_p->Offset += ThisSectors*DISK_SECTOR_SIZE; WrittenData += ThisSectors*DISK_SECTOR_SIZE; } } } /* Read within the last sector */ if ((Size > 0) && (Error == ST_NO_ERROR)) { BOOL EndOfFile = FALSE; if (!(DirEntry_p->Flags & FILE_FLAG_CYCLIC_FILE)) { /* Only for regular files */ stavfs_GetPos(Device_p, Pos_p, &FilePos); EndOfFile = I64_IsLessThan(DirEntry_p->Size.File, FilePos); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -