Differenze tra le versioni di "Sapere se un file di nome sconosciuto è stato creato o distrutto"

Da Gambas-it.org - Wikipedia.
 
Riga 3: Riga 3:
  
 
Per mostrare un primo esempio meramente dimostrativo, faremo l'esempio della immediata verifica della creazione nella cartella "''/dev/pts''" del file speciale di tipo ''pts'' di un Terminale nel momento in cui tale Terminale viene aperto:
 
Per mostrare un primo esempio meramente dimostrativo, faremo l'esempio della immediata verifica della creazione nella cartella "''/dev/pts''" del file speciale di tipo ''pts'' di un Terminale nel momento in cui tale Terminale viene aperto:
  '''Public''' Sub Form_Open()
+
  Public Sub Form_Open()
 
   
 
   
 
   Dim b As Byte
 
   Dim b As Byte
Riga 9: Riga 9:
 
   Dim s, dr As String
 
   Dim s, dr As String
 
    
 
    
  dr = "/dev/pts"
+
  dr = "/dev/pts"
 
    
 
    
 
  <FONT color=gray>' ''Assegna ad una variabile vettoriale il nome dei file presenti nella cartella "/dev/pts":''</font>
 
  <FONT color=gray>' ''Assegna ad una variabile vettoriale il nome dei file presenti nella cartella "/dev/pts":''</font>
  b = Dir(dr, Null, gb.Device).Copy()
+
  b = Dir(dr, Null, gb.Device).Copy()
 
   
 
   
 
  <FONT color=gray>' ''Resta in attesa sino a quando un Terminale non è stato aperto:''</font>
 
  <FONT color=gray>' ''Resta in attesa sino a quando un Terminale non è stato aperto:''</font>
  Do
+
  Repeat
    Wait 0.01
+
    Wait 0.01
  Loop Until Dir(dr, Null, gb.Device).Count = ss.Count + 1
+
  Until Dir(dr, Null, gb.Device).Count = ss.Count + 1
 
   
 
   
 
  <FONT color=gray>' ''Effettua la verifica di quale file speciale di tipo "pts" corrisponde a quello del Terminale appena aperto:''
 
  <FONT color=gray>' ''Effettua la verifica di quale file speciale di tipo "pts" corrisponde a quello del Terminale appena aperto:''
 
  ' ''il nuovo file "pts", non presente nella variabile vettore di tipo stringa, è quello del Terminale:''</font>
 
  ' ''il nuovo file "pts", non presente nella variabile vettore di tipo stringa, è quello del Terminale:''</font>
    For Each s In Dir(dr, Null, gb.Device)
+
  For Each s In Dir(dr, Null, gb.Device)
      If Not ss.Exist(s) Then Exit
+
    If Not ss.Exist(s) Then Exit
    Next
+
  Next
 
      
 
      
    Print s
+
  Print s
 
   
 
   
  '''End'''
+
  End
  
  
Riga 40: Riga 40:
 
   
 
   
 
   
 
   
  '''Public''' Sub Main()
+
  Public Sub Main()
 
    
 
    
 
   w = New Watch("/tmp") As "Cartella"
 
   w = New Watch("/tmp") As "Cartella"
 
    
 
    
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Public''' Sub Cartella_Create()
+
  Public Sub Cartella_Create()
 
    
 
    
 
   Print "Creato: "; Watch.Name
 
   Print "Creato: "; Watch.Name
 
    
 
    
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Public''' Sub Cartella_Delete()
+
  Public Sub Cartella_Delete()
 
    
 
    
 
   Print "Distrutto: "; Watch.Name
 
   Print "Distrutto: "; Watch.Name
 
    
 
    
  '''End'''
+
  End
  
  
Riga 68: Riga 68:
 
   
 
   
 
   
 
   
  '''Public''' Sub Main()
+
  Public Sub Main()
 
    
 
    
 
   Dim b As Byte
 
   Dim b As Byte
 
   Dim ss As New String[]
 
   Dim ss As New String[]
 
    
 
    
  dr = "/tmp"
+
  dr = "/tmp"
  ss = Dir(dr, Null, gb.File).Copy()
+
  ss = Dir(dr, Null, gb.File).Copy()
 
    
 
    
  With tempus = New Timer As "Tempus"
