GNU/Linux >> Tutoriels Linux >  >> Linux

Howto :Programmation en C avec des répertoires sous Linux

Quand on dit que sous Linux, tout est un fichier, c'est vraiment vrai. La plupart des opérations que nous pouvons effectuer sur les fichiers peuvent être effectuées sur d'autres entités telles que socket, pipe, répertoires, etc.

Il existe certaines situations dans lesquelles un utilitaire logiciel peut avoir à parcourir des répertoires dans le système Linux pour trouver ou faire correspondre quelque chose. C'est le cas d'utilisation où le programmeur de cet utilitaire doit gérer la programmation de répertoires. Ainsi, dans cet article, nous couvrirons les bases suivantes de la programmation d'annuaires avec un exemple.

  1.  Créer des répertoires.
  2.  Lire des répertoires.
  3.  Suppression de répertoires.
  4.  Fermer le répertoire.
  5.  Obtenir le répertoire de travail actuel.

Nous passerons en revue les fonctions utilisées pour chaque étape ci-dessus, puis nous verrons enfin un exemple qui résumera toutes les opérations sur les répertoires.

1. Création de répertoires

Le système Linux fournit l'appel système suivant pour créer des répertoires :

#include <sys/stat.h>
#include <sys/types.h>
int mkdir(const char *pathname, mode_t mode);

L'argument 'pathname' est utilisé pour le nom du répertoire.

Depuis la page de manuel :

Le mode d'argument spécifie les autorisations à utiliser. Il est modifié par le processus umask de la manière habituelle :les permissions du répertoire créé sont (mode &~umask &0777). Les autres bits de mode du répertoire créé dépendent du système d'exploitation. Pour Linux, voir ci-dessous.

Le répertoire nouvellement créé appartiendra à l'ID utilisateur effectif du processus. Si le répertoire contenant le fichier a le bit set-group-ID défini, ou si le système de fichiers est monté avec la sémantique du groupe BSD (mount -o bsdgroups ou, synonyme mount -o grpid), le nouveau répertoire héritera de la propriété du groupe de son parent ; sinon, il appartiendra à l'ID de groupe effectif du processus. Si le répertoire parent a le bit set-group-ID défini, il en sera de même pour le répertoire nouvellement créé.

2. Répertoires de lecture

Une famille de fonctions permet de lire le contenu du répertoire.

1. Tout d'abord, un flux de répertoire doit être ouvert. Cela se fait par l'appel système suivant :

#include <sys/types.h>
#include <dirent.h>
DIR *opendir(const char *name);

Depuis la page de manuel :

La fonction opendir() ouvre un flux de répertoire correspondant au nom du répertoire et renvoie un pointeur vers le flux de répertoire. Le flux est positionné à la première entrée du répertoire.

2. Ensuite, pour lire les entrées du répertoire, le flux ouvert ci-dessus est utilisé par l'appel système suivant :

#include
struct dirent *readdir(DIR *dirp);

Depuis la page de manuel :

La fonction readdir() renvoie un pointeur vers une structure dirent représentant la prochaine entrée de répertoire dans le flux de répertoire pointé par dirp. Il renvoie NULL lorsqu'il atteint la fin du flux de répertoire ou si une erreur s'est produite.

Sous Linux, la structure dirent est définie comme suit :

struct dirent
{
    ino_t          d_ino;       /* inode number */
    off_t          d_off;       /* offset to the next dirent */
    unsigned short d_reclen;    /* length of this record */
    unsigned char  d_type;      /* type of file; not supported
                                   by all file system types */
    char           d_name[256]; /* filename */
};

3. Suppression de répertoires

Le système Linux fournit l'appel système suivant pour supprimer les répertoires :

#include <unistd.h>
int rmdir(const char *pathname);

Depuis la page de manuel :

rmdir() supprime le répertoire représenté par 'pathname' s'il est vide. SI le répertoire n'est pas vide alors cette fonction ne réussira pas.

