📄 file.c
字号:
Error = STAVFS_ERROR_OUT_OF_RANGE; } else if (WritePosition) { stavfs_SetPos(Device_p, DirEntry_p, &CurrentPos, &(FileHandle_p->Write)); } else { stavfs_SetPos(Device_p, DirEntry_p, &CurrentPos, &(FileHandle_p->Read)); } } return (Error);}/******************************************************************************Function Name : stavfs_SeekCyclicFile Description : Parameters :******************************************************************************/ST_ErrorCode_t stavfs_SeekCyclicFile (STAVFS_FileHandle_t Handle, S64 Position, STAVFS_TypePosition_t Mode, BOOL WritePosition){ ST_ErrorCode_t Error = ST_NO_ERROR; int FileId = (int)Handle; stavfs_OpenFileHandle_t *FileHandle_p = FileHandleTable+FileId; stavfs_Device_t *Device_p = FileHandle_p->Device_p; stavfs_DirEntry_t *DirEntry_p = FileHandle_p->DirEntry_p; U64 CurrentPos; U64 BuffSize; /* Size of the cyclic buffer in bytes */ U64 Offset; /* Offset into the buffer */ assert (FileHandle_p->Device_p != NULL); assert (FileHandle_p->DirEntry_p != NULL); /* Set the offset */ I64_SetValue(DirEntry_p->Size.Cyclic.TopOffset, 0, Offset); /* Get the file size in bytes */ INT_I64_MulLit(DirEntry_p->AllocSize, Device_p->ClusterSize, BuffSize); /* Multiply by sector size */ I64_ShiftLeft(9, BuffSize); /* Move relative to a given position */ if (Error == ST_NO_ERROR) { switch (Mode) { case STAVFS_START : { /* * We have a lot of wrapping issues. So we calculate an unwrapped * and wrapped base and check for a valid offset against both. */ U64 Base; U64 Diff; U64 One = {1, 0}; /* Calculate the unwrapped base */ INT_I64_MulLit(DirEntry_p->AllocSize, DirEntry_p->Size.Cyclic.LoopCount-1, Base); INT_I64_MulLit(Base, Device_p->ClusterSize, Base); /* Multiply by the sector size */ I64_ShiftLeft(9, Base); /* Get the offset */ I64_Sub(Position, Base, CurrentPos); /* Check it is in range */ I64_Sub(CurrentPos, Offset, Diff); /* * We can go to the last byte but not the first * So zero diff is not valid. */ I64_Sub(Diff, One, Diff); /* Because this is an unsigned comparison */ /* negative values will also be out of range */ if (I64_IsLessThan(Diff, BuffSize)) { /* We are in range */ } else { /* We could be out of range */ /* Calculate the wrapped base */ INT_I64_MulLit(DirEntry_p->AllocSize, DirEntry_p->Size.Cyclic.LoopCount, Base); INT_I64_MulLit(Base, Device_p->ClusterSize, Base); /* Multiply by the sector size */ I64_ShiftLeft(9, Base); /* Get the offset */ I64_Sub(Position, Base, CurrentPos); I64_Add(CurrentPos, BuffSize, CurrentPos); /* Check it is in range */ I64_Sub(CurrentPos, Offset, Diff); /* * We can go to the last byte but not the first * So zero diff is not valid. */ I64_Sub(Diff, One, Diff); /* Because this is an unsigned comparison */ /* negative values will also be out of range */ if (I64_IsLessThan(Diff, BuffSize)) { /* We are in range */ } else { /* We are out of range */ Error = STAVFS_ERROR_OUT_OF_RANGE; } } } break; case STAVFS_END : if (I64_IsLessThan(Position, BuffSize)) { /* Get the position relative to the offset */ I64_Add(Position, Offset, CurrentPos); } else { Error = STAVFS_ERROR_OUT_OF_RANGE; } I64_Sub(Offset, Position, CurrentPos); break; case STAVFS_CURRENT : { U64 Diff; if (WritePosition) { /* Get the write offset */ Error = stavfs_GetPos(Device_p, &(FileHandle_p->Write), &CurrentPos); } else { /* Get the read offset */ Error = stavfs_GetPos(Device_p, &(FileHandle_p->Read), &CurrentPos); } /* Are we going backwards */ if (I64_IsNegative(Position)) { /* Going backwards (We are working with negative numbers) */ /* Get the position relative to the offset */ I64_Sub(Offset, CurrentPos, Diff); if (!I64_IsNegative(Diff)) { I64_Sub(Diff, BuffSize, Diff); } /* Check for any wrapping */ if (I64_IsLessThan(Diff, Position)) { /* In range */ I64_Add(CurrentPos, Position, CurrentPos); } else { Error = STAVFS_ERROR_OUT_OF_RANGE; } } else { /* Going forwards */ /* Get the position relative to the offset */ I64_Sub(Offset, CurrentPos, Diff); if (I64_IsNegative(Diff)) { I64_Add(Diff, BuffSize, Diff); } /* Check for any wrapping */ if (I64_IsGreaterOrEqual(Diff, Position)) { /* In range */ I64_Add(CurrentPos, Position, CurrentPos); } else { Error = STAVFS_ERROR_OUT_OF_RANGE; } } } break; default : Error = ST_ERROR_BAD_PARAMETER; break; } } /* Set the position */ if (Error == ST_NO_ERROR) { /* Check for wrapping */ if (I64_IsNegative(CurrentPos)) { I64_Add(CurrentPos, BuffSize, CurrentPos); } else if (I64_IsGreaterOrEqual(CurrentPos, BuffSize)) { I64_Sub(CurrentPos, BuffSize, CurrentPos); } /* Set the loop count */ if (WritePosition) { if (I64_IsLessThan(Offset, CurrentPos)) { FileHandle_p->LoopCount = DirEntry_p->Size.Cyclic.LoopCount -1; } else { FileHandle_p->LoopCount = DirEntry_p->Size.Cyclic.LoopCount; } } /* Set the file position */ if (WritePosition) { stavfs_SetPos(Device_p, DirEntry_p, &CurrentPos, &(FileHandle_p->Write)); } else { stavfs_SetPos(Device_p, DirEntry_p, &CurrentPos, &(FileHandle_p->Read)); } } return (Error);}/******************************************************************************Function Name : stavfs_AllocDiskSpace Description : Allocate more space to the file. Parameters :******************************************************************************/static ST_ErrorCode_t stavfs_AllocDiskSpace(stavfs_Device_t *Device_p, stavfs_DirEntry_t *DirEntry_p, U64 Size){ ST_ErrorCode_t Error = ST_NO_ERROR; int AllocationUnits = 1; U64 PrevLBA; U64 FreeLBA; assert(Device_p != NULL); assert(DirEntry_p != NULL); if (DirEntry_p->Flags & FILE_FLAG_STREAM_MODE) { /* Allocate Cluster Blocks */ AllocationUnits = CLUSTERS_PER_BLOCK(Device_p); } else { /* Allocate Clusters */ AllocationUnits = 1; } /* Find the end of the File allocation chain */ PrevLBA = DirEntry_p->EndLBA; if (ST_NO_ERROR != (Error = stavfs_WalkTheChain(Device_p, FALSE, &PrevLBA, NULL))) { } else if (0 == stavfs_GetFreeClusters(Device_p, AllocationUnits, &(PrevLBA), &(FreeLBA))) { /* No space available */ STTBX_Print(("Failed to find free disk space\n")); Error = STAVFS_ERROR_DISK_FULL; } else { /* Are we appending */ if (INT_I64_AreEqual(NullLBA, DirEntry_p->StartLBA)) { /* First allocation to file. We must link the on-disk directory entry to the chain before we allocate any cluster, in order that things can be recovered in the event of a crash */ stavfs_ModifyDirEntry(Device_p, DirEntry_p); DirEntry_p->StartLBA = FreeLBA; DirEntry_p->EndLBA = FreeLBA; PrevLBA = NullLBA; Error = stavfs_FlushDir(Device_p, NULL); } if (Error == ST_NO_ERROR) { U32 RequiredSize = 0; U32 AllocatedSize = 0; U32 Round = 0; /* Rescale Size to Sectors */ if (Size.LSW & 0X000001FF) { Round = 1; } else { Round = 0; } /* Divide by the sector size */ I64_ShiftRight(9, Size); RequiredSize += Size.LSW +Round; /* Rescale to Allocation units */ if (RequiredSize % (AllocationUnits * Device_p->ClusterSize)) { Round = 1; } else { Round = 0; } RequiredSize = RequiredSize/(AllocationUnits * Device_p->ClusterSize) + Round; /* Allocate the required space */ /* Impose a minimum size */ if (0 == RequiredSize) { RequiredSize = 1; } /* In Clusters */ RequiredSize *= AllocationUnits; AllocatedSize = stavfs_AllocFreeClusters (Device_p, RequiredSize, AllocationUnits, &(PrevLBA), &(FreeLBA)); RequiredSize -= AllocatedSize; if (AllocatedSize != 0) { /* We allocated something */ stavfs_ModifyDirEntry(Device_p, DirEntry_p); DirEntry_p->EndLBA = PrevLBA; INT_I64_AddLit(DirEntry_p->AllocSize, AllocatedSize, DirEntry_p->AllocSize); } if (RequiredSize != 0) { /* Not all space allocated */ Error = STAVFS_ERROR_DISK_FULL; } } } return (Error);}/***********************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -