#include <cstdlib>
#include <iostream>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <string>
#include <vector>
#include <errno.h>
#include <fcntl.h>
#include <sstream>
using namespace std;
extern int errno;
struct File{ int inum;
int nblinks;
string name;
};
void afficheTab (vector<File> *tab)
/*
Permet d'afficher le résultat de l'excécution du programme
*/
{
int fichOui = 0; //Nombre de fichiers intègres
int fichNon = 0; //Nombre de fichiers corrompus
bool b=false; // test d'affichage
for(int i=0 ; i<(*tab).size();i++) //Parcours de la liste des fichiers traités
{
if (((*tab)[i]).nblinks>1) // si tous les liens du fichier n'ont pas été trouvés
{
if (!b) //test d'affichage
{
cout<<"Liste des fichiers en danger :"<<endl;
b=true;
}
cout<<"\tnum : "<<(*tab)[i].inum<<", nom : "<<(*tab)[i].name<<", liens : "<<(*tab)[i].nblinks<<endl; // On affiche les fichiers problématiques
fichNon++; // on incrémente le nombre de fichiers corrompus
}
else //si tous les liens du fichier ont étaient atteinds
{
fichOui++; // incrémentation du nombre de fichiers intègres
}
}
cout<<"\nBilan de l'excécution : "<<endl;
cout<<"Nombre de fichiers avec liens durs traités : "<<fichOui+fichNon<<"."<<endl;
cout<<"\tdont :"<<endl;
cout<<"\t\t"<<fichOui<<" fichiers intègres."<<endl;
cout<<"\t\t"<<fichNon<<" fichiers à problème."<<endl;
}
void traiteFichier (int num , int nblien ,char* temp, vector<File> *tab)
/*
traite un fichier possèdant plus de deux liens.
*/
{
int indiceFichier=0; //Indice du fichier recherché
bool b=false;
for (int i=0 ;( i<(*tab).size() and !b) ; i++) //Parcours de la liste des fichiers
{
b = ((*tab)[i].inum == num); // Si le fichier possède le même numéro d'inode que le paramètre num.
indiceFichier=i; // on sauvegarde l'indice du fichier dans le vecteur
}
if (b) //Si le fichier existe déja dans le tableau
{
(*tab)[indiceFichier].nblinks = (*tab)[indiceFichier].nblinks - 1; //On décrémente le nombre de liens à trouver
}
else // si le ficher n'est pas dans la liste
{
struct stat istique;
int er=stat(temp,&istique);
struct File fic;
fic.inum=istique.st_ino;
fic.nblinks=istique.st_nlink;
fic.name=temp;
(*tab).push_back(fic);// on ajoute de fichier dans la liste
}
}
bool dejaVu (int num , vector<int> *Vu)
{
bool b = false;
for (int i = 0 ; (i<(*Vu).size() and !b); i++ )
{
b = (num == (*Vu)[i]);
}
return b;
}
bool verificationArborescence (char s[],vector<int> *Vu, vector<File> *tab)
/*
Parcours récursif de l'arborescence dans le but de vérifier l'intégrité des fichiers
*/
{
DIR *rep = opendir(s); //ouverture du dossier passé en paramètre
if (rep == NULL) // Si l'ouverture a échouée
{
cout<<"Erreur ouverture du dossier : '"<<s<<"'\n\tMessage d'erreur : "<<strerror(errno)<<"."<<endl; // message d'erreur
}
else //si l'ouverture s'est bien passée
{
cout<<"Ouverture du dossier : '"<<s<<"'"<<endl;
struct dirent *repertoire; // on récupère une structure pour parcourir le répertoire
repertoire = readdir(rep); //lecture du premier fichier
struct stat inode; //déclaration d'une structure d'inode pour traiter le fichier
struct stat inode2;
while ((repertoire != NULL)) //tant que le répertoire possède des fichiers
{
string nomFichier =s; //construction du chemin absolue du fichier
nomFichier=nomFichier+'/'; // rajout du carctère '/' au chemin du répertoire
nomFichier = nomFichier+((*repertoire).d_name); // concaténation du nom du fichier
if ( ((*repertoire).d_name)[0]!='.' ) // exclu les fichiers '.' et '..'
{
char fichier[nomFichier.size()+1]; // déclaration d'un tableau de caractère pour pouvoir utiliser stat()
strncpy( fichier, nomFichier.c_str(), nomFichier.size()+1 ); // Copie du nom de fichier dans le tableau de caractère
int resultatStat = stat (fichier, &inode); //apel de la fonction stat()
if (resultatStat == 0) // si l'appel système s'est bien passé
{
int resultatLstat = lstat (fichier, &inode2);
if (resultatLstat==0 and S_ISLNK(inode2.st_mode))
{
char q[500];
for (int i=0 ; i<500 ; i++)
{
q[i]='^';
}
char *qt = q;
readlink(fichier, qt, 500);
string ss=s+'/';
int j=0;
while (qt[j]!='^')
{
ss = ss+qt[j];
j++;
}
char fich[ss.size()+1];
strncpy( fich, ss.c_str(), ss.size()+1 );
if (S_ISDIR(inode.st_mode) and !dejaVu(inode.st_ino , Vu))
{
(*Vu).push_back(inode.st_ino);
verificationArborescence (fich, Vu, tab);
}
}
else if ( S_ISDIR(inode.st_mode) and !dejaVu(inode.st_ino , Vu))
{
(*Vu).push_back(inode.st_ino);
verificationArborescence (fichier,Vu,tab);
}
else if (!S_ISDIR(inode.st_mode))
{
if (inode.st_nlink>1)
{
traiteFichier(inode.st_ino, inode.st_nlink , fichier , tab);
}
}
}
else
{
cout<<"Erreur fonction stat() sur le fichier : '"<<fichier<<"'\n\tMessage d'erreur : vous n'avez pas les droits de passage sur l'un des dossiers du chemin."<<endl;
}
}
repertoire = readdir(rep);
}
int rclose = closedir(rep);
if (rclose!=0)
{
cout<<"La fermeture s'est mal passée"<<endl;
}
}
}
int main (int argc, char *argv[])
{
if (argc >1)
{
struct stat inode;
int r = stat ("toto.txt", &inode);
int i =0;
vector<int> *Vu = new vector<int>;
vector<File> *tab;
struct File fish;
fish.inum=0;
fish.nblinks=0;
fish.name="";
(*Vu).assign(0,0);
(*tab).assign(0,fish);
cout<<"Trace d'excécution :"<<endl;
verificationArborescence(argv[1], Vu, tab);
afficheTab(tab);
}
else
{
cout<< "Tp necessite le passage en paramètre du chemin de la racine de l'arbre à vérifier"<<endl;
}
}


