This commit is contained in:
Pavel 2025-07-29 12:49:05 +03:00
parent 97f8794849
commit 4339cac86f
2 changed files with 255 additions and 6 deletions

View File

@ -18,12 +18,14 @@ procedure InitMount(GameStartupInfo:TGameStartupInfo);
function TemporaryDataMount (mountPoint:pchar;format:Boolean):Integer;
function TemporaryDataUnmount(mountPoint:pchar):Integer;
function TemporaryDataFormat (mountPoint:pchar):Integer;
function TemporaryDataGetAvailableSpaceKb(mountPoint:pchar;availableSpaceKb:PQWORD):Integer;
implementation
uses
sysutils,
fileutil,
LazFileUtils,
strings,
errno,
kern_mtx,
@ -326,6 +328,219 @@ begin
FileClose(F);
end;
function DeleteDirectory(const DirectoryName: RawByteString; OnlyChildren: boolean): boolean;
type
PNode=^TNode;
TNode=record
N:PNode;
S:RawByteString;
B:Boolean;
end;
var
stack:PNode;
procedure Push(const S:RawByteString;B:Boolean); inline;
var
new:PNode;
begin
new:=GetMem(SizeOf(TNode));
new^.N:=stack;
new^.S:=S;
new^.B:=B;
stack:=new;
end;
Function Pop(var S:RawByteString;var B:Boolean):Boolean; inline;
var
old:PNode;
begin
if (stack<>nil) then
begin
old:=stack;
stack:=old^.N;
S:=old^.S;
B:=old^.B;
Finalize(old);
FreeMem(old);
Result:=True;
end else
begin
Result:=False;
end;
end;
const
//Don't follow symlinks on *nix, just delete them
DeleteMask = faAnyFile {$ifdef unix} or faSymLink{%H-} {$endif unix};
var
FileInfo: TSearchRec;
CurSrcDir: RawByteString;
CurFilename: RawByteString;
label
_next;
begin
Result:=false;
CurSrcDir:=CleanAndExpandDirectory(DirectoryName);
stack:=nil;
_next:
if SysUtils.FindFirst(CurSrcDir+GetAllFilesMask,DeleteMask,FileInfo)=0 then
begin
repeat
// check if special file
if (FileInfo.Name='.') or (FileInfo.Name='..') or (FileInfo.Name='') then
begin
continue;
end;
CurFilename:=CurSrcDir+FileInfo.Name;
if ((FileInfo.Attr and faDirectory)>0)
{$ifdef unix} and ((FileInfo.Attr and faSymLink{%H-})=0) {$endif unix} then
begin
Push(CurSrcDir,OnlyChildren);
CurSrcDir:=CleanAndExpandDirectory(CurFilename);
OnlyChildren:=False;
SysUtils.FindClose(FileInfo);
goto _next;
end else
begin
if not SysUtils.DeleteFile(CurFilename) then exit;
end;
until SysUtils.FindNext(FileInfo)<>0;
SysUtils.FindClose(FileInfo);
end;
if (not OnlyChildren) then
begin
if (not SysUtils.RemoveDir(CurSrcDir)) then exit;
end;
if Pop(CurSrcDir,OnlyChildren) then
begin
goto _next;
end;
Result:=true;
end;
function GetDirectorySizeLikePFS(const DirectoryName:RawByteString):Int64;
type
PNode=^TNode;
TNode=record
N:PNode;
S:RawByteString;
F:TSearchRec;
end;
var
stack:PNode;
procedure Push(const S:RawByteString;const F:TSearchRec); inline;
var
new:PNode;
begin
new:=GetMem(SizeOf(TNode));
new^.N:=stack;
new^.S:=S;
new^.F:=F;
stack:=new;
end;
Function Pop(var S:RawByteString;var F:TSearchRec):Boolean; inline;
var
old:PNode;
begin
if (stack<>nil) then
begin
old:=stack;
stack:=old^.N;
S:=old^.S;
F:=old^.F;
Finalize(old);
FreeMem(old);
Result:=True;
end else
begin
Result:=False;
end;
end;
function AlignUp(addr:Int64;alignment:Int64):Int64; inline;
var
tmp:Int64;
begin
if (alignment=0) then Exit(addr);
tmp:=addr+Int64(alignment-1);
Result:=tmp-(tmp mod alignment);
end;
const
//Don't follow symlinks on *nix, just delete them
FindMask = faAnyFile {$ifdef unix} or faSymLink{%H-} {$endif unix};
var
files_size :Int64;
inode_count:Int64;
dirent_size:Int64;
//
FileInfo: TSearchRec;
CurSrcDir: RawByteString;
CurFilename: RawByteString;
const
c_block_size =4*1024; //????
c_dirent_size=16;
c_inode_size =168;
c_inodes_per_block=c_block_size div c_inode_size;
label
_down,
_next;
begin
Result:=0;
files_size :=0;
inode_count:=0;
dirent_size:=0;
CurSrcDir:=CleanAndExpandDirectory(DirectoryName);
stack:=nil;
_down:
if SysUtils.FindFirst(CurSrcDir+GetAllFilesMask,FindMask,FileInfo)=0 then
begin
repeat
// check if special file
if (FileInfo.Name='.') or (FileInfo.Name='..') or (FileInfo.Name='') then
begin
continue;
end;
//
CurFilename:=CurSrcDir+FileInfo.Name;
//
inode_count:=inode_count+1;
dirent_size:=dirent_size+AlignUp(c_dirent_size+Length(FileInfo.Name)+1,8);
//
if ((FileInfo.Attr and faDirectory)>0)
{$ifdef unix} and ((FileInfo.Attr and faSymLink{%H-})=0) {$endif unix} then
begin
Push(CurSrcDir,FileInfo);
CurSrcDir:=CleanAndExpandDirectory(CurFilename);
goto _down;
end else
begin
files_size:=files_size+AlignUp(FileInfo.Size,c_block_size);
end;
//
_next:
until SysUtils.FindNext(FileInfo)<>0;
SysUtils.FindClose(FileInfo);
end;
if Pop(CurSrcDir,FileInfo) then
begin
goto _next;
end;
//Very approximate size
Result:=files_size+
AlignUp(dirent_size,c_block_size)+
AlignUp(inode_count,c_inodes_per_block)*c_block_size;
end;
function FormatMount(const fs_src:RawByteString):Integer;
begin
//Delete all content in directory
@ -423,5 +638,44 @@ begin
mtx_unlock(mount_mtx);
end;
function TemporaryDataGetAvailableSpaceKb(mountPoint:pchar;availableSpaceKb:PQWORD):Integer;
const
MAX_SIZE_KB=1*1024*1024;
var
size:QWORD;
fs_src:RawByteString;
begin
if (strlcomp(mountPoint,TEMP0,MOUNT_MAXSIZE)<>0) then Exit(ENOTDIR);
mtx_lock(mount_mtx);
if TemporaryMount then
begin
fs_src:=ExcludeTrailingPathDelimiter(g_LocalDir)+unix_to_host(APP_TEMP);
size:=GetDirectorySizeLikePFS(fs_src);
size:=size div 1024; //to KB
if (size>MAX_SIZE_KB) then
begin
size:=0;
end else
begin
size:=MAX_SIZE_KB-size;
end;
availableSpaceKb^:=size;
Result:=0;
end else
begin
Result:=ENOTDIR;
end;
mtx_unlock(mount_mtx);
end;
end.

View File

@ -244,12 +244,7 @@ begin
if not InitAppContent then Exit(SCE_APP_CONTENT_ERROR_NOT_INITIALIZED);
if (mountPoint=nil) or (availableSpaceKb=nil) then Exit(SCE_APP_CONTENT_ERROR_PARAMETER);
{
_sig_lock;
Result:=GetTmpPathAvailableSpaceKb(PChar(mountPoint),availableSpaceKb);
_sig_unlock;
}
Result:=-1;
Result:=px2ce(TemporaryDataGetAvailableSpaceKb(pchar(mountPoint),availableSpaceKb));
end;
function ps4_sceAppContentDownloadDataGetAvailableSpaceKb(mountPoint:pSceAppContentMountPoint;availableSpaceKb:PQWORD):Integer;