#include #include #include #include #include #include #include //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éens typedef 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ée struct 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 choisi typedef bool (*cmp) (struct ls_node *, struct ls_node *); //Filtrage de certains fichiers bool 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émoire void no_memory() { puts ("Plus de mémoire"); exit(0); } //Insérer un noeud à un emplacement dicté par la fonction de tri struct 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 noeuds void 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; }