|
@@ -3,7 +3,7 @@
|
|
-------------------------------------------------------------------------
|
|
-------------------------------------------------------------------------
|
|
This is a thread-component sends an event when a change in the file system occurs.
|
|
This is a thread-component sends an event when a change in the file system occurs.
|
|
|
|
|
|
- Copyright (C) 2009-2021 Alexander Koblov ([email protected])
|
|
|
|
|
|
+ Copyright (C) 2009-2022 Alexander Koblov ([email protected])
|
|
Copyright (C) 2011 Przemyslaw Nagay ([email protected])
|
|
Copyright (C) 2011 Przemyslaw Nagay ([email protected])
|
|
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
This program is free software; you can redistribute it and/or modify
|
|
@@ -71,6 +71,7 @@ type
|
|
aWatcherEvent: TFSWatcherEvent);
|
|
aWatcherEvent: TFSWatcherEvent);
|
|
class procedure RemoveWatch(aWatcherEvent: TFSWatcherEvent);
|
|
class procedure RemoveWatch(aWatcherEvent: TFSWatcherEvent);
|
|
class function CanWatch(const WatchPaths: array of String): Boolean;
|
|
class function CanWatch(const WatchPaths: array of String): Boolean;
|
|
|
|
+ class function AvailableWatchFilter: TFSWatchFilter;
|
|
end;
|
|
end;
|
|
|
|
|
|
implementation
|
|
implementation
|
|
@@ -84,13 +85,33 @@ uses
|
|
, inotify, BaseUnix, FileUtil, DCConvertEncoding, DCUnix
|
|
, inotify, BaseUnix, FileUtil, DCConvertEncoding, DCUnix
|
|
{$ELSEIF DEFINED(BSD)}
|
|
{$ELSEIF DEFINED(BSD)}
|
|
, BSD, Unix, BaseUnix, UnixType, FileUtil, DCOSUtils
|
|
, BSD, Unix, BaseUnix, UnixType, FileUtil, DCOSUtils
|
|
|
|
+ {$ELSEIF DEFINED(HAIKU)}
|
|
|
|
+ , DCConvertEncoding
|
|
|
|
+ {$IF DEFINED(LCLQT5)}
|
|
|
|
+ , Qt5
|
|
|
|
+ {$ELSEIF DEFINED(LCLQT6)}
|
|
|
|
+ , Qt6
|
|
|
|
+ {$ENDIF}
|
|
{$ENDIF};
|
|
{$ENDIF};
|
|
|
|
|
|
|
|
+{$IF DEFINED(HAIKU) AND (DEFINED(LCLQT5) OR DEFINED(LCLQT6))}
|
|
|
|
+ {$DEFINE HAIKUQT}
|
|
|
|
+{$ENDIF}
|
|
|
|
+
|
|
{$if lcl_fullversion < 2030000}
|
|
{$if lcl_fullversion < 2030000}
|
|
{$macro on}
|
|
{$macro on}
|
|
{$define SameMethod:= CompareMethods}
|
|
{$define SameMethod:= CompareMethods}
|
|
{$endif}
|
|
{$endif}
|
|
|
|
|
|
|
|
+{$IF DEFINED(UNIX)}
|
|
|
|
+type
|
|
|
|
+ {$IF DEFINED(HAIKUQT)}
|
|
|
|
+ TNotifyHandle = QFileSystemWatcherH;
|
|
|
|
+ {$ELSE}
|
|
|
|
+ TNotifyHandle = THandle;
|
|
|
|
+ {$ENDIF}
|
|
|
|
+{$ENDIF}
|
|
|
|
+
|
|
{$IF DEFINED(MSWINDOWS)}
|
|
{$IF DEFINED(MSWINDOWS)}
|
|
const
|
|
const
|
|
// For each outstanding ReadDirectoryW a buffer of this size will be allocated
|
|
// For each outstanding ReadDirectoryW a buffer of this size will be allocated
|
|
@@ -148,7 +169,7 @@ type
|
|
FOldFileName: String; // for FILE_ACTION_RENAMED_OLD_NAME action
|
|
FOldFileName: String; // for FILE_ACTION_RENAMED_OLD_NAME action
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
{$IF DEFINED(UNIX)}
|
|
{$IF DEFINED(UNIX)}
|
|
- FNotifyHandle: THandle;
|
|
|
|
|
|
+ FNotifyHandle: TNotifyHandle;
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
procedure CreateHandle;
|
|
procedure CreateHandle;
|
|
procedure DestroyHandle;
|
|
procedure DestroyHandle;
|
|
@@ -159,7 +180,7 @@ type
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
public
|
|
public
|
|
constructor Create(const aWatchPath: String
|
|
constructor Create(const aWatchPath: String
|
|
- {$IFDEF UNIX}; aNotifyHandle: THandle{$ENDIF}); reintroduce;
|
|
|
|
|
|
+ {$IFDEF UNIX}; aNotifyHandle: TNotifyHandle{$ENDIF}); reintroduce;
|
|
destructor Destroy; override;
|
|
destructor Destroy; override;
|
|
procedure UpdateFilter;
|
|
procedure UpdateFilter;
|
|
{$IF DEFINED(MSWINDOWS)}
|
|
{$IF DEFINED(MSWINDOWS)}
|
|
@@ -179,14 +200,18 @@ type
|
|
FWatcherLock: syncobjs.TCriticalSection;
|
|
FWatcherLock: syncobjs.TCriticalSection;
|
|
FOSWatchers: TOSWatchs;
|
|
FOSWatchers: TOSWatchs;
|
|
{$IF DEFINED(UNIX)}
|
|
{$IF DEFINED(UNIX)}
|
|
- FNotifyHandle: THandle;
|
|
|
|
|
|
+ FNotifyHandle: TNotifyHandle;
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
{$IF DEFINED(LINUX)}
|
|
{$IF DEFINED(LINUX)}
|
|
FEventPipe: TFilDes;
|
|
FEventPipe: TFilDes;
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
FCurrentEventData: TFSWatcherEventData;
|
|
FCurrentEventData: TFSWatcherEventData;
|
|
FFinished: Boolean;
|
|
FFinished: Boolean;
|
|
-
|
|
|
|
|
|
+ {$IF DEFINED(HAIKUQT)}
|
|
|
|
+ FFinishEvent: TSimpleEvent;
|
|
|
|
+ FHook: QFileSystemWatcher_hookH;
|
|
|
|
+ procedure DirectoryChanged(Path: PWideString); cdecl;
|
|
|
|
+ {$ENDIF}
|
|
procedure DoWatcherEvent;
|
|
procedure DoWatcherEvent;
|
|
function GetWatchersCount: Integer;
|
|
function GetWatchersCount: Integer;
|
|
function GetWatchPath(var aWatchPath: String): Boolean;
|
|
function GetWatchPath(var aWatchPath: String): Boolean;
|
|
@@ -242,11 +267,6 @@ begin
|
|
begin
|
|
begin
|
|
DCDebug('Waiting for FileSystemWatcher thread');
|
|
DCDebug('Waiting for FileSystemWatcher thread');
|
|
FileSystemWatcher.Terminate;
|
|
FileSystemWatcher.Terminate;
|
|
- {$IF (fpc_version<2) or ((fpc_version=2) and (fpc_release<5))}
|
|
|
|
- If (MainThreadID=GetCurrentThreadID) then
|
|
|
|
- while not FileSystemWatcher.FFinished do
|
|
|
|
- CheckSynchronize(100);
|
|
|
|
- {$ENDIF}
|
|
|
|
FileSystemWatcher.WaitFor;
|
|
FileSystemWatcher.WaitFor;
|
|
FreeAndNil(FileSystemWatcher);
|
|
FreeAndNil(FileSystemWatcher);
|
|
end;
|
|
end;
|
|
@@ -305,6 +325,15 @@ begin
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
|
|
|
|
|
+class function TFileSystemWatcher.AvailableWatchFilter: TFSWatchFilter;
|
|
|
|
+begin
|
|
|
|
+ Result := [wfFileNameChange
|
|
|
|
+{$IF NOT DEFINED(HAIKUQT)}
|
|
|
|
+ , wfAttributesChange
|
|
|
|
+{$ENDIF}
|
|
|
|
+ ];
|
|
|
|
+end;
|
|
|
|
+
|
|
// ----------------------------------------------------------------------------
|
|
// ----------------------------------------------------------------------------
|
|
|
|
|
|
procedure ShowError(const sErrMsg: String);
|
|
procedure ShowError(const sErrMsg: String);
|
|
@@ -780,11 +809,32 @@ begin
|
|
end; { case }
|
|
end; { case }
|
|
end; { while }
|
|
end; { while }
|
|
end;
|
|
end;
|
|
|
|
+{$ELSEIF DEFINED(HAIKUQT)}
|
|
|
|
+begin
|
|
|
|
+ while not Terminated do
|
|
|
|
+ begin
|
|
|
|
+ FFinishEvent.WaitFor(INFINITE);
|
|
|
|
+ end;
|
|
|
|
+end;
|
|
{$ELSE}
|
|
{$ELSE}
|
|
begin
|
|
begin
|
|
end;
|
|
end;
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
|
|
|
|
|
+{$IF DEFINED(HAIKUQT)}
|
|
|
|
+procedure TFileSystemWatcherImpl.DirectoryChanged(Path: PWideString); cdecl;
|
|
|
|
+begin
|
|
|
|
+ FCurrentEventData.Path := CeUtf16ToUtf8(Path^);
|
|
|
|
+ FCurrentEventData.EventType := fswUnknownChange;
|
|
|
|
+ FCurrentEventData.FileName := EmptyStr;
|
|
|
|
+ FCurrentEventData.NewFileName := EmptyStr;
|
|
|
|
+ {$IFDEF DEBUG_WATCHER}
|
|
|
|
+ DCDebug('FSWatcher: Send event, Path %s', [FCurrentEventData.Path]);
|
|
|
|
+ {$ENDIF};
|
|
|
|
+ DoWatcherEvent;
|
|
|
|
+end;
|
|
|
|
+{$ENDIF}
|
|
|
|
+
|
|
procedure TFileSystemWatcherImpl.DoWatcherEvent;
|
|
procedure TFileSystemWatcherImpl.DoWatcherEvent;
|
|
var
|
|
var
|
|
i, j: Integer;
|
|
i, j: Integer;
|
|
@@ -892,17 +942,9 @@ end;
|
|
|
|
|
|
constructor TFileSystemWatcherImpl.Create;
|
|
constructor TFileSystemWatcherImpl.Create;
|
|
begin
|
|
begin
|
|
-{$IF (fpc_version<2) or ((fpc_version=2) and (fpc_release<5))}
|
|
|
|
- // Workaround for race condition, see FPC Mantis #16884.
|
|
|
|
- inherited Create(True);
|
|
|
|
-{$ELSE}
|
|
|
|
- inherited Create(False);
|
|
|
|
-{$ENDIF}
|
|
|
|
-
|
|
|
|
FOSWatchers := TOSWatchs.Create({$IFDEF MSWINDOWS}False{$ELSE}True{$ENDIF});
|
|
FOSWatchers := TOSWatchs.Create({$IFDEF MSWINDOWS}False{$ELSE}True{$ENDIF});
|
|
FWatcherLock := syncobjs.TCriticalSection.Create;
|
|
FWatcherLock := syncobjs.TCriticalSection.Create;
|
|
|
|
|
|
- FreeOnTerminate := False;
|
|
|
|
FFinished := False;
|
|
FFinished := False;
|
|
|
|
|
|
{$IF DEFINED(MSWINDOWS)}
|
|
{$IF DEFINED(MSWINDOWS)}
|
|
@@ -942,13 +984,18 @@ begin
|
|
FNotifyHandle := kqueue();
|
|
FNotifyHandle := kqueue();
|
|
if FNotifyHandle = feInvalidHandle then
|
|
if FNotifyHandle = feInvalidHandle then
|
|
ShowError('kqueue() failed');
|
|
ShowError('kqueue() failed');
|
|
|
|
+ {$ELSEIF DEFINED(HAIKUQT)}
|
|
|
|
+ FFinishEvent:= TSimpleEvent.Create;
|
|
|
|
+ FNotifyHandle:= QFileSystemWatcher_Create();
|
|
|
|
+ FHook:= QFileSystemWatcher_hook_Create(FNotifyHandle);
|
|
|
|
+ QFileSystemWatcher_hook_hook_directoryChanged(FHook, @DirectoryChanged);
|
|
{$ELSEIF DEFINED(UNIX)}
|
|
{$ELSEIF DEFINED(UNIX)}
|
|
FNotifyHandle := feInvalidHandle;
|
|
FNotifyHandle := feInvalidHandle;
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
|
|
|
-{$IF (fpc_version<2) or ((fpc_version=2) and (fpc_release<5))}
|
|
|
|
- Resume;
|
|
|
|
-{$ENDIF}
|
|
|
|
|
|
+ inherited Create(False);
|
|
|
|
+
|
|
|
|
+ FreeOnTerminate := False;
|
|
end;
|
|
end;
|
|
|
|
|
|
destructor TFileSystemWatcherImpl.Destroy;
|
|
destructor TFileSystemWatcherImpl.Destroy;
|
|
@@ -976,6 +1023,11 @@ begin
|
|
FileClose(FNotifyHandle);
|
|
FileClose(FNotifyHandle);
|
|
FNotifyHandle := feInvalidHandle;
|
|
FNotifyHandle := feInvalidHandle;
|
|
end;
|
|
end;
|
|
|
|
+ {$ELSEIF DEFINED(HAIKUQT)}
|
|
|
|
+ QFileSystemWatcher_hook_hook_directoryChanged(FHook, nil);
|
|
|
|
+ QFileSystemWatcher_hook_Destroy(FHook);
|
|
|
|
+ QFileSystemWatcher_Destroy(FNotifyHandle);
|
|
|
|
+ FreeAndNil(FFinishEvent);
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
|
|
|
if Assigned(FOSWatchers) then
|
|
if Assigned(FOSWatchers) then
|
|
@@ -1214,6 +1266,10 @@ begin
|
|
end; { if }
|
|
end; { if }
|
|
end; { if }
|
|
end; { if }
|
|
end;
|
|
end;
|
|
|
|
+{$ELSEIF DEFINED(HAIKUQT)}
|
|
|
|
+begin
|
|
|
|
+ FFinishEvent.SetEvent;
|
|
|
|
+end;
|
|
{$ELSE}
|
|
{$ELSE}
|
|
begin
|
|
begin
|
|
end;
|
|
end;
|
|
@@ -1224,7 +1280,7 @@ end;
|
|
{ TOSWatch }
|
|
{ TOSWatch }
|
|
|
|
|
|
constructor TOSWatch.Create(const aWatchPath: String
|
|
constructor TOSWatch.Create(const aWatchPath: String
|
|
- {$IFDEF UNIX}; aNotifyHandle: THandle{$ENDIF});
|
|
|
|
|
|
+ {$IFDEF UNIX}; aNotifyHandle: TNotifyHandle{$ENDIF});
|
|
begin
|
|
begin
|
|
FObservers := TOSWatchObservers.Create(True);
|
|
FObservers := TOSWatchObservers.Create(True);
|
|
FWatchFilter := [];
|
|
FWatchFilter := [];
|
|
@@ -1389,6 +1445,17 @@ begin
|
|
end; { if }
|
|
end; { if }
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
+{$ELSEIF DEFINED(HAIKUQT)}
|
|
|
|
+var
|
|
|
|
+ APath: WideString;
|
|
|
|
+begin
|
|
|
|
+ FHandle := 1;
|
|
|
|
+ APath := CeUtf8ToUtf16(FWatchPath);
|
|
|
|
+ {$IFDEF DEBUG_WATCHER}
|
|
|
|
+ DCDebug('FSWatcher: Add watch ', FWatchPath);
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ QFileSystemWatcher_addPath(FNotifyHandle, @APath);
|
|
|
|
+end;
|
|
{$ELSE}
|
|
{$ELSE}
|
|
begin
|
|
begin
|
|
FHandle := feInvalidHandle;
|
|
FHandle := feInvalidHandle;
|
|
@@ -1399,6 +1466,9 @@ procedure TOSWatch.DestroyHandle;
|
|
{$IF DEFINED(MSWINDOWS)}
|
|
{$IF DEFINED(MSWINDOWS)}
|
|
var
|
|
var
|
|
tmpHandle: THandle;
|
|
tmpHandle: THandle;
|
|
|
|
+{$ELSEIF DEFINED(HAIKUQT)}
|
|
|
|
+var
|
|
|
|
+ APath: WideString;
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
begin
|
|
begin
|
|
if FHandle <> feInvalidHandle then
|
|
if FHandle <> feInvalidHandle then
|
|
@@ -1420,6 +1490,13 @@ begin
|
|
tmpHandle := FHandle;
|
|
tmpHandle := FHandle;
|
|
FHandle := feInvalidHandle;
|
|
FHandle := feInvalidHandle;
|
|
CloseHandle(tmpHandle);
|
|
CloseHandle(tmpHandle);
|
|
|
|
+ {$ELSEIF DEFINED(HAIKUQT)}
|
|
|
|
+ FHandle := feInvalidHandle;
|
|
|
|
+ APath := CeUtf8ToUtf16(FWatchPath);
|
|
|
|
+ {$IFDEF DEBUG_WATCHER}
|
|
|
|
+ DCDebug('FSWatcher: Remove watch ', FWatchPath);
|
|
|
|
+ {$ENDIF}
|
|
|
|
+ QFileSystemWatcher_removePath(FNotifyHandle, @APath);
|
|
{$ELSE}
|
|
{$ELSE}
|
|
FHandle := feInvalidHandle;
|
|
FHandle := feInvalidHandle;
|
|
{$ENDIF}
|
|
{$ENDIF}
|