/* Gnome-VFS plugin for Tux Commander * Copyright (C) 2005 Tomas Bzatek * Check for updates on tuxcmd.sourceforge.net * * 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" // Some plugin constants static const int const_default_bsize = 65536; static const int const_default_ftp_bsize = 8192; // Declaration of the global plugin object struct TVFSGlobs { TVFSLogFunc log_func; int list_item_id; GnomeVFSDirectoryHandle *read_handle; GnomeVFSFileInfo *cached_file_info; GnomeVFSURI *uri; int path_require_reread; int break_get_dir_size; int block_size; }; // Basic initialization functions int VFSAllocNeeded() { return sizeof(struct TVFSGlobs); } void VFSInit(struct TVFSGlobs *globs, TVFSLogFunc log_func) { globs->log_func = log_func; globs->log_func("Gnome-VFS plugin: VFSInit"); globs->path_require_reread = 1; globs->break_get_dir_size = 0; globs->block_size = const_default_bsize; /* remember to initialize GnomeVFS! */ if (!gnome_vfs_init ()) { printf ("Could not initialize GnomeVFS\n"); } } void VFSDestroy(struct TVFSGlobs *globs) { // gnome_vfs_shutdown(); globs->log_func("Gnome-VFS plugin: VFSDestroy"); } int VFSVersion() { return cVFSVersion; } struct TVFSInfo VFSGetInfo() { static const struct TVFSInfo info = { "Gnome-VFS plugin", "Gnome-VFS interconnection plugin", "version 0.99.5\nBuild date: 2008-05-17", "Copyright © 2005 Tomáš Bžatek", }; return info; } char *VFSGetExts() { return ""; } char *VFSGetServices() { return "http;https;ftp;sftp;smb;network"; } char *VFSGetPrefix(struct TVFSGlobs *globs) { return gnome_vfs_uri_to_string(gnome_vfs_uri_resolve_relative(globs->uri, "/"), GNOME_VFS_URI_HIDE_NONE); } TVFSResult VFSOpen(struct TVFSGlobs *globs, char *sName) { if (strlen(sName) > 0) { globs->uri = gnome_vfs_uri_new(sName); if (globs->uri != NULL) return cVFS_OK; else return cVFS_Failed; } else { // Auto Fallback globs->uri = gnome_vfs_uri_new("file:///"); return cVFS_Not_Supported; } } TVFSResult VFSClose(struct TVFSGlobs *globs) { if (globs->uri != NULL) gnome_vfs_uri_unref(globs->uri); return cVFS_OK; } char *VFSGetPath(struct TVFSGlobs *globs) { return (char*)gnome_vfs_uri_get_path(globs->uri); } guint64 VFSGetFileSystemFree(struct TVFSGlobs *globs, char *APath) { int result; GnomeVFSFileSize size; result = gnome_vfs_get_volume_free_space(gnome_vfs_uri_resolve_relative(globs->uri, APath), &size); if (result != 0) return 0; else return size; } guint64 VFSGetFileSystemSize(struct TVFSGlobs *globs, char *APath) { return 1024; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////// TVFSResult VFSChangeDir(struct TVFSGlobs *globs, char *NewPath) { GnomeVFSURI *uri; globs->path_require_reread = 1; uri = gnome_vfs_uri_resolve_relative(globs->uri, NewPath); GnomeVFSResult result; printf("Chdir URI is now: %s\n", gnome_vfs_uri_to_string(uri, GNOME_VFS_URI_HIDE_NONE)); printf("Opening directory...\n"); result = gnome_vfs_directory_open_from_uri(&globs->read_handle, uri, GNOME_VFS_FILE_INFO_DEFAULT); /* if the operation was not successful, print the error and abort */ printf("open result = %i = %s\n", result, gnome_vfs_result_to_string(result)); if (result != GNOME_VFS_OK) return cVFS_Failed; globs->path_require_reread = 0; // Try to retrieve first item to determine correct access permissions int i=0; while (i == 0) { globs->cached_file_info = gnome_vfs_file_info_new(); result = gnome_vfs_directory_read_next(globs->read_handle, globs->cached_file_info); if (result == GNOME_VFS_ERROR_EOF) { i = 1; gnome_vfs_file_info_unref(globs->cached_file_info); globs->cached_file_info = NULL; printf("EOF.\n"); // No more files in this directory and no error occured break; } if (result && result != GNOME_VFS_ERROR_EOF) { gnome_vfs_file_info_unref(globs->cached_file_info); globs->cached_file_info = NULL; printf("no permission\n"); return cVFS_Failed; } else if ((strcmp(globs->cached_file_info->name, ".") == 0) || (strcmp(globs->cached_file_info->name, "..") == 0)) { gnome_vfs_file_info_unref(globs->cached_file_info); } else { i = 1; }; } // Copy the URI if everything goes OK gnome_vfs_uri_unref(globs->uri); globs->uri = uri; return cVFS_OK; } int VFSLogin(struct TVFSGlobs *globs, char *user, char *pass) { printf("*** begin login: %s/%s\n", user, pass); gnome_vfs_uri_set_user_name(globs->uri, user); gnome_vfs_uri_set_password(globs->uri, pass); GnomeVFSResult result; GnomeVFSFileInfo *file_info; // Test if we can open the new location result = gnome_vfs_directory_open_from_uri(&globs->read_handle, globs->uri, GNOME_VFS_FILE_INFO_DEFAULT); printf("gnome_vfs_directory_open_from_uri result = %i = %s\n", result, gnome_vfs_result_to_string(result)); if (result != GNOME_VFS_OK) return cVFS_Failed; // Try to retrieve first item to determine correct access permissions file_info = gnome_vfs_file_info_new(); result = gnome_vfs_directory_read_next(globs->read_handle, file_info); gnome_vfs_file_info_unref(file_info); if (result && result != GNOME_VFS_ERROR_EOF) return cVFS_Failed; gnome_vfs_directory_close(globs->read_handle); return cVFS_OK; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////// void ProcessDirItem(GnomeVFSFileInfo *file_info, struct TVFSItem *VFSItem) { VFSItem->sFileName = strdup(file_info->name); switch (file_info->type) { case GNOME_VFS_FILE_TYPE_UNKNOWN: case GNOME_VFS_FILE_TYPE_REGULAR: VFSItem->ItemType = vRegular; break; case GNOME_VFS_FILE_TYPE_DIRECTORY: VFSItem->ItemType = vDirectory; break; case GNOME_VFS_FILE_TYPE_FIFO: VFSItem->ItemType = vFifo; break; case GNOME_VFS_FILE_TYPE_SOCKET: VFSItem->ItemType = vSock; break; case GNOME_VFS_FILE_TYPE_CHARACTER_DEVICE: VFSItem->ItemType = vChardev; break; case GNOME_VFS_FILE_TYPE_BLOCK_DEVICE: VFSItem->ItemType = vBlockdev; break; case GNOME_VFS_FILE_TYPE_SYMBOLIC_LINK: VFSItem->ItemType = vSymlink; break; } VFSItem->iMode = (u_int64_t)file_info->permissions; VFSItem->iUID = file_info->uid; VFSItem->iGID = file_info->gid; VFSItem->iSize = file_info->size; VFSItem->a_time = file_info->atime; VFSItem->m_time = file_info->mtime; VFSItem->c_time = file_info->ctime; // Hack for special items if (file_info->mime_type != NULL) if ((strcmp(file_info->mime_type, "application/x-desktop") == 0)) { VFSItem->ItemType = vDirectory; VFSItem->iMode = S_IRWXU | S_IRWXG | S_IRWXO; } if ((file_info->flags == GNOME_VFS_FILE_FLAGS_SYMLINK) && (file_info->symlink_name != NULL)) VFSItem->sLinkTo = strdup(file_info->symlink_name); else { VFSItem->sLinkTo = NULL; } printf("name = %s, type = %i, perm = %i, flags = %i, MIME = %s\n", file_info->name, file_info->type, file_info->permissions, file_info->flags, file_info->mime_type); } TVFSResult VFSListFirst(struct TVFSGlobs *globs, char *sDir, struct TVFSItem *Item) { printf("List URI is now: %s\n", gnome_vfs_uri_to_string(globs->uri, GNOME_VFS_URI_HIDE_NONE)); if (globs->path_require_reread != 0) VFSChangeDir(globs, sDir); if (globs->cached_file_info == NULL) return cVFS_No_More_Files; // We should have the first item cached ProcessDirItem(globs->cached_file_info, Item); gnome_vfs_file_info_unref(globs->cached_file_info); return cVFS_OK; } TVFSResult VFSListNext(struct TVFSGlobs *globs, char *sDir, struct TVFSItem *Item) { GnomeVFSResult result; GnomeVFSFileInfo *file_info; // fprintf(stderr, "(II) Entering VFSListNext(sDir = %s; Item = %d)...\n", sDir, Item, NULL); gboolean b = 1; while (b) { file_info = gnome_vfs_file_info_new(); result = gnome_vfs_directory_read_next(globs->read_handle, file_info); if (result == GNOME_VFS_ERROR_EOF) return cVFS_No_More_Files; if (result && result != GNOME_VFS_ERROR_EOF) { gnome_vfs_file_info_unref(file_info); return cVFS_Failed; } if ((strcmp(file_info->name, ".") == 0) || (strcmp(file_info->name, "..") == 0)) gnome_vfs_file_info_unref(file_info); else b = 0; } // fprintf(stderr, "(II) Processing VFSListNext...\n"); ProcessDirItem(file_info, Item); gnome_vfs_file_info_unref(file_info); globs->path_require_reread = 1; // fprintf(stderr, "(II) Leaving VFSListNext...\n"); return cVFS_OK; } TVFSResult VFSListClose(struct TVFSGlobs *globs) { GnomeVFSResult result; result = gnome_vfs_directory_close(globs->read_handle); if (result != GNOME_VFS_OK) return cVFS_Failed; return cVFS_OK; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////// long VFSFileExists(struct TVFSGlobs *globs, const char *FileName, const long Use_lstat) { GnomeVFSURI *uri; long res; uri = gnome_vfs_uri_resolve_relative(globs->uri, FileName); if (uri == NULL) return FALSE; res = gnome_vfs_uri_exists(uri); gnome_vfs_uri_unref(uri); return res; } TVFSResult VFSFileInfo(struct TVFSGlobs *globs, char *AFileName, struct TVFSItem *Item) { GnomeVFSURI *uri; GnomeVFSResult res; GnomeVFSFileInfo *file_info; uri = gnome_vfs_uri_resolve_relative(globs->uri, AFileName); if (uri == NULL) return cVFS_Failed; file_info = gnome_vfs_file_info_new(); res = gnome_vfs_get_file_info_uri(uri, file_info, GNOME_VFS_FILE_INFO_DEFAULT); gnome_vfs_uri_unref(uri); if (res) { gnome_vfs_file_info_unref(file_info); printf("gnome_vfs_get_file_info_uri result = %i = %s\n", res, gnome_vfs_result_to_string(res)); return cVFS_Failed; } ProcessDirItem(file_info, Item); free(Item->sFileName); Item->sFileName = strdup(AFileName); gnome_vfs_file_info_unref(file_info); return cVFS_OK; } TVFSResult VFSMkDir(struct TVFSGlobs *globs, const char *sDirName) { GnomeVFSURI *uri; GnomeVFSResult res; uri = gnome_vfs_uri_resolve_relative(globs->uri, sDirName); if (uri == NULL) return cVFS_Failed; res = gnome_vfs_make_directory_for_uri(uri, S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH); gnome_vfs_uri_unref(uri); if (res) { printf("gnome_vfs_make_directory_for_uri result = %i = %s\n", res, gnome_vfs_result_to_string(res)); return cVFS_Failed; } return cVFS_OK; } TVFSResult VFSRemove(struct TVFSGlobs *globs, const char *APath) { GnomeVFSURI *uri; GnomeVFSResult res; GnomeVFSFileInfo *file_info; uri = gnome_vfs_uri_resolve_relative(globs->uri, APath); if (uri == NULL) return cVFS_Failed; file_info = gnome_vfs_file_info_new(); res = gnome_vfs_get_file_info_uri(uri, file_info, GNOME_VFS_FILE_INFO_DEFAULT); if (res) { gnome_vfs_uri_unref(uri); printf("VFSRemove: gnome_vfs_get_file_info_uri result = %i = %s\n", res, gnome_vfs_result_to_string(res)); return cVFS_Failed; } // Determine if we have to remove the directory or unlink the file if (file_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) { gnome_vfs_file_info_unref(file_info); res = gnome_vfs_remove_directory_from_uri(uri); gnome_vfs_uri_unref(uri); if (res) { printf("VFSRemove: gnome_vfs_remove_directory_from_uri result = %i = %s\n", res, gnome_vfs_result_to_string(res)); return cVFS_Failed; } } else { gnome_vfs_file_info_unref(file_info); res = gnome_vfs_unlink_from_uri(uri); gnome_vfs_uri_unref(uri); if (res) { printf("VFSRemove: gnome_vfs_unlink_from_uri result = %i = %s\n", res, gnome_vfs_result_to_string(res)); return cVFS_Failed; } } return cVFS_OK; } TVFSResult VFSRename(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName) { GnomeVFSURI *srcuri, *dsturi; GnomeVFSResult res; srcuri = gnome_vfs_uri_resolve_relative(globs->uri, sSrcName); if (srcuri == NULL) return cVFS_Failed; dsturi = gnome_vfs_uri_resolve_relative(globs->uri, sDstName); if (dsturi == NULL) return cVFS_Failed; res = gnome_vfs_move_uri(srcuri, dsturi, 1); gnome_vfs_uri_unref(srcuri); gnome_vfs_uri_unref(dsturi); if (res) { printf("gnome_vfs_move_uri result = %i = %s\n", res, gnome_vfs_result_to_string(res)); return cVFS_Failed; } return cVFS_OK; } TVFSResult VFSMakeSymLink(struct TVFSGlobs *globs, const char *NewFileName, const char *PointTo) { GnomeVFSURI *uri; GnomeVFSResult res; uri = gnome_vfs_uri_resolve_relative(globs->uri, NewFileName); if (uri == NULL) return cVFS_Failed; res = gnome_vfs_create_symbolic_link(uri, PointTo); gnome_vfs_uri_unref(uri); if (res) { printf("gnome_vfs_create_symbolic_link result = %i = %s\n", res, gnome_vfs_result_to_string(res)); return cVFS_Failed; } return cVFS_OK; } TVFSResult VFSChmod(struct TVFSGlobs *globs, const char *FileName, const uint Mode) { GnomeVFSURI *uri; GnomeVFSResult res; GnomeVFSFileInfo *file_info; uri = gnome_vfs_uri_resolve_relative(globs->uri, FileName); if (uri == NULL) return cVFS_Failed; file_info = gnome_vfs_file_info_new(); if (file_info == NULL) return cVFS_Failed; file_info->permissions = (GnomeVFSFilePermissions)Mode; res = gnome_vfs_set_file_info_uri(uri, file_info, GNOME_VFS_SET_FILE_INFO_PERMISSIONS); gnome_vfs_file_info_unref(file_info); gnome_vfs_uri_unref(uri); if (res) { printf("gnome_vfs_set_file_info_uri result = %i = %s\n", res, gnome_vfs_result_to_string(res)); return cVFS_Failed; } return cVFS_OK; } TVFSResult VFSChown(struct TVFSGlobs *globs, const char *FileName, const uint UID, const uint GID) { GnomeVFSURI *uri; GnomeVFSResult res; GnomeVFSFileInfo *file_info; uri = gnome_vfs_uri_resolve_relative(globs->uri, FileName); if (uri == NULL) return cVFS_Failed; file_info = gnome_vfs_file_info_new(); if (file_info == NULL) return cVFS_Failed; file_info->uid = UID; file_info->gid = GID; res = gnome_vfs_set_file_info_uri(uri, file_info, GNOME_VFS_SET_FILE_INFO_OWNER); gnome_vfs_file_info_unref(file_info); gnome_vfs_uri_unref(uri); if (res) { printf("gnome_vfs_set_file_info_uri result = %i = %s\n", res, gnome_vfs_result_to_string(res)); return cVFS_Failed; } return cVFS_OK; } TVFSResult VFSChangeTimes(struct TVFSGlobs *globs, char *APath, long mtime, long atime) { GnomeVFSURI *uri; GnomeVFSResult res; GnomeVFSFileInfo *file_info; uri = gnome_vfs_uri_resolve_relative(globs->uri, APath); if (uri == NULL) return cVFS_Failed; file_info = gnome_vfs_file_info_new(); if (file_info == NULL) return cVFS_Failed; file_info->atime = atime; file_info->mtime = mtime; res = gnome_vfs_set_file_info_uri(uri, file_info, GNOME_VFS_SET_FILE_INFO_TIME); gnome_vfs_file_info_unref(file_info); gnome_vfs_uri_unref(uri); if (res) { printf("gnome_vfs_set_file_info_uri result = %i = %s\n", res, gnome_vfs_result_to_string(res)); return cVFS_Failed; } return cVFS_OK; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////// void VFSGetDirSize_recurse(struct TVFSGlobs *globs, char *APath, guint64 *Size) { GnomeVFSURI *uri; GnomeVFSResult result; GnomeVFSDirectoryHandle *dir_handle; GnomeVFSFileInfo *file_info; // First change dir... uri = gnome_vfs_uri_resolve_relative(globs->uri, APath); result = gnome_vfs_directory_open_from_uri(&dir_handle, uri, GNOME_VFS_FILE_INFO_DEFAULT); if (result != GNOME_VFS_OK) return; // Get file info... while (1) { if (globs->break_get_dir_size == 1) return; file_info = gnome_vfs_file_info_new(); result = gnome_vfs_directory_read_next(dir_handle, file_info); if (result) { gnome_vfs_file_info_unref(file_info); // Some error occured... break; } if ((file_info == NULL) || (file_info->name == NULL)) break; if ((strcmp(file_info->name, ".") != 0) && (strcmp(file_info->name, "..") != 0)) { // Process the file // printf("Found file: %s\n", file_info->name); if (file_info->type == GNOME_VFS_FILE_TYPE_DIRECTORY) { char *NewPath; NewPath = (char*)malloc(strlen(APath) + 2 + strlen(file_info->name)); strcpy(NewPath, APath); strcat(NewPath, "/"); strcat(NewPath, file_info->name); // printf("Entering directory %s\n", NewPath); VFSGetDirSize_recurse(globs, NewPath, Size); free(NewPath); } else *Size += file_info->size; } gnome_vfs_file_info_unref(file_info); } gnome_vfs_directory_close(dir_handle); gnome_vfs_uri_unref(uri); } guint64 VFSGetDirSize(struct TVFSGlobs *globs, char *APath) { if (globs == NULL) return 0; guint64 Size = 0; globs->break_get_dir_size = 0; VFSGetDirSize_recurse(globs, APath, &Size); globs->break_get_dir_size = 0; return Size; } void VFSBreakGetDirSize(struct TVFSGlobs *globs) { printf("################################### calling Break\n"); if (globs != NULL) globs->break_get_dir_size = 1; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////// TVFSFileDes VFSOpenFile(struct TVFSGlobs *globs, const char *APath, int Mode, int *Error) { GnomeVFSResult res = GNOME_VFS_OK; GnomeVFSHandle *handle; GnomeVFSURI *uri; uri = gnome_vfs_uri_resolve_relative(globs->uri, APath); switch (Mode) { case cVFS_OpenRead: res = gnome_vfs_open_uri(&handle, uri, GNOME_VFS_OPEN_READ); if (res == GNOME_VFS_ERROR_INTERNAL) { printf("buggy implementation in gnome_vfs_open_uri\n"); } if (res != GNOME_VFS_OK) printf("gnome_vfs_open_uri result = %i = %s\n", res, gnome_vfs_result_to_string(res)); break; case cVFS_OpenWrite: res = gnome_vfs_create_uri(&handle, uri, GNOME_VFS_OPEN_WRITE, 0, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ); if (res != GNOME_VFS_OK) printf("gnome_vfs_create_uri result = %i = %s\n", res, gnome_vfs_result_to_string(res)); break; case cVFS_OpenAppend: res = gnome_vfs_open_uri(&handle, uri, GNOME_VFS_OPEN_WRITE); if (res != GNOME_VFS_OK) printf("gnome_vfs_open_uri result = %i = %s\n", res, gnome_vfs_result_to_string(res)); if (res == GNOME_VFS_OK) { res = gnome_vfs_seek(handle, GNOME_VFS_SEEK_END, 0); if (res != GNOME_VFS_OK) printf("gnome_vfs_seek result = %i = %s\n", res, gnome_vfs_result_to_string(res)); } break; } gnome_vfs_uri_unref(uri); *Error = res; return (TVFSFileDes)handle; } TVFSResult VFSCloseFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor) { GnomeVFSResult res; // Preventive seek to 0 when closing file to avoid some bugs in FTP protocol implementation if (strcmp(gnome_vfs_uri_get_scheme(globs->uri), "ftp") == 0) { res = gnome_vfs_seek((GnomeVFSHandle*)FileDescriptor, GNOME_VFS_SEEK_START, 0); if (res != GNOME_VFS_OK) printf("gnome_vfs_seek result = %i = %s; ignore this please\n", res, gnome_vfs_result_to_string(res)); } res = gnome_vfs_close((GnomeVFSHandle*)FileDescriptor); if (res != GNOME_VFS_OK) printf("gnome_vfs_close result = %i = %s\n", res, gnome_vfs_result_to_string(res)); // return res; return cVFS_OK; } guint64 VFSFileSeek(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, guint64 AbsoluteOffset, int *Error) { GnomeVFSResult res; GnomeVFSFileSize offset_return = 0; res = gnome_vfs_seek((GnomeVFSHandle*)FileDescriptor, GNOME_VFS_SEEK_START, AbsoluteOffset); if (res != GNOME_VFS_OK) printf("gnome_vfs_seek result = %i = %s\n", res, gnome_vfs_result_to_string(res)); if (res == GNOME_VFS_OK) { res = gnome_vfs_tell((GnomeVFSHandle*)FileDescriptor, &offset_return); if (res != GNOME_VFS_OK) printf("gnome_vfs_tell result = %i = %s\n", res, gnome_vfs_result_to_string(res)); } *Error = res; return offset_return; } int VFSReadFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, gpointer Buffer, int ABlockSize, int *Error) { GnomeVFSResult res; GnomeVFSFileSize bytes_read; res = gnome_vfs_read((GnomeVFSHandle*)FileDescriptor, Buffer, ABlockSize, &bytes_read); if (res != GNOME_VFS_OK) printf("gnome_vfs_read result = %i = %s\n", res, gnome_vfs_result_to_string(res)); if (res == GNOME_VFS_ERROR_EOF) res = (GnomeVFSResult)0; *Error = res; return bytes_read; } int VFSWriteFile(struct TVFSGlobs *globs, TVFSFileDes FileDescriptor, gpointer Buffer, int BytesCount, int *Error) { GnomeVFSResult res; GnomeVFSFileSize bytes_written; res = gnome_vfs_write((GnomeVFSHandle*)FileDescriptor, Buffer, BytesCount, &bytes_written); if (res != GNOME_VFS_OK) printf("gnome_vfs_write result = %i = %s\n", res, gnome_vfs_result_to_string(res)); *Error = res; return bytes_written; } void VFSSetBlockSize(struct TVFSGlobs *globs, int Value) { printf("VFSSetBlockSize: scheme = %s\n", gnome_vfs_uri_get_scheme(globs->uri)); if ((strcmp(gnome_vfs_uri_get_scheme(globs->uri), "ftp") == 0) || (strcmp(gnome_vfs_uri_get_scheme(globs->uri), "sftp") == 0)) globs->block_size = const_default_ftp_bsize; else globs->block_size = Value; } gboolean VFSIsOnSameFS(struct TVFSGlobs *globs, const char *Path1, const char *Path2) { GnomeVFSResult res; gboolean same_fs_return = 0; GnomeVFSURI *uri1, *uri2; // Prepare the correct URIs uri1 = gnome_vfs_uri_resolve_relative(globs->uri, Path1); uri2 = gnome_vfs_uri_resolve_relative(globs->uri, Path2); res = gnome_vfs_check_same_fs_uris(uri1, uri2, &same_fs_return); if (res != GNOME_VFS_OK) printf("gnome_vfs_check_same_fs result = %i = %s\n", res, gnome_vfs_result_to_string(res)); gnome_vfs_uri_unref(uri1); gnome_vfs_uri_unref(uri2); return same_fs_return; } gboolean VFSTwoSameFiles(struct TVFSGlobs *globs, const char *Path1, const char *Path2) { GnomeVFSURI *uri1, *uri2; gboolean same = 0; uri1 = gnome_vfs_uri_resolve_relative(globs->uri, Path1); uri2 = gnome_vfs_uri_resolve_relative(globs->uri, Path2); same = gnome_vfs_uri_equal(uri1, uri2); gnome_vfs_uri_unref(uri1); gnome_vfs_uri_unref(uri2); return same; } //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //////////////////////// void internal_close_seek(struct TVFSGlobs *globs, GnomeVFSHandle *file) { GnomeVFSResult res; // Preventive seek to 0 when closing file to avoid some bugs in FTP protocol implementation if (strcmp(gnome_vfs_uri_get_scheme(globs->uri), "ftp") == 0) { res = gnome_vfs_seek(file, GNOME_VFS_SEEK_START, 0); if (res != GNOME_VFS_OK) printf("gnome_vfs_seek result = %i = %s; ignore this please\n", res, gnome_vfs_result_to_string(res)); } gnome_vfs_close(file); } TVFSResult VFSCopyOut(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, gboolean Append) { void *buffer; GnomeVFSFileSize bytes_read; uint bytes_written = 0; guint64 bytes_done; GnomeVFSResult res; GnomeVFSHandle *read_handle; GnomeVFSURI *uri; FILE *dest_file; // Open the source file for reading uri = gnome_vfs_uri_resolve_relative(globs->uri, sSrcName); res = gnome_vfs_open_uri(&read_handle, uri, GNOME_VFS_OPEN_READ); gnome_vfs_uri_unref(uri); if (res != GNOME_VFS_OK) { printf("VFSCopyOut: gnome_vfs_open_uri result = %i = %s\n", res, gnome_vfs_result_to_string(res)); return cVFS_ReadErr; } // Open the destination file for writing if (! Append) dest_file = fopen(sDstName, "w"); else dest_file = fopen(sDstName, "a"); if (dest_file == NULL) { printf("VFSCopyOut: fopen result = %i = %s\n", errno, strerror(errno)); return cVFS_WriteErr; } // Alloc the memory space... buffer = (void*)malloc(globs->block_size); if (buffer == NULL) { printf("VFSCopyOut: malloc failed = %i = %s\n", errno, strerror(errno)); return cVFS_mallocFailed; } bytes_done = 0; // Read each block and write it do { res = gnome_vfs_read(read_handle, buffer, globs->block_size, &bytes_read); if ((bytes_read == 0) && (res != GNOME_VFS_OK) && (res != GNOME_VFS_ERROR_EOF)) { printf("VFSCopyOut: gnome_vfs_read result = %i = %s\n", res, gnome_vfs_result_to_string(res)); fclose(dest_file); internal_close_seek(globs, read_handle); free(buffer); return cVFS_ReadErr; } if (bytes_read > 0) { bytes_written = fwrite(buffer, 1, bytes_read, dest_file); if (bytes_written < bytes_read) { printf("VFSCopyOut: fwrite result = %i = %s\n", errno, strerror(errno)); fclose(dest_file); internal_close_seek(globs, read_handle); free(buffer); return cVFS_WriteErr; } } bytes_done += bytes_read; // Call the progress function and break the processing if needed if ((pCallBackProgress != NULL) && (!pCallBackProgress(bytes_done, 0, data))) { internal_close_seek(globs, read_handle); fclose(dest_file); free(buffer); return cVFS_Cancelled; } } while ((bytes_read > 0) && (bytes_written == bytes_read)); // Close the files and free the objects internal_close_seek(globs, read_handle); fclose(dest_file); free(buffer); return cVFS_OK; } TVFSResult VFSCopyIn(struct TVFSGlobs *globs, const char *sSrcName, const char *sDstName, TVFSCopyCallBackFunc pCallBackProgress, void *data, gboolean Append) { void *buffer; uint bytes_read; GnomeVFSFileSize bytes_written; guint64 bytes_done; GnomeVFSResult res; GnomeVFSHandle *write_handle; GnomeVFSURI *uri; FILE *src_file; int err; // Open the source file for reading src_file = fopen(sSrcName, "r"); if (src_file == NULL) { printf("VFSCopyIn: fopen result = %i = %s\n", errno, strerror(errno)); return cVFS_ReadErr; } // Open the destination file for writing uri = gnome_vfs_uri_resolve_relative(globs->uri, sDstName); if (! Append) { res = gnome_vfs_create_uri(&write_handle, uri, GNOME_VFS_OPEN_WRITE, 0, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ); gnome_vfs_uri_unref(uri); if (res != GNOME_VFS_OK) { printf("VFSCopyIn: gnome_vfs_create_uri result = %i = %s\n", res, gnome_vfs_result_to_string(res)); return cVFS_WriteErr; } } else { res = gnome_vfs_open_uri(&write_handle, uri, GNOME_VFS_OPEN_WRITE); gnome_vfs_uri_unref(uri); if (res != GNOME_VFS_OK) { printf("VFSCopyIn: gnome_vfs_open_uri result = %i = %s\n", res, gnome_vfs_result_to_string(res)); return cVFS_WriteErr; } if (res == GNOME_VFS_OK) { res = gnome_vfs_seek(write_handle, GNOME_VFS_SEEK_END, 0); if (res != GNOME_VFS_OK) { printf("VFSCopyIn: gnome_vfs_seek result = %i = %s\n", res, gnome_vfs_result_to_string(res)); return cVFS_WriteErr; } } } // Alloc the memory space... buffer = (void*)malloc(globs->block_size); if (buffer == NULL) { printf("VFSCopyIn: malloc failed = %i = %s\n", errno, strerror(errno)); return cVFS_mallocFailed; } bytes_done = 0; // Read each block and write it do { bytes_read = fread(buffer, 1, globs->block_size, src_file); err = errno; if ((bytes_read == 0) && (err != 0) && (feof(src_file) == 0)) { printf("VFSCopyIn: fread result = %i = %s\n", err, strerror(err)); fclose(src_file); gnome_vfs_close(write_handle); free(buffer); return cVFS_ReadErr; } if (bytes_read > 0) { res = gnome_vfs_write(write_handle, buffer, bytes_read, &bytes_written); if (bytes_written < bytes_read) { printf("VFSCopyIn: gnome_vfs_write result = %i = %s\n", res, gnome_vfs_result_to_string(res)); fclose(src_file); gnome_vfs_close(write_handle); free(buffer); return cVFS_WriteErr; } } bytes_done += bytes_read; // Call the progress function and break the processing if needed if ((pCallBackProgress != NULL) && (!pCallBackProgress(bytes_done, 0, data))) { fclose(src_file); gnome_vfs_close(write_handle); free(buffer); return cVFS_Cancelled; } } while ((bytes_read > 0) && (bytes_written == bytes_read)); // Close the files and free the objects fclose(src_file); gnome_vfs_close(write_handle); free(buffer); return cVFS_OK; } //////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////