diff options
| author | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2009-11-28 13:11:51 +0100 |
|---|---|---|
| committer | Tomas Bzatek <tbzatek@users.sourceforge.net> | 2009-11-28 13:11:51 +0100 |
| commit | 9382f127ccebdd59917c97c61d008ed0e127cd75 (patch) | |
| tree | 0a48c8296199b343c76ef532eef014f908bc2e4d /common | |
| parent | 70eeaa4ec712895539ca6ecd60a42b93ec9b0904 (diff) | |
| download | tuxcmd-modules-0.6.72.tar.xz | |
Engine and VFS API cleanupv0.6.72
Also enable symlink resolving by default.
Diffstat (limited to 'common')
| -rw-r--r-- | common/filelist-vfs-intf.c | 263 | ||||
| -rw-r--r-- | common/filelist-vfs-intf.h | 68 | ||||
| -rw-r--r-- | common/filelist.c | 382 | ||||
| -rw-r--r-- | common/filelist.h | 99 | ||||
| -rw-r--r-- | common/strutils.c | 157 | ||||
| -rw-r--r-- | common/strutils.h | 36 | ||||
| -rw-r--r-- | common/treepath_vfs.c | 231 | ||||
| -rw-r--r-- | common/treepath_vfs.h | 61 | ||||
| -rw-r--r-- | common/treepathutils.c | 386 | ||||
| -rw-r--r-- | common/treepathutils.h | 58 | ||||
| -rw-r--r-- | common/tuxcmd-vfs.h (renamed from common/vfs_types.h) | 130 | ||||
| -rw-r--r-- | common/vfsutils.c | 80 | ||||
| -rw-r--r-- | common/vfsutils.h | 24 |
13 files changed, 1038 insertions, 937 deletions
diff --git a/common/filelist-vfs-intf.c b/common/filelist-vfs-intf.c new file mode 100644 index 0000000..e806334 --- /dev/null +++ b/common/filelist-vfs-intf.c @@ -0,0 +1,263 @@ +/* Tux Commander VFS: convenient interface for VFS modules to a filelist tree + * Copyright (C) 2007-2009 Tomas Bzatek <tbzatek@users.sourceforge.net> + * Check for updates on tuxcmd.sourceforge.net + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <string.h> +#include <glib.h> + +#include "tuxcmd-vfs.h" +#include "strutils.h" +#include "vfsutils.h" +#include "filelist.h" +#include "filelist-vfs-intf.h" + + + + + + +struct VfsFilelistData * +vfs_filelist_new (struct PathTree *files) +{ + struct VfsFilelistData * data; + + data = g_malloc0 (sizeof (struct VfsFilelistData)); + + log ("vfs_filelist_new()\n"); + data->files = files; + + return data; +} + +void +vfs_filelist_free (struct VfsFilelistData *data) +{ + if (! data) { + fprintf (stderr, "vfs_filelist_free: data == NULL !\n"); + return; + } + g_free (data->list_dir_path); + g_free (data); +} + + +/* -------------------------------------------------------------------------------------- */ + +guint64 +internal_get_dir_size (struct VfsFilelistData *data, struct PathTree *tree) +{ + guint64 Size; + struct PathTree *n; + unsigned long idx; + + Size = 0; + if (! data->break_get_dir_size && tree) { + n = NULL; + idx = 0; + while ((n = filelist_tree_get_item_by_index (tree, idx))) { + if (data->break_get_dir_size) + break; + if (n->data) { + log ("internal_get_dir_size: found item '%s', size = %zd \n", n->node, n->data->iSize); + Size += (n->data->ItemType == vDirectory) ? internal_get_dir_size (data, n) : n->data->iSize; + } + idx++; + } + } + return Size; +} + +guint64 +vfs_filelist_get_dir_size (struct VfsFilelistData *data, const char *APath) +{ + struct PathTree *node; + + if (! data) + return 0; + data->break_get_dir_size = FALSE; + + node = filelist_tree_find_node_by_path (data->files, APath); + if (node) { + return internal_get_dir_size (data, node); + } else { + printf ("(EE) VFSGetDirSize: path '%s' not found\n", APath); + return 0; + } +} + +void +vfs_filelist_get_dir_size_break (struct VfsFilelistData *data) +{ + if (data) + data->break_get_dir_size = TRUE; +} + + +/* -------------------------------------------------------------------------------------- */ + +static void +assign_file_info (struct PathTree* node, struct TVFSItem *Item, const char *reference_full_path, gboolean follow_symlinks, gboolean add_full_path) +{ + copy_vfs_item (node->data, Item); + if (add_full_path && reference_full_path) { + g_free (Item->FName); + g_free (Item->FDisplayName); + Item->FName = g_strdup (reference_full_path); + Item->FDisplayName = g_filename_display_name (reference_full_path); + } + if (follow_symlinks && node->symlink_target_data) { + Item->iSize = node->symlink_target_data->iSize; + Item->iPackedSize = node->symlink_target_data->iPackedSize; + Item->ItemType = node->symlink_target_data->ItemType; + } +} + +TVFSResult +vfs_filelist_file_info (struct VfsFilelistData *data, const char *AFileName, struct TVFSItem *Item, gboolean FollowSymlinks, gboolean AddFullPath) +{ + struct PathTree *node; + + if (data && data->files) { + node = filelist_tree_find_node_by_path (data->files, AFileName); + if (node) { + if (node->data) { + assign_file_info (node, Item, AFileName, FollowSymlinks, AddFullPath); + printf ("(II) VFSFileInfo: found file: '%s'\n", Item->FName); + return cVFS_OK; + } else { + printf ("(EE) VFSFileInfo: node->data == NULL! \n"); + return cVFS_Failed; + } + } else { + printf ("(EE) VFSFileInfo: file specified not found\n"); + return cVFS_No_More_Files; + } + } else { + printf ("(EE) VFSFileInfo: Invalid pointers to data objects.\n"); + return cVFS_Failed; + } +} + +TVFSResult +vfs_filelist_list_first (struct VfsFilelistData *data, const char *sDir, struct TVFSItem *Item, gboolean FollowSymlinks, gboolean AddFullPath) +{ + struct PathTree *node; + char *full_path; + + data->list_dir_index = -1; + data->list_dir_node = NULL; + + if (sDir == NULL) { + printf ("(EE) VFSListFirst: sDir is NULL!\n"); + return cVFS_Failed; + } + + data->list_dir_index = 0; + data->list_dir_node = filelist_tree_find_node_by_path (data->files, sDir); + data->follow_symlinks = FollowSymlinks; + data->add_full_path = AddFullPath; + data->list_dir_path = include_trailing_path_sep (sDir); + + /* Find the directory in the filelist */ + if (data->list_dir_node) { + node = filelist_tree_get_item_by_index (data->list_dir_node, data->list_dir_index); + if (node) { + full_path = NULL; + if (AddFullPath) + full_path = g_build_filename (sDir, node->data->FName, NULL); + assign_file_info (node, Item, full_path, FollowSymlinks, AddFullPath); + g_free (full_path); + printf ("(II) VFSListFirst: found file: %s\n", Item->FName); + return cVFS_OK; + } else { + printf ("(II) VFSListFirst: no more files\n"); + return cVFS_No_More_Files; + } + } else { + printf ("(EE) VFSListFirst: Directory '%s' not found.\n", sDir); + return cVFS_Failed; + } +} + +TVFSResult +vfs_filelist_list_next (struct VfsFilelistData *data, struct TVFSItem *Item) +{ + struct PathTree *node; + char *full_path; + + full_path = NULL; + if (! data->list_dir_node) { + printf ("(EE) VFSListNext: data->list_dir_node is NULL!\n"); + return cVFS_Failed; + } + data->list_dir_index++; + + node = filelist_tree_get_item_by_index (data->list_dir_node, data->list_dir_index); + if (node) { + if (data->add_full_path) + full_path = g_build_filename (data->list_dir_path, node->data->FName, NULL); + assign_file_info (node, Item, full_path, data->follow_symlinks, data->add_full_path); + g_free (full_path); + printf ("(II) VFSListNext: found file: %s\n", Item->FName); + return cVFS_OK; + } else { + printf ("(II) VFSListNext: no more files\n"); + return cVFS_No_More_Files; + } +} + +TVFSResult +vfs_filelist_list_close (struct VfsFilelistData *data) +{ + data->list_dir_index = -1; + data->list_dir_node = NULL; + g_free (data->list_dir_path); + data->list_dir_path = NULL; + return cVFS_OK; +} + + +/* -------------------------------------------------------------------------------------- */ + +char * +vfs_filelist_change_dir (struct VfsFilelistData *data, const char *NewPath) +{ + char *ANewPath; + + if (NewPath == NULL) { + printf("(EE) VFSChangeDir: NewPath is NULL!\n"); + return NULL; + } + + /* make up the target path */ + printf ("(--) VFSChangeDir: Going to change dir from '%s'\n", NewPath); + ANewPath = exclude_trailing_path_sep (NewPath); + if (! ANewPath || strlen (ANewPath) <= 0) + ANewPath = g_strdup ("/"); + printf ("(--) VFSChangeDir: Going to change dir to '%s'\n", ANewPath); + + /* find the directory in the filelist */ + if (filelist_tree_find_node_by_path (data->files, ANewPath)) { + return ANewPath; + } else { + printf ("(EE) VFSChangeDir: Directory '%s' not found.\n", ANewPath); + g_free (ANewPath); + return NULL; + } +} diff --git a/common/filelist-vfs-intf.h b/common/filelist-vfs-intf.h new file mode 100644 index 0000000..ce93e1e --- /dev/null +++ b/common/filelist-vfs-intf.h @@ -0,0 +1,68 @@ +/* Tux Commander VFS: convenient interface for VFS modules to a filelist tree + * Copyright (C) 2007-2009 Tomas Bzatek <tbzatek@users.sourceforge.net> + * Check for updates on tuxcmd.sourceforge.net + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __TREEPATH_VFS_H__ +#define __TREEPATH_VFS_H__ + +#ifdef __cplusplus + extern "C" { +#endif + + +#include <glib.h> + +#include "tuxcmd-vfs.h" +#include "filelist.h" + + +struct VfsFilelistData { + struct PathTree *files; + + unsigned int list_dir_index; + struct PathTree *list_dir_node; + char * list_dir_path; + + gboolean follow_symlinks; + gboolean add_full_path; + + gboolean break_get_dir_size; +}; + + +struct VfsFilelistData * vfs_filelist_new (struct PathTree *files); +void vfs_filelist_free (struct VfsFilelistData *data); + +guint64 vfs_filelist_get_dir_size (struct VfsFilelistData *data, const char *APath); +void vfs_filelist_get_dir_size_break (struct VfsFilelistData *data); + +gboolean vfs_filelist_file_exists (struct VfsFilelistData *data, const char *FileName, const long Use_lstat); +TVFSResult vfs_filelist_file_info (struct VfsFilelistData *data, const char *AFileName, struct TVFSItem *Item, gboolean FollowSymlinks, gboolean AddFullPath); + +TVFSResult vfs_filelist_list_first (struct VfsFilelistData *data, const char *sDir, struct TVFSItem *Item, gboolean FollowSymlinks, gboolean AddFullPath); +TVFSResult vfs_filelist_list_next (struct VfsFilelistData *data, struct TVFSItem *Item); +TVFSResult vfs_filelist_list_close (struct VfsFilelistData *data); + +char * vfs_filelist_change_dir (struct VfsFilelistData *data, const char *NewPath); + + + +#ifdef __cplusplus + } +#endif +#endif /* __TREEPATH_VFS_H__ */ diff --git a/common/filelist.c b/common/filelist.c new file mode 100644 index 0000000..cae250e --- /dev/null +++ b/common/filelist.c @@ -0,0 +1,382 @@ +/* Tux Commander VFS: Filelist tree storage + * Copyright (C) 2007-2009 Tomas Bzatek <tbzatek@users.sourceforge.net> + * Check for updates on tuxcmd.sourceforge.net + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include <stdio.h> +#include <string.h> +#include <glib.h> + +#include "filelist.h" +#include "strutils.h" +#include "vfsutils.h" + + + +struct PathTree * +filelist_tree_new () +{ + struct PathTree *tree; + + tree = g_malloc0 (sizeof (struct PathTree)); + log ("filelist_tree_new()\n"); + tree->items = g_ptr_array_new (); + tree->data = NULL; + tree->original_index = 0; + tree->node = g_strdup ("/"); + tree->original_pathstr = NULL; + + /* create placeholder data */ + tree->data = create_placeholder_item (tree->node, vDirectory); + + return tree; +} + +void +filelist_tree_free (struct PathTree *tree) +{ + int i; + + if (! tree) { + fprintf (stderr, "filelist_tree_free: tree == NULL !\n"); + return; + } + + if (tree->items && tree->items->len > 0) { + for (i = 0; i < tree->items->len; i++) + filelist_tree_free (g_ptr_array_index (tree->items, i)); + } + if (tree->items) + g_ptr_array_free (tree->items, TRUE); + free_vfs_item (tree->data); + g_free (tree->node); + g_free (tree->original_pathstr); + g_free (tree); +} + + +/* -------------------------------------------------------------------------------------- */ + +static void +filelist_tree_print_recurr (struct PathTree *tree, int level) +{ + char *fill; + int i; + struct PathTree* t; + + if (tree) { + fill = g_strnfill (level * 2, 32); + g_print (" %s#%lu. \"%s\"\n", fill, tree->original_index, tree->node); + + if (tree->items && tree->items->len > 0) + for (i = 0; i < tree->items->len; i++) { + t = g_ptr_array_index (tree->items, i); + filelist_tree_print_recurr (t, level + 1); + } + g_free (fill); + } +} + +void +filelist_tree_print (struct PathTree *tree) +{ + filelist_tree_print_recurr (tree, 0); +} + + +/* -------------------------------------------------------------------------------------- */ + +struct PathTree * +filelist_tree_find_node_by_path (struct PathTree *tree, const char *path) +{ + char *p; + char *first_part; + char *last_part; + struct PathTree *node; + struct PathTree *t; + unsigned int i; + + /* remove leading './' */ + if (strstr (path, "./") == path) + path += 2; + /* remove leading and trailing '/' if present */ + p = exclude_trailing_path_sep (path + G_IS_DIR_SEPARATOR (*path)); + log (" filelist_tree_find_node_by_path: path = '%s', p = '%s'\n", path, p); + + node = NULL; + if (tree && tree->node && g_strcmp0 (tree->node, "/") == 0 && g_strcmp0 (path, "/") == 0) { + log (" filelist_tree_find_node_by_path: matched root '/' element, returning.\n"); + node = tree; + } else + if (tree && tree->items && tree->items->len > 0) { + split_path (p, &first_part, &last_part); + log (" filelist_tree_find_node_by_path: pos = '%s'\n", pos); + log (" filelist_tree_find_node_by_path: first_part = '%s'\n", first_part); + log (" filelist_tree_find_node_by_path: last_part = '%s'\n", last_part); + + /* find existing node */ + for (i = 0; i < tree->items->len; i++) { + t = g_ptr_array_index (tree->items, i); + if (g_strcmp0 (t->node, first_part) == 0) { + /* this is the final station */ + if (! last_part) { + node = t; + log (" filelist_tree_find_node_by_path: found final node '%s', returning.\n", t->node); + } else + + /* recurse to child items */ + if (t->items && last_part) { + log (" filelist_tree_find_node_by_path: found node '%s', recursing in deep.\n", t->node); + node = filelist_tree_find_node_by_path (t, last_part); + } else { + /* item found but no subitems */ + log (" filelist_tree_find_node_by_path: found node '%s', but no subitems found.\n", t->node); + } + + break; + } + } + g_free (first_part); + g_free (last_part); + } + g_free (p); + return node; +} + +unsigned long int +filelist_find_original_index_by_path (struct PathTree *tree, const char *path) +{ + struct PathTree *node; + + node = filelist_tree_find_node_by_path (tree, path); + return node ? node->original_index : 0; +} + + +/* -------------------------------------------------------------------------------------- */ + +static void +filelist_tree_add_item_recurr (struct PathTree *tree, const char *path, struct TVFSItem *item, const char *original_pathstr, unsigned long int original_index) +{ + char *first_part; + char *last_part; + struct PathTree *t; + struct PathTree *node; + unsigned int i; + + split_path (path, &first_part, &last_part); + log (" filelist_tree_add_item_recur: pos = '%s'\n", pos); + log (" filelist_tree_add_item_recur: first_part = '%s'\n", first_part); + log (" filelist_tree_add_item_recur: last_part = '%s'\n", last_part); + + if (last_part == NULL) { + /* final destination, create new item here */ + log (" filelist_tree_add_item_recur: creating new item here.\n"); + t = g_malloc0 (sizeof (struct PathTree)); + t->items = NULL; + t->data = item; + t->node = g_strdup (first_part); + t->original_index = original_index; + t->original_pathstr = g_strdup (original_pathstr); + if (t->data) { + g_free (t->data->FName); + g_free (t->data->FDisplayName); + t->data->FName = g_strdup (path); + t->data->FDisplayName = g_filename_display_name (path); + } + /* create new list of subitems and add new item */ + if (! tree->items) + tree->items = g_ptr_array_new (); + g_ptr_array_add (tree->items, t); + } else { + /* not a final place, find parent node or create new one if doesn't exist */ + log (" filelist_tree_add_item_recur: node '%s', path '%s'\n", tree->node, path); + if (! tree->items) + tree->items = g_ptr_array_new (); + + node = NULL; + if (tree->items->len > 0) + for (i = 0; i < tree->items->len; i++) { + t = g_ptr_array_index (tree->items, i); + if (g_strcmp0 (t->node, first_part) == 0) { + log (" filelist_tree_add_item_recur: found node '%s'\n", t->node); + node = t; + break; + } + } + + if (node == NULL) { + /* create new path holder node */ + log (" filelist_tree_add_item_recur: parent node not found, creating new path holder\n"); + node = g_malloc0 (sizeof (struct PathTree)); + node->items = g_ptr_array_new (); + node->node = g_strdup (first_part); + node->original_index = 0; + node->original_pathstr = NULL; + + /* create placeholder data */ + node->data = create_placeholder_item (node->node, vDirectory); + g_ptr_array_add (tree->items, node); + } + + /* and recurse one level deeper */ + filelist_tree_add_item_recurr (node, last_part, item, original_pathstr, original_index); + } + g_free (first_part); + g_free (last_part); +} + + +gboolean +filelist_tree_add_item (struct PathTree *tree, const char *path, struct TVFSItem *item, const char *original_pathstr, unsigned long int original_index) +{ + char *p; + char *pp; + struct PathTree *found; + + if (! tree) { + fprintf (stderr, "filelist_tree_add_item: tree == NULL !\n"); + return FALSE; + } + if (! path) { + fprintf (stderr, "filelist_tree_add_item: path == NULL !\n"); + return FALSE; + } + + if (g_strcmp0 (path, "/") == 0 || g_strcmp0 (path, ".") == 0 || g_strcmp0 (path, "..") == 0 || g_strcmp0 (path, "./") == 0) { + fprintf (stderr, "filelist_tree_add_item: path '%s' is not a valid path\n", path); + return FALSE; + } + + /* remove leading './' */ + if (g_strstr_len (path, -1, "./") == path) + path += 2; + + /* remove leading and trailing '/' if present */ + p = exclude_trailing_path_sep (path + G_IS_DIR_SEPARATOR (*path)); + log (" filelist_tree_add_item: p = '%s'\n", p); + + pp = canonicalize_filename (p); + if (! pp) + pp = g_strdup (p); + + found = filelist_tree_find_node_by_path (tree, pp); + if (found) { + /* replace old data with current ones (record might have been created automatically during path building) */ + log (" filelist_tree_add_item: found old item, replacing data\n"); + found->original_index = original_index; + /* free old data */ + free_vfs_item (found->data); + found->data = item; + if (found->data) { + g_free (found->data->FName); + g_free (found->data->FDisplayName); + found->data->FName = g_strdup (found->node); + found->data->FDisplayName = g_filename_display_name (found->node); + } + } else { + /* create new item recursively */ + filelist_tree_add_item_recurr (tree, pp, item, original_pathstr, original_index); + } + + g_free (p); + g_free (pp); + return TRUE; +} + + +/* -------------------------------------------------------------------------------------- */ + +struct PathTree * +filelist_tree_get_item_by_index (struct PathTree *tree, unsigned long int index) +{ + struct PathTree *t = NULL; + + if (tree && tree->items && tree->items->len > index) + t = g_ptr_array_index (tree->items, index); + return t; +} + + +/* -------------------------------------------------------------------------------------- */ + +static void +resolve_symlink_recurr (struct PathTree *node, struct PathTree *root_tree, const char *path, const char *link_dest, int level) +{ + char *rel; + char *new_path; + struct PathTree *link_t; + + rel = resolve_relative (path, link_dest); + g_print (" resolve_symlink_recurr: relative = '%s'\n", rel); + if (rel) { + link_t = filelist_tree_find_node_by_path (root_tree, rel); + if (link_t && link_t->data) { + if (link_t->data->IsLink) { + /* another symlink, recurse into deep */ + new_path = g_path_get_dirname (rel); + if (level > FILELIST_MAX_SYMLINK_DEPTH || ! new_path) { + node->symlink_target_data = link_t->data; + g_print (" resolve_symlink_recurr: max depth reached, link is broken. new_path = '%s'\n", new_path); + } else { + g_print (" resolve_symlink_recurr: going deep, rel = '%s', new_path = '%s'\n", rel, new_path); + resolve_symlink_recurr (node, root_tree, new_path, link_t->data->sLinkTo, level + 1); + } + g_free (new_path); + } else { + /* final destination */ + node->symlink_target_data = link_t->data; + g_print (" resolve_symlink_recurr: reached target '%s'\n", rel); + } + } else { + /* target not found, link is broken */ + node->symlink_target_data = NULL; + g_print (" resolve_symlink_recurr: target '%s' not found, link is broken\n", rel); + } + } + g_free (rel); +} + +static void +filelist_tree_resolve_symlinks_recurr (struct PathTree *tree, struct PathTree *root_tree, const char *path) +{ + struct PathTree *t; + char *new_path; + unsigned int i; + + if (tree && tree->items && tree->items->len > 0) { + for (i = 0; i < tree->items->len; i++) { + t = g_ptr_array_index (tree->items, i); + + if (t && t->data && t->data->IsLink && t->data->sLinkTo) { + g_print ("filelist_tree_resolve_symlinks: found '%s/%s' --> '%s', resolving...\n", path, t->node, t->data->sLinkTo); + resolve_symlink_recurr (t, root_tree, path, t->data->sLinkTo, 1); + } + new_path = g_build_filename (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/filelist.h b/common/filelist.h new file mode 100644 index 0000000..e28699e --- /dev/null +++ b/common/filelist.h @@ -0,0 +1,99 @@ +/* Tux Commander VFS: Filelist tree storage + * Copyright (C) 2007-2009 Tomas Bzatek <tbzatek@users.sourceforge.net> + * Check for updates on tuxcmd.sourceforge.net + * + * This program 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 2 of the License, or + * (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#ifndef __TREEPATHUTILS_H__ +#define __TREEPATHUTILS_H__ + +#ifdef __cplusplus + extern "C" { +#endif + + +#include <glib.h> +#include "tuxcmd-vfs.h" + + +/**** + * USAGE / RULES: + * + * 1. create new tree, add items one by one with filelist_tree_add_item(), found during first archive listing + * 2. optionally call filelist_tree_resolve_symlinks() + * 3. when mapping a file back, use filelist_find_original_index_by_path() or filelist_tree_find_node_by_path() + * and take the particular attribute (original_XXX) as a reference to match the archive records against. + * + * + * - don't set the FName and FDisplayName values, filelist functions set these dynamically + * when traversing tree during adding. + * + * - due to the previous fact, the FDisplayName string is taken from original path, making + * sure it's valid UTF-8. No way to have different display name than the file name. + * + * - it's important to set either 'original_index' or 'original_pathstr' value, to match + * exact file back in the archive during VFSCopyToLocal operation. These attributes are + * left untouched by filelist functions. + * + * - all returned values are constants, do not modify anything (except of the item data itself). + * + * - the 'symlink_target_data' member is just a pointer to an existing data, don't free it. + * + * - the single 'node' and 'tree' objects are virtually equal, linked together. It may lead + * to a slight confusion. + * + */ + + +#define FILELIST_MAX_SYMLINK_DEPTH 20 /* do not go deeper than 20 levels */ + + +struct PathTree { + GPtrArray * items; + struct TVFSItem * data; + struct TVFSItem * symlink_target_data; + unsigned long int original_index; /* original index as stored in the archive, for matching back */ + char * node; + char * original_pathstr; /* original path as stored in the archive, for matching back */ +}; + + +struct PathTree * filelist_tree_new (); +void filelist_tree_free (struct PathTree *tree); + +/* Convenient function to print whole tree, for debugging purposes. */ +void filelist_tree_print (struct PathTree *tree); + +/* Add item into the particular structure under the 'path' node. This function tries to find the right node + * and creates placeholder nodes in between, when a part of the directory structure is missing. + */ +gboolean filelist_tree_add_item (struct PathTree *tree, const char *path, struct TVFSItem *item, const char *original_pathstr, unsigned long int original_index); + +struct PathTree * filelist_tree_find_node_by_path (struct PathTree *tree, const char *path); +unsigned long int filelist_find_original_index_by_path (struct PathTree *tree, const char *path); + +void filelist_tree_resolve_symlinks (struct PathTree *tree); + +/* Find the n-th item inside one node, the 'index' argument is absolute position in the list. + * Don't confuse with 'original_index' member. Used in vfs_filelist_list_next(). + */ +struct PathTree * filelist_tree_get_item_by_index (struct PathTree *tree, unsigned long int index); + + +#ifdef __cplusplus + } +#endif +#endif /* __TREEPATHUTILS_H__ */ diff --git a/common/strutils.c b/common/strutils.c index 5383b8a..3b0a1db 100644 --- a/common/strutils.c +++ b/common/strutils.c @@ -1,4 +1,4 @@ -/* Tux Commandern VFS: String utilities +/* Tux Commander VFS: String utilities * Copyright (C) 2007 Tomas Bzatek <tbzatek@users.sourceforge.net> * Check for updates on tuxcmd.sourceforge.net * @@ -17,89 +17,102 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <stdio.h> #include <string.h> #include <glib.h> + #include "strutils.h" -char* include_trailing_path_sep(const char *APath) + +char * +include_trailing_path_sep (const char *APath) { - if (APath == NULL) return NULL; - char *ANewPath; -// log("xxx = %s\n", (APath + strlen(APath) - 1)); - if (strcmp(APath + strlen(APath) - 1, "/") != 0) { - ANewPath = (char*)malloc(strlen(APath) + 2); - snprintf(ANewPath, strlen(APath) + 2, "%s/", APath); - } else ANewPath = strdup(APath); - return ANewPath; + if (APath == NULL) + return NULL; + if (g_strcmp0 (APath + strlen (APath) - 1, "/") != 0) + return g_strdup_printf ("%s/", APath); + else + return g_strdup (APath); } -char* exclude_trailing_path_sep(const char *APath) +char * +exclude_trailing_path_sep (const char *APath) { - if (APath == NULL) return NULL; - char *ANewPath; -// log("orig = %s, len = %d, xxx = %s\n", APath, (int)strlen(APath), (APath + strlen(APath) - 1)); - if ((strcmp(APath + strlen(APath) - 1, "/") == 0) && (strlen(APath) > 1)) { - ANewPath = (char*)malloc(strlen(APath)); - snprintf(ANewPath, strlen(APath), "%s", APath); // The number of bytes copied includes the trailing \0 - } else ANewPath = strdup(APath); - return ANewPath; + if (APath == NULL) + return NULL; + if (strlen (APath) > 1 && g_strcmp0 (APath + strlen (APath) - 1, "/") == 0) + return g_strndup (APath, strlen (APath) - 1); + else + return g_strdup(APath); } -char* include_leading_path_sep(const char *APath) +char * +include_leading_path_sep (const char *APath) { - if (APath == NULL) return NULL; - char *ANewPath; -// log("xxx = %s, %lu, strlen(APath) = %d, index() = %ld\n", APath, (unsigned long int)APath, (int)strlen(APath), (unsigned long int)index(APath, 0x2f)); - if (index(APath, 0x2f) != APath) { - ANewPath = (char*)malloc(strlen(APath) + 2); - snprintf(ANewPath, strlen(APath) + 2, "/%s", APath); // The number of bytes copied includes the trailing \0 - } else ANewPath = strdup(APath); - return ANewPath; + if (APath == NULL) + return NULL; + if (! g_path_is_absolute (APath)) + return g_strdup_printf ("/%s", APath); + else + return g_strdup (APath); } -char* exclude_leading_path_sep(const char* APath) +char * +exclude_leading_path_sep (const char *APath) { - if (APath == NULL) return NULL; - char *s = strdup(APath); - char *ss; - if (IS_DIR_SEP(*s)) ss = strdup(s + 1); else ss = strdup(s); - free(s); - return ss; + if (APath == NULL) + return NULL; + if (g_path_is_absolute (APath)) + return g_strdup (APath + 1); + else + return g_strdup (APath); } -char* extract_file_name(const char *APath) +/* -------------------------------------------------------------------------------------- */ + +char * +resolve_relative (const char *source, const char *point_to) { - if (APath == NULL) return NULL; -// log("xxx = %s\n", (APath + strlen(APath) - 1)); - const char *file_part = rindex(APath, 0x2f); // returns NULL if not found or if the file is in the root ( / ) - if (file_part == NULL) return NULL; - return strdup(file_part + 1); + char *rel; + char *canon; + + if (source == NULL) + return NULL; + if (point_to == NULL) + return g_strdup (source); + if (g_path_is_absolute (point_to)) + return g_strdup (point_to); + + rel = g_build_filename (source, point_to, NULL); + log ("resolve_relative: rel = '%s'\n", rel); + canon = canonicalize_filename (rel); + log ("resolve_relative: canon = '%s'\n", canon); + g_free (rel); + + return canon; } -// Extracts file path starting with "/" and ending with "/" -char* extract_file_path(const char *APath) +void +split_path (const char *path, char **first_part, char **last_part) { - if (APath == NULL) return NULL; -// log("xxx = %s\n", (APath + strlen(APath) - 1)); - const char *file_part = rindex(APath, 0x2f); // returns NULL if not found or if the file is in the root ( / ) - if (file_part == NULL) return NULL; - char *ANewPath = (char*)malloc(file_part - APath + 2); - snprintf(ANewPath, file_part - APath + 2, "%s", APath); - return ANewPath; + const char *pos; + + pos = strstr (path, "/"); + if (pos) { + *first_part = g_strndup (path, pos - path); + *last_part = g_strdup (pos + 1); + } else { + *first_part = g_strdup (path); + *last_part = NULL; + } } +/* -------------------------------------------------------------------------------------- */ - - - - - -// canonicalize_filename() is stolen from glib-2.16 -// Copyright (C) 2006-2007 Alexander Larsson <alexl@redhat.com> +/* canonicalize_filename() has been stolen from glib-2.16 */ +/* Copyright (C) 2006-2007 Alexander Larsson <alexl@redhat.com> */ char * canonicalize_filename (const char *filename) { @@ -179,34 +192,18 @@ canonicalize_filename (const char *filename) } -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; -} - - +/* -------------------------------------------------------------------------------------- */ -// Originally stolen from wine-0.9.19, utf8.c -// Copyright 2000 Alexandre Julliard -char* +/* stolen from wine-0.9.19, utf8.c */ +/* Copyright 2000 Alexandre Julliard */ +char * wide_to_utf8 (const wchar_t *src) { #define CONV_BUFF_MAX 32768 int len; char *buf, *dst, *ret; - buf = (char *) malloc (CONV_BUFF_MAX); - memset (&buf[0], 0, CONV_BUFF_MAX); + buf = (char *) g_malloc0 (CONV_BUFF_MAX); dst = buf; if (src) @@ -251,6 +248,6 @@ wide_to_utf8 (const wchar_t *src) } ret = g_strdup (buf); - free (buf); + g_free (buf); return ret; } diff --git a/common/strutils.h b/common/strutils.h index 84f6013..7fed4c5 100644 --- a/common/strutils.h +++ b/common/strutils.h @@ -20,32 +20,36 @@ #ifndef __STRUTILS_H__ #define __STRUTILS_H__ - - -#include <string.h> -#include <stdlib.h> +#ifdef __cplusplus + extern "C" { +#endif #ifdef __VERBOSE_DEBUG - #define log(msg...) printf(msg) + #define log(msg...) g_print(msg) #else #define log(msg...) { } #endif -#define IS_DIR_SEP(ch) ((ch) == '/') +/* path manipulating functions, all return newly allocated string */ +char * include_trailing_path_sep (const char *APath); +char * exclude_trailing_path_sep (const char *APath); +char * include_leading_path_sep (const char *APath); +char * exclude_leading_path_sep (const char *APath); + +char * resolve_relative (const char *source, const char *point_to); -// path manipulating functions, all return newly allocated string, you can then free them as you want -char* include_trailing_path_sep(const char *APath); -char* exclude_trailing_path_sep(const char *APath); -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); -char* canonicalize_filename(const char *filename); +/* split the first path element (single level) and copy the rest (multiple levels) */ +void split_path (const char *path, char **first_part, char **last_part); -char* wide_to_utf8(const wchar_t *src); +char * canonicalize_filename (const char *filename); +char * wide_to_utf8 (const wchar_t *src); + + +#ifdef __cplusplus + } +#endif #endif /* __STRUTILS_H__ */ diff --git a/common/treepath_vfs.c b/common/treepath_vfs.c deleted file mode 100644 index 34a779a..0000000 --- a/common/treepath_vfs.c +++ /dev/null @@ -1,231 +0,0 @@ -/* Tux Commander VFS: basic tree_path routines - * Copyright (C) 2007 Tomas Bzatek <tbzatek@users.sourceforge.net> - * Check for updates on tuxcmd.sourceforge.net - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <stdio.h> -#include <string.h> -#include <glib.h> - -#include "vfs_types.h" -#include "strutils.h" -#include "vfsutils.h" -#include "treepathutils.h" -#include "treepath_vfs.h" - - - - - - -struct VfsFilelistData* vfs_filelist_new(struct PathTree *files) -{ - struct VfsFilelistData *data= (struct VfsFilelistData*)malloc(sizeof(struct VfsFilelistData)); - memset(data, 0, sizeof(struct VfsFilelistData)); - - log("vfs_filelist_new()\n"); - data->files = files; - - return data; -} - - -void vfs_filelist_free(struct VfsFilelistData *data) -{ - if (! data) { - fprintf(stderr, "vfs_filelist_free: data == NULL !\n"); - return; - } - if (data) - { - free(data); - } -} - -void vfs_filelist_set_files(struct VfsFilelistData *data, struct PathTree *files) -{ - if (data) data->files = files; -} - - - - - -u_int64_t internal_get_dir_size(struct VfsFilelistData *data, struct PathTree *tree) -{ - if (data->break_get_dir_size) return 0; - u_int64_t Size = 0; - if (tree) { - struct PathTree *n = NULL; - unsigned long idx = 0; - while ((n = filelist_tree_get_item_by_index(tree, idx))) { - if (data->break_get_dir_size) break; - if (n->data) { - log("internal_get_dir_size: found item '%s', size = %zd \n", n->node, n->data->iSize); - Size += (n->data->ItemType == vDirectory) ? internal_get_dir_size(data, n) : n->data->iSize; - } - idx++; - } - } - return Size; -} - -u_int64_t vfs_filelist_get_dir_size(struct VfsFilelistData *data, char *APath) -{ - if (! data) return 0; - data->break_get_dir_size = FALSE; - - struct PathTree* node = filelist_tree_find_node_by_path(data->files, APath); - if (node) { - return internal_get_dir_size(data, node); - } else { - printf("(EE) VFSGetDirSize: path '%s' not found\n", APath); - return 0; - } -} - -void vfs_filelist_get_dir_size_break(struct VfsFilelistData *data) -{ - if (data) data->break_get_dir_size = TRUE; -} - - - - - - -long vfs_filelist_file_exists(struct VfsFilelistData *data, const char *FileName, const long Use_lstat) -{ - if ((data) && (data->files)) { - struct PathTree* node = filelist_tree_find_node_by_path(data->files, FileName); - return node != NULL; - } else { - printf ("(EE) VFSFileExists: Invalid pointers to data objects.\n"); - return FALSE; - } -} - - -TVFSResult vfs_filelist_file_info(struct VfsFilelistData *data, char *AFileName, struct TVFSItem *Item) -{ - if ((data) && (data->files)) { - struct PathTree* node = filelist_tree_find_node_by_path(data->files, AFileName); - if (node) { - if (node->data) { - copy_vfs_item(node->data, Item); - Item->FName = strdup(AFileName); - Item->FDisplayName = strdup(AFileName); - printf("(II) VFSFileInfo: found file: '%s'\n", Item->FName); - return cVFS_OK; - } else { - printf("(EE) VFSFileInfo: node->data == NULL! \n"); - return cVFS_Failed; - } - } else { - printf("(EE) VFSFileInfo: file specified not found\n"); - return cVFS_No_More_Files; - } - } else { - printf ("(EE) VFSFileInfo: Invalid pointers to data objects.\n"); - return cVFS_Failed; - } -} - - - - - - -TVFSResult vfs_filelist_list_first(struct VfsFilelistData *data, char *sDir, struct TVFSItem *Item) -{ - data->list_dir_index = -1; - data->list_dir_node = NULL; - - if (sDir == NULL) { - printf("(EE) VFSListFirst: sDir is NULL!\n"); - return cVFS_Failed; - } - - data->list_dir_index = 0; - data->list_dir_node = filelist_tree_find_node_by_path(data->files, sDir); - - // Find the directory in the filelist - if (data->list_dir_node) { - struct PathTree* node = filelist_tree_get_item_by_index(data->list_dir_node, data->list_dir_index); - if (node) { - copy_vfs_item(node->data, Item); - printf("(II) VFSListFirst: found file: %s\n", Item->FName); - return cVFS_OK; - } else { - printf("(II) VFSListFirst: no more files\n"); - return cVFS_No_More_Files; - } - } else { - printf ("(EE) VFSListFirst: Directory '%s' not found.\n", sDir); - return cVFS_Failed; - } -} - -TVFSResult vfs_filelist_list_next(struct VfsFilelistData *data, char *sDir, struct TVFSItem *Item) -{ - if (! data->list_dir_node) { - printf("(EE) VFSListNext: data->list_dir_node is NULL!\n"); - return cVFS_Failed; - } - data->list_dir_index++; - - struct PathTree* node = filelist_tree_get_item_by_index(data->list_dir_node, data->list_dir_index); - if (node) { - copy_vfs_item(node->data, Item); - printf("(II) VFSListNext: found file: %s\n", Item->FName); - return cVFS_OK; - } else { - printf("(II) VFSListNext: no more files\n"); - return cVFS_No_More_Files; - } -} - -TVFSResult vfs_filelist_list_close(struct VfsFilelistData *data) -{ - data->list_dir_index = -1; - data->list_dir_node = NULL; - return cVFS_OK; -} - - -char* vfs_filelist_change_dir(struct VfsFilelistData *data, char *NewPath) -{ - if (NewPath == NULL) { - printf("(EE) VFSChangeDir: NewPath is NULL!\n"); - return NULL; - } - - // Make up the target path - printf ("(--) VFSChangeDir: Going to change dir from '%s'\n", NewPath); - char *ANewPath = exclude_trailing_path_sep(NewPath); - if (strlen(ANewPath) <= 0) ANewPath = strdup("/"); - printf ("(--) VFSChangeDir: Going to change dir to '%s'\n", ANewPath); - - // Find the directory in the filelist - if (filelist_tree_find_node_by_path(data->files, ANewPath)) { - return ANewPath; - } else { - printf ("(EE) VFSChangeDir: Directory '%s' not found.\n", ANewPath); - free(ANewPath); - return NULL; - } -} diff --git a/common/treepath_vfs.h b/common/treepath_vfs.h deleted file mode 100644 index 2f78414..0000000 --- a/common/treepath_vfs.h +++ /dev/null @@ -1,61 +0,0 @@ -/* Tux Commander VFS: basic tree_path routines - * Copyright (C) 2007 Tomas Bzatek <tbzatek@users.sourceforge.net> - * Check for updates on tuxcmd.sourceforge.net - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __TREEPATH_VFS_H__ -#define __TREEPATH_VFS_H__ - - -#include <stdio.h> -#include <string.h> -#include <glib.h> - -#include "vfs_types.h" -#include "treepathutils.h" - - -struct VfsFilelistData { - struct PathTree *files; - - unsigned int list_dir_index; - struct PathTree *list_dir_node; - - gboolean break_get_dir_size; -}; - - -struct VfsFilelistData* vfs_filelist_new(struct PathTree *files); -void vfs_filelist_free(struct VfsFilelistData *data); -void vfs_filelist_set_files(struct VfsFilelistData *data, struct PathTree *files); - -u_int64_t vfs_filelist_get_dir_size(struct VfsFilelistData *data, char *APath); -void vfs_filelist_get_dir_size_break(struct VfsFilelistData *data); - -long vfs_filelist_file_exists(struct VfsFilelistData *data, const char *FileName, const long Use_lstat); -TVFSResult vfs_filelist_file_info(struct VfsFilelistData *data, char *AFileName, struct TVFSItem *Item); - -TVFSResult vfs_filelist_list_first(struct VfsFilelistData *data, char *sDir, struct TVFSItem *Item); -TVFSResult vfs_filelist_list_next(struct VfsFilelistData *data, char *sDir, struct TVFSItem *Item); -TVFSResult vfs_filelist_list_close(struct VfsFilelistData *data); - -char* vfs_filelist_change_dir(struct VfsFilelistData *data, char *NewPath); - - - - -#endif /* __TREEPATH_VFS_H__ */ diff --git a/common/treepathutils.c b/common/treepathutils.c deleted file mode 100644 index c8f2b18..0000000 --- a/common/treepathutils.c +++ /dev/null @@ -1,386 +0,0 @@ -/* Tux Commander VFS: String utilities - * Copyright (C) 2007-2008 Tomas Bzatek <tbzatek@users.sourceforge.net> - * Check for updates on tuxcmd.sourceforge.net - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#include <stdio.h> -#include <unistd.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <glib.h> - -#include "treepathutils.h" -#include "strutils.h" -#include "vfsutils.h" - - - - - - -struct PathTree* filelist_tree_new() -{ - struct PathTree *tree = (struct PathTree*)malloc(sizeof(struct PathTree)); - memset(tree, 0, sizeof(struct PathTree)); - log("filelist_tree_new()\n"); - tree->items = g_ptr_array_new(); - tree->data = NULL; - tree->index = 0; - tree->node = strdup("/"); - tree->original_pathstr = NULL; - - // create placeholder data - tree->data = (struct TVFSItem*)malloc(sizeof(struct TVFSItem)); - memset(tree->data, 0, sizeof(struct TVFSItem)); - tree->data->FName = strdup(tree->node); - tree->data->FDisplayName = strdup(tree->node); - tree->data->ItemType = vDirectory; - tree->data->iMode = S_IRWXO + S_IRWXG + S_IRWXU; - tree->data->iUID = geteuid(); - tree->data->iGID = getegid(); - tree->data->m_time = time(NULL); - tree->data->c_time = tree->data->m_time; - tree->data->a_time = tree->data->m_time; - - return tree; -} - - -void filelist_tree_free(struct PathTree *tree) -{ - if (! tree) { - fprintf(stderr, "filelist_tree_free: tree == NULL !\n"); - return; - } - if (tree) - { - if ((tree->items) && (tree->items->len > 0)) { - unsigned int i; - for (i = 0; i < tree->items->len; i++) - filelist_tree_free((struct PathTree*)g_ptr_array_index(tree->items, i)); - } - if (tree->items) - g_ptr_array_free(tree->items, TRUE); - if (tree->data) { - if (tree->data->FName) free(tree->data->FName); - if (tree->data->FDisplayName) free(tree->data->FDisplayName); - if (tree->data->sLinkTo) free(tree->data->sLinkTo); - free(tree->data); - } - if (tree->node) - free(tree->node); - if (tree->original_pathstr) - free(tree->original_pathstr); - free(tree); - } -} - - -void filelist_tree_print_recurr(struct PathTree *tree, int level) -{ - if (tree) { - char *fill = g_strnfill(level * 2, 32); - printf(" %s#%lu. \"%s\"\n", fill, tree->index, tree->node); - - 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); - filelist_tree_print_recurr(t, level + 1); - } - } - - g_free(fill); - } -} - - -void filelist_tree_print(struct PathTree *tree) -{ - filelist_tree_print_recurr(tree, 0); -} - - -struct PathTree* filelist_tree_find_node_by_path(struct PathTree *tree, const char *path) -{ - // remove leading './' - if (strstr(path, "./") == path) path += 2; - - // remove leading and trailing '/' if present - char *p; - if (IS_DIR_SEP(*path)) p = exclude_trailing_path_sep(path + 1); - else p = exclude_trailing_path_sep(path); - - log(" filelist_tree_find_node_by_path: path = '%s', p = '%s'\n", path, p); -// log("xx: '%s', '%s'\n", tree->node, path); - - struct PathTree* node = NULL; - if ((tree) && (tree->node) && (strcmp(tree->node, "/") == 0) && (strcmp(path, "/") == 0)) { - log(" filelist_tree_find_node_by_path: matched root '/' element, returning.\n"); - node = tree; - } else - if ((tree) && (tree->items) && (tree->items->len > 0)) { - // split path - char *pos = strstr(p, "/"); - char *first_part; - char *last_part; - if (pos) { - first_part = strndup(p, pos - p); - if (strlen(pos + 1) > 0) last_part = strdup(pos + 1); - else last_part = NULL; - } else { - first_part = strdup(p); - last_part = NULL; - } - log(" filelist_tree_find_node_by_path: pos = '%s'\n", pos); - log(" filelist_tree_find_node_by_path: first_part = '%s'\n", first_part); - log(" filelist_tree_find_node_by_path: last_part = '%s'\n", last_part); - - // find existing node - unsigned int i; - for (i = 0; i < tree->items->len; i++) - { - struct PathTree* t = (struct PathTree*)g_ptr_array_index(tree->items, i); - if (strcmp(t->node, first_part) == 0) { - // this is the final station - if (! last_part) { - node = t; - log(" filelist_tree_find_node_by_path: found final node '%s', returning.\n", t->node); - } else - // recurse to child items - if ((t->items) && (last_part)) { - log(" filelist_tree_find_node_by_path: found node '%s', recursing in deep.\n", t->node); - node = filelist_tree_find_node_by_path(t, last_part); - } else { - // item found but no subitems - log(" filelist_tree_find_node_by_path: found node '%s', but no subitems found.\n", t->node); - } - - break; - } - } - free(first_part); - free(last_part); - } - free(p); - return node; -} - -unsigned long int filelist_find_index_by_path(struct PathTree *tree, const char *path) -{ - struct PathTree* node = filelist_tree_find_node_by_path(tree, path); - if (node) return node->index; - else return 0; -} - -void filelist_tree_add_item_recurr(struct PathTree *tree, const char *path, const char *original_pathstr, struct TVFSItem *item, unsigned long index) -{ - const char *pos = strstr(path, "/"); - char *first_part; - char *last_part; - if (pos) { - first_part = strndup(path, pos - path); - if (strlen(pos + 1) > 0) last_part = strdup(pos + 1); - else last_part = NULL; - } else { - first_part = strdup(path); - last_part = NULL; - } - log(" filelist_tree_add_item_recur: pos = '%s'\n", pos); - log(" filelist_tree_add_item_recur: first_part = '%s'\n", first_part); - log(" filelist_tree_add_item_recur: last_part = '%s'\n", last_part); - - if (! last_part) - { // final destination, create new item here - log(" filelist_tree_add_item_recur: creating new item here.\n"); - struct PathTree *t = (struct PathTree*)malloc(sizeof(struct PathTree)); - memset(t, 0, sizeof(struct PathTree)); - t->items = NULL; - t->data = item; - t->index = index; - t->node = strdup(path); - if (original_pathstr) t->original_pathstr = strdup(original_pathstr); - if (t->data) t->data->FName = strdup(path); - if (t->data) t->data->FDisplayName = strdup(path); - // create new list of subitems and add new item - if (! tree->items) tree->items = g_ptr_array_new(); - g_ptr_array_add(tree->items, t); - } else - { // find parent node or create new one if doesn't exist - log(" filelist_tree_add_item_recur: node '%s', path '%s'\n", tree->node, path); - if (! tree->items) tree->items = g_ptr_array_new(); - - struct PathTree *node = NULL; - if (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); - if (strcmp(t->node, first_part) == 0) { - log(" filelist_tree_add_item_recur: found node '%s'\n", t->node); - node = t; - break; - } - } - } - - // create new path holder node - if (! node) { - log(" filelist_tree_add_item_recur: parent node not found, creating new path holder\n"); - node = (struct PathTree*)malloc(sizeof(struct PathTree)); - memset(node, 0, sizeof(struct PathTree)); - node->items = g_ptr_array_new(); - node->index = 0; - node->node = strdup(first_part); - node->original_pathstr = NULL; - - // create placeholder data - node->data = (struct TVFSItem*)malloc(sizeof(struct TVFSItem)); - memset(node->data, 0, sizeof(struct TVFSItem)); - node->data->FName = strdup(node->node); - node->data->FDisplayName = strdup(node->node); - node->data->ItemType = vDirectory; - node->data->iMode = S_IRWXO + S_IRWXG + S_IRWXU; - node->data->iUID = geteuid(); - node->data->iGID = getegid(); - node->data->m_time = time(NULL); - node->data->c_time = node->data->m_time; - node->data->a_time = node->data->m_time; - - g_ptr_array_add(tree->items, node); - } - - // and recurse one level deeper - filelist_tree_add_item_recurr(node, last_part, original_pathstr, item, index); - } - - free(first_part); - free(last_part); -} - - -gboolean filelist_tree_add_item(struct PathTree *tree, const char *path, const char *original_pathstr, struct TVFSItem *item, unsigned long index) -{ - if (! tree) { - fprintf(stderr, "filelist_tree_add_item: tree == NULL !\n"); - return FALSE; - } - if (! path) { - fprintf(stderr, "filelist_tree_add_item: path == NULL !\n"); - return FALSE; - } - - if ((strcmp(path, "/") == 0) || (strcmp(path, ".") == 0) || (strcmp(path, "..") == 0) || (strcmp(path, "./") == 0)) { - fprintf(stderr, "filelist_tree_add_item: path '%s' is not a valid path\n", path); - return FALSE; - } - - // remove leading './' - if (strstr(path, "./") == path) path += 2; - - // remove leading and trailing '/' if present - char *p; - if (IS_DIR_SEP(*path)) p = exclude_trailing_path_sep(path + 1); - else p = exclude_trailing_path_sep(path); - log(" filelist_tree_add_item: p = '%s'\n", p); - - char *pp; - pp = canonicalize_filename (p); - if (! pp) - pp = strdup (p); - - struct PathTree* found = filelist_tree_find_node_by_path(tree, pp); - - if (found) - { // replace old data with current ones (record might have been created automatically during path building) - log(" filelist_tree_add_item: found old item, replacing data\n"); - found->index = index; - // free old data - if (found->data) free_vfs_item(found->data); - found->data = item; - if (found->data) found->data->FName = strdup(found->node); - if (found->data) found->data->FDisplayName = strdup(found->node); - } else - // create new item recursively - filelist_tree_add_item_recurr(tree, pp, original_pathstr, item, index); - - free(p); - free(pp); - return TRUE; -} - -struct PathTree* filelist_tree_get_item_by_index(struct PathTree *tree, unsigned long index) -{ - struct PathTree* t = NULL; - if ((tree) && (tree->items) && (tree->items->len > index)) { - t = (struct PathTree*)g_ptr_array_index(tree->items, index); - } - 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); - if (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 deleted file mode 100644 index a902a33..0000000 --- a/common/treepathutils.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Tux Commander VFS: String utilities - * Copyright (C) 2007-2008 Tomas Bzatek <tbzatek@users.sourceforge.net> - * Check for updates on tuxcmd.sourceforge.net - * - * This program 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 2 of the License, or - * (at your option) any later version. - * - * This program 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 this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ - -#ifndef __TREEPATHUTILS_H__ -#define __TREEPATHUTILS_H__ - - -#include <stdio.h> -#include <string.h> -#include <glib.h> - -#include "vfs_types.h" - - -struct PathTree { - GPtrArray* items; - struct TVFSItem *data; - unsigned long index; - char *node; - char *original_pathstr; -}; - - -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, const char *original_pathstr, 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); -struct PathTree* filelist_tree_get_item_by_index(struct PathTree *tree, unsigned long index); - - - - - - -#endif /* __TREEPATHUTILS_H__ */ diff --git a/common/vfs_types.h b/common/tuxcmd-vfs.h index 49c62e9..2ebed6d 100644 --- a/common/vfs_types.h +++ b/common/tuxcmd-vfs.h @@ -1,9 +1,9 @@ /* Tux Commander VFS: Virtual File System types and definitions * - prototypes functions and types - * draft version 3 + * draft version 5 * * Copyright (C) 2003 Radek Cervinka <radek.cervinka@centrum.cz> - * Copyright (C) 2008 Tomas Bzatek <tbzatek@users.sourceforge.net> + * Copyright (C) 2008-2009 Tomas Bzatek <tbzatek@users.sourceforge.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,10 +23,12 @@ #ifndef __VFS_TYPES_H__ #define __VFS_TYPES_H__ +#ifdef __cplusplus + extern "C" { +#endif -#include <stdio.h> -#include <stdint.h> -#include <sys/types.h> + +#include <glib.h> typedef int TVFSResult; @@ -49,62 +51,50 @@ typedef enum { } TVFSPasswordSave; -typedef void (* TVFSLogFunc)(const char *s); -typedef void *TVFSFileDes; +typedef void (* TVFSLogFunc) (const char *s); +typedef void * TVFSFileDes; /* Return FALSE to break the operation */ typedef int (* TVFSProgressCallback) - (u_int64_t position, - u_int64_t max, - void *user_data); + (guint64 position, + guint64 max, + void *user_data); /* Return index of the choice selected or negative number when dialog has been cancelled */ typedef void (* TVFSAskQuestionCallback) - (const char *message, + (const char *message, const char **choices, - int *choice, - int cancel_choice, - void *user_data); + int *choice, + int cancel_choice, + void *user_data); typedef int (* TVFSAskPasswordCallback) - (const char *message, - const char *default_user, - const char *default_domain, - const char *default_password, - TVFSAskPasswordFlags flags, - char **username, - char **password, - int *anonymous, - char **domain, - TVFSPasswordSave *password_save, - void *user_data); - - -static const int cVFSVersion = 5; // current version of the VFS API - -// Capabilities -static const int capVFS_nil = 0; -static const int capVFS_List = 1 << 0; -static const int capVFS_CopyOut = 1 << 1; -static const int capVFS_CopyIn = 1 << 2; -static const int capVFS_MkDir = 1 << 3; -static const int capVFS_RmDir = 1 << 4; -static const int capVFS_Multiple = 1 << 5; // support multiple files = background copy & thread safe -static const int capVFS_Delete = 1 << 6; -static const int capVFS_Rename = 1 << 7; -static const int capVFS_Execute = 1 << 8; -static const int capVFS_Append = 1 << 9; - -// Error codes (TVFSResult) + (const char *message, + const char *default_user, + const char *default_domain, + const char *default_password, + TVFSAskPasswordFlags flags, + char **username, + char **password, + int *anonymous, + char **domain, + TVFSPasswordSave *password_save, + void *user_data); + + +/* current version of the VFS API */ +static const int cVFSVersion = 5; + +/* error codes (TVFSResult) */ enum { cVFS_OK = 0, - cVFS_Failed = 1, // also No such file + cVFS_Failed = 1, /* also No such file */ cVFS_Cancelled = 2, cVFS_Not_Supported = 3, cVFS_No_More_Files = 4, cVFS_ReadErr = 5, - cVFS_WriteErr = 6, // also Readonly FileSystem + cVFS_WriteErr = 6, /* also Readonly FileSystem */ cVFS_LoginFailed = 7, cVFS_PermissionDenied = 8, cVFS_NoSpaceLeft = 9, @@ -115,7 +105,7 @@ enum { }; -// Open modes +/* open modes */ enum { cVFS_OpenRead, cVFS_OpenWrite, @@ -123,40 +113,42 @@ enum { }; -// Item Type enum enum TVFSItemType { vRegular = 0, - vSymlink = 1, - vChardev = 2, - vBlockdev = 3, - vDirectory = 4, - vFifo = 5, - vSock = 6, - vOther = 7 + vChardev = 1, + vBlockdev = 2, + vDirectory = 3, + vFifo = 4, + vSock = 5, + vOther = 6 }; struct TVFSItem { - char *FName; - char *FDisplayName; // valid UTF-8 string - int64_t iSize; - int64_t iPackedSize; // set to -1 if plugin doesn't support this feature - __time_t m_time; // numbers should be located before the other variables (bug?) - __time_t a_time; - __time_t c_time; - __mode_t iMode; - char *sLinkTo; - __uid_t iUID; - __gid_t iGID; + char *FName; + char *FDisplayName; /* valid UTF-8 string */ + guint64 iSize; + gint64 iPackedSize; /* set to -1 if plugin doesn't support this feature */ + guint32 m_time; + guint32 a_time; + guint32 c_time; + guint32 iMode; + gboolean IsLink; + char *sLinkTo; + guint32 iUID; + guint32 iGID; enum TVFSItemType ItemType; }; struct TVFSInfo { - char *ID; // unique identifier, not shown in GUI - char *Name; // plugin name, GUI string (UTF-8) - char *About; // GUI string (UTF-8) - char *Copyright; // GUI string (UTF-8) + char *ID; /* unique identifier, not shown in GUI */ + char *Name; /* plugin name, GUI string (UTF-8) */ + char *About; /* GUI string (UTF-8) */ + char *Copyright; /* GUI string (UTF-8) */ }; +#ifdef __cplusplus + } +#endif #endif /* __VFS_TYPES_H__ */ diff --git a/common/vfsutils.c b/common/vfsutils.c index 173c0df..856d9f9 100644 --- a/common/vfsutils.c +++ b/common/vfsutils.c @@ -1,5 +1,5 @@ -/* Tux Commander VFS: String utilities - * Copyright (C) 2007 Tomas Bzatek <tbzatek@users.sourceforge.net> +/* Tux Commander VFS: VFS utilities + * Copyright (C) 2007-2009 Tomas Bzatek <tbzatek@users.sourceforge.net> * Check for updates on tuxcmd.sourceforge.net * * This program is free software; you can redistribute it and/or modify @@ -17,52 +17,76 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <stdio.h> +#include <unistd.h> #include <string.h> +#include <sys/stat.h> #include <glib.h> #include "strutils.h" -#include "vfs_types.h" +#include "tuxcmd-vfs.h" -void copy_vfs_item(struct TVFSItem *src, struct TVFSItem *dst) +void +copy_vfs_item (struct TVFSItem *src, struct TVFSItem *dst) { + memcpy (dst, src, sizeof (struct TVFSItem)); dst->FName = g_strdup (src->FName); dst->FDisplayName = g_strdup (src->FDisplayName); - dst->iSize = src->iSize; - dst->iPackedSize = src->iPackedSize; - dst->m_time = src->m_time; - dst->a_time = src->a_time; - dst->c_time = src->c_time; - dst->iMode = src->iMode; dst->sLinkTo = g_strdup (src->sLinkTo); - dst->iUID = src->iUID; - dst->iGID = src->iGID; - dst->ItemType = src->ItemType; } -void free_vfs_item(struct TVFSItem *item) +void +free_vfs_item (struct TVFSItem *item) { if (item) { - if (item->FName) - free(item->FName); - if (item->FDisplayName) - free(item->FDisplayName); - if (item->sLinkTo) - free(item->sLinkTo); - free(item); + g_free (item->FName); + g_free (item->FDisplayName); + g_free (item->sLinkTo); + g_free (item); } } -int compare_two_same_files(const char *Path1, const char *Path2) +/* -------------------------------------------------------------------------------------- */ + +struct TVFSItem * +create_placeholder_item (const char *name, enum TVFSItemType item_type) +{ + struct TVFSItem *data; + + data = g_malloc0 (sizeof (struct TVFSItem)); + data->FName = g_strdup (name); + data->FDisplayName = g_strdup (name); + data->ItemType = item_type; + data->iMode = S_IRWXO + S_IRWXG + S_IRWXU; + data->IsLink = FALSE; + data->iUID = geteuid (); + data->iGID = getegid (); + data->m_time = time (NULL); + data->c_time = data->m_time; + data->a_time = data->m_time; + data->iSize = 0; + data->iPackedSize = -1; + + return data; +} + + +/* -------------------------------------------------------------------------------------- */ + +gboolean +compare_two_same_files (const char *path1, const char *path2) { - char *f1 = exclude_trailing_path_sep(Path1); - char *f2 = exclude_trailing_path_sep(Path2); - gboolean b = strcmp(f1, f2) == 0; - free(f1); - free(f2); + char *f1, *f2; + gboolean b; + + f1 = exclude_trailing_path_sep (path1); + f2 = exclude_trailing_path_sep (path2); + b = (g_strcmp0 (f1, f2) == 0); + g_free (f1); + g_free (f2); + return b; } diff --git a/common/vfsutils.h b/common/vfsutils.h index 5dd61f2..404b313 100644 --- a/common/vfsutils.h +++ b/common/vfsutils.h @@ -1,5 +1,5 @@ -/* Tux Commander VFS: String utilities - * Copyright (C) 2007 Tomas Bzatek <tbzatek@users.sourceforge.net> +/* Tux Commander VFS: VFS utilities + * Copyright (C) 2007-2009 Tomas Bzatek <tbzatek@users.sourceforge.net> * Check for updates on tuxcmd.sourceforge.net * * This program is free software; you can redistribute it and/or modify @@ -20,20 +20,28 @@ #ifndef __VFSUTILS_H__ #define __VFSUTILS_H__ +#ifdef __cplusplus + extern "C" { +#endif + -#include <stdio.h> -#include <string.h> #include <glib.h> -#include "vfs_types.h" +#include "tuxcmd-vfs.h" + +void copy_vfs_item (struct TVFSItem *src, struct TVFSItem *dst); +void free_vfs_item (struct TVFSItem *item); -void copy_vfs_item(struct TVFSItem *src, struct TVFSItem *dst); -void free_vfs_item(struct TVFSItem *item); +/* creates a placeholder item */ +struct TVFSItem * create_placeholder_item (const char *name, enum TVFSItemType item_type); -int compare_two_same_files(const char *Path1, const char *Path2); +gboolean compare_two_same_files (const char *path1, const char *path2); +#ifdef __cplusplus + } +#endif #endif /* __VFSUTILS_H__ */ |
