34
Programmation Orient´ ee Syst` eme Cours 9: La Gestion des Fichiers et des epertoires Francesco Belardinelli Laboratoire IBISC Diapos bas´ ees sur Introduction to UNIX par Mme Cantaut 20 f´ evrier 2018

Programmation Orientée Système Cours 9: La Gestion des

  • Upload
    others

  • View
    6

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Programmation Orientée Système Cours 9: La Gestion des

Programmation Orientee Systeme

Cours 9: La Gestion des Fichiers et des

Repertoires

Francesco Belardinelli

Laboratoire IBISC

Diapos basees sur Introduction to UNIX par Mme Cantaut

20 fevrier 2018

Page 2: Programmation Orientée Système Cours 9: La Gestion des

Cours 9 : La Gestion des Fichiers

• Overture, fermeture, lecture et ecriture des fichiers

• Manipulation des fichiers

• Overture, fermeture, lecture et ecriture des repertoires

• Manipulation des repertoires

Page 3: Programmation Orientée Système Cours 9: La Gestion des

Le Filesystem et le langage C

• En C on peut lire et ecrire des donnees dans des fichiers

• les acces aux fichiers se font par l’intermediaire d’une memoire-tampon (buffer)

• ca permet de reduire le nombre d’acces aux peripheriques (disque, etc.)

• avant de lire ou d’ecrire dans un fichier, on notifie son acces par la commandeopen()

• la fonction open() prend comme argument le nom du fichier et initialise un flotde donnees (utilise pour l’ecriture ou la lecture)

• apres le traitement des donnees, on annule la liaison entre le fichier et le flotgrace a la fonction close()

Page 4: Programmation Orientée Système Cours 9: La Gestion des

Ouverture d’un Fichier

• La function primitive open() permet a un processus de realiser une ouverture defichier

#include <fcntl.h>

int open(const char *nom, int flags);int open(const char *nom, int flags, mode_t mode);

• nom est la reference du fichier a ouvrir

• flags demande la realisation d’operations particulieres au cours de l’ouvertureet/ou parametre le comportement des operations de lecture/ecriture dans lefichier ouvert

• il s’agit d’une disjonction (|) de constantes definies dans fcntl.h

• cette disjonction comporte :I exactement une des trois constantes precisant le mode d’ouverture

I O_RDONLY : lecture seuleI O_WRONLY : ecriture seuleI O_RDWR : lecture et ecriture

I des constantes signalant les operations complementairesI O_TRUNC : fichier tronque a l’ouvertureI O_APPEND : positionnement de l’offset a la fin du fichierI O_CREAT : creation du fichier s’il n’existe pas. Il faut associer des droitsI O_EXCL : si O_CREAT est positionne et le fichier existe, open renvoie une erreurI O_NONBLOCK : empeche le processus appelant d’etre bloque lors de l’ouverture.I O_SYNC : les ecritures dans le fichier bloquent le processus appelant jusqu’a terminaison

• En cas de succes, open() renvoie le descripteur du fichier

• En cas d’echec, la valeur renvoyee est -1

Page 5: Programmation Orientée Système Cours 9: La Gestion des

Ouverture d’un Fichier

Example 1le programme o1.c ouvre le fichier in1 pour la lecture, et imprime la valeur dudescripteur de fichier

• si on n’a pas cree le fichier in1, alors il va imprimer -1

• si in1 existe, alors on va imprimer 3, le descripteur de fichier qu’on a obtenu

#include <stdio.h>#include <fcntl.h>

int main(){

int fd;

fd = open("in1", O_RDONLY);printf("%d\n", fd);

return 0;}

Pourquoi 3 ?

• pour chaque processus, trois flux d’E/S sont ouverts par defaut : stdin, stdoutet stderr

• ces trois prennent les descripteurs de fichiers 0, 1 et 2

Page 6: Programmation Orientée Système Cours 9: La Gestion des

Ouverture d’un Fichier

• la fonction perror() peut etre utilisee pour renvoyer un message d’erreurcomprensible a l’utilisateur

• exemple : le programme o2.c essaie d’ouvrir le fichier out1 pour l’ecriture.

#include <stdio.h>#include <stdlib.h>#include <fcntl.h>

int main(){

int fd;

fd = open("out1", O_WRONLY);if (fd < 0) {perror("out1");exit(1);

}else printf("%d\n", fd);

return 0;}

• il echoue si out1 n’existe pas

• pour ouvrir un nouveau fichier pour l’ecriture, on utilise(O_WRONLY | O_CREAT | O_TRUNC) comme argument de flags

• l’argument mode ne doit etre utilisee que si on cree un nouveau fichier

• il specifie les autorisations du nouveau fichier

• 0644 est la valeur la plus typique (rw-r--r--)

Page 7: Programmation Orientée Système Cours 9: La Gestion des

Creations d’un Fichier

• dans C on a a disposition la fonction

int create(const char *nom, mode_t mode);

pour creer un fichier de nom nom

• l’appel a fonction

create(nom, mode);

correspond a l’appel

open(nom, O_WRONLY | O_CREAT | O_TRUNC, mode);

Page 8: Programmation Orientée Système Cours 9: La Gestion des

Fermeture d’un Fichier

• La fonction primitive close() permet a un processus de fermer un descripteur defichier

#include <unistd.h>

int close(int fd);

ou fd est le descripteur retourne par la fonction open() correspondante

• l’OS peut reutiliser le descripteur de fichier

Example 2Le programme c1.c ouvre le fichier in1 deux fois, apres il ferme in1 une fois, enfin ilessaye de fermer le meme fichier une deuxieme fois.

Page 9: Programmation Orientée Système Cours 9: La Gestion des

Lecture d’un Fichier

• la fonction read() permet a un processus de lire le contenu d’un fichier

#include <unistd.h>

int read(int fd, char *buf, int size)

• son appel correspond a la demande de lecture d’au plus size caracteres dans lefichier de descripteur fd

• les caracteres lus sont stockes dans l’espace memoire d’adresse buf

• ce pointeur doit donc correspondre a une zone de taille au moins egale a size

• read() renvoie un entier correspondant au nombre de bits effectivement lus

Page 10: Programmation Orientée Système Cours 9: La Gestion des

Algorithme de fonctionnement

1. read() renvoie -1 en cas d’erreur de parametre

2. s’il n’y a pas de verrou exclusif imperatif sur le fichier2.1 si la fin du fichier n’est pas atteinte, elle lit des caracteres a partir de l’offset courant,

jusqu’a ce que la fin du fichier soit atteinte ou que size octets aient ete lus.2.2 elle renvoie le nombre de caracteres lus et la valeur de l’offset est augmentee de ce

nombre.2.3 si la fin de fichier est atteinte, elle renvoie 0.

3. s’il y a un verrou exclusif imperatif sur le fichier :3.1 si le mode de lecture est bloquant (O_NONBLOCK non positionne), le processus est bloque

jusqu’a ce qu’il n’y ait plus de verrou ou que l’appel soit interrompu.3.2 si le mode de lecture est non bloquant, aucun caractere n’est lu et la value retournee

est -1.

Page 11: Programmation Orientée Système Cours 9: La Gestion des

Lecture d’un Fichier

Example 3Le programme r1.c lit le fichier in1 et affiche sur la sortie standard (ecran) soncontenu.

• le buffer c doit pointer sur une adresse de memoire valide ; ceci est realise parcalloc

• on peut egalement declarer c comme un tableau statique de 100 caracteres :

char c[100];

• c est termine par \0 pour assurer que printf() comprenne

• si read() renvoie 0, alors la fin du fichier a ete atteinte

• si read() renvoie moins d’octets qu’on avait demande, alors on a atteint la fin dufichier

Page 12: Programmation Orientée Système Cours 9: La Gestion des

Ecriture d’un Fichier

• la fonction write() permet a un processus d’ecrire dans un fichier

#include <unistd.h>

int write(int fd, char *buf, int size);

• son appel correspond a la demande d’ecriture, dans le fichier de descripteur fd, desize caracteres stockes a l’adresse buf dans l’espace d’adressage du processus.

Example 4Le programme w1.c ouvre le fichier out3 pour l’ecriture et ecrit la chaıneHello world!

Page 13: Programmation Orientée Système Cours 9: La Gestion des

Algorithme de fonctionnement

1. write() renvoie -1 en cas d’erreur de parametre

2. s’il n’y a pas de verrou imperatif, exclusif ou partage, sur le fichier, l’ecriture estrealisee. Le nombre de caracteres ecrits est renvoye : une valeur inferieure a size

signale une erreur.

3. s’il y a un verrou imperatif, exclusif ou partage, sur le fichier :3.1 si aucun des indicateurs O_NONBLOCK et O_NDELAY n’est positionne, le processus est

bloque jusqu’a ce qu’il n’y ait plus de verrou de ce type ou que l’appel soit interrompu.3.2 si l’un des indicateurs precedents est positionne, le retour est immediat sans ecriture

avec la valeur -1.

Page 14: Programmation Orientée Système Cours 9: La Gestion des

Les Sorties Standards

• trois sorties standard peuvent etre utilisees sans qu’il soit necessaire de les ouvrirou de les fermer :

I stdin (standard input) : unite d’entree (par defaut, le clavier ; valeur = 0)I stdout (standard output) : unite de sortie (par defaut, l’ecran ; valeur = 1) ;I stderr (standard error) : unite d’affichage des messages d’erreur (par defaut, l’ecran ;

valeur = 2).

• on peut lire sur l’entree standard, en utilisant read(0, ...), et ecrire sur lasortie standard en utilisant write(1, ...)

Example 5On peut ecrire un programme simpcat.c qui copie l’entree standard sur la sortiestandard

#include <stdlib.h>#include <unistd.h>#include <fcntl.h>

int main(){char c;

while (read(0, &c, 1) == 1)write(1, &c, 1);

return 0;}

Page 15: Programmation Orientée Système Cours 9: La Gestion des

Exemples d’E/S sur Fichiers

• le programme tfile_ex.c ouvre le fichier tfile deux fois, il ecrit une fois et litune fois par deux descripteurs de fichiers differents

#include<string.h>

#include<unistd.h>

#include<stdio.h>

#include<fcntl.h>

#define string "tfile"

int main(void){

int fd[2];

char buf1[12] = "just a test";

char buf2[12];

fd[0] = open(string,O_RDWR);

printf("overture de %s avec id %d\n", string, fd[0]);

fd[1] = open(string,O_RDWR);

printf("overture de %s avec id %d\n", string, fd[1]);

printf("ecriture de %s sur le ficher avec id %d\n", buf1, fd[0]);

write(fd[0],buf1,strlen(buf1));

printf("lecture du ficher avec id %d sur buf2\n", fd[1]);

printf("ecriture de buf2 sur la sortie standard\n");

write(1, buf2, read(fd[1],buf2,12));

printf("\n");

close(fd[0]);

close(fd[1]);

return 0;

}

• Exemple : programme copierFichier.c pour copier un fichier dans un autre.

Page 16: Programmation Orientée Système Cours 9: La Gestion des

Table du Systeme

Le schema suivant resume l’organisation des tables mises en jeu par le mecanismed’entree-sorties d’un systeme Unix :

Page 17: Programmation Orientée Système Cours 9: La Gestion des

Table du Systeme

• Tables des descripteurs : 1 par processus, descripteur = indice.

• Table des fichiers ouverts : nb descripteurs correspondant, mode d’ouverture,offset, pointeur sur le i-noeud en memoire.

• Table des inodes en memoire : nb total d’ouvertures, id disque logique, etat del’inode.

• Table des verrous.

Page 18: Programmation Orientée Système Cours 9: La Gestion des

Manipulation des Fichiers

De nombreuses caracteristiques des fichiers sont regroupees dans la structure stat

#include <sys/types.h>

#include <sys/stat.h>

struct stat{

dev_t st_dev; /* ID du disque logique */

ino_t st_ino; /* Numero i-noeud sur le disque */

mode_t st_mode; /* Type du fichier et droits des utilisateurs */

nlink_t st_nlink; /* Nb liens physiques */

uid_t st_uid; /* UID proprietaire */

gid_t st_gid; /* GID proprietaire */

off_t st_size; /* Taille totale en octets */

time_t st_atime; /* Heure dernier acces */

time_t st_mtime; /* Heure derniere modification */

time_t st_ctime; /* Heure dernier changement etat */

};

Page 19: Programmation Orientée Système Cours 9: La Gestion des

Manipulation des Fichiers

Le champ st_mode definit le type du fichier (generalement sur 4 bits) et les droitsd’acces au fichier (generalement sur 12 bits).

S_IFMT S_IFREG, S_IFBLK TypeS_IFCHR,S_IFDIRS_IFLNK,S_IFFIFOS_IFSOCK,S_IFDOOR

S_ISUIDS_ISGIDS_ISVTX

S_ISRWXU S_IRUSRS_IWUSRS_IXUSR

S_ISRWXG S_IRGRPS_IWGRPS_IXGRP

S_ISRWXO S_IROTHS_IWOTHS_IXOTH

Les droits rwxr-x--x correspondent a la disjonctionS_ISRWXU | S_IRGRP | S_IXGRP | S_IXOTH

Page 20: Programmation Orientée Système Cours 9: La Gestion des

Manipulation des Fichiers

st_mode & S_IFMT Type du fichier Fonction de TestS_IFREG Fichier regulier S_ISREG()

S_IFBLK Fichier special bloc S_ISBLK()

S_IFCHR Fichier special caractere S_ISCHR()

S_IFDIR Repertoire S_ISDIR()

S_IFLNK Lien symbolique S_ISLNK()

S_IFIFO Tube nomme S_ISFIFO()

S_IFSOCK Socket S_ISSOCK()

S_IFDOOR Door S_ISDOOR()

Page 21: Programmation Orientée Système Cours 9: La Gestion des

Manipulation des Fichiers

• stat est un appel systeme qui est utilise pour determiner des informationsconcernant un fichier en fonction de son chemin d’acces

#include <sys/types.h>

#include <sys/stat.h>

#include <unistd.h>

int stat(const char *path, struct stat *buf);

ou

• const char *path est le chemin du fichier qui est interroge

• struct stat *buf est la structure stat ou les donnees sur le fichier serontstockees

• aucun droit particulier sur le fichier n’est necessaire

• valeur de retour : 0 si succes, -1 si echec

Example 6

• Programmes stat_ex.c fstat_ex.c pour afficher les infos relatives a un fichier.

• Programme compare_inodes.c pour comparer deux i-noeuds.

• Programme test_droits.c pour tester les droits d’un fichier.

Page 22: Programmation Orientée Système Cours 9: La Gestion des

Manipulation des Repertoires

• La bibliotheque dirent.h contient la definition du type DIR

• La consultation d’un repertoire suppose l’acquisition d’un pointeur sur un objetde ce type qui designe des lors ce repertoire

• La bibliotheque dirent.h contient aussi la definition d’une structure dirent

correspondant a une entree dans un repertoire

struct dirent{

__ino_t d_ino; /* numero serial de fichier */

__off_t d_off; /* distance des fichiers */

unsigned char d_type; /* type de fichier */

char d_name[256]; /* nom du fichier */

}

Page 23: Programmation Orientée Système Cours 9: La Gestion des

Entrees/Sorties sur les Repertoires

Les fonctions de consultation sont :

#include <sys/types.h>

#include <dirent.h>

/* ouverture d’un repertoire. */

DIR *opendir(const char *nom);

/* lecture d’un repertoire. */

struct dirent *readdir(DIR *dir);

/* rembobinage d’un repertoire. */

void rewinddir(DIR *dir);

/* fermeture d’un repertoire. */

int closedir(DIR *dir);

Page 24: Programmation Orientée Système Cours 9: La Gestion des

Affichage d’un Chemin de Repertoire

• Pour obtenir le repertoire de travail courant sous UNIX, on utilise la commandepwd

• L’appel systeme derriere la commande pwd est l’appel getcwd()

#include<unistd.h>

char *getcwd(char * buf, /* chemin d’acces renvoye */

size_t bufsize /* sizeof buf */

);

• getcwd() renvoie un pointeur vers buf en cas de succes et NULL en cas d’echec

• bufsize est la taille maximale du chemin

Page 25: Programmation Orientée Système Cours 9: La Gestion des

Affichage d’un Chemin de Repertoire

Example 7Programme getcwd_ex.c pour imprimer a l’ecran le repertoire de travail courant

#include<stdio.h>#include<stdlib.h>#include<unistd.h>

int main(){

long max;char *buf;

max = pathconf("/",_PC_PATH_MAX);buf =(char*)malloc(max);getcwd(buf,max);printf("%s\n",buf);

return 0;}

Page 26: Programmation Orientée Système Cours 9: La Gestion des

Ouverture d’un Repertoire

• L’en-tete <dirent.h> declare des fonctions d’ouverture, de lecture, derembobinage et de fermeture de repertoires

• Pour afficher les fichiers dans un repertoire, on doit d’abord l’ouvrir en utilisant lafonction opendir() :

DIR *opendir(const char *path);

• opendir() renvoie un pointeur sur DIR

• DIR est une structure de donnees qui represente un repertoire

• une valeur de retour NULL indique une erreur

• path doit etre le chemin a un repertoire existant

Page 27: Programmation Orientée Système Cours 9: La Gestion des

Lecture d’un Repertoire

• Pour parcourir un repertoire ouvert on utilise la fonction readdir() :

struct dirent *readdir(DIR *PDIR);

ou PDIR est le pointeur obtenu a partir d’un precedent appel a opendir()

• readdir() renvoie un pointeur sur une structure dirent dont le membre d_name

contient le nom du fichier courant

• chaque appel successif a readdir() avance au fichier suivant dans le repertoire

• readdir() renvoie NULL soit dans le cas d’une erreur ou une fois qu’on a traversetous les fichiers dans le repertoire

• pour distinguer ces deux conditions, verifier errno apres chaque appel readdir()

• comme readdir() change errno seulement si une erreur s’est produite, on doitla reinitialise explicitement avant chaque appel readdir()

Page 28: Programmation Orientée Système Cours 9: La Gestion des

Fermeture d’un Repertoire

• Finalement, on utilise closedir() pour fermer le repertoire une fois qu’on atermine :

int closedir(DIR *PDIR);

ou PDIR est le pointeur obtenu a partir d’un precedent appel opendir()

Page 29: Programmation Orientée Système Cours 9: La Gestion des

Entrees/Sorties sur les Repertoires

Example 8Le programme opendir_ex.c enumere le contenu du repertoire de travail courant :

#include <errno.h>

#include <dirent.h>

#include <stdio.h>

#include <stdlib.h>

int main(){

DIR *pdir;

struct dirent *pent;

pdir = opendir("."); /*"." refers to the current dir*/

if (!pdir){

printf("opendir() failure; terminating.\n");

exit(1);

}

errno = 0;

while ((pent = readdir(pdir))){

printf("%s\n", pent->d_name);

}

if (errno){

printf ("readdir() failure; terminating.\n");

exit(1);

}

closedir(pdir);

return 0;

}

Page 30: Programmation Orientée Système Cours 9: La Gestion des

Rembobinage d’un Repertoire

• La fonction rewinddir() reinitialise un flux repertoire a la premiere entree :

void rewinddir(DIR *PDIR);

• rewinddir() s’assure egalement que le repertoire reflete fidelement leschangements dans le repertoire (suppression de fichiers, renommage, etc) depuisle dernier appel opendir() ou rewinddir()

Example 9Programme rewinddir_ex.c pour afficher le premier element du repertoire courant,rembobiner, et afficher a nouveau le premier element

Page 31: Programmation Orientée Système Cours 9: La Gestion des

Creation d’un Repertoire

• D’autres operations relatives aux repertoires, telles que la creation, la suppressionet la modification, sont disponibles

• la fonction mkdir() cree un nouveau repertoire :

int mkdir (const char *dirname);

int mkdir (const char *dirname, mode_t perm);

ou dirname contient le nom du nouveau repertoire

• un nom de repertoire non valide donne un echec

• perm indique les permissions du repertoire

Page 32: Programmation Orientée Système Cours 9: La Gestion des

Suppression d’un Repertoire

• La fonction rmdir() supprime un repertoire existant :

int rmdir(const char *dirname);

• rmdir() echoue si le repertoire n’est pas vide

• pour supprimer un repertoire qui contient des fichiers, on doit supprimer cesfichiers d’abord et ensuite appeler rmdir()

• exemple mkdir_ex.c :#include <sys/stat.h>

#include <unistd.h>

#include <stdio.h>

#include <stdlib.h>

int main(int argc,char *argv[]){

int md,rd;

md = mkdir(argv[1],0777);

if(md == 0)

printf("%s directory is created\n",argv[1]);

else

printf("%s directory is not created\n",argv[1]);

rd = rmdir(argv[2]);

if(rd == 0)

printf("%s directory is removed\n",argv[2]);

else

printf("%s directory is not removed\n",argv[2]);

return 0;

}

Page 33: Programmation Orientée Système Cours 9: La Gestion des

Changement de Repertoire

• La fonction chdir() change le repertoire de travail courant du processus :

int chdir(const char *dirname);

• Si dirname n’est pas un nom de chemin d’acces valide ou si le processus nedispose pas des autorisations necessaires, chdir() echoue.

Exemple : programme miniLs.c

Page 34: Programmation Orientée Système Cours 9: La Gestion des

Conclusions : La Gestion des Fichiers et des Repertoires

• Overture, fermeture, lecture et ecriture des fichiers

• Manipulation des fichiers

• Overture, fermeture, lecture et ecriture des repertoires

• Manipulation des repertoires