+
  With tempus = New Timer As "Tempus"
    .Delay = 100
+
    .Delay = 100
    .Start
+
    .Start
  End With
+
  End With
 
    
 
    
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Public''' Sub Tempus_Timer()
+
  Public Sub Tempus_Timer()
 
    
 
    
 
   Dim b As Byte
 
   Dim b As Byte
 
   Dim s As String
 
   Dim s As String
 
    
 
    
  If ss.Count <> Dir(dr, Null, gb.File).Count Then
+
  If ss.Count <> Dir(dr, Null, gb.File).Count Then
    For Each s In Dir(dr, Null, gb.File)
+
    For Each s In Dir(dr, Null, gb.File)
      If Not ss.Exist(s) Then
+
      If Not ss.Exist(s) Then
        Print "\nCreato il file: "; s
+
        Print "\nCreato il file: "; s
        ss = Dir(dr, Null, gb.File).Copy()
+
        ss = Dir(dr, Null, gb.File).Copy()
      Endif
+
      Endif
    Next
+
    Next
    For Each s In ss
+
    For Each s In ss
      If Not Exist(dr &/ s) Then
+
      If Not Exist(dr &/ s) Then
        Print "\nDistrutto il file: "; s
+
        Print "\nDistrutto il file: "; s
        ss = Dir(dr, Null, gb.File).Copy()
+
        ss = Dir(dr, Null, gb.File).Copy()
      Endif
+
      Endif
    Next
+
    Next
  Endif
+
  Endif
 
    
 
    
  '''End'''
+
  End
  
  
Riga 110: Riga 110:
 
==Uso delle risorse del API di ''inotify''==
 
==Uso delle risorse del API di ''inotify''==
 
E' possibile anche utilizzare le risorse ''inotify'', dichiarate nel file header ''sys/inotify.h'' .
 
E' possibile anche utilizzare le risorse ''inotify'', dichiarate nel file header ''sys/inotify.h'' .
 +
<BR>Va ricordato che vari pseudo-filesystem come "/proc", "/sys" e "/dev/pts" non sono monitorabili con ''inotify''.
  
 
Mostriamo un esempio, nel quale si verificheranno la creazione e la distruzione di un determinato file mediante due ''Button'':
 
Mostriamo un esempio, nel quale si verificheranno la creazione e la distruzione di un determinato file mediante due ''Button'':
Riga 177: Riga 178:
 
   
 
   
 
   
 
   
  '''Public''' Sub Form_Open()
+
  Public Sub Form_Open()
 
    
 
    
 
   Dim percorso_file As String
 
   Dim percorso_file As String
Riga 186: Riga 187:
 
   Dim pl As New Pollfd
 
   Dim pl As New Pollfd
 
    
 
    
  Me.Show
+
  Me.Show
 
    
 
    
 
  <FONT Color=gray>' '' == Poniamo sotto osservazione la Cartella "/tmp", qualora venga creato o venga distrutto un file ==''</font>
 
  <FONT Color=gray>' '' == Poniamo sotto osservazione la Cartella "/tmp", qualora venga creato o venga distrutto un file ==''</font>
 
    
 
    
  percorso_file = "/tmp"
+
  percorso_file = "/tmp"
 
      
 
      
  fd = inotify_init()
+
  fd = inotify_init()
  If fd = -1 Then Error.Raise("Impossibile inizializare 'inotify' !")
+
  If fd = -1 Then Error.Raise("Impossibile inizializare 'inotify' !")
 
      
 
      
  wa = inotify_add_watch(fd, percorso_file, IN_ALL_EVENTS)
+
  wa = inotify_add_watch(fd, percorso_file, IN_ALL_EVENTS)
  If wa = -1 Then Error.Raise("Errore alla funzione esterna 'inotify_add_watch()' !")
+
  If wa = -1 Then Error.Raise("Errore alla funzione esterna 'inotify_add_watch()' !")
 
      
 
      
  Print "Cartella '"; percorso_file; "' ...sotto osservazione !\n"
+
  Print "Cartella '"; percorso_file; "' ...sotto osservazione !\n"
 
      
 
      
  buf = Alloc(CInt(BUFFER))
+
  buf = Alloc(CInt(BUFFER))
 
    
 
    
  While bo = False
+
  While bo = False  
     
+
    pl.fd = fd
    pl.fd = fd
+
    pl.events = POLLIN
    pl.events = POLLIN
+
    letti = poll(pl, 1, 100)
   
+
    Select Case letti
    letti = poll(pl, 1, 100)
+
      Case -1
    Select Case letti
+
        Error.Raise("Errore alla funzione esterna 'poll()' !")
      Case -1
+
      Case 1
        Error.Raise("Errore alla funzione esterna 'poll()' !")
+
        letti = read_C(fd, buf, BUFFER)
      Case 1
+
        If letti = -1 Then Error.Raise("Errore alla funzione esterna 'read_C()' !")
        letti = read_C(fd, buf, BUFFER)
+
    End Select
        If letti = -1 Then Error.Raise("Errore alla funzione esterna 'read_C()' !")
+
    p = buf
    End Select
+
    While p < buf + CInt(letti)
   
+
      evento = p
    p = buf
+
      If evento.mask And IN_CREATE Then Print "Creato il nuevo file: "; String@(evento.name.Data)
     
+
      If evento.mask And IN_DELETE Then Print "Eliminato il file: "; String@(evento.name.Data)
    While p < buf + CInt(letti)
+
      If evento.mask And IN_MOVED_FROM Then Print "Spostato nel cestino il file: "; String@(evento.name.Data)
      evento = p
+
      p += 16 + evento.lenI
      If evento.mask And IN_CREATE Then Print "Creato il nuevo file: "; String@(evento.name.Data)
+
    Wend
      If evento.mask And IN_DELETE Then Print "Eliminato il file: "; String@(evento.name.Data)
+
    Wait 0.1
      If evento.mask And IN_MOVED_FROM Then Print "Spostato nel cestino il file: "; String@(evento.name.Data)
+
  Wend
      p += 16 + evento.lenI
 
    Wend
 
     
 
    Wait 0.1
 
     
 
  Wend
 
 
      
 
      
 
 
 
  <FONT Color=gray>' ''Libera memoria in chiusura:''</font>
 
  <FONT Color=gray>' ''Libera memoria in chiusura:''</font>
  Free(buf)
+
  Free(buf)
  inotify_rm_watch(fd, wa)
+
  inotify_rm_watch(fd, wa)
  close_C(fd)
+
  close_C(fd)
  Me.Close
+
  Me.Close
 
    
 
    
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Public''' Sub Button1_Click()
+
  Public Sub Button1_Click()
 
    
 
    
 
  <FONT Color=gray>' ''Va in chiusura...''</font>
 
  <FONT Color=gray>' ''Va in chiusura...''</font>
  bo = True
