diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2015-12-01 20:11:27 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2015-12-01 20:12:35 (GMT) |
commit | 1c9e36639b949cc765dab316825f9fec7af85a6e (patch) | |
tree | 862c1aaf89f31972930b5c938ae49cee4bb724ec /src/common/pathname.c | |
parent | 99f653189e448b3ff3f2f02ab876231d44fa1ce3 (diff) |
Computed relative and absolute paths.
Diffstat (limited to 'src/common/pathname.c')
-rw-r--r-- | src/common/pathname.c | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/src/common/pathname.c b/src/common/pathname.c new file mode 100644 index 0000000..181fd1f --- /dev/null +++ b/src/common/pathname.c @@ -0,0 +1,173 @@ + +/* Chrysalide - Outil d'analyse de fichiers binaires + * pathname.c - manipulation de chemins de fichiers + * + * Copyright (C) 2015 Cyrille Bagard + * + * This file is part of Chrysalide. + * + * OpenIDA is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * OpenIDA is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Foobar. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "pathname.h" + + +#include <assert.h> +#include <glib.h> +#include <malloc.h> +#include <string.h> + + +#include "extstr.h" + + + +/****************************************************************************** +* * +* Paramètres : ref = fichier servant de référence aux calculs. * +* target = fichier absolu ciblé par la procédure. * +* * +* Description : Calcule le chemin relatif entre deux fichiers donnés. * +* * +* Retour : Chemin d'accès déterminé. * +* * +* Remarques : Les chemins de type 'a//b' ne sont pas supportés. * +* * +******************************************************************************/ + +char *build_relative_filename(const char *ref, const char *target) +{ + char *result; /* Chemin à retourner */ + size_t common; /* Taille de la partie commune */ + const char *found; /* Séparateur suivant rencontré*/ + size_t ref_next; /* Prochain séparateur #1 */ + size_t target_next; /* Prochain séparateur #2 */ + int ret; /* Bilan d'un appel */ + unsigned int levels; /* Niveaux de décalage */ + unsigned int i; /* Boucle de parcours #1 */ + + common = 0; + + /* Recherche d'une base commune */ + + while (1) + { + found = strchr(ref + common, G_DIR_SEPARATOR); + if (found == NULL) break; + + ref_next = found - ref; + + found = strchr(target + common, G_DIR_SEPARATOR); + if (found == NULL) break; + + target_next = found - target; + + /* Comparaison rapide sur la longeur du nom */ + if (ref_next != target_next) break; + + /* Comparaison sur une portion de chemin */ + ret = strncmp(ref + common, target + common, ref_next - common); + if (ret != 0) break; + + common = ref_next + 1; + + } + + /* Décompte du décalage entre la référence et la cible */ + + found = ref + common; + + for (levels = 0; ; levels++) + { + found = strchr(found, G_DIR_SEPARATOR); + if (found == NULL) break; + + found++; + + } + + /* Construction du résultat final */ + + result = strdup(target + common); + + for (i = 0; i < levels; i++) + { + result = strprep(result, G_DIR_SEPARATOR_S); + result = strprep(result, ".."); + } + + return result; + +} + + +/****************************************************************************** +* * +* Paramètres : ref = fichier servant de référence aux calculs. * +* target = fichier relatif ciblé par la procédure. * +* * +* Description : Calcule le chemin absolu d'un fichier par rapport à un autre.* +* * +* Retour : Chemin d'accès déterminé ou NULL en cas d'erreur. * +* * +* Remarques : Les chemins de type 'a//b' ne sont pas supportés. * +* * +******************************************************************************/ + +char *build_absolute_filename(const char *ref, const char *target) +{ + char *result; /* Chemin à retourner */ + char *last_sep; /* Dernier séparateur trouvé */ + const char *target_base; /* Base de la relativité */ + + static const char upper[4] = { '.', '.', G_DIR_SEPARATOR, '\0' }; + + result = strdup(ref); + + last_sep = strrchr(result, G_DIR_SEPARATOR); + assert(last_sep != NULL); + + target_base = target; + + /* Remontée des répertoires */ + while (1) + { + if (strncmp(target_base, upper, 3) != 0) + break; + + target_base += 3; + + *last_sep = '\0'; + last_sep = strrchr(result, G_DIR_SEPARATOR); + + /* S'il devient impossible de remonter autant... */ + if (last_sep == NULL) break; + + } + + if (last_sep == NULL) + { + free(result); + result = NULL; + } + else + { + *(last_sep + 1) = '\0'; + result = stradd(result, target_base); + } + + return result; + +} |