/* GIO - GLib Input, Output and Streaming Library * * Copyright (C) 2009 Benjamin Otte * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General * Public License along with this library; if not, write to the * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * Author: Benjamin Otte */ #include #include #include #include #include "gvfsftpfile.h" /** * GVfsFtpFile: * * This structure maps between GVfs paths and the actual paths as used on an * FTP server. The mapping may not be a 1-to-1 mapping, so always use this * structure if you need to do operations on paths. */ struct _GVfsFtpFile { GVfsBackendFtp * backend; /* the backend */ char * gvfs_path; /* path in gvfs terms */ char * ftp_path; /* path in ftp terms */ }; /*** VFUNCS (that aren't yet made into vfuncs) ***/ /* FIXME: This most likely needs adaption to non-unix like directory structures. * There's at least the case of multiple roots (Netware) plus probably a shitload * of weird old file systems (starting with MS-DOS) * But we first need a way to detect that. */ static char * g_vfs_ftp_file_compute_ftp_path (const char *gvfs_path) { return g_strdup (gvfs_path); } static char * g_vfs_ftp_file_compute_gvfs_path (const char *ftp_path) { return g_strdup (ftp_path); } /*** API ***/ /** * g_vfs_ftp_file_new_from_gvfs: * @ftp: the ftp backend this file is to be used on * @gvfs_path: gvfs path to create the file from * * Constructs a new #GVfsFtpFile representing the given gvfs path. * * Returns: a new file **/ GVfsFtpFile * g_vfs_ftp_file_new_from_gvfs (GVfsBackendFtp *ftp, const char *gvfs_path) { GVfsFtpFile *file; g_return_val_if_fail (G_VFS_IS_BACKEND_FTP (ftp), NULL); g_return_val_if_fail (gvfs_path != NULL, NULL); file = g_slice_new (GVfsFtpFile); file->backend = g_object_ref (ftp); file->gvfs_path = g_strdup (gvfs_path); file->ftp_path = g_vfs_ftp_file_compute_ftp_path (gvfs_path); return file; } /** * g_vfs_ftp_file_new_from_ftp: * @ftp: the ftp backend this file is to be used on * @ftp_path: ftp path to create the file from * * Constructs a new #GVfsFtpFile representing the given ftp path. * * Returns: a new file **/ GVfsFtpFile * g_vfs_ftp_file_new_from_ftp (GVfsBackendFtp *ftp, const char *ftp_path) { GVfsFtpFile *file; g_return_val_if_fail (G_VFS_IS_BACKEND_FTP (ftp), NULL); g_return_val_if_fail (ftp_path != NULL, NULL); file = g_slice_new (GVfsFtpFile); file->backend = g_object_ref (ftp); file->ftp_path = g_strdup (ftp_path); file->gvfs_path = g_vfs_ftp_file_compute_gvfs_path (ftp_path); return file; } /** * g_vfs_ftp_file_new_parent: * @file: file to get the parent directory from * * Creates a new file to represent the parent directory of @file. If @file * already references the root directory, the new file will also reference * the root. * * Returns: a new file representing the parent directory of @file **/ GVfsFtpFile * g_vfs_ftp_file_new_parent (const GVfsFtpFile *file) { char *dirname; GVfsFtpFile *dir; g_return_val_if_fail (file != NULL, NULL); if (g_vfs_ftp_file_is_root (file)) return g_vfs_ftp_file_copy (file); dirname = g_path_get_dirname (file->gvfs_path); dir = g_vfs_ftp_file_new_from_gvfs (file->backend, dirname); g_free (dirname); return dir; } /** * g_vfs_ftp_file_new_child: * @parent: the parent file * @display_name: the basename to use for the new file * @error: location to take an eventual error or %NULL * * Tries to create a new file for the given @display_name in the given @parent * directory. If the display name is invalid, @error is set and %NULL is * returned. * * Returns: a new file or %NULL on error **/ GVfsFtpFile * g_vfs_ftp_file_new_child (const GVfsFtpFile *parent, const char *display_name, GError **error) { char *new_path; GVfsFtpFile *child; g_return_val_if_fail (parent != NULL, NULL); g_return_val_if_fail (display_name != NULL, NULL); if (strpbrk (display_name, "/\r\n")) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_FILENAME, _("Filename contains invalid characters.")); return NULL; } new_path = g_strconcat (parent->gvfs_path, parent->gvfs_path[1] == 0 ? "" : "/", display_name, NULL); child = g_vfs_ftp_file_new_from_gvfs (parent->backend, new_path); g_free (new_path); return child; } /** * g_vfs_ftp_file_copy: * @file: file to copy * * Creates a copy of the given @file. * * Returns: an identical copy of @file **/ GVfsFtpFile * g_vfs_ftp_file_copy (const GVfsFtpFile *file) { GVfsFtpFile *copy; g_return_val_if_fail (file != NULL, NULL); copy = g_slice_new (GVfsFtpFile); copy->backend = g_object_ref (file->backend); copy->ftp_path = g_strdup (file->ftp_path); copy->gvfs_path = g_strdup (file->gvfs_path); return copy; } /** * g_vfs_ftp_file_free: * @file: file to free * * Frees the given file structure and all associated resources. **/ void g_vfs_ftp_file_free (GVfsFtpFile *file) { g_return_if_fail (file != NULL); g_object_unref (file->backend); g_free (file->gvfs_path); g_free (file->ftp_path); g_slice_free (GVfsFtpFile, file); } /** * g_vfs_ftp_file_is_root: * @file: the file to check * * Checks if the given file references the root directory. * * Returns: %TRUE if @file references the root directory **/ gboolean g_vfs_ftp_file_is_root (const GVfsFtpFile *file) { g_return_val_if_fail (file != NULL, FALSE); return file->gvfs_path[0] == '/' && file->gvfs_path[1] == 0; } /** * g_vfs_ftp_file_get_ftp_path: * @file: a file * * Gets the string to refer to @file on the ftp server. This string may not be * valid UTF-8. * * Returns: the path to refer to @file on the FTP server. **/ const char * g_vfs_ftp_file_get_ftp_path (const GVfsFtpFile *file) { g_return_val_if_fail (file != NULL, NULL); return file->ftp_path; } /** * g_vfs_ftp_file_get_gvfs_path: * @file: a file * * Gets the GVfs path used to refer to @file. * * Returns: the GVfs path used to refer to @file. **/ const char * g_vfs_ftp_file_get_gvfs_path (const GVfsFtpFile *file) { g_return_val_if_fail (file != NULL, NULL); return file->gvfs_path; } /** * g_vfs_ftp_file_equal: * @a: a #GVfsFtpFile * @b: a #GVfsFtpFile * * Compares @a and @b. If they reference the same file, %TRUE is returned. * This function uses #gconstpointer arguments to the #GEqualFunc type. * * Returns: %TRUE if @a and @b reference the same file. **/ gboolean g_vfs_ftp_file_equal (gconstpointer a, gconstpointer b) { const GVfsFtpFile *af = a; const GVfsFtpFile *bf = b; g_return_val_if_fail (a != NULL, FALSE); g_return_val_if_fail (b != NULL, FALSE); /* FIXME: use ftp path? */ return g_str_equal (af->gvfs_path, bf->gvfs_path); } /** * g_vfs_ftp_file_hash: * @a: a #GvfsFtpFile * * Computes a hash value for the given file to be used in a #GHashTable. * This function uses #gconstpointer arguments to the #GHashFunc type. * * Returns: a hash value for the given file. **/ guint g_vfs_ftp_file_hash (gconstpointer a) { const GVfsFtpFile *af = a; return g_str_hash (af->gvfs_path); }