From 892e407c5f5e06fa8c0ca9250b3bc99851c6a61d Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Fri, 13 Jun 2008 14:17:54 +0200 Subject: Symlink resolving code, disabled by default --- common/strutils.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++ common/strutils.h | 1 + common/treepathutils.c | 50 +++++++++++++++++++++++- common/treepathutils.h | 6 ++- 4 files changed, 158 insertions(+), 2 deletions(-) (limited to 'common') diff --git a/common/strutils.c b/common/strutils.c index 3f390d9..5d9fa65 100644 --- a/common/strutils.c +++ b/common/strutils.c @@ -19,6 +19,7 @@ #include #include +#include #include "strutils.h" @@ -89,3 +90,105 @@ char* extract_file_path(const char *APath) snprintf(ANewPath, file_part - APath + 2, "%s", APath); return ANewPath; } + + + + + + + + +// canonicalize_filename() is stolen from glib-2.16 +// Copyright (C) 2006-2007 Alexander Larsson +static char * +canonicalize_filename (const char *filename) +{ + char *canon, *start, *p, *q; + int i; + + canon = g_strdup (filename); + + start = (char *)g_path_skip_root (canon); + + /* POSIX allows double slashes at the start to + * mean something special (as does windows too). + * So, "//" != "/", but more than two slashes + * is treated as "/". + */ + i = 0; + for (p = start - 1; + (p >= canon) && + G_IS_DIR_SEPARATOR (*p); + p--) + i++; + if (i > 2) + { + i -= 1; + start -= i; + memmove (start, start+i, strlen (start+i)+1); + } + + p = start; + while (*p != 0) + { + if (p[0] == '.' && (p[1] == 0 || G_IS_DIR_SEPARATOR (p[1]))) + { + memmove (p, p+1, strlen (p+1)+1); + } + else if (p[0] == '.' && p[1] == '.' && (p[2] == 0 || G_IS_DIR_SEPARATOR (p[2]))) + { + q = p + 2; + /* Skip previous separator */ + p = p - 2; + if (p < start) + p = start; + while (p > start && !G_IS_DIR_SEPARATOR (*p)) + p--; + if (G_IS_DIR_SEPARATOR (*p)) + *p++ = G_DIR_SEPARATOR; + memmove (p, q, strlen (q)+1); + } + else + { + /* Skip until next separator */ + while (*p != 0 && !G_IS_DIR_SEPARATOR (*p)) + p++; + + if (*p != 0) + { + /* Canonicalize one separator */ + *p++ = G_DIR_SEPARATOR; + } + } + + /* Remove additional separators */ + q = p; + while (*q && G_IS_DIR_SEPARATOR (*q)) + q++; + + if (p != q) + memmove (p, q, strlen (q)+1); + } + + /* Remove trailing slashes */ + if (p > start && G_IS_DIR_SEPARATOR (*(p-1))) + *(p-1) = 0; + + return canon; +} + + +char* resolve_relative(const char *source, const char *point_to) +{ + if (source == NULL) return NULL; + if (point_to == NULL) return strdup(source); + if (g_path_is_absolute(point_to)) return strdup(point_to); + + char *rel = g_build_filename(source, point_to, NULL); + log("resolve_relative: rel = '%s'\n", rel); + char *canon = canonicalize_filename(rel); + log("resolve_relative: canon = '%s'\n", canon); + free(rel); + + return canon; +} diff --git a/common/strutils.h b/common/strutils.h index a301c53..95cc16b 100644 --- a/common/strutils.h +++ b/common/strutils.h @@ -43,6 +43,7 @@ char* include_leading_path_sep(const char *APath); char* exclude_leading_path_sep(const char *APath); char* extract_file_name(const char *APath); char* extract_file_path(const char *APath); +char* resolve_relative(const char *source, const char *point_to); #endif /* __STRUTILS_H__ */ diff --git a/common/treepathutils.c b/common/treepathutils.c index 301f173..6215a14 100644 --- a/common/treepathutils.c +++ b/common/treepathutils.c @@ -1,5 +1,5 @@ /* Tux Commander VFS: String utilities - * Copyright (C) 2008 Tomas Bzatek + * Copyright (C) 2007-2008 Tomas Bzatek * Check for updates on tuxcmd.sourceforge.net * * This program is free software; you can redistribute it and/or modify @@ -311,3 +311,51 @@ struct PathTree* filelist_tree_get_item_by_index(struct PathTree *tree, unsigned return t; } + +void filelist_tree_resolve_symlinks_recurr(struct PathTree *tree, struct PathTree *root_tree, const char *path) +{ + if (tree) { + if ((tree->items) && (tree->items->len > 0)) { + unsigned int i; + for (i = 0; i < tree->items->len; i++) + { + struct PathTree* t = (struct PathTree*)g_ptr_array_index(tree->items, i); + gchar *new_path; + + if ((t) && (t->data) && (t->data->ItemType == vSymlink) && (t->data->sLinkTo)) { + log("filelist_tree_resolve_symlinks: found '%s/%s' --> '%s'\n", path, t->node, t->data->sLinkTo); + gchar *rel = resolve_relative(path, t->data->sLinkTo); + log(" filelist_tree_resolve_symlinks: relative = '%s'\n", rel); + struct PathTree* link_t = filelist_tree_find_node_by_path(root_tree, rel); + if ((link_t) && (link_t->data)) { + /* WARNING: this is dangerous since we're destroying the symlink type */ +// t->data->ItemType = link_t->data->ItemType; + t->data->a_time = link_t->data->a_time; + t->data->c_time = link_t->data->c_time; + t->data->m_time = link_t->data->m_time; + t->data->iGID = link_t->data->iGID; + t->data->iUID = link_t->data->iUID; + t->data->iMode = link_t->data->iMode; + t->data->iSize = link_t->data->iSize; + } + g_free(rel); + } + if ((strlen(path) == 1) && (IS_DIR_SEP(*path))) + new_path = g_strconcat("/", t->node, NULL); + else + new_path = g_strconcat(path, "/", t->node, NULL); + + filelist_tree_resolve_symlinks_recurr(t, root_tree, new_path); + g_free(new_path); + } + } + } +} + +void filelist_tree_resolve_symlinks(struct PathTree *tree) +{ + log("filelist_tree_resolve_symlinks: begin\n"); + filelist_tree_resolve_symlinks_recurr(tree, tree, "/"); + log("filelist_tree_resolve_symlinks: end\n"); +} + diff --git a/common/treepathutils.h b/common/treepathutils.h index 658f582..13f3057 100644 --- a/common/treepathutils.h +++ b/common/treepathutils.h @@ -1,5 +1,5 @@ /* Tux Commander VFS: String utilities - * Copyright (C) 2007 Tomas Bzatek + * Copyright (C) 2007-2008 Tomas Bzatek * Check for updates on tuxcmd.sourceforge.net * * This program is free software; you can redistribute it and/or modify @@ -40,6 +40,10 @@ struct PathTree* filelist_tree_new(); void filelist_tree_free(struct PathTree *tree); void filelist_tree_print(struct PathTree *tree); +/* Symlink resolving: strongly discouraged to use at the present state of art. + * We would have to implement full symlink system, do loop checking etc. */ +void filelist_tree_resolve_symlinks(struct PathTree *tree); + gboolean filelist_tree_add_item(struct PathTree *tree, const char *path, struct TVFSItem *item, unsigned long index); struct PathTree* filelist_tree_find_node_by_path(struct PathTree *tree, const char *path); unsigned long int filelist_find_index_by_path(struct PathTree *tree, const char *path); -- cgit v1.2.3