static void do_query_info_on_read (GVfsBackend *backend, GVfsJobQueryInfoRead *job, GVfsBackendHandle handle, GFileInfo *info, GFileAttributeMatcher *attribute_matcher) { int fd, res; struct stat statbuf; fd = GPOINTER_TO_INT (handle); res = fstat (fd, &statbuf); if (res == -1) { int errsv = errno; g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, g_io_error_from_errno (errsv), "Error querying info in file: %s", g_strerror (errsv)); } else { g_file_info_set_size (info, statbuf.st_size); g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_DEVICE, statbuf.st_dev); g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_MODIFIED, statbuf.st_mtime); g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS, statbuf.st_atime); g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CHANGED, statbuf.st_ctime); g_vfs_job_succeeded (G_VFS_JOB (job)); } }
static gboolean read_idle_cb (gpointer data) { GVfsJobRead *job = data; int fd; ssize_t res; fd = GPOINTER_TO_INT (job->handle); res = read (fd, job->buffer, job->bytes_requested); if (res == -1) { int errsv = errno; g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, g_io_error_from_errno (errsv), "Error reading from file: %s", g_strerror (errsv)); } else { g_vfs_job_read_set_size (job, res); g_vfs_job_succeeded (G_VFS_JOB (job)); } return FALSE; }
static void do_seek_on_read (GVfsBackend *backend, GVfsJobSeekRead *job, GVfsBackendHandle handle, goffset offset, GSeekType type) { int whence; int fd; off_t final_offset; g_print ("seek_on_read (%d, %u)\n", (int)offset, type); if ((whence = gvfs_seek_type_to_lseek (type)) == -1) whence = SEEK_SET; fd = GPOINTER_TO_INT (handle); final_offset = lseek (fd, offset, whence); if (final_offset == (off_t)-1) { int errsv = errno; g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, g_io_error_from_errno (errsv), "Error seeking in file: %s", g_strerror (errsv)); } else { g_vfs_job_seek_read_set_offset (job, offset); g_vfs_job_succeeded (G_VFS_JOB (job)); } }
static gboolean try_query_info (GVfsBackend *backend, GVfsJobQueryInfo *job, const char *filename, GFileQueryInfoFlags flags, GFileInfo *info, GFileAttributeMatcher *matcher) { if (is_root (filename)) { GIcon *icon; g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY); g_file_info_set_name (info, "/"); g_file_info_set_display_name (info, g_vfs_backend_get_display_name (backend)); g_file_info_set_content_type (info, "inode/directory"); icon = g_vfs_backend_get_icon (backend); if (icon != NULL) g_file_info_set_icon (info, icon); icon = g_vfs_backend_get_symbolic_icon (backend); if (icon != NULL) g_file_info_set_symbolic_icon (info, icon); g_vfs_job_succeeded (G_VFS_JOB (job)); } else update_cache (G_VFS_BACKEND_AFP_BROWSE (backend), G_VFS_JOB (job)->cancellable, query_info_cb, job); return TRUE; }
static void query_info_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GVfsBackendAfpBrowse *afp_backend = G_VFS_BACKEND_AFP_BROWSE (source_object); GVfsJobQueryInfo *job = G_VFS_JOB_QUERY_INFO (user_data); GError *err = NULL; GVfsAfpVolumeData *vol_data; if (!update_cache_finish (afp_backend, res, &err)) { g_vfs_job_failed_from_error (G_VFS_JOB (job), err); g_error_free (err); return; } vol_data = find_volume (afp_backend, job->filename); if (!vol_data) { g_vfs_job_failed_literal (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("File doesn't exist")); return; } fill_info (job->file_info, vol_data, afp_backend); g_vfs_job_succeeded (G_VFS_JOB (job)); }
static void enumerate_cache_updated_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GVfsBackendAfpBrowse *afp_backend = G_VFS_BACKEND_AFP_BROWSE (source_object); GVfsJobEnumerate *job = G_VFS_JOB_ENUMERATE (user_data); GError *err = NULL; guint i; if (!update_cache_finish (afp_backend, res, &err)) { g_vfs_job_failed_from_error (G_VFS_JOB (job), err); g_error_free (err); return; } g_vfs_job_succeeded (G_VFS_JOB (job)); for (i = 0; i < afp_backend->volumes->len; i++) { GVfsAfpVolumeData *vol_data = g_ptr_array_index (afp_backend->volumes, i); GFileInfo *info; info = g_file_info_new (); fill_info (info, vol_data, afp_backend); g_vfs_job_enumerate_add_info (job, info); g_object_unref (info); } g_vfs_job_enumerate_done (job); }
/* *** read_close () *** */ static void close_read_ready (GObject *source_object, GAsyncResult *result, gpointer user_data) { GInputStream *stream; GVfsJob *job; GError *error; gboolean res; job = G_VFS_JOB (user_data); stream = G_INPUT_STREAM (source_object); res = g_input_stream_close_finish (stream, result, &error); if (res == FALSE) { g_vfs_job_failed_literal (G_VFS_JOB (job), error->domain, error->code, error->message); g_error_free (error); } else g_vfs_job_succeeded (job); g_object_unref (stream); }
static gboolean try_seek_on_read (GVfsBackend *backend, GVfsJobSeekRead *job, GVfsBackendHandle handle, goffset offset, GSeekType type) { GInputStream *stream; GError *error = NULL; stream = G_INPUT_STREAM (handle); if (!g_seekable_seek (G_SEEKABLE (stream), offset, type, G_VFS_JOB (job)->cancellable, &error)) { g_vfs_job_failed_literal (G_VFS_JOB (job), error->domain, error->code, error->message); g_error_free (error); return FALSE; } else { g_vfs_job_seek_read_set_offset (job, g_seekable_tell (G_SEEKABLE (stream))); g_vfs_job_succeeded (G_VFS_JOB (job)); } return TRUE; }
/* *** read () *** */ static void read_ready (GObject *source_object, GAsyncResult *result, gpointer user_data) { GInputStream *stream; GVfsJob *job; GError *error; gssize nread; stream = G_INPUT_STREAM (source_object); error = NULL; job = G_VFS_JOB (user_data); nread = g_input_stream_read_finish (stream, result, &error); if (nread < 0) { g_vfs_job_failed_literal (G_VFS_JOB (job), error->domain, error->code, error->message); g_error_free (error); return; } g_vfs_job_read_set_size (G_VFS_JOB_READ (job), nread); g_vfs_job_succeeded (job); }
static gboolean trash_backend_delete (GVfsBackend *vfs_backend, GVfsJobDelete *job, const char *filename) { GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend); GError *error = NULL; g_debug ("before job: %d\n", G_OBJECT(job)->ref_count); if (filename[1] == '\0') g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, _("The trash folder may not be deleted")); else { gboolean is_toplevel; TrashItem *item; GFile *real; if (!backend->file_monitor && !backend->dir_monitor) trash_watcher_rescan (backend->watcher); real = trash_backend_get_file (backend, filename, &item, &is_toplevel, &error); if (real) { /* not interested in the 'real', but the item */ g_object_unref (real); if (!is_toplevel) g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, _("Items in the trash may not be modified")); else { if (trash_item_delete (item, &error)) { trash_backend_schedule_thaw (backend); g_vfs_job_succeeded (G_VFS_JOB (job)); trash_item_unref (item); return TRUE; } } trash_item_unref (item); } } g_vfs_job_failed_from_error (G_VFS_JOB (job), error); g_error_free (error); return TRUE; }
static void trash_backend_enumerate_non_root (GVfsBackendTrash *backend, GVfsJobEnumerate *job, const gchar *filename, GFileAttributeMatcher *attribute_matcher, GFileQueryInfoFlags flags) { GError *error = NULL; GFile *real; real = trash_backend_get_file (backend, filename, NULL, NULL, &error); if (real) { GFileEnumerator *enumerator; enumerator = g_file_enumerate_children (real, job->attributes, job->flags, G_VFS_JOB (job)->cancellable, &error); g_object_unref (real); if (enumerator) { GFileInfo *info; g_vfs_job_succeeded (G_VFS_JOB (job)); while ((info = g_file_enumerator_next_file (enumerator, G_VFS_JOB (job)->cancellable, &error))) { trash_backend_add_info (NULL, info, FALSE); g_vfs_job_enumerate_add_info (job, info); g_object_unref (info); } /* error from next_file? ignore. */ if (error) g_error_free (error); g_vfs_job_enumerate_done (job); g_object_unref (enumerator); return; } } g_vfs_job_failed_from_error (G_VFS_JOB (job), error); g_error_free (error); }
static gboolean try_mount (GVfsBackend *backend, GVfsJobMount *job, GMountSpec *mount_spec, GMountSource *mount_source, gboolean is_automount) { GVfsBackendHttp *op_backend; const char *uri_str; char *path; SoupURI *uri; GMountSpec *real_mount_spec; op_backend = G_VFS_BACKEND_HTTP (backend); uri = NULL; uri_str = g_mount_spec_get (mount_spec, "uri"); if (uri_str) uri = soup_uri_new (uri_str); g_debug ("+ try_mount: %s\n", uri_str ? uri_str : "(null)"); if (uri == NULL) { g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Invalid mount spec")); return TRUE; } real_mount_spec = g_mount_spec_new ("http"); g_mount_spec_set (real_mount_spec, "uri", uri_str); if (uri->path != NULL) { path = g_uri_unescape_string (uri->path, "/"); g_free (real_mount_spec->mount_prefix); real_mount_spec->mount_prefix = g_mount_spec_canonicalize_path (path); g_free (path); } g_vfs_backend_set_mount_spec (backend, real_mount_spec); op_backend->mount_base = uri; g_vfs_job_succeeded (G_VFS_JOB (job)); return TRUE; }
static gboolean try_mount (GVfsBackend *backend, GVfsJobMount *job, GMountSpec *mount_spec, GMountSource *mount_source, gboolean is_automount) { GVfsBackendAfpBrowse *afp_backend = G_VFS_BACKEND_AFP_BROWSE (backend); const char *host, *portstr, *user; guint16 port = 548; host = g_mount_spec_get (mount_spec, "host"); if (host == NULL) { g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("No hostname specified")); return TRUE; } portstr = g_mount_spec_get (mount_spec, "port"); if (portstr != NULL) { port = atoi (portstr); } afp_backend->addr = G_NETWORK_ADDRESS (g_network_address_new (host, port)); user = g_mount_spec_get (mount_spec, "user"); afp_backend->user = g_strdup (user); return FALSE; }
static void do_unmount (GVfsBackend *backend, GVfsJobUnmount *job, GMountUnmountFlags flags, GMountSource *mount_source) { GVfsBackendAfpBrowse *afp_backend = G_VFS_BACKEND_AFP_BROWSE (backend); if (!(flags & G_MOUNT_UNMOUNT_FORCE)) { g_vfs_afp_server_logout_sync (afp_backend->server, G_VFS_JOB (job)->cancellable, NULL); } g_vfs_job_succeeded (G_VFS_JOB (job)); }
static gboolean try_enumerate (GVfsBackend *backend, GVfsJobEnumerate *job, const char *filename, GFileAttributeMatcher *matcher, GFileQueryInfoFlags flags) { GFileInfo *info1, *info2; GList *l; g_print ("try_enumerate (%s)\n", filename); g_vfs_job_succeeded (G_VFS_JOB (job)); info1 = g_file_info_new (); info2 = g_file_info_new (); g_file_info_set_name (info1, "file1"); g_file_info_set_file_type (info1, G_FILE_TYPE_REGULAR); g_file_info_set_name (info2, "file2"); g_file_info_set_file_type (info2, G_FILE_TYPE_REGULAR); l = NULL; l = g_list_append (l, info1); l = g_list_append (l, info2); g_vfs_job_enumerate_add_infos (job, l); g_list_free (l); g_object_unref (info1); g_object_unref (info2); g_vfs_job_enumerate_done (job); return TRUE; }
static gboolean trash_backend_query_fs_info (GVfsBackend *vfs_backend, GVfsJobQueryFsInfo *job, const char *filename, GFileInfo *info, GFileAttributeMatcher *matcher) { g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, "trash"); g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_REMOTE, FALSE); g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_READONLY, FALSE); g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_FILESYSTEM_USE_PREVIEW, G_FILESYSTEM_PREVIEW_TYPE_IF_LOCAL); g_vfs_job_succeeded (G_VFS_JOB (job)); return TRUE; }
static gboolean try_query_info (GVfsBackend *backend, GVfsJobQueryInfo *job, const char *filename, GFileQueryInfoFlags flags, GFileInfo *info, GFileAttributeMatcher *attribute_matcher) { SoupMessage *msg; SoupURI *uri; if (g_file_attribute_matcher_matches_only (attribute_matcher, G_FILE_ATTRIBUTE_THUMBNAIL_PATH)) { g_vfs_job_succeeded (G_VFS_JOB (job)); return TRUE; } uri = http_backend_get_mount_base (backend); msg = soup_message_new_from_uri (SOUP_METHOD_HEAD, uri); http_backend_queue_message (backend, msg, query_info_ready, job); return TRUE; }
/* *** open_read () *** */ static void open_for_read_ready (GObject *source_object, GAsyncResult *result, gpointer user_data) { GInputStream *stream; GVfsJob *job; SoupMessage *msg; gboolean res; gboolean can_seek; GError *error; stream = G_INPUT_STREAM (source_object); error = NULL; job = G_VFS_JOB (user_data); res = g_vfs_http_input_stream_send_finish (stream, result, &error); if (res == FALSE) { g_vfs_job_failed_literal (G_VFS_JOB (job), error->domain, error->code, error->message); g_error_free (error); g_object_unref (stream); return; } msg = g_vfs_http_input_stream_get_message (stream); if (!SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { http_job_failed (G_VFS_JOB (job), msg); g_object_unref (msg); g_object_unref (stream); return; } g_object_unref (msg); can_seek = G_IS_SEEKABLE (stream) && g_seekable_can_seek (G_SEEKABLE (stream)); g_vfs_job_open_for_read_set_can_seek (G_VFS_JOB_OPEN_FOR_READ (job), can_seek); g_vfs_job_open_for_read_set_handle (G_VFS_JOB_OPEN_FOR_READ (job), stream); g_vfs_job_succeeded (job); }
/* ======================= method implementations ======================= */ static gboolean trash_backend_open_for_read (GVfsBackend *vfs_backend, GVfsJobOpenForRead *job, const char *filename) { GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend); GError *error = NULL; if (filename[1] == '\0') g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_IS_DIRECTORY, _("Can't open directory")); else { GFile *real; if (!backend->file_monitor && !backend->dir_monitor) trash_watcher_rescan (backend->watcher); real = trash_backend_get_file (backend, filename, NULL, NULL, &error); if (real) { GFileInputStream *stream; stream = g_file_read (real, G_VFS_JOB (job)->cancellable, &error); g_object_unref (real); if (stream) { g_vfs_job_open_for_read_set_handle (job, stream); g_vfs_job_open_for_read_set_can_seek (job, TRUE); g_vfs_job_succeeded (G_VFS_JOB (job)); return TRUE; } } } g_vfs_job_failed_from_error (G_VFS_JOB (job), error); g_error_free (error); return TRUE; }
static gboolean try_mount (GVfsBackend *backend, GVfsJobMount *job, GMountSpec *mount_spec, GMountSource *mount_source, gboolean is_automount) { g_vfs_job_succeeded (G_VFS_JOB (job)); return TRUE; }
static gboolean recent_backend_delete (GVfsBackend *vfs_backend, GVfsJobDelete *job, const char *filename) { GVfsBackendRecent *backend = G_VFS_BACKEND_RECENT (vfs_backend); GError *error = NULL; g_debug ("before job: %d\n", G_OBJECT(job)->ref_count); if (filename[1] == '\0') { g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_PERMISSION_DENIED, _("The recent folder may not be deleted")); } else { RecentItem *item; item = g_hash_table_lookup (backend->items, filename + 1); if (item) { gboolean res; res = gtk_recent_manager_remove_item (backend->recent_manager, item->uri, &error); if (res) { g_vfs_job_succeeded (G_VFS_JOB (job)); return TRUE; } } else g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("No such file or directory")); } g_vfs_job_failed_from_error (G_VFS_JOB (job), error); g_error_free (error); return TRUE; }
static gboolean try_open_for_read (GVfsBackend *backend, GVfsJobOpenForRead *job, const char *filename) { SoupURI *uri; uri = http_backend_get_mount_base (backend); http_backend_open_for_read (backend, G_VFS_JOB (job), uri); return TRUE; }
static gboolean try_query_fs_info (GVfsBackend *backend, GVfsJobQueryFsInfo *job, const char *filename, GFileInfo *info, GFileAttributeMatcher *matcher) { g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_FILESYSTEM_TYPE, "http"); g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_FILESYSTEM_REMOTE, TRUE); g_vfs_job_succeeded (G_VFS_JOB (job)); return TRUE; }
static gboolean try_mount_mountable (GVfsBackend *backend, GVfsJobMountMountable *job, const char *filename, GMountSource *mount_source) { GVfsBackendAfpBrowse *afp_backend = G_VFS_BACKEND_AFP_BROWSE (backend); if (is_root (filename)) { g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_MOUNTABLE_FILE, _("The file is not a mountable")); return TRUE; } update_cache (afp_backend, G_VFS_JOB (job)->cancellable, mount_mountable_cb, job); return TRUE; }
static gboolean try_enumerate (GVfsBackend *backend, GVfsJobEnumerate *job, const char *filename, GFileAttributeMatcher *attribute_matcher, GFileQueryInfoFlags flags) { GVfsBackendAfpBrowse *afp_backend = G_VFS_BACKEND_AFP_BROWSE (backend); if (!is_root(filename)) { g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("File doesn't exist")); return TRUE; } update_cache (afp_backend, G_VFS_JOB (job)->cancellable, enumerate_cache_updated_cb, job); return TRUE; }
static gboolean trash_backend_close_read (GVfsBackend *backend, GVfsJobCloseRead *job, GVfsBackendHandle handle) { GError *error = NULL; if (g_input_stream_close (handle, G_VFS_JOB (job)->cancellable, &error)) { g_vfs_job_succeeded (G_VFS_JOB (job)); g_object_unref (handle); return TRUE; } g_object_unref (handle); g_vfs_job_failed_from_error (G_VFS_JOB (job), error); g_error_free (error); return TRUE; }
static gboolean trash_backend_seek_on_read (GVfsBackend *backend, GVfsJobSeekRead *job, GVfsBackendHandle handle, goffset offset, GSeekType type) { GError *error = NULL; if (g_seekable_seek (handle, offset, type, NULL, &error)) { g_vfs_job_seek_read_set_offset (job, g_seekable_tell (handle)); g_vfs_job_succeeded (G_VFS_JOB (job)); return TRUE; } g_vfs_job_failed_from_error (G_VFS_JOB (job), error); g_error_free (error); return TRUE; }
static void trash_backend_enumerate_root (GVfsBackendTrash *backend, GVfsJobEnumerate *job, GFileAttributeMatcher *attribute_matcher, GFileQueryInfoFlags flags) { GList *items, *node; g_vfs_job_succeeded (G_VFS_JOB (job)); items = trash_root_get_items (backend->root); for (node = items; node; node = node->next) { TrashItem *item = node->data; GFileInfo *info; info = g_file_query_info (trash_item_get_file (item), job->attributes, flags, G_VFS_JOB (job)->cancellable, NULL); if (info) { g_file_info_set_attribute_mask (info, attribute_matcher); g_file_info_set_name (info, trash_item_get_escaped_name (item)); trash_backend_add_info (item, info, TRUE); g_vfs_job_enumerate_add_info (job, info); g_object_unref (info); } trash_item_unref (item); } g_vfs_job_enumerate_done (job); g_list_free (items); }
static gboolean recent_backend_enumerate (GVfsBackend *vfs_backend, GVfsJobEnumerate *job, const char *filename, GFileAttributeMatcher *attribute_matcher, GFileQueryInfoFlags flags) { GVfsBackendRecent *backend = G_VFS_BACKEND_RECENT (vfs_backend); GHashTableIter iter; gpointer key, value; g_assert (filename[0] == '/'); g_vfs_job_succeeded (G_VFS_JOB (job)); g_hash_table_iter_init (&iter, backend->items); while (g_hash_table_iter_next (&iter, &key, &value)) { RecentItem *item = value; GFileInfo *info; info = g_file_query_info (item->file, job->attributes, flags, G_VFS_JOB (job)->cancellable, NULL); if (info) { g_file_info_set_attribute_mask (info, attribute_matcher); recent_backend_add_info (item, info); g_vfs_job_enumerate_add_info (job, info); g_object_unref (info); } } g_vfs_job_enumerate_done (job); return TRUE; }
static void mount_mountable_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { GVfsBackendAfpBrowse *afp_backend = G_VFS_BACKEND_AFP_BROWSE (source_object); GVfsJobMountMountable *job = G_VFS_JOB_MOUNT_MOUNTABLE (user_data); GError *err; GVfsAfpVolumeData *vol_data; GMountSpec *mount_spec; if (!update_cache_finish (afp_backend, res, &err)) { g_vfs_job_failed_from_error (G_VFS_JOB (job), err); g_error_free (err); return; } vol_data = find_volume (afp_backend, job->filename); if (!vol_data) { g_vfs_job_failed (G_VFS_JOB (job), G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("File doesn't exist")); return; } mount_spec = g_mount_spec_new ("afp-volume"); g_mount_spec_set (mount_spec, "host", g_network_address_get_hostname (G_NETWORK_ADDRESS (afp_backend->addr))); g_mount_spec_set (mount_spec, "volume", vol_data->name); g_mount_spec_set (mount_spec, "user", afp_backend->logged_in_user); g_vfs_job_mount_mountable_set_target (job, mount_spec, "/", TRUE); g_mount_spec_unref (mount_spec); g_vfs_job_succeeded (G_VFS_JOB (job)); }