+
  bo = True
 
        
 
        
  '''End'''
+
  End
 
 
 
 
 
Il precedente codice può essere ovviamente inserito - con le dovute variazioni - anche in un'applicazione ''a riga di comando'':
 
Il precedente codice può essere ovviamente inserito - con le dovute variazioni - anche in un'applicazione ''a riga di comando'':
 
  Private Const BUFFER As Long = 4096
 
  Private Const BUFFER As Long = 4096
Riga 314: Riga 306:
 
   
 
   
 
   
 
   
  '''Public''' Sub Main()
+
  Public Sub Main()
 
    
 
    
 
   Dim percorso_file As String
 
   Dim percorso_file As String
Riga 325: Riga 317:
 
  <FONT Color=gray>' '' == Poniamo sotto osservazione la Cartella "/tmp", qualora venga creato o venga distrutto un file ==''</font>
 
  <FONT Color=gray>' '' == Poniamo sotto osservazione la Cartella "/tmp", qualora venga creato o venga distrutto un file ==''</font>
 
    
 
    
  percorso_file = "/tmp"
+
  percorso_file = "/tmp"
 
      
 
      
  fd = inotify_init()
+
  fd = inotify_init()
  If fd = -1 Then Error.Raise("Impossibile inizializare 'inotify' !")
+
  If fd = -1 Then Error.Raise("Impossibile inizializare 'inotify' !")
 
      
 
      
  wa = inotify_add_watch(fd, percorso_file, IN_ALL_EVENTS)
+
  wa = inotify_add_watch(fd, percorso_file, IN_ALL_EVENTS)
  If wa = -1 Then Error.Raise("Errore alla funzione esterna 'inotify_add_watch()' !")
