0
votes

Itérer sur le répertoire et imprimer des informations

Je veux écrire un programme C qui prend comme argument le chemin d'accès à un dossier et affiche certaines informations sur les fichiers qu'il contient.

Jusqu'à présent, j'ai écrit ceci: P>

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

int main(int argc, char** argv){
    char* dir_path = argv[1];
    char* dir_path_bar = strcat(dir_path, "/");
    DIR* dir = opendir(dir_path);

    for(struct dirent* entry = readdir(dir); entry != NULL; entry = readdir(dir)){
        printf("Next entry is %s\n", entry->d_name);
        char* entry_path = strcat(dir_path_bar, entry->d_name);
        printf("%s\n", entry_path);
        struct stat buf;
        stat(entry_path, &buf);
        printf("Its inode number is %s\n", entry->d_ino);
        printf("Its inode number is %s\n", buf.st_ino);
        printf("Its uid is %s\n", buf.st_uid);
        printf("Its size is %s bytes\n", buf.st_size);
    };
    closedir(dir);
}


1 commentaires

Vous appelez strcat sur l'un des éléments argv . Comment savez-vous que le pointeur a suffisamment d'espace pour cela? Au lieu de cela, créez un tampon local et copier argv [1] dans cela.


3 Réponses :


2
votes

Deux problèmes:

  • Vous êtes Ajout en continu à l'entrée ( argv [1] ) argument qui est un comportement indéfini. Vous ne pouvez pas ajouter aux chaînes de argv .

  • Impression également des valeurs entier utilisant % s non défini aussi. % s attend un argument char * , mais vous vouliez imprimer des valeurs entières.

    Vous pouvez plutôt utiliser un tampon temporaire et le transmettre à stat (2) : xxx

    J'ai également ajouté une vérification des erreurs.


7 commentaires

J'avais à nouveau UV pour l'utilisation sage de (uintMax_t) avec entrée-> d_ino (comme de même 3x endroits.)


J'ai nettoyé des commentaires antérieurs. Avec snaprintf () détection d'erreur robuste utilise int y = snaprintf (p, sz, ...); si (y <0 || y> = n)) erreur (); votre snprintf (...)> = (int) sz) est ok mais n'atteint pas les rares Erreur de codage, ni la situation rare où (int) sz perdre des informations.


En général, une bonne manipulation des erreurs permet malheureusement plus longtemps que le code attrayant. Dommage que cette réponse n'a pas été acceptée.


Je suis d'accord (note que y <0 n'est pas dans la norme C mais POSIX). Mais je ne comprends pas pourquoi (int) sz troncature serait un problème car SnPRINTF renvoie un int . Casting Valeur de retour de Snprintf à Taille_T a le problème opposé (par exemple, SNPRINTF renvoie une valeur négative).


Seulement s'adressant à C, pas POSIX: "Ainsi, la production terminée nulle a été complètement écrite si et uniquement si la valeur renvoyée est non négative et inférieure à n ." C11 §7.21.6.5 3. Test de négatif Y est en raison de la norme C. Dans les cas extrêmes, si sz était int_max + 1 , (int) sz peut devenir une étiquette négative et incorrecte sprintf () < / code> un échec. "La valeur de retour de Snprintf à Taille_T a le problème opposé (par exemple, SnPrintf renvoie une valeur négative)" n'est pas applicable car il est après le y <0 et donc le y> n Cast / Comparer n'est pas exécuté avec négatif Y .


Laissez-nous Continuez cette discussion dans le chat .


J'ai détaillé de certaines réflexions sur snaprintf () en fonction de notre discussion.



2
votes

Comme d'autres personnes ont mentionné, vous ne pouvez pas ajouter à argv [1] . Vous ne pouvez pas continuer à l'ajouter à l'intérieur de la boucle. Et, vous ne pouvez pas utiliser % s pour produire des numéros de sortie.

Voici votre code avec les bogues annotés et fixes [Utilisation #if 0 pour afficher l'ancien code ]: xxx


1 commentaires

"Celles-ci ont besoin% d /% ld /% lld" -> qui n'est pas clair comme .d_ino, .st_ino, .st_uid, .st_size ne sont certainement pas long, long, int, long, int, long Réf . Certains d'entre eux sont des membres non signés également.



1
votes

Non indiqué dans les 2 autres réponses précédentes est une bonne évitant de la copie excessive.

Lors de la formulation du entrée_Path , seule l'entrée elle-même doit être écrasée, et non la chaîne entière. Cela devient précieux avec une longue chaîne de répertoires pré-fixes. xxx


0 commentaires