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

Da Gambas-it.org - Wikipedia.

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