+
  If wa = -1 Then Error.Raise("Errore alla funzione esterna 'inotify_add_watch()' !")
 
      
 
      
  Print "Cartella '"; percorso_file; "' ...sotto osservazione !\n"
+
  Print "Cartella '"; percorso_file; "' ...sotto osservazione !\n"
 
      
 
      
  buf = Alloc(CInt(BUFFER))
+
  buf = Alloc(CInt(BUFFER))
 
    
 
    
  While bo = False
+
  While bo = False
     
+
    pl.fd = fd
    pl.fd = fd
+
    pl.events = POLLIN
    pl.events = POLLIN
+
    letti = poll(pl, 1, 100)
   
+
    Select Case letti
    letti = poll(pl, 1, 100)
+
      Case -1
    Select Case letti
+
        Error.Raise("Errore alla funzione esterna 'poll()' !")
      Case -1
+
      Case 1
        Error.Raise("Errore alla funzione esterna 'poll()' !")
+
        letti = read_C(fd, buf, BUFFER)
      Case 1
+
        If letti = -1 Then Error.Raise("Errore alla funzione esterna 'read_C()' !")
        letti = read_C(fd, buf, BUFFER)
+
    End Select
        If letti = -1 Then Error.Raise("Errore alla funzione esterna 'read_C()' !")
+
    p = buf
    End Select
+
    While p < buf + CInt(letti)
   
+
      evento = p
    p = buf
+
      If evento.mask And IN_CREATE Then Print "Creato il nuevo file: "; String@(evento.name.Data)
     
+
      If evento.mask And IN_DELETE Then Print "Eliminato il file: "; String@(evento.name.Data)
    While p < buf + CInt(letti)
+
      If evento.mask And IN_MOVED_FROM Then Print "Spostato nel cestino il file: "; String@(evento.name.Data)
      evento = p
+
      p += 16 + evento.lenI
      If evento.mask And IN_CREATE Then Print "Creato il nuevo file: "; String@(evento.name.Data)
+
    Wend
      If evento.mask And IN_DELETE Then Print "Eliminato il file: "; String@(evento.name.Data)
+
    Wait 0.1
      If evento.mask And IN_MOVED_FROM Then Print "Spostato nel cestino il file: "; String@(evento.name.Data)
+
  Wend
      p += 16 + evento.lenI
 
    Wend
 
     
 
    Wait 0.1
 
     
 
  Wend
 
 
      
 
      
 
 
 
  <FONT Color=gray>' ''Libera memoria in chiusura:''</font>
 
  <FONT Color=gray>' ''Libera memoria in chiusura:''</font>
  Free(buf)
+
  Free(buf)
  inotify_rm_watch(fd, wa)
+
  inotify_rm_watch(fd, wa)
  close_C(fd)
+
  close_C(fd)
  Quit
+
  Quit
 
    
 
    
  '''End'''
+
  End
 
   
 
   
 
   
 
   
  '''Public''' Sub Application_Read()
+
  Public Sub Application_Read()
 
    
 
    
  <FONT Color=gray>' ''Se si pone il puntatore del mouse nello spazio al di sotto della console''
+
  <FONT Color=gray>' ''Se si pone il puntatore del mouse nello spazio al di sotto della console e si preme il tasto "Invio" della tastiera, allora il programma va in chiusura...''</font>
' ''e si preme il tasto "Invio" della tastiera, allora il programma va in chiusura...''</font>
+
  bo = True
  bo = True
 
 
        
 
        
  '''End'''
+
  End

Versione attuale delle 05:59, 12 set 2023

Può accadere che si voglia sapere se un qualsiasi file, del quale non è conosciuto a priori il nome, sia stato creato o distrutto all'interno di una determinata Cartella.


Per mostrare un primo esempio meramente dimostrativo, faremo l'esempio della immediata verifica della creazione nella cartella "/dev/pts" del file speciale di tipo pts di un Terminale nel momento in cui tale Terminale viene aperto:

Public Sub Form_Open()

 Dim b As Byte
 Dim ss As New String[]
 Dim s, dr As String
 
 dr = "/dev/pts"
 
' Assegna ad una variabile vettoriale il nome dei file presenti nella cartella "/dev/pts":
 b = Dir(dr, Null, gb.Device).Copy()

