1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190
| // Donne le chemin absolu d'un chemin donné en argument
// Prend en compte le répertoire courant pour les noms relatifs
// Supprime les noms inutiles (comme ".")
// Supprime le dernier nom ajouté quand il tombe sur ".."
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define MAXPATHLEN (512) // Devrait être défini dans <unistd.h> mais, bizarrement, je ne l'y trouve pas...
typedef struct s_noeud {
char nom[MAXPATHLEN + 1];
struct s_noeud *next;
} t_noeud;
typedef struct {
t_noeud *path;
} t_chemin;
// Création noeud
t_noeud* create_node(const char const *nom)
{
t_noeud *noeud;
if ((noeud=malloc(sizeof(t_noeud))) == NULL)
return NULL;
strncpy(noeud->nom, nom, MAXPATHLEN);
noeud->nom[MAXPATHLEN]='\0'; // strncpy() ne rajoute pas le '\0' quand n est atteint
noeud->next=NULL;
return noeud;
}
// Initialisation chemin
void init_chemin(t_chemin* const chemin)
{
chemin->path=NULL;
}
// Ajout nom au chemin
t_noeud* append_chemin(t_chemin* const chemin, const char const *nom)
{
t_noeud *noeud;
t_noeud *current;
// Création nouveau noeud sur le nom demandé
if ((noeud=create_node(nom)) == NULL)
return NULL;
// Si on est sur le premier nom
if (chemin->path == NULL)
{
// Ce nom devient le premier de notre chemin
chemin->path=noeud;
return noeud;
}
// Recherche dernier noeud du chemin
for (current=chemin->path; current->next != NULL; current=current->next);
// Ajout du noeud courant
current->next=noeud;
// On renvoie le noeud ajouté (permet de détecter l'erreur de malloc)
return noeud;
}
// Suppression dernier noeud
void pop_chemin(t_chemin* const chemin)
{
t_noeud *current;
// S'il n'y a plus de noeud c'est qu'on est à la racine "/"
if (chemin->path == NULL)
return;
// S'il n'y a qu'un noeud
if (chemin->path->next == NULL)
{
// On le supprime
free(chemin->path);
chemin->path=NULL;
return;
}
// Recherche avant-dernier noeud
for (current=chemin->path; current->next->next != NULL; current=current->next);
// Suppression dernier noeud
free(current->next);
// Modification avant-dernier noeud
current->next=NULL;
}
// Suppression chemmin
void free_chemin(t_chemin* const chemin)
{
t_noeud *current;
t_noeud *previous;
// S'il n'y a plus de noeud
if (chemin->path == NULL)
return;
// Traitement de tous les noeuds
current=chemin->path;
do {
previous=current;
current=current->next;
free(previous);
} while (current != NULL);
// Le chemin a été vidé - On le réinitialise
init_chemin(chemin);
}
// Afficher chemin
void print_chemin(const t_chemin const *chemin)
{
t_noeud *current;
fputc('/', stdout);
for (current=chemin->path; current != NULL; current=current->next)
printf("%s/", current->nom);
fputc('\n', stdout);
}
// Chemin
void cibler(char* const nom)
{
t_chemin chemin;
char *strtok_mem;
char *split;
char cwd[MAXPATHLEN + 1];
// Initialisation chemin
init_chemin(&chemin);
// Si le nom ne commence pas par '/'
if (nom[0] != '/')
{
// Récupération du chemin courant
getcwd(cwd, MAXPATHLEN);
// Découpage du chemin courant
split=NULL;
while ((split=strtok_r(split == NULL ?cwd :NULL, "/", &strtok_mem)) != NULL)
{
// Ajout du nom au chemin
if (append_chemin(&chemin, split) == NULL)
fprintf(stderr, "Erreur alloc(%s) - Abandon !!!", split);
}
}
// Découpage du nom
split=NULL;
while ((split=strtok_r(split == NULL ?nom :NULL, "/", &strtok_mem)) != NULL)
{
// Si le nom est "."
if (strcmp(split, ".") == 0)
// On le passe
continue;
// Si le nom est ".."
if (strcmp(split, "..") == 0)
{
// On supprime le dernier noeud et on passe
pop_chemin(&chemin);
continue;
}
// Ajout du nom au chemin
if (append_chemin(&chemin, split) == NULL)
fprintf(stderr, "Erreur alloc(%s) - Abandon !!!", split);
}
// Affichage chemin
print_chemin(&chemin);
// Libération chemin
free_chemin(&chemin);
}
int main(int argc, char *argv[])
{
char **pt_arg;
for (pt_arg=argv+1; *pt_arg; pt_arg++)
cibler(*pt_arg);
} |
Partager