rendered paste body#include <string.h>#include <stdio.h>#include <sys/types.h>#include <dirent.h>#include <sys/stat.h> #include <unistd.h>#include <stdlib.h>//Options#define OPT_ALL_FILES 0x00000001 // -a, --all#define OPT_CTIME_SORT 0x00000002 // -c, --time=ctime, --time=status#define OPT_ALL_FILES_NOSORT 0x00000401 // -f#define OPT_INODE 0x00000004 // -i, --inode#define OPT_LONG 0x00000008 // -l, --format=long, --format=verbose#define OPT_NUMERIC_UIDGID 0x0000000f // -n, --numeric-uid-gid#define OPT_TYPE_CHAR 0x00000010 // -p#define OPT_REVERSE_SORT 0x00000020 // -r, --reverse#define OPT_MTIME_SORT 0x00000040 // -t, --sort=time#define OPT_ATIME_SORT 0x00000080 // -u, --time=atime, --time=access, --time=use#define OPT_IGNORE_BACKUPS 0x000000f0 // -B, --ignore-backups#define OPT_FULLTYPE_CHAR 0x00000100 // -F, --classify#define OPT_RECURSIVE 0x00000200 // -R, --recursive#define OPT_NOSORT 0x00000400 // -U, --sort=none//Booléenstypedef enum {FALSE=0, TRUE} bool;//Filtres#define ISBACKUP(file) (file[strlen(file) - 1] == '~') ? TRUE : FALSE#define ISDOTDIR(file) (file[0] == '.') ? TRUE : FALSE//Le type d'une entréestruct ls_node{ struct dirent *entry; struct stat ent_stat; struct ls_node *next;};//Fonctions de comparaison pour le tri /* Avec ctime */bool ctime_lt(struct ls_node *a, struct ls_node *b){ return a->ent_stat.st_ctime < b->ent_stat.st_ctime;}bool ctime_gt(struct ls_node *a, struct ls_node *b){ return a->ent_stat.st_ctime > b->ent_stat.st_ctime;} /* Avec mtime */bool mtime_lt(struct ls_node *a, struct ls_node *b){ return a->ent_stat.st_ctime < b->ent_stat.st_ctime;}bool mtime_gt(struct ls_node *a, struct ls_node *b){ return a->ent_stat.st_ctime > b->ent_stat.st_ctime;} /* Avec atime */bool atime_lt(struct ls_node *a, struct ls_node *b){ return a->ent_stat.st_ctime < b->ent_stat.st_ctime;}bool atime_gt(struct ls_node *a, struct ls_node *b){ return a->ent_stat.st_ctime > b->ent_stat.st_ctime;} /* Alphabétique */bool alpha_gt(struct ls_node *a, struct ls_node *b){ return strcasecmp(a->entry->d_name, b->entry->d_name) > 0;} bool alpha_lt(struct ls_node *a, struct ls_node *b){ return strcasecmp(a->entry->d_name, b->entry->d_name) < 0;} /*Pas de comparaison */bool no_sort(struct ls_node *a, struct ls_node *b){ return FALSE;}//Type Pointeur vers le plus_petit choisitypedef bool (*cmp) (struct ls_node *, struct ls_node *);//Filtrage de certains fichiersbool filtered(int options, struct ls_node *node){ if( !(options & OPT_ALL_FILES) ){ if (ISDOTDIR(node->entry->d_name )){ return TRUE; } } if(options & OPT_IGNORE_BACKUPS){ if (ISBACKUP(node->entry->d_name) ){ return TRUE; } } return FALSE;}//Plus de mémoirevoid no_memory(){ puts ("Plus de mémoire"); exit(0);}//Insérer un noeud à un emplacement dicté par la fonction de tristruct ls_node * insert_node (struct ls_node *root, struct ls_node *current, cmp plus_petit){ struct ls_node *root_save = root; if(root == NULL){ return current; } if(!plus_petit(current, root)){ while (root->next != NULL && !plus_petit(current, root->next)) { root = root->next; } current->next = root->next; root->next = current; return root_save; } else{ current->next = root; return current; } }//Effacer tous les noeudsvoid free_nodes(struct ls_node *root){ if (root == NULL){ return; } free_nodes(root->next); free(root);}void display_node(struct ls_node *node){ printf("%s\n",node->entry->d_name);}/* Le traitement principal */void ls(int options, char *rep, cmp plus_petit){ DIR *d = opendir(rep); //Entrée de repertoire courante struct dirent *curdir; if(d == NULL){ printf("ls: %s: Ne parvient pas à ouvrir le repertoire\n", rep); return; } //La liste du contenu du repertoire struct ls_node *root = NULL; //Noeud courant struct ls_node *current; //Chemin d'un noeud char * current_path; //Plus commode si le repertoire se termine par un slash if(rep[strlen(rep)-1] != '/'){ rep=realloc(rep, strlen(rep) + 2); sprintf(rep, "%s/", rep); } while ( (curdir = readdir (d)) != NULL ) { current = (struct ls_node *) calloc (1, sizeof(struct ls_node)); if (current == NULL){ no_memory(); } current->entry = curdir; current_path = (char *)calloc (1, strlen(rep) + strlen(curdir->d_name) + 1); strcpy (current_path, rep); strcat (current_path, curdir->d_name); if(stat (current_path, ¤t->ent_stat) == -1){ printf("%s\n",current_path); } free(current_path); if(!filtered(options, current) ){ root = insert_node (root, current, plus_petit); } else{ free(current); } } current=root; while(current!=NULL){ display_node(current); if((options & OPT_RECURSIVE) && (current->ent_stat.st_mode & S_IFDIR) ){ current_path = (char *)calloc (1, strlen(rep) + strlen(current->entry->d_name) + 1); strcpy (current_path, rep); strcat (current_path, current->entry->d_name); printf("\n%s:\n", current_path); ls(options, current_path, plus_petit); free(current_path); } current=current->next; } closedir(d); free_nodes(root); }int main(int argc, char **argv){ int i; //Pour les options int options = 0; int opt; //Le repertoire à analyser char *rep = (char *)malloc(2); strcpy(rep, "."); //Fonction de tri par défaut cmp plus_petit = &alpha_lt; while ( (opt = getopt(argc, argv, "acfilnprtuBRFU")) != -1 ) { switch (opt) { case 'a': options |= OPT_ALL_FILES; break; case 'c': options |= OPT_CTIME_SORT; if (options & OPT_ATIME_SORT){ options ^= OPT_ATIME_SORT; } if (options & OPT_MTIME_SORT){ options ^= OPT_MTIME_SORT; } if (options & OPT_CTIME_SORT){ options ^= OPT_CTIME_SORT; } break; case 'f': options |= OPT_ALL_FILES_NOSORT; if (options & OPT_MTIME_SORT){ options ^= OPT_MTIME_SORT; } if (options & OPT_ATIME_SORT){ options ^= OPT_ATIME_SORT; } if (options & OPT_CTIME_SORT){ options ^= OPT_CTIME_SORT; } break; case 'i': options |= OPT_INODE; break; case 'l': options |= OPT_LONG; break; case 'n': options |= OPT_NUMERIC_UIDGID; break; case 'p': options |= OPT_TYPE_CHAR; break; case 'r': options |= OPT_REVERSE_SORT; break; case 't': options |= OPT_MTIME_SORT; if (options & OPT_ATIME_SORT){ options ^= OPT_ATIME_SORT; } if (options & OPT_NOSORT){ options ^= OPT_NOSORT; } if (options & OPT_CTIME_SORT){ options ^= OPT_CTIME_SORT; } break; case 'u': options |= OPT_ATIME_SORT; if (options & OPT_MTIME_SORT){ options ^= OPT_MTIME_SORT; } if (options & OPT_NOSORT){ options ^= OPT_NOSORT; } if (options & OPT_CTIME_SORT){ options ^= OPT_CTIME_SORT; } break; case 'B': options |= OPT_IGNORE_BACKUPS; break; case 'F': options |= OPT_FULLTYPE_CHAR; break; case 'R': options |= OPT_RECURSIVE; break; case 'U': options |= OPT_NOSORT; if (options & OPT_MTIME_SORT){ options ^= OPT_MTIME_SORT; } if (options & OPT_ATIME_SORT){ options ^= OPT_ATIME_SORT; } if (options & OPT_CTIME_SORT){ options ^= OPT_CTIME_SORT; } break; } } //On va chercher le repertoire while (*(++argv)!=NULL) { if (argv[0][0] != '-'){ free(rep); rep = (char *)malloc(strlen(*argv) +1); strcpy(rep, *argv); } } //Cherche le plus_petit if (options & OPT_CTIME_SORT){ if(options & OPT_REVERSE_SORT){ plus_petit = &ctime_gt; } else{ plus_petit = &ctime_lt; } } else if (options & OPT_MTIME_SORT){ if(options & OPT_REVERSE_SORT){ plus_petit = &mtime_gt; } else{ plus_petit = &mtime_lt; } } else if (options & OPT_ATIME_SORT){ if(options & OPT_REVERSE_SORT){ plus_petit = &atime_gt; } else{ plus_petit = &atime_lt; } } else if (options & OPT_ATIME_SORT){ if(options & OPT_REVERSE_SORT){ plus_petit = &atime_gt; } else{ plus_petit = &atime_lt; } } else if (options & OPT_NOSORT){ plus_petit = &no_sort; } else if (options & OPT_REVERSE_SORT){ plus_petit = &alpha_gt; } //On lance tout ls(options, rep, plus_petit); free(rep); return 0;}