' Resta in attesa sino a quando un Terminale non è stato aperto:
 Repeat
   Wait 0.01
 Until Dir(dr, Null, gb.Device).Count = ss.Count + 1

' Effettua la verifica di quale file speciale di tipo "pts" corrisponde a quello del Terminale appena aperto:
' il nuovo file "pts", non presente nella variabile vettore di tipo stringa, è quello del Terminale:
 For Each s In Dir(dr, Null, gb.Device)
   If Not ss.Exist(s) Then Exit
 Next
   
 Print s

End


Verificare la creazione e/o la distruzione di un file

Per verificare se un elemento sia stato creato oppure distrutto, se già esistente, all'interno di una cartella, è possibile utilizzare almeno due modalità.

Uso della Classe Watch

La prima modalità prevede l'uso della Classe "Watch" mediante l'attivazione del Componente "gb.inotify".

Mostriamo un esempio pratico:

Private w As Watch


Public Sub Main()
 
 w = New Watch("/tmp") As "Cartella"
  
End


Public Sub Cartella_Create()
 
 Print "Creato: "; Watch.Name
 
End


Public Sub Cartella_Delete()
 
 Print "Distrutto: "; Watch.Name
 
End


Uso della Classe Timer

Quest'altra modalità prevede l'uso della Classe Timer per verificare la creazione e/o la distruzione di un file all'interno ad esempio della Cartella "/tmp". L'uso dell'oggetto Timer, ci consentirà di non chiudere il programma all'interno di un ciclo infinito.

Private tempus As Timer
Private ss As New String[]
Private dr As String


Public Sub Main()
 
 Dim b As Byte
 Dim ss As New String[]
  
 dr = "/tmp"
 ss = Dir(dr, Null, gb.File).Copy()
  
 With tempus = New Timer As "Tempus"
   .Delay = 100
   .Start
 End With
  
End


Public Sub Tempus_Timer()
 
 Dim b As Byte
 Dim s As String
 
 If ss.Count <> Dir(dr, Null, gb.File).Count Then
   For Each s In Dir(dr, Null, gb.File)
     If Not ss.Exist(s) Then
       Print "\nCreato il file: "; s
       ss = Dir(dr, Null, gb.File).Copy()
     Endif
   Next
   For Each s In ss
     If Not Exist(dr &/ s) Then
       Print "\nDistrutto il file: "; s
       ss = Dir(dr, Null, gb.File).Copy()
     Endif
   Next
 Endif
  
End


Uso delle risorse del API di inotify

E' possibile anche utilizzare le risorse inotify, dichiarate nel file header sys/inotify.h .
Va ricordato che vari pseudo-filesystem come "/proc", "/sys" e "/dev/pts" non sono monitorabili con inotify.

Mostriamo un esempio, nel quale si verificheranno la creazione e la distruzione di un determinato file mediante due Button:

Private Const BUFFER As Long = 4096
Private bo As Boolean


Library "libc:6"

Public Struct inotify_event
  wd As Integer
  mask As Integer
  cookie As Integer
  lenI As Integer
  name[32] As Byte
End Struct

Public Struct pollfd
  fd As Integer
  events As Short
  revents As Short
End Struct

Private Const IN_ACCESS As Integer = 1          ' File was accessed.
Private Const IN_MODIFY As Integer = 2          ' File was modified.
Private Const IN_ATTRIB As Integer = 4          ' Metadata changed.
Private Const IN_CLOSE_WRITE As Integer = 8     ' Writtable file was closed.
Private Const IN_CLOSE_NOWRITE As Integer = &10 ' Unwrittable file closed.
Private Const IN_OPEN As Integer = &20          ' File was opened.
Private Const IN_MOVED_FROM As Integer = &40    ' File was moved From X.
Private Const IN_MOVED_TO As Integer = &80      ' File was moved To Y.
Private Const IN_CREATE As Integer = &100       ' Subfile was created.
Private Const IN_DELETE As Integer = &200       ' Subfile was deleted.
Private Const IN_DELETE_SELF As Integer = &400  ' Self was deleted.
Private Const IN_MOVE_SELF As Integer = &800    ' Self was moved.
Private Const IN_UNMOUNT As Integer = &2000     ' Backing fs was unmounted.
Private Const IN_Q_OVERFLOW As Integer = &4000  ' Event queued overflowed.
Private Const IN_IGNORED As Integer = &8000     ' File was ignored.
Private Const IN_ISDIR As Integer = &40000000   ' Event occurred against dir.
Private Const IN_ALL_EVENTS As Integer = 4095

