|
@@ -0,0 +1,265 @@
|
|
|
+#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 "myls.h"
|
|
|
+
|
|
|
+void printls(char* path, char* filename){
|
|
|
+ int length;
|
|
|
+ char* completePath;
|
|
|
+ char permission[11];
|
|
|
+ char mois[5];
|
|
|
+ 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);
|
|
|
+ user = getpwuid(info.st_uid);
|
|
|
+
|
|
|
+ //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;
|
|
|
+ }
|
|
|
+
|
|
|
+ //Affiche
|
|
|
+ printf("%s X %s %s %ld %s %d %d:%d ", permission, user->pw_name, grp->gr_name, info.st_size, mois, date->tm_mday, date->tm_hour, date->tm_min);
|
|
|
+
|
|
|
+ //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);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+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);
|
|
|
+ }
|
|
|
+ //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;
|
|
|
+}
|