Differenze tra le versioni di "Leggere il contenuto di una Directory mediante le risorse dichiarate nel file header "dirent.h""

Da Gambas-it.org - Wikipedia.
 
(5 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
Come si sa, per leggere i file contenuti in una Directory, in Gambas si utilizza la comoda funzione ''Dir()''.
+
Come si sa, per leggere i file contenuti in una Directory, in Gambas si utilizza la comoda funzione "Dir()".
  
In questa pagina viene mostrato come utilizzare alcune risorse dichiarate nel file header "''usr/include/dirent.h''", per conoscere i file presenti in una Directory.
+
In questa pagina viene mostrato come utilizzare alcune risorse dichiarate nel file header "''usr/include/dirent.h'' ", per conoscere i file presenti in una Directory.
  
E' necessario richiamare in Gambas la libreria dinamica condivisa: "''libc:6''"
+
E' necessario richiamare in Gambas la libreria condivisa: "''libc.so.6'' ".
  
 +
Mostriamo di seguito due codici possibili.
  
====Funzionamento====
+
 
E' sufficiente richiamare tre funzioni esterne, dichiarate nel file header ''dirent.h''. I dati saranno immagazzinati in un'area di memoria, creata dalla funzione esterna ''readdir()'' e puntata da apposita variabile di tipo ''Puntatore''. Si procederà alla dereferenziazione di detto ''Puntatore'' mediante le apposite funzioni di dereferenziazione previste da Gambas, tenendo comunque tenendo ben presente che:
+
===1° esempio===
<BR>- i dati utili per la lettura della Dirctory iniziano dal byte di indice <FONT Color=#B22222>64</font> dell'area di memoria puntata dal ''Puntatore'';
+
E' sufficiente richiamare tre funzioni esterne, dichiarate nel file header ''dirent.h''. I dati saranno immagazzinati in un'area di memoria, creata dalla funzione esterna "readdir()" e puntata da apposita variabile di tipo ''Puntatore''. Si procederà alla dereferenziazione di detto ''Puntatore'' mediante le apposite funzioni di dereferenziazione previste da Gambas, tenendo comunque tenendo ben presente che:
 +
<BR>- i dati utili per la lettura della Dirctory iniziano dal byte di indice <FONT Color=#B22222>16</font> dell'area di memoria puntata dal ''Puntatore'';
 
<BR>- l'area di memoria utile è suddivisa in varie porzioni contenenti - quali dati utili alla conoscenza dei file presenti nella Directory - il tipo di file ed il suo nome;
 
<BR>- l'area di memoria utile è suddivisa in varie porzioni contenenti - quali dati utili alla conoscenza dei file presenti nella Directory - il tipo di file ed il suo nome;
 
<BR>- il primo byte di ciascuna porzione di memoria indica la lunghezza in byte della porzione stessa (nella quale sono indicati - come prima detto - il tipo di file ed il suo nome). Nel codice Gambas, sotto mostrato, la lunghezza, espressa in byte, sommata all'indice del byte che la rappresenta, specifica in sostanza l'indice dell'area di memoria, puntata dal ''Puntatore'', dell'analogo byte successivo che rappresenta sia l'inizio della porzione di memoria contenente il nome dell'altro eventuale file, sia ovviamente la lunghezza in byte di tale ulteriore utile porzione;
 
<BR>- il primo byte di ciascuna porzione di memoria indica la lunghezza in byte della porzione stessa (nella quale sono indicati - come prima detto - il tipo di file ed il suo nome). Nel codice Gambas, sotto mostrato, la lunghezza, espressa in byte, sommata all'indice del byte che la rappresenta, specifica in sostanza l'indice dell'area di memoria, puntata dal ''Puntatore'', dell'analogo byte successivo che rappresenta sia l'inizio della porzione di memoria contenente il nome dell'altro eventuale file, sia ovviamente la lunghezza in byte di tale ulteriore utile porzione;
Riga 14: Riga 16:
 
<BR>- il terzo byte indica il "tipo" di file, di cui viene riportato nella corrente porzione di memoria - come prima detto - il tipo di file ed il suo nome;
 
<BR>- il terzo byte indica il "tipo" di file, di cui viene riportato nella corrente porzione di memoria - come prima detto - il tipo di file ed il suo nome;
 
<BR>- dal quarto byte (e fino al byte precedente quello che indica la lunghezza della successiva porzione di memoria contenente il tipo di un altro eventuale file ed il suo nome) iniziano i caratteri che identificano il nome del corrente file.
 
<BR>- dal quarto byte (e fino al byte precedente quello che indica la lunghezza della successiva porzione di memoria contenente il tipo di un altro eventuale file ed il suo nome) iniziano i caratteri che identificano il nome del corrente file.
 +
Library "libc:6"
 +
 
 +
<FONT Color=gray>' ''DIR *opendir (const char *__name)''
 +
' ''Open a directory stream on NAME.''</font>
 +
Private Extern opendir(name As String) As Pointer
 +
 +
<FONT Color=gray>' ''struct dirent *readdir (DIR *__dirp)''
 +
' ''Read a directory entry from DIRP.''</font>
 +
Private Extern readdir(__dirp As Pointer) As Pointer 'Dirent
 +
 +
<FONT Color=gray>' ''int closedir (DIR *__dirp)''
 +
' ''Close the directory stream DIRP.''</font>
 +
Private Extern closedir(dirp As Pointer) As Integer
 +
 +
 +
'''Public''' Sub Main()
 +
 
 +
  Dim directory As String
 +
  Dim drct, dr As Pointer
 +
  Dim b As Byte
 +
  Dim offset As Integer
 +
 +
  Print "TIPI di File:"
 +
  Print " 0 = Sconosciuto  -  1 = Named pipe (FIFO)  -  2 = Character device  -  4 = Directory"
 +
  Print " 6 = Block device  -  8 = Regular file      -  10 = Symbolic link    -  12 = UNIX domain socket  -  14 = Whiteout inode"
 +
  Print "__________________________________________________________________________________________________________________________\n"
 +
 
 +
  directory = "<FONT Color=gray>''/percorso/della/Directory''</font>"
 +
  Print "File contenuti nella Directory: "; directory
 +
  Print "\nTipo  -  Nome file"
 +
 
 +
  drct = opendir(directory)
 +
 
 +
  dr = readdir(drct)
 +
 
 +
  offset = 16
 +
 
 +
  While Byte@(dr + offset) > 0
 +
    b = Byte@(dr + offset + 2)
 +
    Print " "; b; "        "; String@(dr + offset + 3)
 +
    offset += Byte@(dr + offset)
 +
  Wend
 +
 +
  closedir(drct)
 +
 
 +
'''End'''
  
  
Mostriamo un esempio:
+
===2° esempio===
 
  Library "libc:6"
 
  Library "libc:6"
 +
 
 +
Public Struct dirent
 +
  d_ino As Long
 +
  d_off As Long
 +
  d_reclen As Short
 +
  d_type As Byte
 +
  d_name As Byte[]
 +
End Struct
 +
 +
Private tipi As String[] = ["DT_UNKNOWN", "DT_FIFO", "DT_CHR", "", "DT_DIR", "", "DT_BLK",
 +
                            "", "DT_REG", "", "DT_LNK", "", "DT_SOCK", "", "DT_WHT"]
 
   
 
   
 
  <FONT Color=gray>' ''DIR *opendir (const char *__name)''
 
  <FONT Color=gray>' ''DIR *opendir (const char *__name)''
Riga 24: Riga 83:
 
   
 
   
 
  <FONT Color=gray>' ''struct dirent *readdir (DIR *__dirp)''
 
  <FONT Color=gray>' ''struct dirent *readdir (DIR *__dirp)''
  ' Read a directory entry from DIRP.''</font>
+
  ' ''Read a directory entry from DIRP.''</font>
 
  Private Extern readdir(__dirp As Pointer) As Pointer 'Dirent
 
  Private Extern readdir(__dirp As Pointer) As Pointer 'Dirent
 
   
 
   
 
  <FONT Color=gray>' ''int closedir (DIR *__dirp)''
 
  <FONT Color=gray>' ''int closedir (DIR *__dirp)''
  ' Close the directory stream DIRP.''</font>
+
  ' ''Close the directory stream DIRP.''</font>
 
  Private Extern closedir(dirp As Pointer) As Integer
 
  Private Extern closedir(dirp As Pointer) As Integer
 +
 +
 +
'''Public''' Sub Main()
 +
 +
  Dim dr, dirstream As Pointer
 +
  Dim drnt As Dirent
 +
  Dim ddrr As New Dirent[]
 +
  Dim i, n As Integer
 +
 +
  dirstream = opendir("/tmp")
 +
  If dirstream == 0 Then Error.Raise("Impossibile aprire la directory prescelta !")
 +
 
 +
  dr = readdir(dirstream)
 +
  If dr == 0 Then Error.Raise("Impossibile leggere nella directory prescelta !")
 +
 +
  While Long@(dr + i) <> 0 Then Break
 +
    With drnt = New Dirent
 +
      .d_ino = Long@(dr + i)              <FONT Color=gray>' ''d_ino (Inode number)''</font>
 +
      .d_off = Long@(dr + i + 8)          <FONT Color=gray>' ''d_off (current position in the directory stream)''</font>
 +
      .d_reclen = Short@(dr + i + 16)    <FONT Color=gray>' ''d_reclen (Length of this record)''</font>
 +
      .d_type = Byte@(dr + i + 18)        <FONT Color=gray>' ''d_type (Type of file)''</font>
 +
      .d_name = New Byte[]
 +
      For n = 0 To (Byte@(dr + i + 16) - 19) - 1
 +
        .d_name.Push(Byte@(dr + i + 19 + n))
 +
      Next
 +
    End With
 +
    ddrr.Push(drnt)
 +
    i += Short@(dr + i + 16)
 +
  Wend
 +
 +
  closedir(dirstream)
 +
 
 +
  Verifica(ddrr)
 +
 
 +
'''End'''
 +
 +
'''Private''' Procedure Verifica(dd As Dirent[])
 +
 
 +
  Dim d As Dirent
 +
 
 +
  For Each d In dd
 +
    With d
 +
      Print "Tipo di file: "; tipi[.d_type]
 +
      Print "Nome file:    "; String@(.d_name.Data)
 +
      Print
 +
    End With
 +
  Next
 +
 
 +
'''End'''
 +
 +
 +
===3° esempio===
 +
Lettura dei file contenuti nella cartella ''/tmp'':
 +
Library "libc:6"
 +
 +
<FONT Color=gray>' ''DIR *opendir (const char *__name)''
 +
' ''Open a directory stream on NAME.''</font>
 +
Private Extern opendir(__name As String) As Pointer
 +
 +
<FONT Color=gray>' ''struct dirent *readdir (DIR *__dirp)''
 +
' ''Read a directory entry from DIRP.''</font>
 +
Private Extern readdir(__dirp As Pointer) As Pointer 'Dirent
 +
 +
<FONT Color=gray>' ''int closedir (DIR *__dirp)''
 +
' ''Close the directory stream DIRP.''</font>
 +
Private Extern closedir(__dirp As Pointer) As Integer
 
   
 
   
 
   
 
   
 
  '''Public''' Sub Main()
 
  '''Public''' Sub Main()
 
    
 
    
   Dim directory As String
+
   Dim dp, dirent As Pointer
  Dim dir, dr As Pointer
+
   Dim ini As Integer
   Dim b As Byte
+
   Dim tipi As String[]
   Dim offset As Integer
+
   
+
  tipi = ["Sconosciuto", "Pipe/FIFO", "Character device", Null, "Directory", Null, "Block device", Null, "File regolare",
    Print "TIPI di File:"
+
          Null, "Collegamento simbolico", Null, "Local-domain socket", Null, "DT_WHT"]
    Print " 0 = Sconosciuto  -  1 = Named pipe (FIFO)  -  2 = Character device -  4 = Directory"
+
 
    Print " 6 = Block device -  8 = Regular file      -  10 = Symbolic link    - 12 = UNIX domain socket -  14 = Whiteout inode"
+
<FONT Color=gray>' ''Conosciamo la "posizione" del primo valore utile, corrispondente al membro "c_reclen" della Struttura esterna "dirent":''</font>
    Print "__________________________________________________________________________________________________________________________\n"
+
  ini = SizeOf(gb.Long) * 2
   
+
 
    directory = "<FONT Color=gray>''percorso/della/Directory''</font>"
+
  dp = opendir("/tmp")
    Print "File contenuti nella Directory: "; directory
+
  If dp == 0 Then Error.Raise("Impossibile aprire la cartella !")
    Print "\nTipo  -  Nome file"
+
   
+
  dirent = readdir(dp)
    dir = opendir(directory)
+
  If dirent == 0 Then Error.Raise("Errore !")
   
+
 
    dr = readdir(dir)
+
  Repeat 
   
+
<FONT Color=gray>' ''Conosciamo il nome ed il tipo del corrente file individuato:''</font>
    offset = 64
+
     Print String@(dirent + ini + 3); Space(16); tipi[Byte@(dirent + ini + 2)]
      
+
<FONT Color=gray>' ''Conosciamo la "posizione" del successivo valore corrispondente al membro "c_reclen" della Struttura esterna "dirent":''</font>
    While Byte@(dr + offset) > 0
+
    ini += CInt(Short@(dirent + ini))
      b = Byte@(dr + offset + 2)
+
  Until Short@(dirent + ini) == 0
      Print " "; b; "       "; String@(dr + offset + 3)
+
      offset += Byte@(dr + offset)
+
  closedir(dp)
    Wend
 
   
 
    closedir(dir)
 
 
      
 
      
 
  '''End'''
 
  '''End'''
 
  
  

Versione attuale delle 21:03, 5 set 2022

Come si sa, per leggere i file contenuti in una Directory, in Gambas si utilizza la comoda funzione "Dir()".

In questa pagina viene mostrato come utilizzare alcune risorse dichiarate nel file header "usr/include/dirent.h ", per conoscere i file presenti in una Directory.

E' necessario richiamare in Gambas la libreria condivisa: "libc.so.6 ".

Mostriamo di seguito due codici possibili.


1° esempio

E' sufficiente richiamare tre funzioni esterne, dichiarate nel file header dirent.h. I dati saranno immagazzinati in un'area di memoria, creata dalla funzione esterna "readdir()" e puntata da apposita variabile di tipo Puntatore. Si procederà alla dereferenziazione di detto Puntatore mediante le apposite funzioni di dereferenziazione previste da Gambas, tenendo comunque tenendo ben presente che:
- i dati utili per la lettura della Dirctory iniziano dal byte di indice 16 dell'area di memoria puntata dal Puntatore;
- l'area di memoria utile è suddivisa in varie porzioni contenenti - quali dati utili alla conoscenza dei file presenti nella Directory - il tipo di file ed il suo nome;
- il primo byte di ciascuna porzione di memoria indica la lunghezza in byte della porzione stessa (nella quale sono indicati - come prima detto - il tipo di file ed il suo nome). Nel codice Gambas, sotto mostrato, la lunghezza, espressa in byte, sommata all'indice del byte che la rappresenta, specifica in sostanza l'indice dell'area di memoria, puntata dal Puntatore, dell'analogo byte successivo che rappresenta sia l'inizio della porzione di memoria contenente il nome dell'altro eventuale file, sia ovviamente la lunghezza in byte di tale ulteriore utile porzione;
- il secondo byte è sempre uguale a zero;
- il terzo byte indica il "tipo" di file, di cui viene riportato nella corrente porzione di memoria - come prima detto - il tipo di file ed il suo nome;
- dal quarto byte (e fino al byte precedente quello che indica la lunghezza della successiva porzione di memoria contenente il tipo di un altro eventuale file ed il suo nome) iniziano i caratteri che identificano il nome del corrente file.

Library "libc:6"
 
' DIR *opendir (const char *__name)
' Open a directory stream on NAME.
Private Extern opendir(name As String) As Pointer

' struct dirent *readdir (DIR *__dirp)
' Read a directory entry from DIRP.
Private Extern readdir(__dirp As Pointer) As Pointer 'Dirent

' int closedir (DIR *__dirp)
' Close the directory stream DIRP.
Private Extern closedir(dirp As Pointer) As Integer


Public Sub Main()
 
 Dim directory As String
 Dim drct, dr As Pointer
 Dim b As Byte
 Dim offset As Integer

 Print "TIPI di File:"
 Print " 0 = Sconosciuto   -  1 = Named pipe (FIFO)  -   2 = Character device  -   4 = Directory"
 Print " 6 = Block device  -  8 = Regular file       -  10 = Symbolic link     -  12 = UNIX domain socket  -  14 = Whiteout inode"
 Print "__________________________________________________________________________________________________________________________\n"
 
 directory = "/percorso/della/Directory"
 Print "File contenuti nella Directory: "; directory
 Print "\nTipo  -  Nome file"
 
 drct = opendir(directory)
 
 dr = readdir(drct)
 
 offset = 16
 
 While Byte@(dr + offset) > 0
   b = Byte@(dr + offset + 2)
   Print " "; b; "        "; String@(dr + offset + 3)
   offset += Byte@(dr + offset)
 Wend

 closedir(drct)
 
End


2° esempio

Library "libc:6"
 
Public Struct dirent
  d_ino As Long
  d_off As Long
  d_reclen As Short
  d_type As Byte
  d_name As Byte[]
End Struct

Private tipi As String[] = ["DT_UNKNOWN", "DT_FIFO", "DT_CHR", "", "DT_DIR", "", "DT_BLK",
                            "", "DT_REG", "", "DT_LNK", "", "DT_SOCK", "", "DT_WHT"]

' DIR *opendir (const char *__name)
' Open a directory stream on NAME.
Private Extern opendir(name As String) As Pointer

' struct dirent *readdir (DIR *__dirp)
' Read a directory entry from DIRP.
Private Extern readdir(__dirp As Pointer) As Pointer 'Dirent

' int closedir (DIR *__dirp)
' Close the directory stream DIRP.
Private Extern closedir(dirp As Pointer) As Integer


Public Sub Main()

 Dim dr, dirstream As Pointer
 Dim drnt As Dirent
 Dim ddrr As New Dirent[]
 Dim i, n As Integer

 dirstream = opendir("/tmp")
 If dirstream == 0 Then Error.Raise("Impossibile aprire la directory prescelta !")
  
 dr = readdir(dirstream)
 If dr == 0 Then Error.Raise("Impossibile leggere nella directory prescelta !")

 While Long@(dr + i) <> 0 Then Break
   With drnt = New Dirent
     .d_ino = Long@(dr + i)              ' d_ino (Inode number)
     .d_off = Long@(dr + i + 8)          ' d_off (current position in the directory stream)
     .d_reclen = Short@(dr + i + 16)     ' d_reclen (Length of this record)
     .d_type = Byte@(dr + i + 18)        ' d_type (Type of file)
     .d_name = New Byte[]
     For n = 0 To (Byte@(dr + i + 16) - 19) - 1
       .d_name.Push(Byte@(dr + i + 19 + n))
     Next
   End With
   ddrr.Push(drnt)
   i += Short@(dr + i + 16)
 Wend

 closedir(dirstream)
  
 Verifica(ddrr)
 
End

Private Procedure Verifica(dd As Dirent[])
 
 Dim d As Dirent
 
 For Each d In dd
   With d
     Print "Tipo di file: "; tipi[.d_type]
     Print "Nome file:    "; String@(.d_name.Data)
     Print
   End With
 Next
  
End


3° esempio

Lettura dei file contenuti nella cartella /tmp:

Library "libc:6"

' DIR *opendir (const char *__name)
' Open a directory stream on NAME.
Private Extern opendir(__name As String) As Pointer

' struct dirent *readdir (DIR *__dirp)
' Read a directory entry from DIRP.
Private Extern readdir(__dirp As Pointer) As Pointer 'Dirent

' int closedir (DIR *__dirp)
' Close the directory stream DIRP.
Private Extern closedir(__dirp As Pointer) As Integer


Public Sub Main()
 
 Dim dp, dirent As Pointer
 Dim ini As Integer
 Dim tipi As String[]

 tipi = ["Sconosciuto", "Pipe/FIFO", "Character device", Null, "Directory", Null, "Block device", Null, "File regolare",
         Null, "Collegamento simbolico", Null, "Local-domain socket", Null, "DT_WHT"]
  
' Conosciamo la "posizione" del primo valore utile, corrispondente al membro "c_reclen" della Struttura esterna "dirent":
 ini = SizeOf(gb.Long) * 2
 
 dp = opendir("/tmp")
 If dp == 0 Then Error.Raise("Impossibile aprire la cartella !")

 dirent = readdir(dp)
 If dirent == 0 Then Error.Raise("Errore !")
 
 Repeat  
' Conosciamo il nome ed il tipo del corrente file individuato:
   Print String@(dirent + ini + 3); Space(16); tipi[Byte@(dirent + ini + 2)]
' Conosciamo la "posizione" del successivo valore corrispondente al membro "c_reclen" della Struttura esterna "dirent":
   ini += CInt(Short@(dirent + ini))
 Until Short@(dirent + ini) == 0

 closedir(dp)
   
End


Riferimenti