4. Fermeture des répertoires

Le système Linux fournit l'appel système suivant pour fermer les répertoires :

#include <sys/types.h>
#include <dirent.h>
int closedir(DIR *dirp);

Depuis la page de manuel :

La fonction closedir() ferme le flux de répertoire associé à dirp. Un appel réussi à closedir() ferme également le descripteur de fichier sous-jacent associé à dirp. Le descripteur de flux de répertoire dirp n'est pas disponible après cet appel.

5. Obtenir le répertoire de travail actuel

Le système Linux fournit l'appel système suivant pour obtenir le CWD :

#include <unistd.h>
char *getcwd(char *buf, size_t size);

Depuis la page de manuel :

La fonction getcwd() copie un nom de chemin absolu du répertoire de travail actuel dans le tableau pointé par buf, qui est de longueur size. Cette fonction renvoie une chaîne terminée par un caractère nul contenant un nom de chemin absolu qui est le répertoire de travail actuel du processus d'appel. Le nom du chemin est renvoyé comme résultat de la fonction et via l'argument buf, s'il est présent. Si la longueur du nom de chemin absolu du répertoire de travail actuel, y compris l'octet nul de fin, dépasse size octets, NULL est renvoyé et errno est défini sur ERANGE; une application doit vérifier cette erreur et allouer un tampon plus grand si nécessaire.

6. Un exemple

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

int main (int argc, char *argv[])
{
    if(2 != argc)
    {
        printf("\n Please pass in the directory name \n");
        return 1;
    }

    DIR *dp = NULL;
    struct dirent *dptr = NULL;
    // Buffer for storing the directory path
    char buff[128];
    memset(buff,0,sizeof(buff));

    //copy the path set by the user
    strcpy(buff,argv[1]);

    // Open the directory stream
    if(NULL == (dp = opendir(argv[1])) )
    {
        printf("\n Cannot open Input directory [%s]\n",argv[1]);
        exit(1);
    }
    else
    {
        // Check if user supplied '/' at the end of directory name.
        // Based on it create a buffer containing path to new directory name 'newDir'
        if(buff[strlen(buff)-1]=='/')
        {
            strncpy(buff+strlen(buff),"newDir/",7);
        }
        else
        {
            strncpy(buff+strlen(buff),"/newDir/",8);
        }

        printf("\n Creating a new directory [%s]\n",buff);
        // create a new directory
        mkdir(buff,S_IRWXU|S_IRWXG|S_IRWXO);
        printf("\n The contents of directory [%s] are as follows \n",argv[1]);
        // Read the directory contents
        while(NULL != (dptr = readdir(dp)) )
        {
            printf(" [%s] ",dptr->d_name);
        }
        // Close the directory stream
        closedir(dp);
        // Remove the new directory created by us
        rmdir(buff);
        printf("\n");
    }

    return 0;
}

L'exemple ci-dessus devrait maintenant être explicite.

La sortie de l'exemple ci-dessus est :

# ./direntry /home/himanshu/practice/linux

 Creating a new directory [/home/himanshu/practice/linux/newDir/]

 The contents of directory [/home/himanshu/practice/linux] are as follows
 [redhat]  [newDir]  [linuxKernel]  [..]  [ubuntu]  [.]

Linux
  1. Comprendre les appels système sous Linux avec strace

  2. Commande d'arrêt Linux (avec exemples)

  3. Planification des tâches système avec Cron sous Linux

  4. Comment renommer un répertoire sous Linux

  5. Howto :Programmation en C avec des fichiers temporaires sous Linux

Comment supprimer (supprimer) le répertoire sous Linux

Comment comparer des répertoires avec Meld sous Linux

Commande de CD Linux avec exemples

Commande de disponibilité Linux avec exemples

Premiers pas avec le système d'exploitation Linux

Principes de base de la ligne de commande Linux - Travailler avec des fichiers et des répertoires