diff options
| author | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2008-06-07 20:34:49 +0200 |
|---|---|---|
| committer | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2008-06-07 20:34:49 +0200 |
| commit | ecde167da74c86bc047aaf84c5e548cf65a5da98 (patch) | |
| tree | a015dfda84f28a65811e3aa0d369f8f211ec8c60 /vfs/UVFSCore.pas | |
| download | tuxcmd-ecde167da74c86bc047aaf84c5e548cf65a5da98.tar.xz | |
Initial commitv0.6.36release-0.6.36-dev
Diffstat (limited to 'vfs/UVFSCore.pas')
| -rw-r--r-- | vfs/UVFSCore.pas | 1075 |
1 files changed, 1075 insertions, 0 deletions
diff --git a/vfs/UVFSCore.pas b/vfs/UVFSCore.pas new file mode 100644 index 0000000..21fc21b --- /dev/null +++ b/vfs/UVFSCore.pas @@ -0,0 +1,1075 @@ +(* + Tux Commander - UVFSCore - VFS Core utilities and management + Copyright (C) 2007 Tomas Bzatek <tbzatek@users.sourceforge.net> + Check for updates on tuxcmd.sourceforge.net + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +*) +unit UVFSCore; + +{$IFDEF __FPC__} + {$M+} +{$ENDIF} + +interface + +uses GTKForms, Libc, {$IFDEF KYLIX}UGlibC_compat,{$ENDIF} Classes, uVFSprototypes, UEngines, UCoreUtils; + + +type + TVFSPlugin = class + private + FVFSAllocNeeded: TVFSAllocNeeded; + FVFSInit: TVFSInit; + FVFSDestroy: TVFSDestroy; + FVFSVersion: TVFSVersion; + FVFSGetInfo: TVFSGetInfo; + FVFSOpen: TVFSOpen; + FVFSClose: TVFSClose; + FVFSListFirst: TVFSListFirst; + FVFSListNext: TVFSListNext; + FVFSListClose: TVFSListClose; + FVFSChangeDir: TVFSChangeDir; + FVFSGetPath: TVFSGetPath; + FVFSGetPrefix: TVFSGetPrefix; + FVFSGetFileSystemSize: TVFSGetFileSystemSize; + FVFSGetFileSystemFree: TVFSGetFileSystemFree; + FVFSLogin: TVFSLogin; + FVFSFileExists: TVFSFileExists; + FVFSFileInfo: TVFSFileInfo; + FVFSMkDir: TVFSMkDir; + FVFSRemove: TVFSRemove; + FVFSRename: TVFSRename; + FVFSMakeSymLink: TVFSMakeSymLink; + FVFSChmod: TVFSChmod; + FVFSChown: TVFSChown; + FVFSChangeTimes: TVFSChangeTimes; + FVFSGetDirSize: TVFSGetDirSize; + FVFSBreakGetDirSize: TVFSBreakGetDirSize; + FVFSOpenFile: TVFSOpenFile; + FVFSReadFile: TVFSReadFile; + FVFSWriteFile: TVFSWriteFile; + FVFSCloseFile: TVFSCloseFile; + FVFSFileSeek: TVFSFileSeek; + FVFSSetBlockSize: TVFSSetBlockSize; + FVFSCopyOut: TVFSCopyOut; + FVFSCopyIn: TVFSCopyIn; + FVFSIsOnSameFS: TVFSIsOnSameFS; + FVFSTwoSameFiles: TVFSTwoSameFiles; + FVFSGetExts: TVFSGetExts; + FVFSGetServices: TVFSGetServices; + FVFSSetPassword: TVFSSetPassword; + FVFSGetPasswordRequired: TVFSGetPasswordRequired; + public + ModuleHandle: Pointer; + FullPath: string; // module path + Extensions, Services: TOpenStringArray; // the list of the extensions plugin can handle + constructor Create(PluginHandle: Pointer); + destructor Destroy; override; + published + function VFSVersion: integer; + function VFSName: PChar; + function VFSDescription: PChar; + function VFSAbout: PChar; + function VFSCopyright: PChar; + end; + + + TVFSEngine = class(TPanelEngine) + private + FGlobs: Pointer; + FSourcePlugin: TVFSPlugin; + FBlockSize: Cardinal; + FProgressFunc: TEngineProgressFunc; + FSenderThread: Pointer; + BreakProcessingKind: integer; + FPassword: string; + procedure SetFPassword(Value: string); + public + ArchiveMode: boolean; + constructor Create(SourcePlugin: TVFSPlugin); + function VFSOpenURI(OpenFile: string): boolean; + function VFSOpenEx(OpenFile: string): TVFSResult; + function VFSClose: boolean; + + destructor Destroy; override; + function GetListing(var List: TList; const AddDotFiles: boolean): integer; override; + function GetListing(var List: TList; const AddDotFiles: boolean; APath: string): integer; override; + function ChangeDir(const NewPath: string; const ShowProgress: boolean = True): integer; override; + function ExplicitChDir(const NewPath: string): integer; override; + function GetFileSystemSize: Int64; override; + function GetFileSystemSize(const APath: string): Int64; override; + function GetFileSystemFree: Int64; override; + function GetFileSystemFree(const APath: string): Int64; override; + function MakeDir(const NewDir: string): integer; override; + function GetDirSize(APath: string): Int64; override; + function Remove(APath: string): integer; override; + procedure FillDirFiles(APath: string; List: TList; ALevel: word); override; + function GetFileInfoSL(APath: string): PDataItemSL; override; + function FileExists(const FileName: string; const Use_lstat: boolean = False): Boolean; override; + function DirectoryExists(const FileName: string; const Use_lstat: boolean = False): Boolean; override; + function MakeSymLink(const NewFileName, PointTo: string): integer; override; + function Chmod(const FileName: string; const Mode: integer): integer; override; + function Chown(const FileName: string; const UID, GID: integer): integer; override; + procedure BreakProcessing(ProcessingKind: integer); override; + function RenameFile(SourceFile, DestFile: string): integer; override; + function ChangeTimes(APath: string; mtime, atime: Int64): integer; override; + procedure GetFileSystemInfo(const APath: string; var FSSize, FSFree: Int64; var FSName: string); override; + function OpenFile(const APath: string; Mode: integer; var Error: integer): TEngineFileDes; override; + function ReadFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; ABlockSize: integer; var Error: integer): integer; override; + function WriteFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; BytesCount: integer; var Error: integer): integer; override; + function CloseFile(const FileDescriptor: TEngineFileDes): integer; override; + function FileSeek(const FileDescriptor: TEngineFileDes; const AbsoluteOffset: Int64; var Error: integer): Int64; override; + function IsOnROMedium(const FileName: string): boolean; override; + function FileCanRun(const FileName: string): boolean; override; + function GetPath: string; override; + procedure SetPath(Value: string); override; + function GetPrefix: string; override; + function Login(Username, Password: string): integer; override; + + function GetBlockSize: Cardinal; override; + procedure SetBlockSize(Value: Cardinal); override; + function CopyFileIn(Sender: Pointer; SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; override; + function CopyFileOut(Sender: Pointer; SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; override; + function IsOnSameFS(const Path1, Path2: string): boolean; override; + function TwoSameFiles(const Path1, Path2: string): boolean; override; + + function SetPassword(Password: string): integer; + function GetPasswordRequired: boolean; + published + property Path: string read GetPath write SetPath; + property BlockSize: Cardinal read GetBlockSize write SetBlockSize; + property Password: string read FPassword write SetFPassword; + end; + + + +procedure DoInitPlugins; + +var PluginList: TList; + +implementation + +uses SysUtils, ModuleLoader, UConfig, ULocale; + + +const ConstGlobalModulePath1 = '/usr/lib/tuxcmd'; + ConstGlobalModulePath2 = '/usr/local/lib/tuxcmd'; + ConstLocalModulePath1 = '~/.tuxcmd/plugins'; + ConstLocalModulePath2 = './plugins'; + ConstLocalModulePath3 = '../lib/tuxcmd'; + + ConstVFSVersionRequired = 2; + +var BinaryPath: string; + + +procedure VFSLogFunc(s: PChar); cdecl; +begin + DebugMsg([' ### VFS ###: ', s]); +end; + +(********************************************************************************************************************************) +constructor TVFSPlugin.Create(PluginHandle: Pointer); +begin + inherited Create; + ModuleHandle := PluginHandle; + + // Find the symbols + @FVFSAllocNeeded := GetModuleSymbol(ModuleHandle, 'VFSAllocNeeded'); + @FVFSInit := GetModuleSymbol(ModuleHandle, 'VFSInit'); + @FVFSDestroy := GetModuleSymbol(ModuleHandle, 'VFSDestroy'); + @FVFSVersion := GetModuleSymbol(ModuleHandle, 'VFSVersion'); + @FVFSGetInfo := GetModuleSymbol(ModuleHandle, 'VFSGetInfo'); + @FVFSOpen := GetModuleSymbol(ModuleHandle, 'VFSOpen'); + @FVFSClose := GetModuleSymbol(ModuleHandle, 'VFSClose'); + @FVFSListFirst := GetModuleSymbol(ModuleHandle, 'VFSListFirst'); + @FVFSListNext := GetModuleSymbol(ModuleHandle, 'VFSListNext'); + @FVFSListClose := GetModuleSymbol(ModuleHandle, 'VFSListClose'); + @FVFSGetPath := GetModuleSymbol(ModuleHandle, 'VFSGetPath'); + @FVFSChangeDir := GetModuleSymbol(ModuleHandle, 'VFSChangeDir'); + @FVFSGetPrefix := GetModuleSymbol(ModuleHandle, 'VFSGetPrefix'); + @FVFSGetFileSystemSize := GetModuleSymbol(ModuleHandle, 'VFSGetFileSystemSize'); + @FVFSGetFileSystemFree := GetModuleSymbol(ModuleHandle, 'VFSGetFileSystemFree'); + @FVFSLogin := GetModuleSymbol(ModuleHandle, 'VFSLogin'); + @FVFSFileExists := GetModuleSymbol(ModuleHandle, 'VFSFileExists'); + @FVFSFileInfo := GetModuleSymbol(ModuleHandle, 'VFSFileInfo'); + @FVFSMkDir := GetModuleSymbol(ModuleHandle, 'VFSMkDir'); + @FVFSRemove := GetModuleSymbol(ModuleHandle, 'VFSRemove'); + @FVFSRename := GetModuleSymbol(ModuleHandle, 'VFSRename'); + @FVFSMakeSymLink := GetModuleSymbol(ModuleHandle, 'VFSMakeSymLink'); + @FVFSChmod := GetModuleSymbol(ModuleHandle, 'VFSChmod'); + @FVFSChown := GetModuleSymbol(ModuleHandle, 'VFSChown'); + @FVFSChangeTimes := GetModuleSymbol(ModuleHandle, 'VFSChangeTimes'); + @FVFSGetDirSize := GetModuleSymbol(ModuleHandle, 'VFSGetDirSize'); + @FVFSBreakGetDirSize := GetModuleSymbol(ModuleHandle, 'VFSBreakGetDirSize'); + @FVFSCopyOut := GetModuleSymbol(ModuleHandle, 'VFSCopyOut'); + @FVFSCopyIn := GetModuleSymbol(ModuleHandle, 'VFSCopyIn'); + @FVFSOpenFile := GetModuleSymbol(ModuleHandle, 'VFSOpenFile'); + @FVFSReadFile := GetModuleSymbol(ModuleHandle, 'VFSReadFile'); + @FVFSWriteFile := GetModuleSymbol(ModuleHandle, 'VFSWriteFile'); + @FVFSCloseFile := GetModuleSymbol(ModuleHandle, 'VFSCloseFile'); + @FVFSFileSeek := GetModuleSymbol(ModuleHandle, 'VFSFileSeek'); + @FVFSSetBlockSize := GetModuleSymbol(ModuleHandle, 'VFSSetBlockSize'); + @FVFSIsOnSameFS := GetModuleSymbol(ModuleHandle, 'VFSIsOnSameFS'); + @FVFSTwoSameFiles := GetModuleSymbol(ModuleHandle, 'VFSTwoSameFiles'); + @FVFSGetExts := GetModuleSymbol(ModuleHandle, 'VFSGetExts'); + @FVFSGetServices := GetModuleSymbol(ModuleHandle, 'VFSGetServices'); + @FVFSSetPassword := GetModuleSymbol(ModuleHandle, 'VFSSetPassword'); + @FVFSGetPasswordRequired := GetModuleSymbol(ModuleHandle, 'VFSGetPasswordRequired'); + // Initialize the extensions list + SetLength(Extensions, 0); + SetLength(Services, 0); + if @FVFSGetExts <> nil then ParseString(FVFSGetExts, ';', Extensions); + if @FVFSGetServices <> nil then ParseString(FVFSGetServices, ';', Services); +end; + +destructor TVFSPlugin.Destroy; +begin + if ModuleHandle <> nil then UnloadModule(ModuleHandle); + inherited Destroy; +end; + +(********************************************************************************************************************************) +function TVFSPlugin.VFSVersion: integer; +begin + if @FVFSVersion <> nil then Result := FVFSVersion + else Result := -1; +end; + +function TVFSPlugin.VFSName: PChar; +var Info: TVFSInfo; +begin + if @FVFSGetInfo <> nil then begin + Info := FVFSGetInfo; + Result := Info.Name; + end else Result := nil; +end; + +function TVFSPlugin.VFSDescription: PChar; +var Info: TVFSInfo; +begin + if @FVFSGetInfo <> nil then begin + Info := FVFSGetInfo; + Result := Info.Description; + end else Result := nil; +end; + +function TVFSPlugin.VFSAbout: PChar; +var Info: TVFSInfo; +begin + if @FVFSGetInfo <> nil then begin + Info := FVFSGetInfo; + Result := Info.About; + end else Result := nil; +end; + +function TVFSPlugin.VFSCopyright: PChar; +var Info: TVFSInfo; +begin + if @FVFSGetInfo <> nil then begin + Info := FVFSGetInfo; + Result := Info.Copyright; + end else Result := nil; +end; + +(********************************************************************************************************************************) +(********************************************************************************************************************************) +constructor TVFSEngine.Create(SourcePlugin: TVFSPlugin); +begin + inherited Create; + FSourcePlugin := SourcePlugin; + FBlockSize := 65536; + ArchiveMode := False; + BreakProcessingKind := 0; + if @FSourcePlugin.FVFSAllocNeeded <> nil then begin + FGlobs := Libc.malloc(FSourcePlugin.FVFSAllocNeeded); + Libc.memset(FGlobs, 0, FSourcePlugin.FVFSAllocNeeded); + end else begin + FGlobs := Libc.malloc(SizeOf(FGlobs)); + Libc.memset(FGlobs, 0, SizeOf(FGlobs)); + end; + +{$IFNDEF KYLIX} + DebugMsg(['sizeof(TVFSItem) = ', sizeof(TVFSItem)]); + DebugMsg(['sizeof(TVFSItem.sFileName) = ', sizeof(TVFSItem.sFileName)]); + DebugMsg(['sizeof(TVFSItem.iSize) = ', sizeof(TVFSItem.iSize)]); + DebugMsg(['sizeof(TVFSItem.m_time) = ', sizeof(TVFSItem.m_time)]); + DebugMsg(['sizeof(TVFSItem.a_time) = ', sizeof(TVFSItem.a_time)]); + DebugMsg(['sizeof(TVFSItem.c_time) = ', sizeof(TVFSItem.c_time)]); + DebugMsg(['sizeof(TVFSItem.iMode) = ', sizeof(TVFSItem.iMode)]); + DebugMsg(['sizeof(TVFSItem.sLinkTo) = ', sizeof(TVFSItem.sLinkTo)]); + DebugMsg(['sizeof(TVFSItem.iUID) = ', sizeof(TVFSItem.iUID)]); + DebugMsg(['sizeof(TVFSItem.iGID) = ', sizeof(TVFSItem.iGID)]); + DebugMsg(['sizeof(TVFSItem.ItemType) = ', sizeof(TVFSItem.ItemType)]); +{$ENDIF} + + if @FSourcePlugin.FVFSInit <> nil then FSourcePlugin.FVFSInit(FGlobs, @VFSLogFunc); + FPassword := ''; +end; + +function TVFSEngine.VFSOpenURI(OpenFile: string): boolean; +begin + Result := False; + if @FSourcePlugin.FVFSOpen <> nil then Result := FSourcePlugin.FVFSOpen(FGlobs, PChar(OpenFile)) = cVFS_OK; +end; + +function TVFSEngine.VFSOpenEx(OpenFile: string): TVFSResult; +begin + Result := cVFS_OK; + if @FSourcePlugin.FVFSOpen <> nil then Result := FSourcePlugin.FVFSOpen(FGlobs, PChar(OpenFile)); +end; + +function TVFSEngine.VFSClose: boolean; +begin + Result := False; + if @FSourcePlugin.FVFSClose <> nil then Result := FSourcePlugin.FVFSClose(FGlobs) = cVFS_OK; +end; + +destructor TVFSEngine.Destroy; +begin + try + if @FSourcePlugin.FVFSDestroy <> nil then FSourcePlugin.FVFSDestroy(FGlobs); + libc.free(FGlobs); + except + on E: Exception do DebugMsg(['*** TVFSEngine.Destroy() -Exception: ', E.Message]); + end; +end; + +function TVFSEngine.GetListing(var List: TList; const AddDotFiles: boolean; APath: string): integer; +var P: PVFSItem; + Item: PDataItem; + i, Res: integer; +begin + DebugMsg(['^^VFS (II): GetListing begin']); + Result := 0; + try + if @FSourcePlugin.FVFSListFirst = nil then Exit; + P := Libc.malloc(SizeOf(TVFSItem)); + Libc.memset(P, 0, SizeOf(TVFSItem)); +// DebugMsg(['Item = ', Int64(P)]); +// DebugMsg(['FVFSListFirst']); + Res := FSourcePlugin.FVFSListFirst(FGlobs, PChar(APath), P); + if Res <> cVFS_OK then begin + FSourcePlugin.FVFSListClose(FGlobs); + if Res = cVFS_Not_More_Files then Result := 0 + else Result := Res; + Libc.free(P); + Exit; + end; + + repeat +// DebugMsg(['begin--']); + if AddDotFiles or (not ((Length(P^.sFileName) > 1) and (P^.sFileName[0] = '.') and (P^.sFileName[1] <> '.'))) then begin +// DebugMsg(['Checkpoint 1']); + Item := Libc.malloc(SizeOf(TDataItem)); + Libc.memset(Item, 0, SizeOf(TDataItem)); +// DebugMsg(['Checkpoint 2']); + for i := 0 to Length(Item^.ColumnData) - 1 do Item^.ColumnData[i] := nil; +// DebugMsg(['Checkpoint 3']); + with Item^ do + try + AName := strdup(P^.sFileName); + if P^.sLinkTo <> nil + then begin + LnkPointTo := strdup(P^.sLinkTo); + DebugMsg(['LnkPointTo = ', P^.sLinkTo]); + end else LnkPointTo := nil; + Mode := P^.iMode; +// DebugMsg(['Checkpoint 4']); + IsDotFile := (Length(AName) > 1) and (AName[0] = '.') and (AName[1] <> '.'); + IsDir := TVFSItemType(P^.ItemType) = vDirectory; + IsLnk := TVFSItemType(P^.ItemType) = vSymlink; + IsBlk := TVFSItemType(P^.ItemType) = vBlockdev; + IsChr := TVFSItemType(P^.ItemType) = vChardev; + IsFIFO := TVFSItemType(P^.ItemType) = vFifo; + IsSock := TVFSItemType(P^.ItemType) = vSock; +// DebugMsg(['Checkpoint 5']); + ModifyTime := UnixTimeToTDateTime(P^.m_time); +// DebugMsg(['Returned datetime: ', Longword(P^.m_time)]); +// DebugMsg(['Checkpoint 6']); + UID := P^.iUID; +// DebugMsg(['Checkpoint 7']); + GID := P^.iGID; +// DebugMsg(['Checkpoint 8']); + UpDir := False; +// DebugMsg(['Checkpoint 9']); + Selected := False; +// DebugMsg(['Checkpoint 10']); + Size := P^.iSize; +// DebugMsg(['Checkpoint 11']); + List.Add(Item); +// DebugMsg(['Checkpoint 12']); + except + on E: Exception do + DebugMsg(['^^VFS (EE): GetListing: Item-Exception: ', E.Message]); + end; + end; // of if AddDotFiles + Libc.free(P); // Not needed - just zero-erase the memory +// DebugMsg(['Checkpoint 13']); + P := Libc.malloc(SizeOf(TVFSItem)); + Libc.memset(P, 0, SizeOf(TVFSItem)); +// DebugMsg(['Item = ', Int64(P)]); +// DebugMsg(['Checkpoint 14']); +// DebugMsg(['FVFSListNext --begin']); + Res := FSourcePlugin.FVFSListNext(FGlobs, PChar(APath), P); +// DebugMsg(['FVFSListNext --end']); +// Sleep(500); + until (Res <> cVFS_OK) or (BreakProcessingKind = 2); + if BreakProcessingKind <> 0 then DebugMsg(['^^VFS (WW): GetListing: stopped by BreakProcessing']); + + Libc.free(P); + FSourcePlugin.FVFSListClose(FGlobs); + if Res <> cVFS_Not_More_Files then Result := Res; + except + on E: Exception do + DebugMsg(['^^VFS (EE): GetListing: Exception: ', E.Message]); + end; + BreakProcessingKind := 0; + DebugMsg(['^^VFS (II): GetListing end.']); +end; + +function TVFSEngine.GetListing(var List: TList; const AddDotFiles: boolean): integer; +begin + Result := GetListing(List, AddDotFiles, GetPath); +end; + +function TVFSEngine.ExplicitChDir(const NewPath: string): integer; +begin + Result := __chdir(PChar(NewPath)); + if Result <> 0 then Result := errno; +end; + +function TVFSEngine.GetFileSystemSize: Int64; +begin + Result := GetFileSystemSize(GetPath); +end; + +function TVFSEngine.GetFileSystemSize(const APath: string): Int64; +begin + if @FSourcePlugin.FVFSGetFileSystemSize <> nil + then Result := FSourcePlugin.FVFSGetFileSystemSize(FGlobs, PChar(APath)) + else Result := 0; +end; + +function TVFSEngine.GetFileSystemFree: Int64; +begin + Result := GetFileSystemFree(GetPath); +end; + +function TVFSEngine.GetFileSystemFree(const APath: string): Int64; +begin + if @FSourcePlugin.FVFSGetFileSystemFree <> nil + then Result := FSourcePlugin.FVFSGetFileSystemFree(FGlobs, PChar(APath)) + else Result := 0; +end; + +procedure TVFSEngine.GetFileSystemInfo(const APath: string; var FSSize, FSFree: Int64; var FSName: string); +begin + FSSize := GetFileSystemSize(APath); + FSFree := GetFileSystemFree(APath); + FSName := 'plugin'; +end; + +function TVFSEngine.IsOnROMedium(const FileName: string): boolean; +begin + Result := True; +end; + +function TVFSEngine.FileCanRun(const FileName: string): boolean; +var Item: PDataItemSL; +begin + Item := GetFileInfoSL(FileName); + Result := Assigned(Item) and Item^.IsExecutable; + FreeDataItem(Item); +end; + +function TVFSEngine.GetPrefix: string; +begin + if @FSourcePlugin.FVFSGetPrefix <> nil then Result := URIHidePassword(FSourcePlugin.FVFSGetPrefix(FGlobs)) + else Result := 'VFS'; +end; + +function TVFSEngine.GetPath: string; +begin + if @FSourcePlugin.FVFSGetPath <> nil then Result := FSourcePlugin.FVFSGetPath(FGlobs) + else Result := '/'; +end; + +function TVFSEngine.ChangeDir(const NewPath: string; const ShowProgress: boolean = True): integer; +begin + DebugMsg(['^^VFS (II): ChangeDir begin']); + Result := 0; + try + Result := FSourcePlugin.FVFSChangeDir(FGlobs, PChar(NewPath)); +// Sleep(3000); + except + on E: Exception do DebugMsg(['^^VFS (EE): ChangeDir: Exception: ', E.Message]); + end; + DebugMsg(['^^VFS (II): ChangeDir end.']); +end; + +procedure TVFSEngine.SetPath(Value: string); +begin + ChangeDir(Value); +end; + +function TVFSEngine.Login(Username, Password: string): integer; +begin + if @FSourcePlugin.FVFSLogin <> nil then Result := FSourcePlugin.FVFSLogin(FGlobs, PChar(Username), PChar(Password)) + else Result := cVFS_OK; +end; + +function TVFSEngine.FileExists(const FileName: string; const Use_lstat: boolean = False): Boolean; +begin + if @FSourcePlugin.FVFSFileExists <> nil then Result := FSourcePlugin.FVFSFileExists(FGlobs, PChar(FileName), Use_lstat) + else Result := False; +end; + +function TVFSEngine.DirectoryExists(const FileName: string; const Use_lstat: boolean = False): Boolean; +var P: PVFSItem; + Res: integer; +begin + if @FSourcePlugin.FVFSFileExists <> nil then begin + Result := FSourcePlugin.FVFSFileExists(FGlobs, PChar(FileName), Use_lstat); + if Result and (@FSourcePlugin.FVFSFileInfo <> nil) then begin + P := Libc.malloc(SizeOf(TVFSItem)); + Libc.memset(P, 0, SizeOf(TVFSItem)); + Res := FSourcePlugin.FVFSFileInfo(FGlobs, PChar(FileName), P); + if (Res <> cVFS_OK) or (P = nil) or (TVFSItemType(P^.ItemType) <> vDirectory) then Result := False; + Libc.free(P); + end; + end else Result := False; +end; + +function TVFSEngine.GetFileInfoSL(APath: string): PDataItemSL; +var P: PVFSItem; + Item: PDataItemSL; + Res: integer; +begin + Result := nil; + if @FSourcePlugin.FVFSFileInfo = nil then Exit; + P := Libc.malloc(SizeOf(TVFSItem)); + Libc.memset(P, 0, SizeOf(TVFSItem)); + + Res := FSourcePlugin.FVFSFileInfo(FGlobs, PChar(APath), P); + if Res <> cVFS_OK then begin + DebugMsg(['*** VFSFileInfo(', APath, ') failed. Code = ', Res]); + Exit; + end; + + try + Item := Libc.malloc(SizeOf(TDataItemSL)); + Libc.memset(Item, 0, SizeOf(TDataItemSL)); + with Item^ do begin + AName := strdup(P^.sFileName); + if P^.sLinkTo <> nil then LnkPointTo := strdup(P^.sLinkTo) + else LnkPointTo := nil; + ADestination := nil; + Stage1 := True; + Level := 0; + IsDir := TVFSItemType(P^.ItemType) = vDirectory; + IsLnk := TVFSItemType(P^.ItemType) = vSymlink; + ForceMove := False; +{***} IsOnRO := True; + IsExecutable := P^.iMode and S_IXUSR = S_IXUSR; + Mode := P^.iMode; + ModifyTime := UnixTimeToTDateTime(P^.m_time); + mtime := P^.m_time; + atime := P^.a_time; + UID := P^.iUID; + GID := P^.iGID; + Size := P^.iSize; + Libc.free(P); + end; + Result := Item; + except + on E: Exception do DebugMsg(['*** TVFSEngine.GetFileInfoSL(APath=', APath, ') -Exception: ', E.Message]); + end; +end; + +function TVFSEngine.MakeDir(const NewDir: string): integer; +begin + if @FSourcePlugin.FVFSMkDir <> nil then Result := FSourcePlugin.FVFSMkDir(FGlobs, PChar(NewDir)) + else Result := cVFS_Failed; +end; + +function TVFSEngine.Remove(APath: string): integer; +begin + if @FSourcePlugin.FVFSRemove <> nil then Result := FSourcePlugin.FVFSRemove(FGlobs, PChar(APath)) + else Result := cVFS_Failed; +end; + +function TVFSEngine.RenameFile(SourceFile, DestFile: string): integer; +begin + if @FSourcePlugin.FVFSRename <> nil then Result := FSourcePlugin.FVFSRename(FGlobs, PChar(SourceFile), PChar(DestFile)) + else Result := cVFS_Failed; +end; + +procedure TVFSEngine.FillDirFiles(APath: string; List: TList; ALevel: word); +var Item: PDataItemSL; + i, Res: integer; + FilesList: TList; + LocalList: TStringList; + P: PVFSItem; + + + procedure AddEntry(FPath: string; AddCurrDirStage, AStage1: boolean); + begin + Item := Libc.malloc(SizeOf(TDataItemSL)); + Libc.memset(Item, 0, SizeOf(TDataItemSL)); + with Item^ do begin +// AName := Libc.malloc(Length(FPath) + 1); +// Libc.memset(AName, 0, Length(FPath) + 1); + AName := strdup(PChar(FPath)); + if P^.sLinkTo <> nil then LnkPointTo := strdup(P^.sLinkTo) + else LnkPointTo := nil; + ADestination := nil; + Stage1 := AStage1; + IsDir := TVFSItemType(P^.ItemType) = vDirectory; + IsLnk := TVFSItemType(P^.ItemType) = vSymlink; + if IsLnk and AddCurrDirStage then DebugMsg(['*** Assertion failed AddEntry: Item^.IsLnk = True']); + ForceMove := False; +{***} IsOnRO := True; + IsExecutable := AddCurrDirStage or (P^.iMode and S_IXUSR = S_IXUSR); + Mode := P^.iMode; + ModifyTime := UnixTimeToTDateTime(P^.m_time); + mtime := P^.m_time; + atime := P^.a_time; + UID := P^.iUID; + GID := P^.iGID; + Size := P^.iSize; + {$WARNINGS OFF} + Level := ALevel + Ord(not AddCurrDirStage); + {$WARNINGS ON} + end; + if AddCurrDirStage then List.Add(Item) + else FilesList.Add(Item); + end; + +begin + if not Assigned(List) then Exit; + FilesList := TList.Create; + LocalList := TStringList.Create; + try + try + P := Libc.malloc(SizeOf(TVFSItem)); + Libc.memset(P, 0, SizeOf(TVFSItem)); + Res := FSourcePlugin.FVFSFileInfo(FGlobs, PChar(APath), P); + if Res <> cVFS_OK then DebugMsg(['*** FillDirFiles - VFSFileInfo(', APath, ') failed. Code = ', Res]); + AddEntry(APath, True, True); + Libc.free(P); + + APath := IncludeTrailingPathDelimiter(APath); + if @FSourcePlugin.FVFSChangeDir <> nil then Res := FSourcePlugin.FVFSChangeDir(FGlobs, PChar(APath)) + else Exit; + if Res <> 0 then Exit; + + if @FSourcePlugin.FVFSListFirst = nil then Exit; + P := Libc.malloc(SizeOf(TVFSItem)); + Libc.memset(P, 0, SizeOf(TVFSItem)); + Res := FSourcePlugin.FVFSListFirst(FGlobs, PChar(APath), P); + if Res <> cVFS_OK then begin + FSourcePlugin.FVFSListClose(FGlobs); + Libc.free(P); + Exit; + end; + + repeat + if TVFSItemType(P^.ItemType) = vDirectory + then LocalList.Add(APath + String(P^.sFileName)) + else AddEntry(APath + String(P^.sFileName), False, True); + Libc.free(P); + P := Libc.malloc(SizeOf(TVFSItem)); + Libc.memset(P, 0, SizeOf(TVFSItem)); + Res := FSourcePlugin.FVFSListNext(FGlobs, PChar(GetPath), P); + until (Res <> cVFS_OK); + + Libc.free(P); + FSourcePlugin.FVFSListClose(FGlobs); + + {$WARNINGS OFF} + if LocalList.Count > 0 then + for i := 0 to LocalList.Count - 1 do + FillDirFiles(LocalList[i], List, ALevel + 1); + {$WARNINGS ON} + + if FilesList.Count > 0 then + for i := 0 to FilesList.Count - 1 do + List.Add(FilesList[i]); + except + on E: Exception do DebugMsg(['*** TVFSEngine.FillDirFiles(APath=', APath, ', Level=', ALevel, ') -Exception: ', E.Message]); + end; + finally + P := Libc.malloc(SizeOf(TVFSItem)); + Libc.memset(P, 0, SizeOf(TVFSItem)); + Res := FSourcePlugin.FVFSFileInfo(FGlobs, PChar(APath), P); + if Res <> cVFS_OK then DebugMsg(['*** FillDirFiles - VFSFileInfo(', APath, ') failed. Code = ', Res]); + AddEntry(APath, True, False); + Libc.free(P); + + LocalList.Free; + FilesList.Free; + end; +end; + +function TVFSEngine.MakeSymLink(const NewFileName, PointTo: string): integer; +begin + if @FSourcePlugin.FVFSMakeSymLink <> nil then Result := FSourcePlugin.FVFSMakeSymLink(FGlobs, PChar(NewFileName), PChar(PointTo)) + else Result := cVFS_Failed; +end; + +function TVFSEngine.Chmod(const FileName: string; const Mode: integer): integer; +begin + if @FSourcePlugin.FVFSChmod <> nil then Result := FSourcePlugin.FVFSChmod(FGlobs, PChar(FileName), Mode) + else Result := cVFS_Failed; +end; + +function TVFSEngine.Chown(const FileName: string; const UID, GID: integer): integer; +begin + if @FSourcePlugin.FVFSChown <> nil then Result := FSourcePlugin.FVFSChown(FGlobs, PChar(FileName), UID, GID) + else Result := cVFS_Failed; +end; + +function TVFSEngine.ChangeTimes(APath: string; mtime, atime: Int64): integer; +begin + if @FSourcePlugin.FVFSChangeTimes <> nil then Result := FSourcePlugin.FVFSChangeTimes(FGlobs, PChar(APath), mtime, atime) + else Result := cVFS_Failed; +end; + +function TVFSEngine.GetDirSize(APath: string): Int64; +begin + if @FSourcePlugin.FVFSGetDirSize <> nil then Result := FSourcePlugin.FVFSGetDirSize(FGlobs, PChar(APath)) + else Result := 0; +end; + +procedure TVFSEngine.BreakProcessing(ProcessingKind: integer); +begin + case ProcessingKind of + 1: if @FSourcePlugin.FVFSBreakGetDirSize <> nil then FSourcePlugin.FVFSBreakGetDirSize(FGlobs); + end; +end; + +function TVFSEngine.GetBlockSize: Cardinal; +begin + Result := FBlockSize; +end; + +procedure TVFSEngine.SetBlockSize(Value: Cardinal); +begin + if @FSourcePlugin.FVFSSetBlockSize <> nil then FSourcePlugin.FVFSSetBlockSize(FGlobs, Value); +end; + + + +(********************************************************************************************************************************) +function TVFSEngine.IsOnSameFS(const Path1, Path2: string): boolean; +begin + if @FSourcePlugin.FVFSIsOnSameFS <> nil then Result := FSourcePlugin.FVFSIsOnSameFS(FGlobs, PChar(Path1), PChar(Path2)) + else Result := True; +end; + +function TVFSEngine.OpenFile(const APath: string; Mode: integer; var Error: integer): TEngineFileDes; +var i: integer; +begin + if @FSourcePlugin.FVFSOpenFile <> nil then begin + Result := FSourcePlugin.FVFSOpenFile(FGlobs, PChar(APath), Mode, @i); + Error := i; + end else Result := nil; +end; + +function TVFSEngine.ReadFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; ABlockSize: integer; var Error: integer): integer; +var i: integer; +begin + if @FSourcePlugin.FVFSReadFile <> nil then begin + Result := FSourcePlugin.FVFSReadFile(FGlobs, FileDescriptor, Buffer, ABlockSize, @i); + Error := i; + end else Result := -1; +end; + +function TVFSEngine.WriteFile(const FileDescriptor: TEngineFileDes; Buffer: Pointer; BytesCount: integer; var Error: integer): integer; +var i: integer; +begin + if @FSourcePlugin.FVFSWriteFile <> nil then begin + Result := FSourcePlugin.FVFSWriteFile(FGlobs, FileDescriptor, Buffer, BytesCount, @i); + Error := i; + end else Result := -1; +end; + +function TVFSEngine.CloseFile(const FileDescriptor: TEngineFileDes): integer; +begin + if @FSourcePlugin.FVFSCloseFile <> nil then Result := FSourcePlugin.FVFSCloseFile(FGlobs, FileDescriptor) + else Result := 0; +end; + +function TVFSEngine.FileSeek(const FileDescriptor: TEngineFileDes; const AbsoluteOffset: Int64; var Error: integer): Int64; +var i: integer; +begin + if @FSourcePlugin.FVFSFileSeek <> nil then begin + Result := FSourcePlugin.FVFSFileSeek(FGlobs, FileDescriptor, AbsoluteOffset, @i); + Error := i; + end else Result := -1; +end; + +function TVFSEngine.TwoSameFiles(const Path1, Path2: string): boolean; +begin + if @FSourcePlugin.FVFSTwoSameFiles <> nil then Result := FSourcePlugin.FVFSTwoSameFiles(FGlobs, PChar(Path1), PChar(Path2)) + else Result := False; +end; + + + +(********************************************************************************************************************************) + +function VFSCopyCallBackFunc(iPos, iMax:Int64; data: Pointer): LongBool; cdecl; +begin +// DebugMsg(['VFSCopyCallBackFunc called (iPos = ', iPos, ', iMax = ', iMax, ')']); + Result := True; + if not Assigned(data) then Exit; + if Assigned(TVFSEngine(data).FProgressFunc) then + try + Result := TVFSEngine(data).FProgressFunc(TVFSEngine(data).FSenderThread, iPos); + except + on E: Exception do DebugMsg(['*** Exception raised in VFSCopyCallBackFunc(iPos=', iPos, ', iMax=', iMax, ', data=', data, '): (', E.ClassName, '): ', E.Message]); + end; +end; + +function TVFSEngine.CopyFileOut(Sender: Pointer; SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; +var Res: TVFSResult; +begin + try + if @FSourcePlugin.FVFSCopyOut <> nil then begin + FSenderThread := Sender; + FProgressFunc := ProgressFunc; +// DebugMsg(['0 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$']); +// DebugMsg([' Pointer(FGlobs) = 0x', IntToHex(Int64(FGlobs), 16), ', Pointer(@NewVFSCopyCallBackFunc) = 0x', IntToHex(Int64(@NewVFSCopyCallBackFunc), 16), ', Pointer(Self) = 0x', IntToHex(Int64(Self), 16)]); + try + Res := FSourcePlugin.FVFSCopyOut(FGlobs, PChar(SourceFile), PChar(DestFile), @VFSCopyCallBackFunc, Self, Append); + except + on E: Exception do begin + DebugMsg(['*** Exception raised in TVFSEngine.CopyFileOut(Sender=', QWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]); + Res := cVFS_WriteErr; + end; + end; +// DebugMsg(['1 $$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$']); + Result := Res = cVFS_OK; + if (Res <> cVFS_OK) and Assigned(ErrorFunc) then + case Res of + cVFS_ReadErr: Result := ErrorFunc(Sender, 6, 0, SourceFile); + cVFS_WriteErr: Result := ErrorFunc(Sender, 7, 0, DestFile); + cVFS_mallocFailed: ErrorFunc(Sender, 1, 0, SourceFile); + cVFS_Cancelled: Result := False; + end; + end else Result := False; + except + on E: Exception do DebugMsg(['*** Exception raised in TVFSEngine.CopyFileOut(Sender=', QWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]); + end; +end; + +function TVFSEngine.CopyFileIn(Sender: Pointer; SourceFile, DestFile: string; ProgressFunc: TEngineProgressFunc; ErrorFunc: TEngineErrorFunc; Append: boolean): boolean; +var Res: TVFSResult; +begin + try + if @FSourcePlugin.FVFSCopyIn <> nil then begin + FSenderThread := Sender; + FProgressFunc := ProgressFunc; + try + Res := FSourcePlugin.FVFSCopyIn(FGlobs, PChar(SourceFile), PChar(DestFile), @VFSCopyCallBackFunc, Self, Append); + except + on E: Exception do begin + DebugMsg(['*** Exception raised in TVFSEngine.CopyFileIn(Sender=', QWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]); + Res := cVFS_WriteErr; + end; + end; + Result := Res = cVFS_OK; + if (Res <> cVFS_OK) and Assigned(ErrorFunc) then + case Res of + cVFS_ReadErr: Result := ErrorFunc(Sender, 6, 0, SourceFile); + cVFS_WriteErr: Result := ErrorFunc(Sender, 7, 0, DestFile); + cVFS_mallocFailed: ErrorFunc(Sender, 1, 0, SourceFile); + cVFS_Cancelled: Result := False; + end; + end else Result := False; + except + on E: Exception do DebugMsg(['*** Exception raised in TVFSEngine.CopyFileIn(Sender=', QWord(Sender), ', SourceFile=', SourceFile, ', DestFile=', DestFile, '): (', E.ClassName, '): ', E.Message]); + end; +end; + + +(********************************************************************************************************************************) +(********************************************************************************************************************************) +function TVFSEngine.SetPassword(Password: string): integer; +begin + if @FSourcePlugin.FVFSSetPassword <> nil then Result := FSourcePlugin.FVFSSetPassword(FGlobs, PChar(Password)) + else Result := 0; + FPassword := Password; +end; + +function TVFSEngine.GetPasswordRequired: boolean; +begin + if @FSourcePlugin.FVFSGetPasswordRequired <> nil then Result := FSourcePlugin.FVFSGetPasswordRequired(FGlobs) + else Result := False; +end; + +procedure TVFSEngine.SetFPassword(Value: string); +begin + SetPassword(Value); +end; + + +(********************************************************************************************************************************) +(********************************************************************************************************************************) +function GetBinaryPath: string; +var i: integer; + Buf: array[0..1024] of char; +begin + Result := ParamStr(0); // Fallback + try + DebugMsg(['Trying to determine binary path...']); + DebugMsg(['Fallback path = ', Result]); + Buf[0] := #0; + FillChar(Buf, 1025, 0); + i := readlink(PChar(Format('/proc/%d/exe', [getpid])), @Buf, 1024); + if i < 1 then begin + DebugMsg(['Something went wrong during readlink: ', string(strerror(errno))]); + Exit; + end; + Buf[i] := #0; + Result := string(PChar(@Buf)); + DebugMsg(['Path to executable = ', Result]); + except + on E: Exception do DebugMsg(['*** Exception raised in GetBinaryPath: (', E.ClassName, '): ', E.Message]); + end; +end; + + +procedure QueryModules(APath: string); +var Handle: PDirectoryStream; + DirEnt: PDirent64; + s: string; + PluginItem: TVFSPlugin; + ModuleHandler: TModuleHandle; + VFSVersionFunc: TVFSVersion; + i: integer; + Buf: PChar; + b: boolean; +begin + if Length(APath) < 1 then Exit; + try + try + APath := ReplaceStr(APath, '~', GetHomePath); + DebugMsg(['------------------ Querying modules in ', APath, ' ---']); + + // First change to the program starting directory + if APath[1] <> '/' then begin + s := ExtractFilePath(BinaryPath); + DebugMsg(['----> Changing dir to ', s]); + i := __chdir(PChar(s)); + if i <> 0 then DebugMsg(['Something went wrong during chdir: ', string(strerror(errno))]); + s := get_current_dir_name; + DebugMsg([' [II] Changed dir to ', s]); + end; + + // Change to the required directory + s := APath; + DebugMsg(['----> Changing dir to ', s]); + i := __chdir(PChar(s)); + if i <> 0 then begin + DebugMsg(['Something went wrong during chdir: ', string(strerror(errno))]); + Exit; + end; + s := get_current_dir_name; + DebugMsg([' [II] Changed dir to ', s, ', trying to list the files...']); + + // Going to read the directory and search for the files... + Handle := opendir(PChar(s)); + if not Assigned(Handle) then begin + DebugMsg(['Something went wrong during opendir: ', string(strerror(errno))]); + Exit; + end; + repeat + DirEnt := readdir64(Handle); + if Assigned(DirEnt) then begin + Buf := PChar(@DirEnt^.d_name[0]); + if Assigned(Buf) and (strcmp(Buf, '.') <> 0) and (strcmp(Buf, '..') <> 0) then + begin + DebugMsg(['$$$ Found ', Buf, ', trying to load...']); + + // Try to find the plugin in the plugin list to prevent multiple plugin loading + b := False; + if PluginList.Count > 0 then + for i := 0 to PluginList.Count - 1 do + if CompareStr(TVFSPlugin(PluginList[i]).FullPath, IncludeTrailingPathDelimiter(s) + Buf) = 0 then begin + b := True; + Break; + end; + + ModuleHandler := nil; + if b then DebugMsg(['Module ', s, ' is already loaded --> skipping...']) else + if not LoadModule(ModuleHandler, IncludeTrailingPathDelimiter(s) + Buf) then DebugMsg([' XXX Error loading module: ', dlerror]) + else try + @VFSVersionFunc := GetModuleSymbol(ModuleHandler, 'VFSVersion'); + if (@VFSVersionFunc <> nil) and (VFSVersionFunc >= ConstVFSVersionRequired) then begin + PluginItem := TVFSPlugin.Create(ModuleHandler); + PluginItem.FullPath := IncludeTrailingPathDelimiter(s) + Buf; + PluginList.Add(PluginItem); + end else DebugMsg([' $XXX: Error getting version info or version mismatch']); + except end; + end; + end; + until DirEnt = nil; + closedir(Handle); + except + on E: Exception do DebugMsg(['*** Exception raised in QueryModules(APath = ', APath, '): (', E.ClassName, '): ', E.Message]); + end; + finally + DebugMsg(['------------------ Done querying modules ---------------']); + end; +end; + + +procedure UnloadModules; +var i: integer; +begin + if Assigned(PluginList) and (PluginList.Count > 0) then + for i := PluginList.Count - 1 downto 0 do + try + UnloadModule(TVFSPlugin(PluginList[i]).ModuleHandle); + TVFSPlugin(PluginList[i]).Free; + PluginList.Delete(i); + except + on E: Exception do DebugMsg(['*** Exception raised in UnloadModules(i = ', i, '): (', E.ClassName, '): ', E.Message]); + end; +end; + + +procedure DoInitPlugins; +begin + PluginList := TList.Create; + if not ParamDisablePlugins then begin + BinaryPath := GetBinaryPath; + QueryModules(ConstGlobalModulePath1); + QueryModules(ConstGlobalModulePath2); + QueryModules(ConstLocalModulePath1); + QueryModules(ConstLocalModulePath2); + QueryModules(ConstLocalModulePath3); + end; +end; + +initialization +finalization + UnloadModules; + PluginList.Free; +end. |