Private Const POLLIN As Short = 1

' int inotify_init (void)
' Create and initialize inotify instance.
Private Extern inotify_init() As Integer

' int inotify_add_watch (int __fd, const char *__name, uint32_t __mask)
' Add watch of object NAME to inotify instance FD.
Private Extern inotify_add_watch(__fd As Integer, name As String, __mask As Integer) As Integer

' int inotify_rm_watch (int __fd, int __wd)
' Remove the watch specified by WD from the inotify instance FD.
Private Extern inotify_rm_watch(__fd As Integer, __wd As Integer) As Integer

' int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
' Poll the file descriptors described by the NFDS structures starting at FDS.
Private Extern poll(__fds As Pollfd, __nfds As Long, __timeout As Integer) As Integer

' ssize_t read (int __fd, void *__buf, size_t __nbytes)
' Read NBYTES into BUF from FD.
Private Extern read_C(__fd As Integer, __buf As Pointer, __nbytes As Long) As Long Exec "read"

' int close (int __fd)
' Close the file descriptor FD.
Private Extern close_C(__fd As Integer) As Integer Exec "close"


Public Sub Form_Open()
 
 Dim percorso_file As String
 Dim fd, wa As Integer
 Dim buf, p As Pointer
 Dim letti As Long
 Dim evento As New Inotify_event
 Dim pl As New Pollfd
 
 Me.Show
  
'  == Poniamo sotto osservazione la Cartella "/tmp", qualora venga creato o venga distrutto un file ==
  
 percorso_file = "/tmp"
   
 fd = inotify_init()
 If fd = -1 Then Error.Raise("Impossibile inizializare 'inotify' !")
   
 wa = inotify_add_watch(fd, percorso_file, IN_ALL_EVENTS)
 If wa = -1 Then Error.Raise("Errore alla funzione esterna 'inotify_add_watch()' !")
   
 Print "Cartella '"; percorso_file; "' ...sotto osservazione !\n"
   
 buf = Alloc(CInt(BUFFER))
  
 While bo = False    
   pl.fd = fd
   pl.events = POLLIN
   letti = poll(pl, 1, 100)
   Select Case letti
     Case -1
       Error.Raise("Errore alla funzione esterna 'poll()' !")
     Case 1
       letti = read_C(fd, buf, BUFFER)
       If letti = -1 Then Error.Raise("Errore alla funzione esterna 'read_C()' !")
   End Select
   p = buf
   While p < buf + CInt(letti)
     evento = p
     If evento.mask And IN_CREATE Then Print "Creato il nuevo file: "; String@(evento.name.Data)
     If evento.mask And IN_DELETE Then Print "Eliminato il file: "; String@(evento.name.Data)
     If evento.mask And IN_MOVED_FROM Then Print "Spostato nel cestino il file: "; String@(evento.name.Data)
     p += 16 + evento.lenI
   Wend
   Wait 0.1
 Wend
   
' Libera memoria in chiusura:
 Free(buf)
 inotify_rm_watch(fd, wa)
 close_C(fd)
 Me.Close
  
End


Public Sub Button1_Click()
  
' Va in chiusura...
 bo = True
     
End

Il precedente codice può essere ovviamente inserito - con le dovute variazioni - anche in un'applicazione a riga di comando:

Private Const BUFFER As Long = 4096
Private bo As Boolean


Library "libc:6"

Public Struct inotify_event
  wd As Integer
  mask As Integer
  cookie As Integer
  lenI As Integer
  name[32] As Byte
End Struct

Public Struct pollfd
  fd As Integer
  events As Short
  revents As Short
End Struct

