From 9edcc05f98afb705071e9a906492aaf4d3a10160 Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Sun, 4 Oct 2009 16:27:34 +0200 Subject: Consolidate VFS memory management --- UConfig.pas | 4 +-- vfs/UVFSCore.pas | 94 ++++++++++++++++++++++++++++++++++++++++++-------- vfs/uVFSprototypes.pas | 20 ++++++----- 3 files changed, 93 insertions(+), 25 deletions(-) diff --git a/UConfig.pas b/UConfig.pas index e4f919f..341f1ca 100644 --- a/UConfig.pas +++ b/UConfig.pas @@ -25,8 +25,8 @@ uses Classes, ULocale; resourcestring ConstAppTitle = 'Tux Commander'; - ConstAboutVersion = '0.6.65-dev'; - ConstAboutBuildDate = '2009-10-03'; + ConstAboutVersion = '0.6.66-dev'; + ConstAboutBuildDate = '2009-10-04'; {$IFDEF FPC} {$INCLUDE fpcver.inc} diff --git a/vfs/UVFSCore.pas b/vfs/UVFSCore.pas index 7c98303..45bfc83 100644 --- a/vfs/UVFSCore.pas +++ b/vfs/UVFSCore.pas @@ -189,6 +189,7 @@ end; (********************************************************************************************************************************) constructor TVFSPlugin.Create(PluginHandle: Pointer); +var s: PChar; begin inherited Create; ModuleHandle := PluginHandle; @@ -235,11 +236,24 @@ begin @FVFSGetPasswordRequired := dlsym(ModuleHandle, 'VFSGetPasswordRequired'); @FVFSSetCallbacks := dlsym(ModuleHandle, 'VFSSetCallbacks'); @FVFSResetPassword := dlsym(ModuleHandle, 'VFSResetPassword'); + // Initialize the extensions list SetLength(Extensions, 0); SetLength(Services, 0); - if @FVFSGetExts <> nil then ParseString(FVFSGetExts, ';', Extensions); - if @FVFSGetServices <> nil then ParseString(FVFSGetServices, ';', Services); + if @FVFSGetExts <> nil then begin + s := FVFSGetExts; + if s <> nil then begin + ParseString(String(s), ';', Extensions); + libc_free(s); + end; + end; + if @FVFSGetServices <> nil then begin + s := FVFSGetServices; + if s <> nil then begin + ParseString(String(s), ';', Services); + libc_free(s); + end; + end; end; destructor TVFSPlugin.Destroy; @@ -257,39 +271,53 @@ begin else Result := -1; end; +procedure _free_PVFSInfo(Info: PVFSInfo); +begin + if Info <> nil then begin + if Info^.Name <> nil then libc_free(Info^.Name); + if Info^.ID <> nil then libc_free(Info^.ID); + if Info^.About <> nil then libc_free(Info^.About); + if Info^.Copyright <> nil then libc_free(Info^.Copyright); + end; +end; + function TVFSPlugin.ModuleID: string; -var Info: TVFSInfo; +var Info: PVFSInfo; begin if @FVFSGetInfo <> nil then begin Info := FVFSGetInfo; Result := String(Info.ID); + _free_PVFSInfo(Info); end else Result := ''; end; function TVFSPlugin.ModuleName: string; -var Info: TVFSInfo; +var Info: PVFSInfo; begin if @FVFSGetInfo <> nil then begin Info := FVFSGetInfo; Result := String(Info.Name); + _free_PVFSInfo(Info); end else Result := ''; end; function TVFSPlugin.ModuleAbout: string; -var Info: TVFSInfo; +var Info: PVFSInfo; begin if @FVFSGetInfo <> nil then begin Info := FVFSGetInfo; Result := String(Info.About); + _free_PVFSInfo(Info); end else Result := ''; end; function TVFSPlugin.ModuleCopyright: string; -var Info: TVFSInfo; +var Info: PVFSInfo; begin if @FVFSGetInfo <> nil then begin Info := FVFSGetInfo; Result := String(Info.Copyright); + _free_PVFSInfo(Info); end else Result := ''; end; @@ -425,6 +453,9 @@ begin DebugMsg(['^^VFS (EE): GetListing: Item-Exception: ', E.Message]); end; end; // of if AddDotFiles + if P^.FName <> nil then libc_free(P^.FName); + if P^.FDisplayName <> nil then libc_free(P^.FDisplayName); + if P^.sLinkTo <> nil then libc_free(P^.sLinkTo); libc_free(P); // Not needed - just zero-erase the memory // DebugMsg(['Checkpoint 13']); P := malloc(SizeOf(TVFSItem)); @@ -505,26 +536,41 @@ begin end; function TVFSEngine.GetPrefix: string; +var s: PChar; begin - if (FGlobs <> nil) and (@FSourcePlugin.FVFSGetPrefix <> nil) - then Result := FSourcePlugin.FVFSGetPrefix(FGlobs) - else Result := 'VFS'; + Result := 'VFS'; + if (FGlobs <> nil) and (@FSourcePlugin.FVFSGetPrefix <> nil) then begin + s := FSourcePlugin.FVFSGetPrefix(FGlobs); + if s <> nil then begin + Result := String(s); + libc_free(s); + end; + end; end; function TVFSEngine.GetPath: string; +var s: PChar; begin - if (FGlobs <> nil) and (@FSourcePlugin.FVFSGetPath <> nil) - then Result := FSourcePlugin.FVFSGetPath(FGlobs) - else Result := '/'; + Result := '/'; + if (FGlobs <> nil) and (@FSourcePlugin.FVFSGetPath <> nil) then begin + s := FSourcePlugin.FVFSGetPath(FGlobs); + if s <> nil then begin + Result := String(s); + libc_free(s); + end; + end; end; function TVFSEngine.GetPathURI: string; -var x: PChar; +var s: PChar; begin Result := ''; if (FGlobs <> nil) and (@FSourcePlugin.FVFSGetPathURI <> nil) then begin - x := FSourcePlugin.FVFSGetPathURI(FGlobs); - if x <> nil then Result := string(x); + s := FSourcePlugin.FVFSGetPathURI(FGlobs); + if s <> nil then begin + Result := String(s); + libc_free(s); + end; end; end; @@ -624,6 +670,9 @@ begin GID := P^.iGID; Size := P^.iSize; PackedSize := P^.iPackedSize; + if P^.FName <> nil then libc_free(P^.FName); + if P^.FDisplayName <> nil then libc_free(P^.FDisplayName); + if P^.sLinkTo <> nil then libc_free(P^.sLinkTo); libc_free(P); end; Result := Item; @@ -704,6 +753,9 @@ begin Res := FSourcePlugin.FVFSFileInfo(FGlobs, PChar(APath), P); if Res <> cVFS_OK then DebugMsg(['*** FillDirFiles - VFSFileInfo(', APath, ') failed. Code = ', Res]); AddEntry(APath, True, True); + if P^.FName <> nil then libc_free(P^.FName); + if P^.FDisplayName <> nil then libc_free(P^.FDisplayName); + if P^.sLinkTo <> nil then libc_free(P^.sLinkTo); libc_free(P); APath := IncludeTrailingPathDelimiter(APath); @@ -717,6 +769,9 @@ begin Res := FSourcePlugin.FVFSListFirst(FGlobs, PChar(APath), P); if Res <> cVFS_OK then begin FSourcePlugin.FVFSListClose(FGlobs); + if P^.FName <> nil then libc_free(P^.FName); + if P^.FDisplayName <> nil then libc_free(P^.FDisplayName); + if P^.sLinkTo <> nil then libc_free(P^.sLinkTo); libc_free(P); Exit; end; @@ -725,12 +780,18 @@ begin if TVFSItemType(P^.ItemType) = vDirectory then LocalList.Add(APath + String(P^.FName)) else AddEntry(APath + String(P^.FName), False, True); + if P^.FName <> nil then libc_free(P^.FName); + if P^.FDisplayName <> nil then libc_free(P^.FDisplayName); + if P^.sLinkTo <> nil then libc_free(P^.sLinkTo); libc_free(P); P := malloc(SizeOf(TVFSItem)); memset(P, 0, SizeOf(TVFSItem)); Res := FSourcePlugin.FVFSListNext(FGlobs, PChar(GetPath), P); until (Res <> cVFS_OK); + if P^.FName <> nil then libc_free(P^.FName); + if P^.FDisplayName <> nil then libc_free(P^.FDisplayName); + if P^.sLinkTo <> nil then libc_free(P^.sLinkTo); libc_free(P); FSourcePlugin.FVFSListClose(FGlobs); @@ -750,6 +811,9 @@ begin Res := FSourcePlugin.FVFSFileInfo(FGlobs, PChar(APath), P); if Res <> cVFS_OK then DebugMsg(['*** FillDirFiles - VFSFileInfo(', APath, ') failed. Code = ', Res]); AddEntry(APath, True, False); + if P^.FName <> nil then libc_free(P^.FName); + if P^.FDisplayName <> nil then libc_free(P^.FDisplayName); + if P^.sLinkTo <> nil then libc_free(P^.sLinkTo); libc_free(P); LocalList.Free; diff --git a/vfs/uVFSprototypes.pas b/vfs/uVFSprototypes.pas index b454769..d236d01 100644 --- a/vfs/uVFSprototypes.pas +++ b/vfs/uVFSprototypes.pas @@ -80,9 +80,7 @@ const 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 + // Plugin private data for each connection/instance // File descriptor for Open, Read, Write, Close, Seek operations TVFSFileDes = Pointer; @@ -145,6 +143,7 @@ type end; // This structure contains basic informations about the plugin + PVFSInfo = ^TVFSInfo; TVFSInfo = record ID: PChar; // unique identifier, not shown in GUI Name: PChar; // plugin name, GUI string (UTF-8) @@ -187,7 +186,7 @@ type 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; + TVFSLogFunc = procedure(const S: PChar); cdecl; TVFSNew = function (LogFunc: PVFSLogFunc): TVFSGlobs; cdecl; // Allocates memory for the globs structure and performs intialization of the plugin @@ -196,16 +195,20 @@ type 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 // Please use the cVFSVersion constant as return value - TVFSGetInfo = function: TVFSInfo; cdecl; - // Returns the structure with module info + TVFSGetInfo = function: PVFSInfo; cdecl; + // Returns module info struct, tuxcmd will take care of memory deallocation 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") + // tuxcmd will take care of memory deallocation TVFSGetCharset = function (g:TVFSGlobs): PChar; cdecl; // TODO: Returns charset which the plugin uses + // tuxcmd will take care of memory deallocation TVFSGetExts = function: PChar; cdecl; // Returns the list of filename extensions which the module can handle separated by ';' (without a leading dots) + // tuxcmd will take care of memory deallocation TVFSGetServices = function: PChar; cdecl; // Returns the list of supported remote protocols separated by ';' (without the '://') + // tuxcmd will take care of memory deallocation TVFSCaps = function (const sExt: PChar): Integer; cdecl; // TODO: Returns a bit mask of plugin capabilities TVFSSetProtocolLogFunc = procedure (g:TVFSGlobs; ProtocolLogFunc: TVFSLogFunc); cdecl; @@ -236,14 +239,15 @@ type // 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) + // tuxcmd will take care of memory deallocation TVFSGetPathURI = function (g:TVFSGlobs): PChar; cdecl; // Returns the current working path in the URI form - // !!!!!!!!!!! k temhle (a vsem ostatnim) funkcim pridat komentar, kdo ma vubec pamet dealokovat + udelat review pluginus + // tuxcmd will take care of memory deallocation 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 + // Gets the filesystem label, tuxcmd will take care of memory deallocation 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) -- cgit v1.2.3