Newsgroup: it.comp.lang.c
Titolo: apertura file di dimensioni superiori ai 2GB

Ciao a tutti. ho fatto un applicativo che analizza file di testo
utilizzando le funzioni stat e fopen. Una per navigare le directory e
la seconda per aprire il file.
Ho l'esigenza di accedere a directory con file molto grandi il cui
ordine di grandezza superira i 2GB.
Nella documentazione che ho trovato in rete si fa riferimento a
versioni particolari delle precedenti funzioni in particolare a stat64
e a fopen64.
Il prototipo è pressoche identico ad eccezione che il tipo struct stat
utilizzato come parametro della funzione stat64 diventa struct stat64.
Sempre dalla stessa documentazione si evince che le funzioni
sopracitate sono contenute in <sys/stat.h> che ho ovviamente incluso.
Purtroppo non riesco a compilare. la riga incriminata è la seguente:
...
struct stat64 sbuf;
...
e l'errore del compilatore è il seguente:
...
include/xxx.c:140: error: storage size of 'sbuf' isn't known
include/xxx.c:161: warning: implicit declaration of function 'stat64'
include/xxx.c:140: warning: unused variable 'sbuf'
...
mi sembra di capire che il compilatore non riesce a trovare la
definizione di stat64.
Qualcuno sa dirmi casa sbaglio.
Sto compilando con gcc in ambiente linux (distribuzione debian) kernel
6.22.
Ma lo stesso problema l'ho incontrto su Mac OSX 10.4.
Potrebbero esserci dei problemi/limitazioni a livello di file system o
di ambiente su cui gira il binario?
Grazie
   Alessio

Cerco di risponderti in maniera esaustiva.
Il supporto per Large Files (ovvero file piu' grandi di 2GB) e'
purtroppo non ancora standardizzato.
In Mac OS X 10.5, per esempio, sia struct stat che struct stat64 sono
definite. E sia stat() che stat64() sono definiite.
stat64 e' un alias per stat.
Questo perche' il tipo off_t, che esprime il numero di bytes in un
file, nel OS X 10.5 e' un tipo a 64 bit (unsigned long in questo
caso).
Per cui tutte le funzioni su file in questo sistema operativo
supportano file di grandi dimensioni.
Questo e' vero sia che tu compili il tuo codice per Intel o PPC a 64
bit, sia che lo compili per Intel o PPC a 32 bit. Il tipo off_t e'
sempre quello.
In OS X 10.4 il supporto a 64 bit non era completo.
In Linux, l'implementazione e' ancora ibrida purtroppo.
Anche in linux la dimensione dei file nella struttura struct stat
(membro st_size) e' definito come tipo off_t.
Purtroppo, il tipo off_t in Linux cambia in base all'architettura per
cui compili.
Per cui se compili per un processore a 32 bit (gcc -m32), off_t viene
dichiarato a 32bit. Se compili per un'architettura a 64bit (-m64),
off_t viene dichiarato a 64 bit.
In Linux quindi, nativamente, il supporto a dimensioni file >2GB  e'
abilitato in automatico solo se compili per un architettura
compatibile.
In Linux, ci sono pero' due modi di abilitare il supporto a file di
grandi dimensioni anche su architetture a 32 bit:
la prima, e quella che si dovrebbe usare per il futuro (e' quella che
uso nei miei progetti) e' quello di passare il flag -
D_FILE_OFFSET_BITS=64 a gcc. Questo fa si che il tipo off_t venga
forzato a 64 bit anche su piattaforme a 32 bit.
In automatico, tutte le operazioni sui file diventano magicamente
compatibili con file di grandi dimensioni. La struct stat e la
funzione stat() quindi usano un off_t a 64 bit, e tu non devi quindi
cambiare il codice.
C'e' un secondo modo, che e' pero' deprecato ed e' solo per
compatibilita', in cui se tu passi il flag -D_LARGEFILE64_SOURCE
magicamente i nomi struct stat64 e stat64() appaiono, e li puoi usare
per accedere esplicitamente a file di grandi dimensioni anche su
architetture a 32bit.
RICAPITOLANDO:
Per portabilita' e compatibilita' con il futuro, nel tuo codice devi
usare le classice funzioni come stat() e i tipi classici tipo struct
stat. E quando memorizzi dimensioni di file, usa sempre e solo il tipo
off_t.
Quando compili su archietture a 32bit (i686 senza estensioni x86_64
della AMD per esempio), passa al compilatore il flag -
D_FILE_OFFSET_BITS=64, e il tipo off_t sara' a 64bit.


Perfetto, ho modificato il mio make file introducendo la macro che mi
hai suggerito ed ora su linux a 32 bit compila e si comporta
egregiamente.
Grazie mille.