Il File-System
Manipolazioni di file
in ambiente Linux
ISO C Standard Library
v  L’I/O ANSI C si può effettuare attraverso diverse
catagorie di funzioni
Ø  Un carattere alla volta
Ø  Una riga alla volta
Ø  I/O formattato
Ø  R/W diretto
v  Si osservi che il kernel UNIX non differenzia file
ASCII da file Binari
Ø  Il carattere “b” durante l’apertura di un file non ha
effetto
●  “r”==“rb”, “w”==“wb”, etc.
Apertura e chiusura di un file
#include <stdio.h>
FILE *fopen (char *path, char *type);
FILE *fclose (FILE *fp);
v  Metodi di accesso
Ø  r, rb, w, wb, a, ab r+, r+b, etc.
Ø  Il kernel UNIX non differenzia file ASCII da file
Binari
●  “b” durante l’apertura di un file non ha effetto, e.g.
“r”==“rb”, “w”==“wb”, etc.
I/O a caratteri
#include <stdio.h>
int getc (FILE *fp);
int fgetc (FILE *fp);
int putc (int c, FILE *fp);
int fputc (int c, FILE *fp);
v  La funzione getchar è equivalente a getc
(stdin)
v  La funzione putchar è equivalente a putc (c,
stdout)
I/O a righe
#include <stdio.h>
char *fgets (char *buf, int n, FILE *fp);
char gets (char *buf);
int *fputs (char *buf, FILE *fp);
int puts (char *buf);
v  Le righe sono delimitate dal carattere “new line”
v  Occorre specificare la lunghezza massima delle
righe
I/O formattato
#include <stdio.h>
int scanf (char format, …);
int fscanf (FILE *fp, char format, …);
int printf (char format, …);
int fprintf (FILE *fp, char format, …);
v  Elevata duttilità sulla manipolazione di dati
Ø  Formati
Ø  Conversioni
I/O diretto
#include <stdio.h>
size_t fread (void *ptr, size_t size,
size_t nObj, FILE *fp);
size_t fwrite (void *ptr, size_t size,
size_t nObj, FILE *fp);
v  Ogni operazione di I/O si occupa di leggere o
scrivere un oggetto di dimensione specifica
v  Valore di ritorno
Ø  Numero di oggetti letti oppure scritti
Ø  Se il valore non corrisponde si ha avuto un errore
oppure raggiunta la fine del file
I/O diretto
#include <stdio.h>
size_t fread (void *ptr, size_t size,
size_t nObj, FILE *fp);
size_t fwrite (void *ptr, size_t size,
size_t nObj, FILE *fp);
v  Spesso utilizzate per gestire file binari
Ø  R/W di intere strutture
Ø  Potenziali problemi nel gestire dati su archittetture
diverse per problemi di compatibilità dei formati
(e.g., interi, formati, etc.)
Esempi
float data[10];
if (fwrite(&data[2],sizeof(float),4,fp)!=4) {
fprintf (stderr,
"Error: Write %d).\n", n);
}
}
struct {
char name[L];
int n;
float avg;
} item;
if (fwrite(&item,sizeof(item),1,fp))!=1) {
fprintf (stderr,
"Error: Write %d).\n", n);
}
}
POSIX Standard Library
v  L’I/O UNIX si può effettuare interamente
attraverso solo 5 funzioni
Ø  open, read, write, lseek, close
v  Tale tipologia di accesso
Ø  Fa parte di POSIX e della Single UNIX Specification
ma non di ISO C
Ø  Si indica normalmente con il termine di
“unbuffered I/O” nel senso che ciascuna
operazione di read o write corrisponde a una
system call al kernel
System call open ()
v  Nel kernel UNIX un "file descriptor" è un intero
non negativo
v  Per convenzione (anche nella shell)
Ø  Standard input = descrittore 0 = STDIN_FILENO
Ø  Standard output = descrittore 1 =
STDOUT_FILENO
Ø  Standard error = descrittore 2 = STDERR_FILENO
v  Tali descrittori sono definiti nel file di header
unistd.h
System call open ()
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int open (const char *path, int flags);
int open (const char *path, int flags,
mode_t mode);
v  Apre un file definendone i permessi
v  Valori di ritorno
Ø  Il descrittore del file in caso di successo
Ø  Il valore -1 in caso di errore
System call open ()
v  Può avere 2 oppure 3 parametri
Ø  Il parametro mode è opzionale
v  Path indica il file da aprire
v  Flag ha molteplici opzioni
Ø  Si ottiene mediante l’OR bi-a-bit di costanti
presenti nel file di header fcntl.h
Ø  Una delle tre seguenti costanti è obbligatoria
●  O_RDONLY
●  O_WRONLY
●  O_RDWR
open for read-only access
open for write-only access
open for read-write access
System call open ()
Ø  Le seguenti costanti sono invece opzionali
●  O_CREAT
●  O_EXCL
●  O_TRUNC
●  O_APPEND
●  O_SYNC
●  ...
crea il file se non esiste
errore se O_CREAT è settato e il file
esiste
rimuove il contenuto del file
appende al file
ogni write attende l’operazioni di
scrittura fisica sia terminata prima
di proseguire
System call open ()
v  Mode specifica i diritti di accesso
Ø  S_I[RWX]USR
Ø  S_I[RWX]GRP
Ø  S_I[RWX]OTH
rwx --- ----- rwx ----- --- rwx
v  Osservazione
Ø  I permessi con cui viene effettivamente creato un
file sono modificati dall’umask dell’utente
proprietario del processo
●  mode & (~umask)
System call read ()
#include <sys/types.h>
#include <unistd.h>
int read (int fd, void *buf, size_t nbytes);
v  Legge dal file fd un numero di byte uguale a
nbytes, memorizzandoli in buf
v  Valori di ritorno
Ø  Il numero di byte letti in caso di successo
Ø  Il valore -1 in caso di errore
Ø  Il valore 0 in caso di EOF
System call read ()
#include <sys/types.h>
#include <unistd.h>
int read (int fd, void *buf, size_t nbytes);
v  Il valore ritornato è inferiore a nbytes
Ø  Se la fine del file viene raggiunta prima di nbytes
byte
Ø  Se la pipe da cui si sta leggendo non contiene
nbytes bytes
System call write ()
#include <sys/types.h>
#include <unistd.h>
int write (int fd, void *buf, size_t nbytes);
v  Scrive nbytes byte di buf nel file di descrittore
fd
v  Valori di ritorno
Ø  Il numero di byte scritti in caso di successo, cioè
normalmente nbytes
Ø  Il valore -1 in caso di errore
System call write ()
#include <sys/types.h>
#include <unistd.h>
int write (int fd, void *buf, size_t nbytes);
v  Osservazione
Ø  write scrive sui buffer di sistema, non sul disco
●  fd = open (file, O_WRONLY | O_SYNC);
Ø  O_SYNC forza la sync dei buffer, ma solo sul file
sytem ext2
System call close ()
#include <unistd.h>
int close (int fd);
v  Valori di ritorno
Ø  Il valore 0 in caso di successo
Ø  Il valore -1 in caso di errore
v  Tutti i file sono chiusi automaticamente quando il
processo termina
Un esempio di R/W
...
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define BUFFSIZE 4096
...
int nR, nW, fdR, fdW;
char buf[BUFFSIZE];
fdR = open (argv[1], O_RDONLY);
fdW = open (argv[2], O_WRONLY | O_CREAT |
O_TRUNC, S_IRUSR | S_IWUSR);
if (fdR==(-1) || fdW==(-1)) {
fprintf (stdout, “Error Opening a File.\n“);
exit (1);
}
Un esempio di R/W
while ((nR = read (fdR, buf, BUFFSIZE)) > 0) {
nW = write (fdW, buf, nR);
if (nR != nW)
fprintf (stderr,
"Error: Read %d, Write %d).\n", nR, nW);
}
if (nW < 0)
fprintf (stderr, "Write Error.\n");
close (fdR);
close (fdW);
exit(0);
}
Scarica

Manipolazioni di file in ambiente Linux