123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333 |
- #define _POSIX_C_SOURCE 200809L
- #include <stdlib.h>
- #include <stdio.h>
- #include <dirent.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include <string.h>
- #include <grp.h>
- #include <pwd.h>
- #include "error.h"
- #include "color.h"
- #include "constante.h"
- int get_total(char* path, struct dirent** dir, int nb, boolean hidden){
- struct stat info;
- char* completePath;
- int length, total = 0, i = 0;
- //Si besoins passe les fichiers cachés
- while(i < nb && !hidden && *dir[i]->d_name == '.') i++;
- //Parcours tous les fichiers
- for(; i < nb; i++){
- //Création chemin vers le dossier
- length = strlen(path) + strlen(dir[i]->d_name) + 2;
- completePath = malloc(sizeof(char) * length);
- memset(completePath, 0, length);
- if(path[strlen(path)-1] != '/'){
- snprintf(completePath, length, "%s/%s", path, dir[i]->d_name);
- } else {
- snprintf(completePath, length, "%s%s", path, dir[i]->d_name);
- }
- //Recup info fichier
- if(stat(completePath, &info) == ERR){
- free(completePath);
- continue;
- }
- //Ajoute au total
- total += info.st_blocks;
- }
- return total / 2;
- }
- /**
- * Affiche sous la forme ls -l les infos d'un fichier/dossier
- * @param char* Le chemin vers le fichier (avec ou sans le nom du fichier)
- * @param char* Le nom du fichier ou NULL si il est déjà dans le chemin
- */
- void printls(char* path, char* filename){
- int length;
- char* completePath;
- char permission[11];
- char mois[5];
- char jour[3], heure[3], minute[3];
- struct stat info;
- struct group* grp;
- struct passwd* user;
- struct tm* date;
- //Si le nom est en 2 partie
- if(filename != NULL){
- //Création chemin vers le fichier
- length = strlen(path) + strlen(filename) + 2;
- completePath = malloc(sizeof(char) * length);
- memset(completePath, 0, length);
- if(path[strlen(path)-1] != '/'){
- snprintf(completePath, length, "%s/%s", path, filename);
- } else {
- snprintf(completePath, length, "%s%s", path, filename);
- }
- } else {
- filename = path;
- completePath = path;
- path = NULL;
- }
-
- //Recup info fichier
- if(stat(completePath, &info) == ERR){
- addperror("Erreur stat");
- return;
- }
- if(path != NULL){
- free(completePath);
- }
- //Calcul permission
- memset(permission, 0, 11);
- if(S_ISDIR(info.st_mode)){
- permission[0] = 'd';
- }
- else if(S_ISBLK(info.st_mode)){
- permission[0] = 'b';
- }
- else if(S_ISCHR(info.st_mode)){
- permission[0] = 'c';
- }
- #ifdef S_ISFIFO
- else if(S_ISFIFO(info.st_mode)){
- permission[0] = 'p';
- }
- #endif
- #ifdef S_ISLINK
- else if(S_ISLINK(info.st_mode)){
- permission[0] = 'l';
- }
- #endif
- #ifdef S_ISSOCK
- else if(S_ISSOCK(info.st_mode)){
- permission[0] = 's';
- }
- #endif
- else
- permission[0] = '-';
- info.st_mode & S_IRUSR ? (permission[1] = 'r') : (permission[1] = '-');
- info.st_mode & S_IWUSR ? (permission[2] = 'w') : (permission[2] = '-');
- info.st_mode & S_IXUSR ? (permission[3] = 'x') : (permission[3] = '-');
- info.st_mode & S_IRGRP ? (permission[4] = 'r') : (permission[4] = '-');
- info.st_mode & S_IWGRP ? (permission[5] = 'w') : (permission[5] = '-');
- info.st_mode & S_IXGRP ? (permission[6] = 'x') : (permission[6] = '-');
- info.st_mode & S_IROTH ? (permission[7] = 'r') : (permission[7] = '-');
- info.st_mode & S_IWOTH ? (permission[8] = 'w') : (permission[8] = '-');
- info.st_mode & S_IXOTH ? (permission[9] = 'x') : (permission[9] = '-');
- //Recup le groupe et l'utilisateur
- grp = getgrgid(info.st_gid);
- if(grp == NULL){
- return;
- }
- user = getpwuid(info.st_uid);
- if(user == NULL){
- return;
- }
- //Recup la date
- memset(mois, 0, 5);
- date = gmtime(&info.st_mtime);
- switch(date->tm_mon){
- case 0:
- strcpy(mois, "jan.");
- break;
- case 1:
- strcpy(mois, "fev.");
- break;
- case 2:
- strcpy(mois, "mar.");
- break;
- case 3:
- strcpy(mois, "avr.");
- break;
- case 4:
- strcpy(mois, "mai.");
- break;
- case 5:
- strcpy(mois, "jui.");
- break;
- case 6:
- strcpy(mois, "jul.");
- break;
- case 7:
- strcpy(mois, "aou.");
- break;
- case 8:
- strcpy(mois, "sep.");
- break;
- case 9:
- strcpy(mois, "oct.");
- break;
- case 10:
- strcpy(mois, "nov.");
- break;
- case 11:
- strcpy(mois, "dec.");
- break;
- }
- //Met le jour sur 2 chiffre
- memset(jour, 0, 3);
- if(date->tm_mday < 10){
- snprintf(jour, 3, "0%d", date->tm_mday);
- } else {
- snprintf(jour, 3, "%d", date->tm_mday);
- }
- //Met l'heure sur 2 chiffre
- memset(heure, 0, 3);
- if(date->tm_hour < 10){
- snprintf(heure, 3, "0%d", date->tm_hour);
- } else {
- snprintf(heure, 3, "%d", date->tm_hour);
- }
- //Met les minutes sur 2 chiffre
- memset(minute, 0, 3);
- if(date->tm_min < 10){
- snprintf(minute, 3, "0%d", date->tm_min);
- } else {
- snprintf(minute, 3, "%d", date->tm_min);
- }
- //Affiche
- printf("%s %ld %s %s %ld %s %s %s:%s ", permission, info.st_nlink, user->pw_name, grp->gr_name, info.st_size, mois, jour, heure, minute);
- //color the name
- if(permission[0] == 'd'){
- printf(BLUE "%s\n" RESET, filename);
- }
- else if(permission[3] == 'x'){
- printf(GREEN "%s\n" RESET, filename);
- }
- else{
- printf("%s\n", filename);
- }
- }
- /**
- * Affiche tous le contenu d'un dossier
- * @param char* Le chemin vers le dossier
- * @param boolean Affiche ou non les sous dossiers
- * @param boolean Affiche ou non les fichiers/dossiers cachés
- */
- void printdir(char* path, boolean subdir, boolean hidden){
- struct dirent** contentsDir;
- int nbFile;
- int j = 0;
- //Recup info
- if((nbFile = scandir(path, &contentsDir, 0, alphasort)) == ERR){
- addperror("Erreur scandir()");
- return;
- }
- //Si sous dossier on affiche le dossier d'origine
- if(subdir){
- printf("%s :\n", path);
- }
- printf("total %d\n", get_total(path, contentsDir, nbFile, hidden));
- //Si besoins passe les fichiers cachés
- while(j < nbFile && !hidden && *contentsDir[j]->d_name == '.') j++;
- //Parcours les fichiers du dossier
- while(j < nbFile){
- printls(path, contentsDir[j]->d_name);
- j++;
- }
- //Si on affiche les sous dossiers on parcours le contenue pour les trouver
- if(subdir){
- char* completePath;
- int length;
- struct stat info;
- j = 0;
- //Si besoins passe les fichiers cachés
- while(j < nbFile && !hidden && *contentsDir[j]->d_name == '.') j++;
- //Cherche les sous dossiers
- while(j < nbFile){
- length = strlen(contentsDir[j]->d_name);
- if(strncmp(contentsDir[j]->d_name, ".", length) == 0 || strncmp(contentsDir[j]->d_name, "..", length) == 0){
- j++;
- continue;
- }
- //Création chemin vers le dossier
- length += strlen(path) + 2;
- completePath = malloc(sizeof(char) * length);
- memset(completePath, 0, length);
- if(path[strlen(path)-1] != '/'){
- snprintf(completePath, length, "%s/%s", path, contentsDir[j]->d_name);
- } else {
- snprintf(completePath, length, "%s%s", path, contentsDir[j]->d_name);
- }
- //Recup info fichier
- if(stat(completePath, &info) == ERR){
- addperror("Erreur stat");
- free(completePath);
- j++;
- continue;
- }
- //Si c'est un dossier
- if(S_ISDIR(info.st_mode)){
- //On l'affiche
- printf("\n");
- printdir(completePath, subdir, hidden);
- }
- //Tour suivant
- free(completePath);
- j++;
- }
- }
- //Nettoyage
- while (nbFile--) {
- free(contentsDir[nbFile]);
- }
- free(contentsDir);
- }
- int main(int argc, char* argv[]){
- struct stat info;
- int i = 1, displayed = 0, opt;
- boolean hiddenFile = false;
- boolean displaySubDir = false;
- //Gestion des options
- while((opt = getopt(argc, argv, "aR")) != ERR){
- switch(opt){
- case 'a' :
- hiddenFile = true;
- break;
- case 'R' :
- displaySubDir = true;
- break;
- default:
- addperror("getotp error");
- }
- }
- //Time to display
- for(i = 1; i < argc; i++){
- if(argv[i][0] != '-'){
- if(stat(argv[i], &info) == ERR){
- addperror("Erreur stat");
- return EXIT_FAILURE;
- }
- if(S_ISDIR(info.st_mode)){
- //Affiche le dossier
- printdir(argv[i], displaySubDir, hiddenFile);
- displayed = true;
- }
- else{
- printls(argv[i], NULL);
- displayed = true;
- }
- }
- }
- //Si aucun dossier ou fichier en argument
- if(!displayed){
- //On affiche le dossier courrant
- printdir(".", displaySubDir, hiddenFile);
- }
- return EXIT_SUCCESS;
- }
|