web-dev-qa-db-fra.com

Implémentation de la commande ls -al en C

Dans le cadre d'un devoir d'une de mes classes, je dois écrire un programme en C pour dupliquer les résultats de la commande ls -al. J'ai lu le matériel nécessaire mais je n'obtiens toujours pas le bon résultat. Voici mon code jusqu'à présent, il est uniquement censé imprimer la taille et le nom du fichier, mais les tailles de fichier que son impression n'est pas correcte.

Code:

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

int main(int argc, char* argv[])
{
    DIR *mydir;
    struct dirent *myfile;
    struct stat mystat;

    mydir = opendir(argv[1]);
    while((myfile = readdir(mydir)) != NULL)
    {
        stat(myfile->d_name, &mystat);    
        printf("%d",mystat.st_size);
        printf(" %s\n", myfile->d_name);
    }
    closedir(mydir);
}

Voici mes résultats après avoir exécuté le code:

[root@localhost ~]# ./a.out Downloads
4096 ..
4096 hw22.c
4096 ankur.txt
4096 .
4096 destination.txt

Voici les bonnes tailles:

[root@localhost ~]# ls -al Downloads
total 20
drwxr-xr-x.  2 root root 4096 Nov 26 01:35 .
dr-xr-x---. 24 root root 4096 Nov 26 01:29 ..
-rw-r--r--.  1 root root   27 Nov 21 06:32 ankur.txt
-rw-r--r--.  1 root root   38 Nov 21 06:50 destination.txt
-rw-r--r--.  1 root root 1139 Nov 25 23:38 hw22.c

Quelqu'un peut-il s'il vous plaît signaler mon erreur.

Merci,

Ankur

16
ankur3000

myfile->d_name Est le nom de fichier et non le chemin d'accès, vous devez donc d'abord ajouter le nom de fichier au répertoire "Downloads/file.txt", S'il ne s'agit pas du répertoire de travail:

char buf[512];    
while((myfile = readdir(mydir)) != NULL)
{
    sprintf(buf, "%s/%s", argv[1], myfile->d_name);
    stat(buf, &mystat);
....

Quant à savoir pourquoi il affiche 4096 Qui est la taille des liens . Et .. Du dernier appel à stat().

Remarque: vous devez allouer un tampon suffisamment grand pour contenir le nom du répertoire, le nom du fichier l'octet NULL et le séparateur, quelque chose comme ça

strlen(argv[1]) + NAME_MAX + 2;
14
iabdalkader

Ceci est le code final que j'ai pu travailler pour toute personne intéressée. Il imprime les tailles de fichier correctes. Le crédit revient au demandeur et au multiplexeur pour avoir répondu, simplement en assemblant le code. L'entrée pour laquelle j'ai pu travailler est "./main". .

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

int main(int argc, char* argv[])
{
    DIR *mydir;
    struct dirent *myfile;
    struct stat mystat;

    char buf[512];
    mydir = opendir(argv[1]);
    while((myfile = readdir(mydir)) != NULL)
    {
        sprintf(buf, "%s/%s", argv[1], myfile->d_name);
        stat(buf, &mystat);
        printf("%zu",mystat.st_size);
        printf(" %s\n", myfile->d_name);
    }
    closedir(mydir);
}
6
hbteibet

Je pense que vous constaterez que si vous ./a.out . vous obtiendrez le comportement que vous attendez.

Vous avez un bug légèrement subtil, observable si vous examinez le code retour de votre appel à stat(2).

L'erreur fondamentale: les dirents retournés par readdir(2) (les myfile dans votre code) auront un d_name par rapport à mydir. Votre code stat.. d'abord, réussira, et donc mystat contiendra des données valides pour .., puis tous les appels suivants à stat(2) échouera, renvoyant -1, que vous ne vérifiez pas, donc mystat ne sera pas modifié, et vous imprimerez le st_size pour l'ancienne valeur, c'est-à-dire celle de ...

1
Kristian Glass

Le problème est que lorsque vous stat("ankur.txt", &mystat), vous ne travaillez pas sur le fichier "Downloads/ankur.txt". Très probablement, la stat() échoue; alternativement, il fait rapport sur un fichier différent.

Par conséquent, vous devez vérifier si votre système prend en charge fstatat() - nouveau dans POSIX 2008 - ou arranger pour préfixer le nom du fichier avec le nom du répertoire.

0
Jonathan Leffler