From 2a3ca65418b30afde5580e484d0d49f2b3764b33 Mon Sep 17 00:00:00 2001 From: Tomas Bzatek Date: Sun, 24 Aug 2008 19:13:04 +0200 Subject: GVFS plugin - ininital commit Missing authentication code at the moment --- gvfs/Makefile | 44 +++ gvfs/gvfs.c | 1115 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ gvfs/vfs_types.h | 1 + 3 files changed, 1160 insertions(+) create mode 100644 gvfs/Makefile create mode 100644 gvfs/gvfs.c create mode 120000 gvfs/vfs_types.h (limited to 'gvfs') diff --git a/gvfs/Makefile b/gvfs/Makefile new file mode 100644 index 0000000..bc15c60 --- /dev/null +++ b/gvfs/Makefile @@ -0,0 +1,44 @@ +# path definitions +DESTDIR = /usr +INSTALL=install -c +INSTALL_DATA = ${INSTALL} -m 644 + +# compiler options +CC = gcc +CPP = g++ +CFLAGS =-I. -I/usr/include \ + -Wall -fPIC -O2 -g \ + -DG_DISABLE_DEPRECATED -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE + + +LIB_SUFFIX=`if test \`uname -m\` = x86_64; then echo 64; fi` + +# VFS_COMMON_OBJECTS=strutils.o treepathutils.o treepath_vfs.o vfsutils.o +VFS_COMMON_OBJECTS= + +VFS_OBJECTS=gvfs.o + + +.SUFFIXES: .c .cpp +.c.o: + $(CC) $(CFLAGS) `pkg-config glib-2.0 gio-2.0 --cflags` -c $< +.cpp.o: + $(CPP) $(CFLAGS) `pkg-config glib-2.0 gio-2.0 --cflags` -c $< + + +all shared static: libgvfs_plugin.so + +libgvfs_plugin.so: $(VFS_COMMON_OBJECTS) $(VFS_OBJECTS) + $(CPP) -shared -o libgvfs_plugin.so $(VFS_COMMON_OBJECTS) $(VFS_OBJECTS) $(CFLAGS) `pkg-config glib-2.0 gio-2.0 --libs` + +strutils.o: strutils.c strutils.h +treepathutils.o: treepathutils.c treepathutils.h +vfsutils.o: vfsutils.c vfsutils.h +treepath_vfs.o: treepath_vfs.c treepath_vfs.h + +install:: + $(INSTALL) ./libgvfs_plugin.so $(DESTDIR)/lib$(LIB_SUFFIX)/tuxcmd/ + +clean: + rm -f *.o *.d *.gch libgvfs_plugin.so + diff --git a/gvfs/gvfs.c b/gvfs/gvfs.c new file mode 100644 index 0000000..3e1a0d8 --- /dev/null +++ b/gvfs/gvfs.c @@ -0,0 +1,1115 @@ +/* GVFS plugin for Tux Commander + * Copyright (C) 2008 Tomas Bzatek + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library 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 + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "vfs_types.h" + + + +#define VERSION "0.0.1" +#define BUILD_DATE "2008-08-24" +#define DEFAULT_BLOCK_SIZE 0x10000 /* 64kB */ + +#define CONST_DEFAULT_QUERY_INFO_ATTRIBUTES G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_NAME "," \ + G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME "," G_FILE_ATTRIBUTE_STANDARD_SIZE "," \ + G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET "," G_FILE_ATTRIBUTE_TIME_MODIFIED "," \ + G_FILE_ATTRIBUTE_TIME_ACCESS "," G_FILE_ATTRIBUTE_TIME_CHANGED "," \ + G_FILE_ATTRIBUTE_UNIX_MODE "," G_FILE_ATTRIBUTE_UNIX_UID "," \ + G_FILE_ATTRIBUTE_UNIX_GID + +struct TVFSGlobs { + TVFSLogFunc log_func; + GFile *file; + GFileEnumerator *enumerator; + + gboolean break_get_dir_size; + guint32 block_size; +}; + + +int +VFSAllocNeeded () +{ + return sizeof (struct TVFSGlobs); +} + +static TVFSResult +g_error_to_TVFSResult (GError *error) +{ + g_print ("g_error_to_TVFSResult: code = %d\n", error->code); + switch (error->code) { + case G_IO_ERROR_FAILED: + case G_IO_ERROR_NOT_FOUND: + return cVFS_Failed; + break; + case G_IO_ERROR_PERMISSION_DENIED: + return cVFS_PermissionDenied; + break; + case G_IO_ERROR_CANCELLED: + return cVFS_Cancelled; + break; + case G_IO_ERROR_NOT_SUPPORTED: + case G_IO_ERROR_FILENAME_TOO_LONG: + return cVFS_Not_Supported; + break; + case G_IO_ERROR_NO_SPACE: + return cVFS_NoSpaceLeft; + break; + case G_IO_ERROR_IS_DIRECTORY: + case G_IO_ERROR_NOT_REGULAR_FILE: + case G_IO_ERROR_NOT_SYMBOLIC_LINK: + case G_IO_ERROR_NOT_MOUNTABLE_FILE: + case G_IO_ERROR_INVALID_FILENAME: + case G_IO_ERROR_TOO_MANY_LINKS: + case G_IO_ERROR_INVALID_ARGUMENT: + case G_IO_ERROR_NOT_DIRECTORY: + case G_IO_ERROR_NOT_MOUNTED: + case G_IO_ERROR_ALREADY_MOUNTED: + case G_IO_ERROR_WRONG_ETAG: + case G_IO_ERROR_TIMED_OUT: + case G_IO_ERROR_WOULD_RECURSE: + case G_IO_ERROR_HOST_NOT_FOUND: + return cVFS_ReadErr; + break; + case G_IO_ERROR_EXISTS: + case G_IO_ERROR_NOT_EMPTY: + case G_IO_ERROR_CLOSED: + case G_IO_ERROR_PENDING: + case G_IO_ERROR_READ_ONLY: + case G_IO_ERROR_CANT_CREATE_BACKUP: + case G_IO_ERROR_BUSY: + case G_IO_ERROR_WOULD_BLOCK: + case G_IO_ERROR_WOULD_MERGE: + return cVFS_WriteErr; + break; + case G_IO_ERROR_FAILED_HANDLED: + default: + return cVFS_Failed; + } +} + +void +VFSInit (struct TVFSGlobs *globs, TVFSLogFunc log_func) +{ + globs->log_func = log_func; + globs->log_func ("GVFS plugin: VFSInit"); + + globs->file = NULL; + globs->enumerator = NULL; + + globs->break_get_dir_size = FALSE; + globs->block_size = DEFAULT_BLOCK_SIZE; +} + +void +VFSDestroy (struct TVFSGlobs *globs) +{ + globs->log_func ("GVFS plugin: VFSDestroy"); +} + +int +VFSVersion () +{ + return cVFSVersion; +} + +struct TVFSInfo +VFSGetInfo () +{ + struct TVFSInfo module_info; + + module_info.Name = "GVFS plugin"; + module_info.Description = "GVFS plugin"; + module_info.About = g_strdup_printf ("version %s, build date: %s", VERSION, BUILD_DATE); + module_info.Copyright = "Copyright (C) 2008 Tomáš Bžatek"; + return module_info; +} + +char * +VFSGetExts () +{ + return ""; +} + +char * +VFSGetServices () +{ + /* FIXME: retrieve list of supported backends from gvfs subsystem */ + return "http;https;ftp;sftp;smb;network"; +} + +char * +VFSGetPrefix (struct TVFSGlobs *globs) +{ + GFile *f; + char *s; + + if (globs->file) { + f = g_file_resolve_relative_path (globs->file, "/"); + s = g_file_get_uri (f); + g_object_unref (f); + return s; + } + else + return NULL; +} + +TVFSResult +VFSOpen (struct TVFSGlobs *globs, char *sName) +{ + GFile *f; + + g_print ("(II) VFSOpen: opening URI '%s'\n", sName); + globs->file = NULL; + + f = g_file_new_for_commandline_arg (sName); + if (! g_file_query_exists (f, NULL)) { + g_print ("(EE) VFSOpen: The URI specified doesn't exist\n"); + return cVFS_Failed; + } + else + { + globs->file = f; + return cVFS_OK; + } +} + +TVFSResult +VFSClose (struct TVFSGlobs *globs) +{ + g_print ("(II) VFSClose\n"); + + if (globs->file) + g_object_unref (globs->file); + globs->file = NULL; + + return cVFS_OK; +} + +char * +VFSGetPath (struct TVFSGlobs *globs) +{ + if (globs->file) + return g_file_get_path (globs->file); + else + return NULL; +} + +guint64 +VFSGetFileSystemFree (struct TVFSGlobs *globs, char *APath) +{ + GFileInfo *info; + GError *error; + guint64 res; + + if (globs->file == NULL) + return 0; + + error = NULL; + info = g_file_query_filesystem_info (globs->file, G_FILE_ATTRIBUTE_FILESYSTEM_FREE, NULL, &error); + if (error) { + g_print ("(EE) VFSGetFileSystemFree: %s\n", error->message); + g_error_free (error); + return 0; + } + res = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_FREE); + g_object_unref (info); + return res; +} + +guint64 +VFSGetFileSystemSize (struct TVFSGlobs *globs, char *APath) +{ + GFileInfo *info; + GError *error; + guint64 res; + + if (globs->file == NULL) + return 0; + + error = NULL; + info = g_file_query_filesystem_info (globs->file, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE, NULL, &error); + if (error) { + g_print ("(EE) VFSGetFileSystemSize: %s\n", error->message); + g_error_free (error); + return 0; + } + res = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_FILESYSTEM_SIZE); + g_object_unref (info); + return res; +} + + +/**************************************************************************************************************************************/ +/**************************************************************************************************************************************/ + +TVFSResult +VFSChangeDir (struct TVFSGlobs *globs, char *NewPath) +{ + GFile *f; + GFileEnumerator *en; + GError *error; + TVFSResult res; + + if (globs->file == NULL) { + g_print ("(EE) VFSChangeDir: globs->file == NULL !\n"); + return cVFS_Failed; + } + + g_print ("(II) VFSChangeDir: changing dir to '%s'\n", NewPath); + + f = g_file_resolve_relative_path (globs->file, NewPath); + if (f == NULL) { + g_print ("(EE) VFSChangeDir: g_file_resolve_relative_path() failed.\n"); + return cVFS_Failed; + } + + error = NULL; + en = g_file_enumerate_children (f, CONST_DEFAULT_QUERY_INFO_ATTRIBUTES, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error); + if (error) { + g_print ("(EE) VFSChangeDir: g_file_enumerate_children() error: %s\n", error->message); + res = g_error_to_TVFSResult (error); + g_error_free (error); + g_object_unref (f); + return res; + } + globs->enumerator = en; + g_object_unref (globs->file); + globs->file = f; + + return cVFS_OK; +} + +int +VFSLogin (struct TVFSGlobs *globs, char *user, char *pass) +{ + g_print ("(II) VFSLogin: logging in with '%s'/'%s'\n", user, pass); + + /* FIXME: add auth code */ + + return cVFS_Not_Supported; +} + + + +/**************************************************************************************************************************************/ +/**************************************************************************************************************************************/ + +static void +g_file_info_to_TVFSItem (GFileInfo *info, struct TVFSItem *Item) +{ + g_assert (info != NULL); + g_assert (Item != NULL); + + Item->sFileName = g_strdup (g_file_info_get_display_name (info)); + Item->sLinkTo = g_file_info_get_symlink_target (info) == NULL ? NULL : g_strdup (g_file_info_get_symlink_target (info)); + Item->iSize = g_file_info_get_size (info); + Item->iMode = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE); + + Item->m_time = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED); + Item->a_time = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS); + Item->c_time = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED); + Item->iUID = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_UID); + Item->iGID = g_file_info_get_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_GID); + + if (g_file_info_get_is_symlink (info)) { + Item->ItemType = vSymlink; + } + else + { + switch (g_file_info_get_file_type (info)) { + case G_FILE_TYPE_REGULAR: + Item->ItemType = vRegular; + break; + case G_FILE_TYPE_DIRECTORY: + case G_FILE_TYPE_MOUNTABLE: + Item->ItemType = vDirectory; + break; + case G_FILE_TYPE_SYMBOLIC_LINK: + Item->ItemType = vSymlink; + break; + case G_FILE_TYPE_SHORTCUT: + case G_FILE_TYPE_SPECIAL: /* socket, fifo, blockdev, chardev */ + Item->ItemType = vBlockdev; + break; + case G_FILE_TYPE_UNKNOWN: + default: Item->ItemType = vRegular; + } + } +} + +TVFSResult +VFSListNext (struct TVFSGlobs *globs, char *sDir, struct TVFSItem *Item) +{ + GError *error; + GFileInfo *info; + TVFSResult res; + + if (globs->file == NULL) { + g_print ("(EE) VFSListNext: globs->file == NULL !\n"); + return cVFS_Failed; + } + if (globs->enumerator == NULL) { + g_print ("(EE) VFSListNext: globs->enumerator == NULL !\n"); + return cVFS_Failed; + } + + error = NULL; + info = g_file_enumerator_next_file (globs->enumerator, NULL, &error); + if (error) { + g_print ("(EE) VFSListNext: g_file_enumerator_next_file() error: %s\n", error->message); + res = g_error_to_TVFSResult (error); + g_error_free (error); + return res; + } + if (! error && ! info) + return cVFS_No_More_Files; + g_file_info_to_TVFSItem (info, Item); + g_object_unref (info); + return cVFS_OK; +} + +TVFSResult +VFSListFirst (struct TVFSGlobs *globs, char *sDir, struct TVFSItem *Item) +{ + return VFSListNext (globs, sDir, Item); +} + +TVFSResult +VFSListClose (struct TVFSGlobs *globs) +{ + GError *error; + TVFSResult res; + + if (globs->file == NULL) { + g_print ("(EE) VFSListClose: globs->file == NULL !\n"); + return cVFS_Failed; + } + if (globs->enumerator == NULL) { + g_print ("(EE) VFSListClose: globs->enumerator == NULL !\n"); + return cVFS_Failed; + } + g_print ("(II) VFSListClose\n"); + + error = NULL; + g_file_enumerator_close (globs->enumerator, NULL, &error); + g_object_unref (globs->enumerator); + globs->enumerator = NULL; + if (error) { + g_print ("(EE) VFSListClose: g_file_enumerator_close() error: %s\n", error->message); + res = g_error_to_TVFSResult (error); + g_error_free (error); + return res; + } + return cVFS_OK; +} + + +/**************************************************************************************************************************************/ +/**************************************************************************************************************************************/ +long +VFSFileExists (struct TVFSGlobs *globs, const char *FileName, const long Use_lstat) +{ + GFile *f; + GError *error; + GFileInfo *info; + + if (globs->file == NULL) { + g_print ("(EE) VFSFileExists: globs->file == NULL !\n"); + return cVFS_Failed; + } + + f = g_file_resolve_relative_path (globs->file, FileName); + if (f == NULL) { + g_print ("(EE) VFSMkDir: g_file_resolve_relative_path() failed.\n"); + return cVFS_Failed; + } + + error = NULL; + info = g_file_query_info (f, G_FILE_ATTRIBUTE_STANDARD_NAME, + Use_lstat ? G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS : G_FILE_QUERY_INFO_NONE, NULL, &error); + g_object_unref (f); + if (error) { + g_print ("(EE) VFSFileExists: g_file_query_info() error: %s\n", error->message); + g_error_free (error); + return FALSE; + } + g_object_unref (info); + return TRUE; +} + +TVFSResult +VFSFileInfo (struct TVFSGlobs *globs, char *AFileName, struct TVFSItem *Item) +{ + GFile *f; + GError *error; + GFileInfo *info; + TVFSResult res; + + if (globs->file == NULL) { + g_print ("(EE) VFSFileInfo: globs->file == NULL !\n"); + return cVFS_Failed; + } + + f = g_file_resolve_relative_path (globs->file, AFileName); + if (f == NULL) { + g_print ("(EE) VFSMkDir: g_file_resolve_relative_path() failed.\n"); + return cVFS_Failed; + } + + error = NULL; + info = g_file_query_info (f, CONST_DEFAULT_QUERY_INFO_ATTRIBUTES, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error); + g_object_unref (f); + if (error) { + g_print ("(EE) VFSFileInfo: g_file_query_info() error: %s\n", error->message); + res = g_error_to_TVFSResult (error); + g_error_free (error); + return res; + } + g_file_info_to_TVFSItem (info, Item); + g_object_unref (info); + return cVFS_OK; +} + +TVFSResult +VFSMkDir (struct TVFSGlobs *globs, const char *sDirName) +{ + GFile *f; + GError *error; + TVFSResult res; + + if (globs->file == NULL) { + g_print ("(EE) VFSMkDir: globs->file == NULL !\n"); + return cVFS_Failed; + } + + f = g_file_resolve_relative_path (globs->file, sDirName); + if (f == NULL) { + g_print ("(EE) VFSMkDir: g_file_resolve_relative_path() failed.\n"); + return cVFS_Failed; + } + + error = NULL; + g_file_make_directory (f, NULL, &error); + g_object_unref (f); + if (error) { + g_print ("(EE) VFSMkDir: g_file_make_directory() error: %s\n", error->message); + res = g_error_to_TVFSResult (error); + g_error_free (error); + return res; + } + return cVFS_OK; +} + +TVFSResult +VFSRemove (struct TVFSGlobs *globs, const char *APath) +{ + GFile *f; + GError *error; + TVFSResult res; + + if (globs->file == NULL) { + g_print ("(EE) VFSRemove: globs->file == NULL !\n"); + return cVFS_Failed; + } + + f = g_file_resolve_relative_path (globs->file, APath); + if (f == NULL) { + g_print ("(EE) VFSRemove: g_file_resolve_relative_path() failed.\n"); + return cVFS_Failed; + } + + error = NULL; + g_file_delete (f, NULL, &error); + g_object_unref (f); + if (error) { + g_print ("(EE) VFSRemove: g_file_delete() error: %s\n", error->message); + res = g_error_to_TVFSResult (error); + g_error_free (error); + return res; + } + return cVFS_OK; +} + +TVFSResult +VFSRename (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName) +{ + GFile *src, *dst; + GError *error; + TVFSResult res; + + if (globs->file == NULL) { + g_print ("(EE) VFSRename: globs->file == NULL !\n"); + return cVFS_Failed; + } + + src = g_file_resolve_relative_path (globs->file, sSrcName); + if (src == NULL) { + g_print ("(EE) VFSRename: g_file_resolve_relative_path() failed.\n"); + return cVFS_Failed; + } + + g_print ("VFSRename: '%s' --> '%s'\n", sSrcName, sDstName); + + error = NULL; + g_file_set_display_name (src, sDstName, NULL, &error); + if (error) { + g_print ("(WW) VFSRename: g_file_set_display_name() failed (\"%s\"), using fallback g_file_move()\n", error->message); + g_error_free (error); + + dst = g_file_resolve_relative_path (src, sDstName); + if (dst == NULL) { + g_print ("(EE) VFSRename: g_file_resolve_relative_path() failed.\n"); + g_object_unref (src); + return cVFS_Failed; + } + error = NULL; + g_file_move (src, dst, G_FILE_COPY_NONE | G_FILE_COPY_NO_FALLBACK_FOR_MOVE, NULL, NULL, NULL, &error); + if (error) { + g_print ("(EE) VFSRename: g_file_move() error: %s\n", error->message); + res = g_error_to_TVFSResult (error); + g_error_free (error); + g_object_unref (src); + g_object_unref (dst); + return res; + } + g_object_unref (dst); + } + + g_object_unref (src); + return cVFS_OK; +} + +TVFSResult +VFSMakeSymLink (struct TVFSGlobs *globs, const char *NewFileName, const char *PointTo) +{ + GFile *f; + GError *error; + TVFSResult res; + + if (globs->file == NULL) { + g_print ("(EE) VFSMakeSymLink: globs->file == NULL !\n"); + return cVFS_Failed; + } + + f = g_file_resolve_relative_path (globs->file, NewFileName); + if (f == NULL) { + g_print ("(EE) VFSMakeSymLink: g_file_resolve_relative_path() failed.\n"); + return cVFS_Failed; + } + + error = NULL; + g_file_make_symbolic_link (f, PointTo, NULL, &error); + g_object_unref (f); + if (error) { + g_print ("(EE) VFSMakeSymLink: g_file_make_symbolic_link() error: %s\n", error->message); + res = g_error_to_TVFSResult (error); + g_error_free (error); + return res; + } + return cVFS_OK; +} + +TVFSResult +VFSChmod (struct TVFSGlobs *globs, const char *FileName, const uint Mode) +{ + GFile *f; + GError *error; + TVFSResult res; + + if (globs->file == NULL) { + g_print ("(EE) VFSChmod: globs->file == NULL !\n"); + return cVFS_Failed; + } + + f = g_file_resolve_relative_path (globs->file, FileName); + if (f == NULL) { + g_print ("(EE) VFSChmod: g_file_resolve_relative_path() failed.\n"); + return cVFS_Failed; + } + g_print ("(II) VFSChmod (%s, %d): Going to set permissions on '%s'\n", FileName, Mode, g_file_get_uri (f)); + + error = NULL; + g_file_set_attribute_uint32 (f, G_FILE_ATTRIBUTE_UNIX_MODE, Mode, G_FILE_QUERY_INFO_NONE, NULL, &error); + g_object_unref (f); + if (error) { + g_print ("(EE) VFSChmod: g_file_set_attribute_uint32() error: %s\n", error->message); + res = g_error_to_TVFSResult (error); + g_error_free (error); + return res; + } + return cVFS_OK; +} + +TVFSResult +VFSChown (struct TVFSGlobs *globs, const char *FileName, const uint UID, const uint GID) +{ + GFile *f; + GError *error; + TVFSResult res; + + if (globs->file == NULL) { + g_print ("(EE) VFSChown: globs->file == NULL !\n"); + return cVFS_Failed; + } + + f = g_file_resolve_relative_path (globs->file, FileName); + if (f == NULL) { + g_print ("(EE) VFSChown: g_file_resolve_relative_path() failed.\n"); + return cVFS_Failed; + } + + error = NULL; + g_file_set_attribute_uint32 (f, G_FILE_ATTRIBUTE_UNIX_UID, UID, G_FILE_QUERY_INFO_NONE, NULL, &error); + if (error) { + g_print ("(EE) VFSChown: g_file_set_attribute_uint32() error: %s\n", error->message); + res = g_error_to_TVFSResult (error); + g_error_free (error); + g_object_unref (f); + return res; + } + error = NULL; + g_file_set_attribute_uint32 (f, G_FILE_ATTRIBUTE_UNIX_GID, GID, G_FILE_QUERY_INFO_NONE, NULL, &error); + if (error) { + g_print ("(EE) VFSChown: g_file_set_attribute_uint32() error: %s\n", error->message); + res = g_error_to_TVFSResult (error); + g_error_free (error); + g_object_unref (f); + return res; + } + g_object_unref (f); + return cVFS_OK; +} + +TVFSResult +VFSChangeTimes (struct TVFSGlobs *globs, char *APath, long mtime, long atime) +{ + GFile *f; + GError *error; + TVFSResult res; + + if (globs->file == NULL) { + g_print ("(EE) VFSChangeTimes: globs->file == NULL !\n"); + return cVFS_Failed; + } + + f = g_file_resolve_relative_path (globs->file, APath); + if (f == NULL) { + g_print ("(EE) VFSChangeTimes: g_file_resolve_relative_path() failed.\n"); + return cVFS_Failed; + } + + error = NULL; + g_file_set_attribute_uint64 (f, G_FILE_ATTRIBUTE_TIME_MODIFIED, mtime, G_FILE_QUERY_INFO_NONE, NULL, &error); + if (error) { + g_print ("(EE) VFSChangeTimes: g_file_set_attribute_uint64() error: %s\n", error->message); + res = g_error_to_TVFSResult (error); + g_error_free (error); + g_object_unref (f); + return res; + } + error = NULL; + g_file_set_attribute_uint64 (f, G_FILE_ATTRIBUTE_TIME_ACCESS, atime, G_FILE_QUERY_INFO_NONE, NULL, &error); + if (error) { + g_print ("(EE) VFSChangeTimes: g_file_set_attribute_uint64() error: %s\n", error->message); + g_error_free (error); + /* Silently drop the error, atime is not commonly supported on most systems */ + } + g_object_unref (f); + return cVFS_OK; +} + + +/**************************************************************************************************************************************/ +/**************************************************************************************************************************************/ + +static void +VFSGetDirSize_recurse (struct TVFSGlobs *globs, GFile *file, guint64 *size) +{ + GFile *f; + GFileEnumerator *en; + GError *error; + GFileInfo *info; + + if (globs->break_get_dir_size) + return; + + error = NULL; + en = g_file_enumerate_children (file, G_FILE_ATTRIBUTE_STANDARD_TYPE "," G_FILE_ATTRIBUTE_STANDARD_NAME "," G_FILE_ATTRIBUTE_STANDARD_SIZE, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error); + if (error) { + g_print ("(EE) VFSGetDirSize_recurse: g_file_enumerate_children() error: %s\n", error->message); + g_error_free (error); + return; + } + + error = NULL; + while ((info = g_file_enumerator_next_file (en, NULL, &error))) { + if (globs->break_get_dir_size) + break; + + if (g_file_info_get_file_type (info) == G_FILE_TYPE_DIRECTORY) { + f = g_file_resolve_relative_path (file, g_file_info_get_name (info)); + if (f == NULL) { + g_print ("(EE) VFSGetDirSize_recurse: g_file_resolve_relative_path() failed.\n"); + return; + } + VFSGetDirSize_recurse (globs, f, size); + g_object_unref (f); + } + else + *size += g_file_info_get_size (info); + g_object_unref (info); + } + if (error) { + g_print ("(EE) VFSGetDirSize_recurse: g_file_enumerator_next_file() error: %s\n", error->message); + g_error_free (error); + } + g_file_enumerator_close (en, NULL, &error); + g_object_unref (en); + if (error) { + g_print ("(EE) VFSGetDirSize_recurse: g_file_enumerator_close() error: %s\n", error->message); + g_error_free (error); + } +} + +guint64 +VFSGetDirSize (struct TVFSGlobs *globs, char *APath) +{ + GFile *f; + guint64 size; + + if (globs == NULL) return 0; + if (globs->file == NULL) { + g_print ("(EE) VFSGetDirSize: globs->file == NULL !\n"); + return 0; + } + f = g_file_resolve_relative_path (globs->file, APath); + if (f == NULL) { + g_print ("(EE) VFSGetDirSize: g_file_resolve_relative_path() failed.\n"); + return 0; + } + + size = 0; + globs->break_get_dir_size = FALSE; + VFSGetDirSize_recurse (globs, f, &size); + globs->break_get_dir_size = FALSE; + g_object_unref (f); + + return size; +} + +void +VFSBreakGetDirSize (struct TVFSGlobs *globs) +{ + g_print ("(WW) VFSBreakGetDirSize: ################################### calling Break\n"); + if (globs) + globs->break_get_dir_size = TRUE; +} + + +/**************************************************************************************************************************************/ +/**************************************************************************************************************************************/ + +TVFSFileDes +VFSOpenFile (struct TVFSGlobs *globs, const char *APath, int Mode, int *Error) +{ + printf("(WW) VFSOpenFile: Not supported in GVFS plugin.\n"); + return NULL; +} + +TVFSResult +VFSCloseFile (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor) +{ + printf("(WW) VFSCloseFile: Not supported in GVFS plugin.\n"); + return cVFS_Not_Supported; +} + +guint64 +VFSFileSeek (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, guint64 AbsoluteOffset, int *Error) +{ + printf("(WW) VFSFileSeek: Not supported in GVFS plugin.\n"); + return -1; +} + +int +VFSReadFile (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, gpointer Buffer, int ABlockSize, int *Error) +{ + printf("(WW) VFSReadFile: Not supported in GVFS plugin.\n"); + return cVFS_Not_Supported; +} + +int +VFSWriteFile (struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, gpointer Buffer, int BytesCount, int *Error) +{ + printf("(WW) VFSWriteFile: Not supported in GVFS plugin.\n"); + return cVFS_Not_Supported; +} + +void +VFSSetBlockSize (struct TVFSGlobs *globs, int Value) +{ + if (globs) + globs->block_size = Value; +} + +gboolean +VFSIsOnSameFS (struct TVFSGlobs *globs, const char *Path1, const char *Path2) +{ + GFile *file1, *file2; + GFileInfo *info1, *info2; + GError *error; + gboolean res; + + if (globs->file == NULL) { + g_print ("(EE) VFSIsOnSameFS: globs->file == NULL !\n"); + return FALSE; + } + + file1 = g_file_resolve_relative_path (globs->file, Path1); + file2 = g_file_resolve_relative_path (globs->file, Path2); + if (file1 == NULL) { + g_print ("(EE) VFSIsOnSameFS: g_file_resolve_relative_path() failed.\n"); + return FALSE; + } + if (file2 == NULL) { + g_print ("(EE) VFSIsOnSameFS: g_file_resolve_relative_path() failed.\n"); + return FALSE; + } + + error = NULL; + info1 = g_file_query_info (file1, G_FILE_ATTRIBUTE_ID_FILESYSTEM, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error); + if (error) { + g_print ("(EE) VFSIsOnSameFS: g_file_query_info() error: %s\n", error->message); + g_error_free (error); + g_object_unref (file1); + g_object_unref (file2); + return FALSE; + } + info2 = g_file_query_info (file2, G_FILE_ATTRIBUTE_ID_FILESYSTEM, + G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error); + if (error) { + g_print ("(EE) VFSIsOnSameFS: g_file_query_info() error: %s\n", error->message); + g_error_free (error); + g_object_unref (info1); + g_object_unref (file1); + g_object_unref (file2); + return FALSE; + } + + g_print ("(II) VFSIsOnSameFS: '%s' vs. '%s'\n", g_file_info_get_attribute_string (info1, G_FILE_ATTRIBUTE_ID_FILESYSTEM), + g_file_info_get_attribute_string (info2, G_FILE_ATTRIBUTE_ID_FILESYSTEM)); + + res = strcmp (g_file_info_get_attribute_string (info1, G_FILE_ATTRIBUTE_ID_FILESYSTEM), + g_file_info_get_attribute_string (info2, G_FILE_ATTRIBUTE_ID_FILESYSTEM)) == 0; + g_object_unref (file1); + g_object_unref (file2); + g_object_unref (info1); + g_object_unref (info2); + return res; +} + +gboolean +VFSTwoSameFiles (struct TVFSGlobs *globs, const char *Path1, const char *Path2) +{ + GFile *file1, *file2; + gboolean res; + + if (globs->file == NULL) { + g_print ("(EE) VFSTwoSameFiles: globs->file == NULL !\n"); + return FALSE; + } + + file1 = g_file_resolve_relative_path (globs->file, Path1); + file2 = g_file_resolve_relative_path (globs->file, Path2); + if (file1 == NULL) { + g_print ("(EE) VFSTwoSameFiles: g_file_resolve_relative_path() failed.\n"); + return FALSE; + } + if (file2 == NULL) { + g_print ("(EE) VFSTwoSameFiles: g_file_resolve_relative_path() failed.\n"); + return FALSE; + } + + /* FIXME: we should do some I/O test, we're esentially comparing strings at the moment */ + res = g_file_equal (file1, file2); + g_object_unref (file1); + g_object_unref (file2); + return res; +} + + +/**************************************************************************************************************************************/ +/**************************************************************************************************************************************/ + + +struct CopyJobRef { + struct TVFSGlobs *globs; + TVFSCopyCallBackFunc callback_func; + void *callback_data; + + GCancellable *cancellable; +}; + +static void +vfs_copy_progress_callback (goffset current_num_bytes, + goffset total_num_bytes, + gpointer user_data) +{ + struct CopyJobRef *ref; + + g_print ("(II) vfs_copy_progress_callback spawned: current_num_bytes = %lu, total_num_bytes = %lu\n", current_num_bytes, total_num_bytes); + + if (! user_data) + return; + ref = (struct CopyJobRef*) user_data; + + if (ref->callback_func) { + if (! ref->callback_func (current_num_bytes, total_num_bytes, ref->callback_data)) + g_cancellable_cancel (ref->cancellable); + } +} + + +TVFSResult +VFSCopyOut (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, gboolean Append) +{ + GFile *src, *dst; + GError *error; + struct CopyJobRef *ref; + TVFSResult res; + + + if (globs->file == NULL) { + g_print ("(EE) VFSCopyOut: globs->file == NULL !\n"); + return cVFS_Failed; + } + + g_print ("(II) VFSCopyOut: '%s' --> '%s'\n", sSrcName, sDstName); + + src = g_file_resolve_relative_path (globs->file, sSrcName); + if (src == NULL) { + g_print ("(EE) VFSCopyOut: g_file_resolve_relative_path() failed.\n"); + return cVFS_Failed; + } + dst = g_file_new_for_path (sDstName); + if (dst == NULL) { + g_print ("(EE) VFSCopyOut: g_file_resolve_relative_path() failed.\n"); + return cVFS_Failed; + } + + ref = g_slice_new0 (struct CopyJobRef); + ref->globs = globs; + ref->callback_func = pCallBackProgress; + ref->callback_data = data; + ref->cancellable = g_cancellable_new (); + + res = cVFS_OK; + error = NULL; + g_file_copy (src, dst, G_FILE_COPY_OVERWRITE | G_FILE_COPY_NOFOLLOW_SYMLINKS, ref->cancellable, vfs_copy_progress_callback, ref, &error); + if (error) { + g_print ("(EE) VFSCopyOut: g_file_copy() error: %s\n", error->message); +// res = g_error_to_TVFSResult (error); + if (error->code == G_IO_ERROR_CANCELLED) + res = cVFS_Cancelled; + else res = cVFS_ReadErr; + g_error_free (error); + } + + g_object_unref (ref->cancellable); + g_slice_free (struct CopyJobRef, ref); + g_object_unref (src); + g_object_unref (dst); + return res; +} + +TVFSResult +VFSCopyIn (struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, gboolean Append) +{ + GFile *src, *dst; + GError *error; + struct CopyJobRef *ref; + TVFSResult res; + + + if (globs->file == NULL) { + g_print ("(EE) VFSCopyIn: globs->file == NULL !\n"); + return cVFS_Failed; + } + + g_print ("(II) VFSCopyIn: '%s' --> '%s'\n", sSrcName, sDstName); + + src = g_file_new_for_path (sSrcName); + if (src == NULL) { + g_print ("(EE) VFSCopyIn: g_file_resolve_relative_path() failed.\n"); + return cVFS_Failed; + } + dst = g_file_resolve_relative_path (globs->file, sDstName); + if (dst == NULL) { + g_print ("(EE) VFSCopyIn: g_file_resolve_relative_path() failed.\n"); + return cVFS_Failed; + } + + ref = g_slice_new0 (struct CopyJobRef); + ref->globs = globs; + ref->callback_func = pCallBackProgress; + ref->callback_data = data; + ref->cancellable = g_cancellable_new (); + + res = cVFS_OK; + error = NULL; + /* FIXME: Appending not supported */ + g_file_copy (src, dst, G_FILE_COPY_NOFOLLOW_SYMLINKS, ref->cancellable, vfs_copy_progress_callback, ref, &error); + if (error) { + g_print ("(EE) VFSCopyIn: g_file_copy() error: %s\n", error->message); +// res = g_error_to_TVFSResult (error); + if (error->code == G_IO_ERROR_CANCELLED) + res = cVFS_Cancelled; + else res = cVFS_WriteErr; + g_error_free (error); + } + + g_object_unref (ref->cancellable); + g_slice_free (struct CopyJobRef, ref); + g_object_unref (src); + g_object_unref (dst); + return res; +} + + + +/********** + * TODO: + * - block size settings for GIO subsystem + * - variable block size for different protocols? + * - support for appending in VFSCopyIn + * + ***/ diff --git a/gvfs/vfs_types.h b/gvfs/vfs_types.h new file mode 120000 index 0000000..c2235a2 --- /dev/null +++ b/gvfs/vfs_types.h @@ -0,0 +1 @@ +../common/vfs_types.h \ No newline at end of file -- cgit v1.2.3