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 | |
| download | tuxcmd-ecde167da74c86bc047aaf84c5e548cf65a5da98.tar.xz | |
Initial commitv0.6.36release-0.6.36-dev
Diffstat (limited to 'vfs')
| -rw-r--r-- | vfs/ModuleLoader.pas | 156 | ||||
| -rw-r--r-- | vfs/UVFSCore.pas | 1075 | ||||
| -rw-r--r-- | vfs/common/vfs_types.h | 114 | ||||
| -rw-r--r-- | vfs/null_plugin/COPYING | 339 | ||||
| -rw-r--r-- | vfs/null_plugin/Makefile | 22 | ||||
| -rw-r--r-- | vfs/null_plugin/README | 15 | ||||
| -rw-r--r-- | vfs/null_plugin/null_plugin.c | 357 | ||||
| l--------- | vfs/null_plugin/vfs_types.h | 1 | ||||
| -rw-r--r-- | vfs/uVFSprototypes.pas | 246 |
9 files changed, 2325 insertions, 0 deletions
diff --git a/vfs/ModuleLoader.pas b/vfs/ModuleLoader.pas new file mode 100644 index 0000000..51351dd --- /dev/null +++ b/vfs/ModuleLoader.pas @@ -0,0 +1,156 @@ +{******************************************************************} +{ } +{ Project JEDI } +{ OS independent Dynamic Loading Helpers } +{ } +{ The initial developer of the this code is } +{ Robert Marquardt <robert_marquardt@gmx.de) } +{ } +{ Copyright (C) 2000, 2001 Robert Marquardt. } +{ } +{ Obtained through: } +{ Joint Endeavour of Delphi Innovators (Project JEDI) } +{ } +{ You may retrieve the latest version of this file at the Project } +{ JEDI home page, located at http://delphi-jedi.org } +{ } +{ The contents of this file are used with permission, subject to } +{ the Mozilla Public License Version 1.1 (the "License"); you may } +{ not use this file except in compliance with the License. You may } +{ obtain a copy of the License at } +{ http://www.mozilla.org/NPL/NPL-1_1Final.html } +{ } +{ Software distributed under the License is distributed on an } +{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or } +{ implied. See the License for the specific language governing } +{ rights and limitations under the License. } +{ } +{******************************************************************} + +unit ModuleLoader; + +interface +{$WEAKPACKAGEUNIT ON} + + +uses + Libc; +type + // Handle to a loaded .so + TModuleHandle = Pointer; + +const + // Value designating an unassigned TModuleHandle od a failed loading + INVALID_MODULEHANDLE_VALUE = TModuleHandle(nil); + +function LoadModule(var Module: TModuleHandle; FileName: string): Boolean; +function LoadModuleEx(var Module: TModuleHandle; FileName: string; Flags: Cardinal): Boolean; +procedure UnloadModule(var Module: TModuleHandle); +function GetModuleSymbol(Module: TModuleHandle; SymbolName: string): Pointer; +function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: string; var Accu: Boolean): Pointer; +function ReadModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean; +function WriteModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean; + +implementation + +// load the .so file FileName +// the rules for FileName are those of dlopen() +// Returns: True = success, False = failure to load +// Assigns: the handle of the loaded .so to Module +// Warning: if Module has any other value than INVALID_MODULEHANDLE_VALUE +// on entry the function will do nothing but returning success. + +function LoadModule(var Module: TModuleHandle; FileName: string): Boolean; +begin + Module := dlopen(PChar(FileName), RTLD_LAZY); + Result := Module <> INVALID_MODULEHANDLE_VALUE; +end; + +// load the .so file FileName +// dlopen() with flags is used to get better control of the loading +// for the allowed values for flags see "man dlopen". + +function LoadModuleEx(var Module: TModuleHandle; FileName: string; Flags: Cardinal): Boolean; +begin + Module := dlopen(PChar(FileName), Flags); + Result := Module <> INVALID_MODULEHANDLE_VALUE; +end; + +// unload a .so loaded with LoadModule or LoadModuleEx +// The procedure will not try to unload a handle with +// value INVALID_MODULEHANDLE_VALUE and assigns this value +// to Module after unload. + +procedure UnloadModule(var Module: TModuleHandle); +begin + if Module <> INVALID_MODULEHANDLE_VALUE then + dlclose(Module); + Module := INVALID_MODULEHANDLE_VALUE; +end; + +// returns the pointer to the symbol named SymbolName +// if it is exported from the .so Module +// nil is returned if the symbol is not available + +function GetModuleSymbol(Module: TModuleHandle; SymbolName: string): Pointer; +begin + Result := nil; + if Module <> INVALID_MODULEHANDLE_VALUE then + Result := dlsym(Module, PChar(SymbolName)); +end; + +// returns the pointer to the symbol named SymbolName +// if it is exported from the .so Module +// nil is returned if the symbol is not available. +// as an extra the boolean variable Accu is updated +// by anding in the success of the function. +// This is very handy for rendering a global result +// when accessing a long list of symbols. + +function GetModuleSymbolEx(Module: TModuleHandle; SymbolName: string; var Accu: Boolean): Pointer; +begin + Result := nil; + if Module <> INVALID_MODULEHANDLE_VALUE then + Result := dlsym(Module, PChar(SymbolName)); + Accu := Accu and (Result <> nil); +end; + +// get the value of variables exported from a .so Module +// Delphi cannot access variables in a .so directly, so +// this function allows to copy the data from the .so. +// Beware! You are accessing the .so memory image directly. +// Be sure to access a variable not a function and be sure +// to read the correct amount of data. + +function ReadModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean; +var + Sym: Pointer; +begin + Result := True; + Sym := GetModuleSymbolEx(Module, SymbolName, Result); + if Result then + Move(Sym^, Buffer, Size); +end; + +// set the value of variables exported from a .so Module +// Delphi cannot access variables in a .so directly, so +// this function allows to copy the data to the .so! +// BEWARE! You are accessing the .so memory image directly. +// Be sure to access a variable not a function and be sure +// to write the correct amount of data. +// The changes are not persistent. They get lost when the +// .so is unloaded. + +function WriteModuleData(Module: TModuleHandle; SymbolName: string; var Buffer; Size: Cardinal): Boolean; +var + Sym: Pointer; +begin + Result := True; + Sym := GetModuleSymbolEx(Module, SymbolName, Result); + if Result then + Move(Buffer, Sym^, Size); +end; +end. + + + 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. diff --git a/vfs/common/vfs_types.h b/vfs/common/vfs_types.h new file mode 100644 index 0000000..609a78b --- /dev/null +++ b/vfs/common/vfs_types.h @@ -0,0 +1,114 @@ +/* Tux Commander VFS: Virtual File System types and definitions + * - prototypes functions and types + * draft version 3 + * + * Copyright (C) 2003 Radek Cervinka <radek.cervinka@centrum.cz> + * Copyright (C) 2008 Tomas Bzatek <tbzatek@users.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 + */ + +#ifndef __VFS_TYPES_H__ +#define __VFS_TYPES_H__ + + +#include <stdio.h> +#include <stdint.h> +#include <sys/types.h> + +typedef int TVFSResult; + + +typedef void (* TVFSLogFunc)(char *s); +typedef int (* TVFSCopyCallBackFunc)(u_int64_t iPos, u_int64_t iMax, void *data); +typedef void *TVFSFileDes; + +static const int cVFSVersion = 3; // current version of the VFS API + +// Capabilities +static const int capVFS_nil = 0; +static const int capVFS_List = 1 << 0; +static const int capVFS_CopyOut = 1 << 1; +static const int capVFS_CopyIn = 1 << 2; +static const int capVFS_MkDir = 1 << 3; +static const int capVFS_RmDir = 1 << 4; +static const int capVFS_Multiple = 1 << 5; // support multiple files = background copy & thread safe +static const int capVFS_Delete = 1 << 6; +static const int capVFS_Rename = 1 << 7; +static const int capVFS_Execute = 1 << 8; +static const int capVFS_Append = 1 << 9; + +// Error codes (TVFSResult) +enum { + cVFS_OK = 0, + cVFS_Failed = 1, // also No such file + cVFS_Cancelled = 2, + cVFS_Not_Supported = 3, + cVFS_No_More_Files = 4, + cVFS_ReadErr = 5, + cVFS_WriteErr = 6, // also Readonly FileSystem + cVFS_LoginFailed = 7, + cVFS_PermissionDenied = 8, + cVFS_NoSpaceLeft = 9, + cVFS_mallocFailed = 10, + cVFS_BadPassword = 11, + cVFS_MissingVolume = 12, + cVFS_CorruptedArchive = 13 +}; + + +// Open modes +enum { + cVFS_OpenRead, + cVFS_OpenWrite, + cVFS_OpenAppend +}; + + +// Item Type enum +enum TVFSItemType { + vRegular = 0, + vSymlink = 1, + vChardev = 2, + vBlockdev = 3, + vDirectory = 4, + vFifo = 5, + vSock = 6, + vOther = 7 +}; + + +struct TVFSItem { + char *sFileName; + u_int64_t iSize; + __time_t m_time; // numbers should be located before the other variables (bug?) + __time_t a_time; + __time_t c_time; + __mode_t iMode; + char *sLinkTo; + __uid_t iUID; + __gid_t iGID; + enum TVFSItemType ItemType; +}; + +struct TVFSInfo { + const char *Name; + const char *Description; + const char *About; + const char *Copyright; +}; + + +#endif /* __VFS_TYPES_H__ */ diff --git a/vfs/null_plugin/COPYING b/vfs/null_plugin/COPYING new file mode 100644 index 0000000..d511905 --- /dev/null +++ b/vfs/null_plugin/COPYING @@ -0,0 +1,339 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Lesser General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + 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., + 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + <signature of Ty Coon>, 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. diff --git a/vfs/null_plugin/Makefile b/vfs/null_plugin/Makefile new file mode 100644 index 0000000..f2c6e7e --- /dev/null +++ b/vfs/null_plugin/Makefile @@ -0,0 +1,22 @@ +# path definitions +DESTDIR = /usr +INSTALL=install -c +INSTALL_DATA = ${INSTALL} -m 644 +LIB_SUFFIX=`if test \`uname -m\` = x86_64; then echo 64; fi` + +# compiler options +CC = gcc +CFLAGS = -Wall -O2 -g + + +all shared static: null_plugin + +null_plugin: null_plugin.c + $(CC) -c null_plugin.c -I. -fPIC -I/usr/include $(CFLAGS) + $(CC) -shared -Wall -o libnull_plugin.so null_plugin.o + +install:: + $(INSTALL) ./libnull_plugin.so $(DESTDIR)/lib$(LIB_SUFFIX)/tuxcmd/ + +clean: + rm -f *.o libnull_plugin.so diff --git a/vfs/null_plugin/README b/vfs/null_plugin/README new file mode 100644 index 0000000..7123ad0 --- /dev/null +++ b/vfs/null_plugin/README @@ -0,0 +1,15 @@ +null plugin for Tux Commander +Plugin API version 2 + + +Copyright (c) 2005 Tomas Bzatek <tbzatek@users.sourceforge.net> +http://tuxcmd.sourceforge.net + + + +This is the null VFS module for Tux Commander. It is intended as a basic +skeleton structure for writing new plugins. It contains all functions required +for successful access to the fake directory structure it creates. + +Please see vfs/uVFSprototypes.pas file for a brief documentation of the VFS API +and description of each function. diff --git a/vfs/null_plugin/null_plugin.c b/vfs/null_plugin/null_plugin.c new file mode 100644 index 0000000..0d24765 --- /dev/null +++ b/vfs/null_plugin/null_plugin.c @@ -0,0 +1,357 @@ +/* null plugin for Tux Commander + * Copyright (C) 2005 Tomas Bzatek <tbzatek@users.sourceforge.net> + * Check for updates on tuxcmd.sourceforge.net + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <string.h> +#include <stdlib.h> +#include <stdint.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <errno.h> +#include <time.h> +#include "vfs_types.h" + + +// Declaration of the global plugin object +struct TVFSGlobs { + TVFSLogFunc log_func; + int list_item_id; + char *curr_dir; +}; + + + +// Basic initialization functions +int VFSAllocNeeded() +{ + return sizeof(struct TVFSGlobs); +} + +void VFSInit(struct TVFSGlobs *globs, TVFSLogFunc log_func) +{ + + globs->log_func = log_func; + globs->log_func("null plugin: VFSInit"); + globs->curr_dir = NULL; + +} + +void VFSDestroy(struct TVFSGlobs *globs) +{ + + globs->log_func("null plugin: VFSDestroy"); + +} + +int VFSVersion() +{ + return cVFSVersion; +} + +struct TVFSInfo VFSGetInfo() +{ + + static const struct TVFSInfo info = + { + "Null plugin", + "null testing plugin", + "Plugin API version 2", + "Copyright © 2007 Tomáš Bžatek" + }; + + return info; +} + +char *VFSGetPrefix(struct TVFSGlobs *globs) +{ + return "null"; +} + +TVFSResult VFSOpen(struct TVFSGlobs *globs, char *sName) +{ + return cVFS_OK; +} + +TVFSResult VFSClose(struct TVFSGlobs *globs) +{ + return cVFS_OK; +} + +char *VFSGetPath(struct TVFSGlobs *globs) +{ + return globs->curr_dir; +} + +u_int64_t VFSGetFileSystemFree(struct TVFSGlobs *globs, char *APath) +{ + return 0; +} + +u_int64_t VFSGetFileSystemSize(struct TVFSGlobs *globs, char *APath) +{ + return 0; +} + + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////// + +TVFSResult VFSChangeDir(struct TVFSGlobs *globs, char *NewPath) +{ + if (globs->curr_dir != NULL) free(globs->curr_dir); + globs->curr_dir = strdup(NewPath); + return cVFS_OK; +} + +int VFSLogin(struct TVFSGlobs *globs, char *user, char *pass) +{ + return cVFS_OK; +} + + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////// + +static char *items[] = +{ + "This is the first item", + "This is the second item", + "This is the third item", + "This is the fourth item", + "This is the fifth item", + "This is the sixth item", + "This is the seventh item", + "This is the eight item", + "This is the nineth item", + "This is the tenth item", + "This is the eleventh item", + "This is the twelveth item", + "This is the thirteenth item", + "This is the fourteenth item", + "This is the fifteenth item", + "This is the sixteeth item", + "This is the seventeenth item", + "This is the eighteenth item", +}; + + +TVFSResult VFSListFirst(struct TVFSGlobs *globs, char *sDir, struct TVFSItem *Item) +{ + globs->list_item_id = 0; + printf("C Item = %lu \n", (long int)Item); + + Item->sFileName = strdup(items[globs->list_item_id]); +// Item->iSize = rand(); + Item->iSize = globs->list_item_id + 1; + Item->iMode = S_IRWXO + S_IRWXG + S_IRWXU; + Item->sLinkTo = "/tmp"; + Item->ItemType = vSymlink; + Item->iUID = 100; + Item->iGID = 1000; + Item->m_time = time(NULL) + globs->list_item_id; + printf("C sizeof(TVFSItem) = %ld \n", sizeof(struct TVFSItem)); + printf("C sizeof(Item->sFileName) = %ld \n", sizeof(Item->sFileName)); + printf("C sizeof(Item->iSize) = %ld \n", sizeof(Item->iSize)); + printf("C sizeof(Item->m_time) = %ld \n", sizeof(Item->m_time)); + printf("C sizeof(Item->a_time) = %ld \n", sizeof(Item->a_time)); + printf("C sizeof(Item->c_time) = %ld \n", sizeof(Item->c_time)); + printf("C sizeof(Item->iMode) = %ld \n", sizeof(Item->iMode)); + printf("C sizeof(Item->sLinkTo) = %ld \n", sizeof(Item->sLinkTo)); + printf("C sizeof(Item->iUID) = %ld \n", sizeof(Item->iUID)); + printf("C sizeof(Item->iGID) = %ld \n", sizeof(Item->iGID)); + printf("C sizeof(Item->ItemType) = %ld \n", sizeof(Item->ItemType)); + + static struct TVFSItem x; + printf("C sizeof(x.sFileName) = %ld \n", sizeof(x.sFileName)); + printf("C sizeof(x.iSize) = %ld \n", sizeof(x.iSize)); + printf("C sizeof(x.m_time) = %ld \n", sizeof(x.m_time)); + printf("C sizeof(x.a_time) = %ld \n", sizeof(x.a_time)); + printf("C sizeof(x.c_time) = %ld \n", sizeof(x.c_time)); + printf("C sizeof(x.iMode) = %ld \n", sizeof(x.iMode)); + printf("C sizeof(x.sLinkTo) = %ld \n", sizeof(x.sLinkTo)); + printf("C sizeof(x.iUID) = %ld \n", sizeof(x.iUID)); + printf("C sizeof(x.iGID) = %ld \n", sizeof(x.iGID)); + printf("C sizeof(x.ItemType) = %ld \n", sizeof(x.ItemType)); + + return cVFS_OK; +} + +TVFSResult VFSListNext(struct TVFSGlobs *globs, char *sDir, struct TVFSItem *Item) +{ + globs->list_item_id++; + printf("C Item = %lu \n", (long int)Item); + + if (globs->list_item_id >= (sizeof(items) / sizeof(items[0]))) { + Item = NULL; + return cVFS_No_More_Files; + } + + Item->sFileName = strdup(items[globs->list_item_id]); + + Item->iSize = globs->list_item_id + 1; + Item->iMode = S_IRWXO + /* S_IRWXG + */ S_IRWXU; + Item->sLinkTo = NULL; + Item->iUID = 100; + Item->iGID = 1000; + Item->m_time = time(NULL) + globs->list_item_id; + + if (globs->list_item_id < 4) Item->ItemType = vDirectory; + else Item->ItemType = vRegular; + + return cVFS_OK; +} + +TVFSResult VFSListClose(struct TVFSGlobs *globs) +{ + return cVFS_OK; +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////// +long VFSFileExists(struct TVFSGlobs *globs, const char *FileName, const long Use_lstat) +{ + return 0; +} + +TVFSResult VFSFileInfo(struct TVFSGlobs *globs, char *AFileName, struct TVFSItem *Item) +{ + return cVFS_OK; +} + +TVFSResult VFSMkDir(struct TVFSGlobs *globs, const char *sDirName) +{ + return cVFS_OK; +} + +TVFSResult VFSRemove(struct TVFSGlobs *globs, const char *APath) +{ + return cVFS_OK; +} + +TVFSResult VFSRename(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName) +{ + return cVFS_OK; +} + +TVFSResult VFSMakeSymLink(struct TVFSGlobs *globs, const char *NewFileName, const char *PointTo) +{ + return cVFS_OK; +} + +TVFSResult VFSChmod(struct TVFSGlobs *globs, const char *FileName, const uint Mode) +{ + return cVFS_OK; +} + +TVFSResult VFSChown(struct TVFSGlobs *globs, const char *FileName, const uint UID, const uint GID) +{ + return cVFS_OK; +} + +TVFSResult VFSChangeTimes(struct TVFSGlobs *globs, char *APath, long mtime, long atime) +{ + return cVFS_OK; +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////// + +u_int64_t VFSGetDirSize(struct TVFSGlobs *globs, char *APath) +{ + return 0; +} + + +void VFSBreakGetDirSize(struct TVFSGlobs *globs) +{ + +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////// + +TVFSFileDes VFSOpenFile(struct TVFSGlobs *globs, const char *APath, int Mode, int *Error) +{ + *Error = 0; + return (TVFSFileDes)0; +} + +TVFSResult VFSCloseFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor) +{ + return cVFS_OK; +} + +u_int64_t VFSFileSeek(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, u_int64_t AbsoluteOffset, int *Error) +{ + *Error = 0; + return 0; +} + +int VFSReadFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, void *Buffer, int ABlockSize, int *Error) +{ + *Error = 0; + return 0; +} + +int VFSWriteFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, void *Buffer, int BytesCount, int *Error) +{ + *Error = 0; + return 0; +} + +void VFSSetBlockSize(struct TVFSGlobs *globs, int Value) +{ + +} + +int VFSIsOnSameFS(struct TVFSGlobs *globs, const char *Path1, const char *Path2) +{ + return 0; +} + +int VFSTwoSameFiles(struct TVFSGlobs *globs, const char *Path1, const char *Path2) +{ + return 0; +} + + +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// +//////////////////////// + +TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, int Append) +{ + return cVFS_OK; +} + +TVFSResult VFSCopyIn(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, int Append) +{ + return cVFS_OK; +} + +//////////////////////// +//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + + + diff --git a/vfs/null_plugin/vfs_types.h b/vfs/null_plugin/vfs_types.h new file mode 120000 index 0000000..c2235a2 --- /dev/null +++ b/vfs/null_plugin/vfs_types.h @@ -0,0 +1 @@ +../common/vfs_types.h
\ No newline at end of file diff --git a/vfs/uVFSprototypes.pas b/vfs/uVFSprototypes.pas new file mode 100644 index 0000000..7a87aa0 --- /dev/null +++ b/vfs/uVFSprototypes.pas @@ -0,0 +1,246 @@ +(* + Virtual File System support + - prototypes functions and types + draft version 24 + + used in Seksi commander and Tux Commander + + Copyright (C) 2003 Radek Cervinka <radek.cervinka@centrum.cz> + Copyright (C) 2005-2008 Tomas Bzatek <tbzatek@users.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 uVFSprototypes; + +interface + +const + cVFSVersion = 3; // current version of the VFS API + + // Capabilities + capVFS_nil = 0; + capVFS_List = 1; + capVFS_CopyOut = 2; + capVFS_CopyIn = 4; + capVFS_NeedsTemp = 8; // if not set, the seek operation is available + capVFS_Multiple = 16; // support multiple files - ? + capVFS_Execute = 32; + capVFS_Writable = 64; + capVFS_NeedsLogin = 128; // Anonymous is login operation too + + + // Error codes (TVFSResult) + cVFS_OK = 0; + cVFS_Failed = 1; // also No such file + cVFS_Cancelled = 2; + cVFS_Not_Supported = 3; + cVFS_Not_More_Files = 4; // returned while directory listing + cVFS_ReadErr = 5; + cVFS_WriteErr = 6; // also ReadOnlyFileSystem + cVFS_LoginFailed = 7; + cVFS_PermissionDenied = 8; + cVFS_NoSpaceLeft = 9; + cVFS_mallocFailed = 10; + cVFS_BadPassword = 11; + cVFS_MissingVolume = 12; + cVFS_CorruptedArchive = 13; + + + // Open modes (for VFSOpenFile function) + cVFS_OpenRead = 0; + cVFS_OpenWrite = 1; + cVFS_OpenAppend = 2; + + + +type + TVFSResult = longint; + TVFSGlobs = Pointer; + // The plugin can store some data into this object for identify the object instances + // It is allocated in the application side with the size returned by VFSAllocNeeded() + // Generally, it is required for correct cooperation of thread in the module + + // File descriptor for Open, Read, Write, Close, Seek operations + TVFSFileDes = Pointer; + + TVFSItemType = (vRegular=0, vSymlink=1, vChardev=2, vBlockdev=3, vDirectory=4, vFifo=5, vSock=6, vOther=7); + +{$IFDEF KYLIX} + DWORD = Cardinal; +// ShortBool = boolean; +{$ENDIF} +{$IFNDEF CPU64} + ShortBool = boolean; +{$ENDIF} + + PVFSItem = ^TVFSItem; + TVFSItem = packed record +{$IFNDEF CPU64} // 32-bit platform + sFileName: PChar; + iSize: Int64; + m_time: DWORD; + a_time: DWORD; + c_time: DWORD; + iMode: Integer; + sLinkTo: PChar; + iUID: Integer; + iGID: Integer; + ItemType: TVFSItemType; +{$ELSE} // 64-bit platform + sFileName: PChar; + iSize: Int64; + m_time: QWORD; + a_time: QWORD; + c_time: QWORD; + iMode: Longint; + __padding1: array[1..4] of byte; + sLinkTo: PChar; + iUID: Longint; + iGID: Longint; + ItemType: Longint; + __padding: array[1..4] of byte; +{$ENDIF} + end; + + // This structure contains basic informations about the plugin (Name is used to identify the module in the application) + TVFSInfo = packed record + Name: PChar; + Description: PChar; + About: PChar; + Copyright: PChar; + end; + +type + // Log function which could plugin call - the application must handle the messages (e.g. write them to the stdout) + PVFSLogFunc = ^TVFSLogFunc; + TVFSLogFunc = procedure(S: PChar); cdecl; + + TVFSAllocNeeded = function: integer; cdecl; + // Returns sizeof internal structure of TVFSGlobs in the plugin - host application will then allocate corresponding amount of memory + TVFSInit = procedure (g:TVFSGlobs; LogFunc: PVFSLogFunc); cdecl; + // Performs intialization of the plugin and sets the log function for the module (assume allocated memory for TVFSGlobs) + TVFSDestroy = procedure (g:TVFSGlobs); cdecl; + // Performs cleanup and destroy all objects + TVFSVersion = function: integer; cdecl; + // Returns API Version; the host application checks for this number and if the returned number is less than a value required by the host application, the module is not loaded + // The current version for this API is '3' - please use the constant declared above as return value + TVFSGetInfo = function: TVFSInfo; cdecl; + // Returns the structure with module info + TVFSGetPrefix = function (g:TVFSGlobs): PChar; cdecl; + // Returns prefix used in the application to show difference between local and VFS filesystems (e.g. "ftp" or "smb") + TVFSGetCharset = function (g:TVFSGlobs): PChar; cdecl; + // TODO: Returns charset which the plugin uses + TVFSGetExts = function: PChar; cdecl; + // Returns the list of filename extensions which the module can handle separated by ';' (without a leading dots) + TVFSGetServices = function: PChar; cdecl; + // Returns the list of supported remote protocols separated by ';' (without the '://') + TVFSCaps = function (const sExt: PChar): Integer; cdecl; + // TODO: Returns a bit mask of plugin capabilities + TVFSSetProtocolLogFunc = procedure (g:TVFSGlobs; ProtocolLogFunc: TVFSLogFunc); cdecl; + // TODO: Sets the protocol log function (unlike module debug log func this is intended only for server messages (FTP mainly)) + TVFSSetBlockSize = procedure (g:TVFSGlobs; Value: Cardinal); cdecl; + // Sets the block size for I/O operations (not all modules supports this) + + + TVFSOpen = function (g:TVFSGlobs; const sName: PChar): TVFSResult; cdecl; + // TODO: Opens the location (file or URI/URL) + TVFSLogin = function (g:TVFSGlobs; const User, Pass: PChar): TVFSResult; cdecl; + // TODO: Performs login to the server + TVFSClose = function (g:TVFSGlobs): TVFSResult; cdecl; + // Closes the file or connection to the server + TVFSMkDir = function (g:TVFSGlobs; const sDirName: PChar): TVFSResult; cdecl; + TVFSRename = function (g:TVFSGlobs; const sSrcName, sDstName: PChar): TVFSResult; cdecl; + // Only rename/move in this function, the two files/directories have to be on the same filesystem - otherway it needs to be copied and deleted manually + TVFSRemove = function (g:TVFSGlobs; const APath: PChar): TVFSResult; cdecl; + // Removes the file/directory (empty only!) + TVFSFileExists = function (g:TVFSGlobs; const FileName: PChar; const Use_lstat: LongBool): LongBool; cdecl; + // This function checks for existing location; the Use_lstat parameter specifies to not follow the symlinks (default false = follow symlinks) + TVFSMakeSymLink = function (g:TVFSGlobs; const NewFileName, PointTo: PChar): TVFSResult; cdecl; + TVFSChmod = function (g:TVFSGlobs; const FileName: PChar; const Mode: integer): TVFSResult; cdecl; + // The parameter for this function is in classic unix format (glibc) - a bit mask + TVFSChown = function (g:TVFSGlobs; const FileName: PChar; const UID, GID: integer): TVFSResult; cdecl; + TVFSChangeTimes = function (g:TVFSGlobs; APath: PChar; mtime, atime: Longint): TVFSResult; cdecl; + // Changes times for the file/directory - mtime and atime are __time_t parameters (glibc) + TVFSChangeDir = function (g:TVFSGlobs; const NewPath: PChar): TVFSResult; cdecl; + // Try to change the directory when correct permissions + TVFSGetPath = function (g:TVFSGlobs): PChar; cdecl; + // Returns the current working path (not all plugins can support this; just return '/' in this case) + TVFSGetFileSystemSize = function (g:TVFSGlobs; const APath: PChar): Int64; cdecl; + // Gets the size of filesystem; the path is optional, specified to recognize various mounted filesystems in the tree + TVFSGetFileSystemFree = function (g:TVFSGlobs; const APath: PChar): Int64; cdecl; + TVFSGetFSLabel = function (g:TVFSGlobs; const APath: PChar): PChar; cdecl; + // Gets the filesystem label + TVFSIsOnSameFS = function (g:TVFSGlobs; const Path1, Path2: PChar): boolean; cdecl; + TVFSTwoSameFiles = function (g:TVFSGlobs; const Path1, Path2: PChar): boolean; cdecl; + // Checks if the two files are simmilar (used to test the case-insensitive filesystem - or hardlinks) + TVFSGetDirSize = function (g:TVFSGlobs; APath: PChar): Int64; cdecl; + // Calculates recursively the size of the tree specified under the path APath + TVFSBreakGetDirSize = procedure (g:TVFSGlobs); cdecl; + // Call this function to break the calculation performed by VFSGetDirSize + TVFSRun = function (g:TVFSGlobs; const sName: PChar): TVFSResult; cdecl; + // TODO: Runs the command read from inside the archive (typically installing the rpm package) + + + TVFSCopyCallBackFunc = function (iPos, iMax: Int64; data: Pointer):LongBool; cdecl; + // Callback function used during the copy process; return False to break the copy process + + TVFSCopyOut = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; pCallBackProgress: TVFSCopyCallBackFunc; data: Pointer; Append: LongBool): TVFSResult; cdecl; + // Performs the copy process from inside of module to the file in the local system + // (thus sSrcName is a path from inside of module and sDstName is path in the local filesystem where the file should be copied) + // The data pointer is then used to call the callback function in + // Note: if you need to transfer a file between two VFS modules, you need to do it manually - either first copy to local FS or use the Open, Read, Write functions of the module (NOTE: both VFS modules have to support these functions) + + TVFSCopyIn = function (g:TVFSGlobs; const sSrcName, sDstName: PChar; pCallBackProgress: TVFSCopyCallBackFunc; data: Pointer; Append: LongBool): TVFSResult; cdecl; + // Performs the copy process from the local filesystem into the module + + + // This is the set of basic functions which can manipulate with the data + // There is a TVFSFileDes object which identifies the processed file (filedescriptor) + // All these functions needs a pointer to an int variable to store the error code + // NOTE: not all modules could support this set of functions due to its design (unable to set a solid block size) + TVFSOpenFile = function (g:TVFSGlobs; const APath: PChar; Mode: integer; Error: Pinteger): TVFSFileDes; cdecl; + // Opens a file or creates new (the values for the Mode parameter are described above) and returns the assigned filedescriptor + TVFSReadFile = function (g:TVFSGlobs; const FileDescriptor: TVFSFileDes; Buffer: Pointer; ABlockSize: integer; Error: Pinteger): integer; cdecl; + // Returns number of bytes read; the buffer needs to be allocated by a blocksize (set it by VFSSetBlockSize function) + TVFSWriteFile = function (g:TVFSGlobs; const FileDescriptor: TVFSFileDes; Buffer: Pointer; BytesCount: integer; Error: Pinteger): integer; cdecl; + // Returns number of bytes written + TVFSCloseFile = function (g:TVFSGlobs; const FileDescriptor: TVFSFileDes): TVFSResult; cdecl; + TVFSFileSeek = function (g:TVFSGlobs; const FileDescriptor: TVFSFileDes; const AbsoluteOffset: Int64; Error: Pinteger): Int64; cdecl; + // Sets the position in the file from the start and returns real current position + + + // These are the functions used to list the contents of the directory + // First call the VFSListFirst function and then repeat call of VFSListNext until it returns NULL. + // Then call VFSListClose to make cleanup + TVFSListFirst = function (g:TVFSGlobs; const sDir: PChar; VFSItem: PVFSItem): TVFSResult; cdecl; + TVFSListNext = function (g:TVFSGlobs; const sDir: PChar; VFSItem: PVFSItem): TVFSResult; cdecl; + TVFSListClose = function (g:TVFSGlobs): TVFSResult; cdecl; + TVFSFileInfo = function (g:TVFSGlobs; AFileName: PChar; VFSItem: PVFSItem): TVFSResult; cdecl; + // Gets a single info item without need to list a whole directory + + TVFSSetPassword = function (g:TVFSGlobs; pass: PChar): TVFSResult; cdecl; + TVFSGetPasswordRequired = function (g:TVFSGlobs): LongBool; cdecl; + + /// pridat neco jako set_loglevel ?? + +//// pridat typ pluginu - jestli archive nebo protocol - prip. jeste pridat ktery protokoly je to schopno handlovat + + +// TODO: some function to check the CRC of the archive - it should need also some progress feedback - the processed file and percentage progress + +implementation + +end. |