Private Const IN_ACCESS As Integer = 1          ' File was accessed.
Private Const IN_MODIFY As Integer = 2          ' File was modified.
Private Const IN_ATTRIB As Integer = 4          ' Metadata changed.
Private Const IN_CLOSE_WRITE As Integer = 8     ' Writtable file was closed.
Private Const IN_CLOSE_NOWRITE As Integer = &10 ' Unwrittable file closed.
Private Const IN_OPEN As Integer = &20          ' File was opened.
Private Const IN_MOVED_FROM As Integer = &40    ' File was moved From X.
Private Const IN_MOVED_TO As Integer = &80      ' File was moved To Y.
Private Const IN_CREATE As Integer = &100       ' Subfile was created.
Private Const IN_DELETE As Integer = &200       ' Subfile was deleted.
Private Const IN_DELETE_SELF As Integer = &400  ' Self was deleted.
Private Const IN_MOVE_SELF As Integer = &800    ' Self was moved.
Private Const IN_UNMOUNT As Integer = &2000     ' Backing fs was unmounted.
Private Const IN_Q_OVERFLOW As Integer = &4000  ' Event queued overflowed.
Private Const IN_IGNORED As Integer = &8000     ' File was ignored.
Private Const IN_ISDIR As Integer = &40000000   ' Event occurred against dir.
Private Const IN_ALL_EVENTS As Integer = 4095

Private Const POLLIN As Short = 1

' int inotify_init (void)
' Create and initialize inotify instance.
Private Extern inotify_init() As Integer

' int inotify_add_watch (int __fd, const char *__name, uint32_t __mask)
' Add watch of object NAME to inotify instance FD.
Private Extern inotify_add_watch(__fd As Integer, name As String, __mask As Integer) As Integer

' int inotify_rm_watch (int __fd, int __wd)
' Remove the watch specified by WD from the inotify instance FD.
Private Extern inotify_rm_watch(__fd As Integer, __wd As Integer) As Integer

' int poll (struct pollfd *__fds, nfds_t __nfds, int __timeout)
' Poll the file descriptors described by the NFDS structures starting at FDS.
Private Extern poll(__fds As Pollfd, __nfds As Long, __timeout As Integer) As Integer

' ssize_t read (int __fd, void *__buf, size_t __nbytes)
' Read NBYTES into BUF from FD.
Private Extern read_C(__fd As Integer, __buf As Pointer, __nbytes As Long) As Long Exec "read"

' int close (int __fd)
' Close the file descriptor FD.
Private Extern close_C(__fd As Integer) As Integer Exec "close"


Public Sub Main()
 
 Dim percorso_file As String
 Dim fd, wa As Integer
 Dim buf, p As Pointer
 Dim letti As Long
 Dim evento As New Inotify_event
 Dim pl As New Pollfd
  
'  == Poniamo sotto osservazione la Cartella "/tmp", qualora venga creato o venga distrutto un file ==
  
 percorso_file = "/tmp"
   
 fd = inotify_init()
 If fd = -1 Then Error.Raise("Impossibile inizializare 'inotify' !")
   
 wa = inotify_add_watch(fd, percorso_file, IN_ALL_EVENTS)
 If wa = -1 Then Error.Raise("Errore alla funzione esterna 'inotify_add_watch()' !")
   
 Print "Cartella '"; percorso_file; "' ...sotto osservazione !\n"
   
 buf = Alloc(CInt(BUFFER))
  
 While bo = False
   pl.fd = fd
   pl.events = POLLIN
   letti = poll(pl, 1, 100)
   Select Case letti
     Case -1
       Error.Raise("Errore alla funzione esterna 'poll()' !")
     Case 1
       letti = read_C(fd, buf, BUFFER)
       If letti = -1 Then Error.Raise("Errore alla funzione esterna 'read_C()' !")
   End Select
   p = buf
   While p < buf + CInt(letti)
     evento = p
     If evento.mask And IN_CREATE Then Print "Creato il nuevo file: "; String@(evento.name.Data)
     If evento.mask And IN_DELETE Then Print "Eliminato il file: "; String@(evento.name.Data)
     If evento.mask And IN_MOVED_FROM Then Print "Spostato nel cestino il file: "; String@(evento.name.Data)
     p += 16 + evento.lenI
   Wend
   Wait 0.1
 Wend
   
' Libera memoria in chiusura:
 Free(buf)
 inotify_rm_watch(fd, wa)
 close_C(fd)
 Quit
  
End


Public Sub Application_Read()
  
' Se si pone il puntatore del mouse nello spazio al di sotto della console e si preme il tasto "Invio" della tastiera, allora il programma va in chiusura...
 bo = True
     
End