Vous vous apprêtez à lire un tutoriel rédigé par un membre de ce site. Malgré tout le soin que ce membre a pu apporter au tutoriel, nous ne pouvons pas garantir que les informations contenues sur cette page sont exactes à 100%. Merci de garder cela en tête lorsque vous lirez cette page ;o)
Nous allons donc commencer par voir comment déplacer un fichier d'un endroit vers un autre.
Il n'est cependant pas possible de déplacer un fichier vers un autre système de fichiers.
Je m'explique : Si par exemple vous êtes sur Linux et que vous désirez déplacer un fichier sur une autre partition de votre disque vous ne pourrez pas, il n'existe aucune fonction pour le faire.
La fonction permettant de réaliser ceci est la suivante (déclarée dans
<stdio.h>) :
Code : C1 | int rename (const char * old, const char * new);
|
M@teo21 s'est servi de cette fonction dans son cours, mais il a dit qu'elle servait à renommer le fichier !
C'est vrai, cette fonction sert à renommer OU déplacer un fichier
Bon comme je suis sympa je vous fait un petit rappel des paramètres !
- const char * old : Nom du fichier à déplacer (mettre le chemin complet si vous n'êtes pas sur).
- const char * new : Nouvel emplacement (chemin complet, ou relatif à partir de l'emplacement de votre éxecutable).
Je vous rappelle également que la valeur de retour en cas d'échec est -1, comme souvent !
M@teo21 vous donne une fonction dans son
cours afin de supprimer un fichier, je vais donc vous donner une autre fonction qui vous permettra peut-être de comprendre un peu mieux la façon dont les fichiers sont gérés sur les systèmes UNIX.
Code : C1 | int unlink (const char * pathname);
|
Je suppose qu'il est inutile de vous dire que l'unique paramètre est le nom du fichier.
Comme précédemment en cas d'échec la fonction renvoie -1, pensez donc à tester la valeur de retour !
Il faut savoir qu'un fichier (sur système UNIX) est constitué de données et d'un identifiant que l'on appelle L'inode.
Or dans l'arborescence des répertoires du système se trouvent des noms de fichiers qui sont associés aux fichiers sur lesquels ils pointent, ces noms sont appelés liens.
L'appel à la fonction unlink() ne fait que supprimer le nom du fichier indiqué en argument, mais lorsque plus aucun nom ne pointe sur un fichier, le système le supprime automatiquement.
Pour plus de précisions sur cette fonction, comme d'habitude le
manuel est là pour ça !
Récupérer la taille d'un fichier est un petit peu plus long que les opérations précédentes.
Il vous faudra dans un premier temps inclure 3 en-têtes de plus dans votre programme :
Code : C1
2
3 | #include <sys/types.h> // Pour les définitions de types
#include <sys/stat.h> // Pour la fonction
#include <unistd.h>
|
Maintenant que vous avez inclus ces fichiers, voici le prototype de la fonction :
Code : C1 | int stat (const char * file_name, struct stat * buf);
|
Une petite description des paramètres s'impose ! ( Au moins pour un des deux

)
- const char * file_name : Là encore le nom du fichier.
- struct stat * buf : Un pointeur sur une structure
stat qui possède entre autre un attribut stockant la taille
Oui cette fonction retourne aussi -1 en cas d'échec
Voici donc le code pour récupérer tout plein d'informations sur notre fichier

:
Code : C1
2
3
4
5
6
7 | ...
struct stat buf;
if (-1 == stat(nom_fichier, &buf)) // Obtention de la taille, on passe l'adresse de buf car la fonction attend un pointeur!
{
perror("stat() ");
exit(EXIT_FAILURE); // Si erreur on sort
}
|
Si l'appel de la fonction a réussi, notre structure stat contient donc une multitude d'information sur notre fichier, notamment sa taille.
Voici la définition de la structure stat :
Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 | struct stat
{
dev_t st_dev;
ino_t st_ino; // Numéro d'inode
mode_t st_mode; // Permissions
nlink_t st_nlink; // Nombre de noms de fichiers pointant vers ce fichier
uid_t st_uid; // Identifiant utilisateur du propriétaire du fichier
gid_t st_gid; // Identifiant de groupe du propriétaire du fichier
dev_t st_rdev;
struct timespec st_atimespec;
struct timespec st_mtimespec;
struct timespec st_ctimespec;
off_t st_size; // Taille totale du fichier en octets
quad_t st_blocks;
u_long st_blksize;
u_long st_flags;
u_long st_gen;
};
|
La structure comporte beaucoup d'attributs, et je ne connais aucun de leur type !
Si vous avez bien lu le cours de M@teo21, vous avez sûrement compris qu'il s'agit pour la plupart de types standard qui ont été simplement redéfinis par un
typedef.
Si vous avez bien regardé la définition de la structure, vous savez maintenant que la taille du fichier est stocké dans le champ
st_size.
Pour simplement afficher la taille du fichier à l'écran :
Code : C1 | printf("%d\n", (int)buf.st_size);
|
Le forçage de type n'est peut-être pas nécessaire sur tous les systèmes (à vous de voir)
Je vous invite encore à consulter le
man pour de plus ample informations.
Mais qu'est ce donc que POSIX ?
POSIX est tout simplement un standard, si vous voulez en savoir plus, allez jeter un coup d'œil sur l'article de
wikipédia.
POSIX propose donc des fonctions pour manipuler les fichiers, à l'instar des fonctions ANSI C.
Quel est l'intérêt d'apprendre de nouvelles fonctions, les autres marchaient très bien !?
Oui, oui les autres foncions marchent très bien

mais en programmation système il est possible que vous ayez besoin des valeurs de retour de ces fonctions.
Bon assez parler, commençons par les fichiers d'include :
Code : C1
2
3 | #include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
|
Nous pouvons maintenant ouvrir notre fichier :
Code : C1 | int open (const char * pathname, int flags, mode_t mode);
|
Passons donc à l'explication des paramètres :
- const char * pathname : Oui, c'est bien le nom du fichier.
- int flags : Une constante qui définit le mode d'ouverture du fichier, on peut combiner plusieurs modes avec un ou binaire
|
Voici 5 des constantes dont vous aurez le plus besoin :
- O_RDONLY : Ouverture en lecture uniquement (READ ONLY).
- O_WRONLY : Ouverture en écriture uniquement (WRITE ONLY).
- O_RDWR : Ouverture en lecture / écriture (READ/WRITE).
- O_CREAT : Créer le fichier si il n'existe pas, à combiner avec un ou binaire.
- O_APPEND : Ouverture en mode append, à combiner avec un ou binaire (Cf :
cours de M@teo21)
Et enfin le 3ème paramètre est facultatif, il sert à indiquer les permissions si un fichier est créé.
La liste des modes disponibles étant longue, je vous invite à consulter la page de manuel de
open.
Pour ce qui est de la valeur de retour,
open() nous renvoie un
int qui est appelé
File Descriptor.
C'est grâce à cet entier que l'on va pouvoir réaliser les opérations que nous souhaitons sur notre fichier, si l'ouverture échoue -1 est renvoyé.
Je vais donc illustrer ces fonctions par un petit exemple, en créant un fichier et en le remplissant par les 26 lettres de l'alphabet, rien de bien sorcier donc

Il va donc falloir commencer par faire un appel à la fonction
open avec les flags
O_WRONLY et
O_CREAT
Néamoins, si vous avez lu le man, il est clairement précisé que lorsque le flag
O_CREAT est indiqué, le 3ème paramètre,
mode, doit être précisé.
Citation : OPEN(2)Le mode devrait toujours être indiqué quand O_CREAT est dans les attributs flags, (il est ignoré dans les autres cas).
Quel mode choisir, il y en a plein !
Ici choisir le mode est relativement simple, puisque vous voulez écrire dans votre fichier, donc :
Citation : OPEN(2)S_IRWXU
00700 L'utilisateur (propriétaire du fichier) a les autorisations de lecture, écriture, exécution.
Voici donc le code qui crée le fichier et test si tout s'est bien déroulé.
Code : C 1
2
3
4
5
6
7
8
9
10 | int main(void)
{
int fd; // Notre file descriptor
if (-1 == (fd = open("alphabet.txt", O_WRONLY | O_CREAT, S_IRWXU))) // Création du fichier et test
{
perror("open() ");
exit(EXIT_FAILURE);
}
return EXIT_SUCCESS;
}
|
Si aucune erreur ne s'est produite, notre fichier est donc créé, il nous reste plus qu'à écrire à l'intérieur, pour cela on va faire appel à la fonction
Code : C1 | ssize_t write (int fd, const void * buf, size_t count);
|
Rapide petite description :
- int fd : Notre File Descriptor, la valeur renvoyée par open pour ceux qui ne suivent pas !
- const void * buf : Les données à écrire.
- size_t count : La taille des données à écrire (en octets).
write() renvoie le nombre d'octets écrits ou -1 si il échoue (Cf
man)
Nous pouvons donc continuer à écrire notre programme afin de remplir le fichier
Code : C1
2
3
4
5
6
7 | char c = 'a'; // Octet à écrire
int i; // compteur
for (i = 0 ; i < 26 ; i++)
{
write(fd, &c, sizeof(char)); // Ecriture
c++; // Incrément
}
|
Il faut bien passer l'adresse de c, car write() attend un pointeur !
Une fois l'écriture achevée, il faut bien entendu penser à fermer le fichier, pour cela on appelle la fonction :
Code : C
L'unique paramètre de cette fonction est bien entendu notre File Descriptor
Voilà, vous pouvez vérifier, notre fichier texte contient bien les 26 lettres de l'alphabet !
Dernière opération, la lecture, pour cela une fonction :
Code : C1 | ssize_t read (int fd, void * buf, size_t count);
|
Les paramètres sont les mêmes que pour
write() !
Si vous n'avez pas supprimer le fichier, vous pouvez essayer de lire son contenu
Allez, je vous donne la solution
Secret (cliquez pour afficher)Code : C 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | int fd; // Notre file descriptor
if (-1 == (fd = open("alphabet.txt", O_RDONLY, S_IRWXU))) // Création du fichier et test
{
perror("open() ");
exit(EXIT_FAILURE);
}
char c = 0x00; // Octet à lire
int i; // compteur
for (i = 0 ; i < 26 ; i++)
{
read(fd, &c, sizeof(char)); // Lecture
printf("%c", c);
}
printf("\n");
close(fd); // On ferme le fichier !
|