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)); } }
gboolean ostree_zlib_file_header_parse (GVariant *metadata, GFileInfo **out_file_info, GVariant **out_xattrs, GError **error) { gboolean ret = FALSE; guint64 size; guint32 uid, gid, mode, rdev; const char *symlink_target; ot_lobj GFileInfo *ret_file_info = NULL; ot_lvariant GVariant *ret_xattrs = NULL; g_variant_get (metadata, "(tuuuu&s@a(ayay))", &size, &uid, &gid, &mode, &rdev, &symlink_target, &ret_xattrs); size = GUINT64_FROM_BE (size); uid = GUINT32_FROM_BE (uid); gid = GUINT32_FROM_BE (gid); mode = GUINT32_FROM_BE (mode); rdev = GUINT32_FROM_BE (rdev); ret_file_info = g_file_info_new (); g_file_info_set_size (ret_file_info, size); g_file_info_set_attribute_uint32 (ret_file_info, "standard::type", ot_gfile_type_for_mode (mode)); g_file_info_set_attribute_boolean (ret_file_info, "standard::is-symlink", S_ISLNK (mode)); g_file_info_set_attribute_uint32 (ret_file_info, "unix::uid", uid); g_file_info_set_attribute_uint32 (ret_file_info, "unix::gid", gid); g_file_info_set_attribute_uint32 (ret_file_info, "unix::mode", mode); if (S_ISREG (mode)) { ; } else if (S_ISLNK (mode)) { g_file_info_set_attribute_byte_string (ret_file_info, "standard::symlink-target", symlink_target); } else if (S_ISCHR (mode) || S_ISBLK (mode)) { g_file_info_set_attribute_uint32 (ret_file_info, "unix::rdev", rdev); } else if (S_ISFIFO (mode)) { ; } else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Corrupted archive file; invalid mode %u", mode); goto out; } ret = TRUE; ot_transfer_out_value(out_file_info, &ret_file_info); ot_transfer_out_value(out_xattrs, &ret_xattrs); out: return ret; }
static void list_photos_ready_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { DialogData *data = user_data; GError *error = NULL; GList *list; GList *scan; gth_task_dialog (GTH_TASK (data->service), TRUE, NULL); _g_object_list_unref (data->photos); data->photos = flickr_service_list_photos_finish (data->service, result, &error); if (error != NULL) { if (data->service != NULL) gth_task_dialog (GTH_TASK (data->service), TRUE, NULL); _gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->browser), _("Could not get the photo list"), error); g_clear_error (&error); gtk_widget_destroy (data->dialog); return; } list = NULL; for (scan = data->photos; scan; scan = scan->next) { FlickrPhoto *photo = scan->data; GthFileData *file_data; if (photo->url[FLICKR_URL_O] == NULL) continue; file_data = gth_file_data_new_for_uri (photo->url[FLICKR_URL_O], (photo->mime_type != NULL) ? photo->mime_type : "image/jpeg"); g_file_info_set_file_type (file_data->info, G_FILE_TYPE_REGULAR); g_file_info_set_size (file_data->info, FAKE_SIZE); /* set a fake size to make the progress dialog work correctly */ g_file_info_set_attribute_object (file_data->info, "flickr::object", G_OBJECT (photo)); list = g_list_prepend (list, file_data); } gth_file_list_set_files (GTH_FILE_LIST (data->file_list), list); update_selection_status (data); gtk_widget_set_sensitive (GET_WIDGET ("download_button"), list != NULL); _g_object_list_unref (list); }
static void list_photos_ready_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { DialogData *data = user_data; GError *error = NULL; GList *list; GList *scan; gth_task_dialog (GTH_TASK (data->service), TRUE, NULL); _g_object_list_unref (data->photos); data->photos = facebook_service_list_photos_finish (data->service, result, &error); if (error != NULL) { if (data->service != NULL) gth_task_dialog (GTH_TASK (data->service), TRUE, NULL); _gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->browser), _("Could not get the photo list"), error); g_clear_error (&error); gtk_widget_destroy (data->dialog); return; } list = NULL; for (scan = data->photos; scan; scan = scan->next) { FacebookPhoto *photo = scan->data; GthFileData *file_data; file_data = gth_file_data_new_for_uri (facebook_photo_get_original_url (photo), "image/jpeg"); g_file_info_set_file_type (file_data->info, G_FILE_TYPE_REGULAR); g_file_info_set_size (file_data->info, FAKE_SIZE); /* set a fake size to make the progress dialog work correctly */ g_file_info_set_attribute_object (file_data->info, "facebook::object", G_OBJECT (photo)); list = g_list_prepend (list, file_data); } gth_file_list_set_files (GTH_FILE_LIST (data->file_list), list); update_selection_status (data); gtk_dialog_set_response_sensitive (GTK_DIALOG (data->dialog), GTK_RESPONSE_OK, list != NULL); _g_object_list_unref (list); }
static void list_photos_ready_cb (GObject *source_object, GAsyncResult *result, gpointer user_data) { DialogData *data = user_data; PicasaWebService *picasaweb = PICASA_WEB_SERVICE (source_object); GError *error = NULL; GList *list; GList *scan; gth_task_dialog (GTH_TASK (data->service), TRUE, NULL); _g_object_list_unref (data->photos); data->photos = picasa_web_service_list_albums_finish (picasaweb, result, &error); if (error != NULL) { gth_task_dialog (GTH_TASK (data->service), TRUE, NULL); _gtk_error_dialog_from_gerror_show (GTK_WINDOW (data->browser), _("Could not get the photo list"), error); g_clear_error (&error); gtk_widget_destroy (data->dialog); return; } list = NULL; for (scan = data->photos; scan; scan = scan->next) { PicasaWebPhoto *photo = scan->data; GthFileData *file_data; file_data = gth_file_data_new_for_uri (photo->uri, photo->mime_type); g_file_info_set_file_type (file_data->info, G_FILE_TYPE_REGULAR); g_file_info_set_size (file_data->info, photo->size); g_file_info_set_attribute_object (file_data->info, "gphoto::object", G_OBJECT (photo)); list = g_list_prepend (list, file_data); } gth_file_list_set_files (GTH_FILE_LIST (data->file_list), list); update_selection_status (data); gtk_dialog_set_response_sensitive (GTK_DIALOG (data->dialog), GTK_RESPONSE_OK, TRUE); _g_object_list_unref (list); }
static GFileInfo * g_resource_file_query_info (GFile *file, const char *attributes, GFileQueryInfoFlags flags, GCancellable *cancellable, GError **error) { GResourceFile *resource = G_RESOURCE_FILE (file); GError *my_error = NULL; GFileInfo *info; GFileAttributeMatcher *matcher; gboolean res; gsize size; guint32 resource_flags; char **children; gboolean is_dir; char *base; is_dir = FALSE; children = g_resources_enumerate_children (resource->path, 0, NULL); if (children != NULL) { g_strfreev (children); is_dir = TRUE; } /* root is always there */ if (strcmp ("/", resource->path) == 0) is_dir = TRUE; if (!is_dir) { res = g_resources_get_info (resource->path, 0, &size, &resource_flags, &my_error); if (!res) { if (g_error_matches (my_error, G_RESOURCE_ERROR, G_RESOURCE_ERROR_NOT_FOUND)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND, _("The resource at '%s' does not exist"), resource->path); } else g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, my_error->message); g_clear_error (&my_error); return FALSE; } } matcher = g_file_attribute_matcher_new (attributes); info = g_file_info_new (); base = g_resource_file_get_basename (file); g_file_info_set_name (info, base); _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_READ, TRUE); _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_WRITE, FALSE); _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_EXECUTE, FALSE); _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_RENAME, FALSE); _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_DELETE, FALSE); _g_file_info_set_attribute_boolean_by_id (info, G_FILE_ATTRIBUTE_ID_ACCESS_CAN_TRASH, FALSE); if (is_dir) { g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY); } else { GBytes *bytes; char *content_type; g_file_info_set_file_type (info, G_FILE_TYPE_REGULAR); g_file_info_set_size (info, size); if ((_g_file_attribute_matcher_matches_id (matcher, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE) || ((~resource_flags & G_RESOURCE_FLAGS_COMPRESSED) && _g_file_attribute_matcher_matches_id (matcher, G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE))) && (bytes = g_resources_lookup_data (resource->path, 0, NULL))) { const guchar *data; gsize data_size; data = g_bytes_get_data (bytes, &data_size); content_type = g_content_type_guess (base, data, data_size, NULL); g_bytes_unref (bytes); } else content_type = NULL; if (content_type) { _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_CONTENT_TYPE, content_type); _g_file_info_set_attribute_string_by_id (info, G_FILE_ATTRIBUTE_ID_STANDARD_FAST_CONTENT_TYPE, content_type); g_free (content_type); } } g_free (base); g_file_attribute_matcher_unref (matcher); return info; }
static void file_info_from_message (SoupMessage *msg, GFileInfo *info, GFileAttributeMatcher *matcher) { const char *text; GHashTable *params; char *basename; char *ed_name; basename = ed_name = NULL; /* prefer the filename from the Content-Disposition (rfc2183) header if one if present. See bug 551298. */ if (soup_message_headers_get_content_disposition (msg->response_headers, NULL, ¶ms)) { const char *name = g_hash_table_lookup (params, "filename"); if (name) basename = g_strdup (name); g_hash_table_destroy (params); } if (basename == NULL) { const SoupURI *uri; uri = soup_message_get_uri (msg); basename = http_uri_get_basename (uri->path); } g_debug ("basename:%s\n", basename); /* read http/1.1 rfc, until then we copy the local files * behaviour */ if (basename != NULL && (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME) || g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_STANDARD_EDIT_NAME))) ed_name = gvfs_file_info_populate_names_as_local (info, basename); g_free (basename); g_free (ed_name); if (soup_message_headers_get_encoding (msg->response_headers) == SOUP_ENCODING_CONTENT_LENGTH) { goffset start, end, length; gboolean ret; ret = soup_message_headers_get_content_range (msg->response_headers, &start, &end, &length); if (ret && length != -1) { g_file_info_set_size (info, length); } else if (!ret) { length = soup_message_headers_get_content_length (msg->response_headers); g_file_info_set_size (info, length); } } g_file_info_set_file_type (info, G_FILE_TYPE_REGULAR); text = soup_message_headers_get_content_type (msg->response_headers, NULL); if (text) { GIcon *icon; g_file_info_set_content_type (info, text); g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_FAST_CONTENT_TYPE, text); icon = g_content_type_get_icon (text); g_file_info_set_icon (info, icon); g_object_unref (icon); icon = g_content_type_get_symbolic_icon (text); g_file_info_set_symbolic_icon (info, icon); g_object_unref (icon); } text = soup_message_headers_get_one (msg->response_headers, "Last-Modified"); if (text) { SoupDate *sd; GTimeVal tv; sd = soup_date_new_from_string(text); if (sd) { soup_date_to_timeval (sd, &tv); g_file_info_set_modification_time (info, &tv); soup_date_free (sd); } } text = soup_message_headers_get_one (msg->response_headers, "ETag"); if (text) { g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_ETAG_VALUE, text); } }
static gboolean dispatch_open_splice_and_close (OstreeRepo *repo, StaticDeltaExecutionState *state, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; if (!open_output_target (state, cancellable, error)) goto out; if (OSTREE_OBJECT_TYPE_IS_META (state->output_objtype)) { g_autoptr(GVariant) metadata = NULL; guint64 offset; guint64 length; if (!read_varuint64 (state, &length, error)) goto out; if (!read_varuint64 (state, &offset, error)) goto out; if (!validate_ofs (state, offset, length, error)) goto out; if (state->stats_only) { ret = TRUE; goto out; } metadata = g_variant_new_from_data (ostree_metadata_variant_type (state->output_objtype), state->payload_data + offset, length, TRUE, NULL, NULL); { g_autofree guchar *actual_csum = NULL; if (!ostree_repo_write_metadata (state->repo, state->output_objtype, state->checksum, metadata, &actual_csum, cancellable, error)) goto out; } } else { guint64 content_offset; guint64 objlen; g_autoptr(GInputStream) object_input = NULL; g_autoptr(GInputStream) memin = NULL; if (!do_content_open_generic (repo, state, cancellable, error)) goto out; if (!read_varuint64 (state, &state->content_size, error)) goto out; if (!read_varuint64 (state, &content_offset, error)) goto out; if (!validate_ofs (state, content_offset, state->content_size, error)) goto out; if (state->stats_only) { ret = TRUE; goto out; } /* Fast path for regular files to bare repositories */ if (S_ISREG (state->mode) && (repo->mode == OSTREE_REPO_MODE_BARE || repo->mode == OSTREE_REPO_MODE_BARE_USER)) { if (!_ostree_repo_open_content_bare (repo, state->checksum, state->content_size, &state->barecommitstate, &state->content_out, &state->have_obj, cancellable, error)) goto out; if (!state->have_obj) { if (!handle_untrusted_content_checksum (repo, state, cancellable, error)) goto out; if (!content_out_write (repo, state, state->payload_data + content_offset, state->content_size, cancellable, error)) goto out; } } else { /* Slower path, for symlinks and unpacking deltas into archive-z2 */ g_autoptr(GFileInfo) finfo = NULL; finfo = _ostree_header_gfile_info_new (state->mode, state->uid, state->gid); if (S_ISLNK (state->mode)) { g_autofree char *nulterminated_target = g_strndup ((char*)state->payload_data + content_offset, state->content_size); g_file_info_set_symlink_target (finfo, nulterminated_target); } else { g_assert (S_ISREG (state->mode)); g_file_info_set_size (finfo, state->content_size); memin = g_memory_input_stream_new_from_data (state->payload_data + content_offset, state->content_size, NULL); } if (!ostree_raw_file_to_content_stream (memin, finfo, state->xattrs, &object_input, &objlen, cancellable, error)) goto out; { g_autofree guchar *actual_csum = NULL; if (!ostree_repo_write_content (state->repo, state->checksum, object_input, objlen, &actual_csum, cancellable, error)) goto out; } } } if (!dispatch_close (repo, state, cancellable, error)) goto out; ret = TRUE; out: if (state->stats_only) (void) dispatch_close (repo, state, cancellable, NULL); if (!ret) g_prefix_error (error, "opcode open-splice-and-close: "); return ret; }
static gboolean fl_parser_fill_file_info (GFileInfo *info, const char **attr) { gint i; for (i = 0; attr[i]; ++i) { const gchar *name; const gchar *value; name = attr[i]; value = attr[++i]; if (strcmp (name, "name") == 0) { char *display_name; /* Apparently someone decided it was a good idea * to send name="" mem-type="MMC" */ if (!value || strcmp (value, "") == 0) { return FALSE; } g_file_info_set_name (info, value); display_name = g_filename_display_name (value); g_file_info_set_display_name (info, display_name); d(g_print ("Name: '%s'\n", display_name)); g_free (display_name); } else if (strcmp (name, "size") == 0) { g_file_info_set_size (info, strtoll (value, NULL, 10)); d(g_print ("Size: '%"G_GINT64_FORMAT"'\n", g_file_info_get_size (info))); } else if (strcmp (name, "modified") == 0) { GTimeVal time; if (g_time_val_from_iso8601 (value, &time) == FALSE) continue; g_file_info_set_modification_time (info, &time); d(g_print ("Modified: '%s' = '%d'\n", value, (int)time.tv_sec)); } else if (strcmp (name, "created") == 0) { GTimeVal time; if (g_time_val_from_iso8601 (value, &time) == FALSE) continue; g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_CREATED, time.tv_sec); g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_CREATED_USEC, time.tv_usec); d(g_print ("Created: '%s' = '%d'\n", value, (int)time.tv_sec)); } else if (strcmp (name, "accessed") == 0) { GTimeVal time; if (g_time_val_from_iso8601 (value, &time) == FALSE) continue; g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_TIME_ACCESS, time.tv_sec); g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_TIME_ACCESS_USEC, time.tv_usec); d(g_print ("Accessed: '%s' = '%d'\n", value, (int)time.tv_sec)); } else if (strcmp (name, "user-perm") == 0) { /* The permissions don't map well to unix semantics, * since the user is most likely not the same on both * sides. We map the user permissions to "other" on the * local side. D is treated as write, otherwise files * can't be deleted through the module, even if it * should be possible. */ if (strstr (value, "R")) { g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_READ, TRUE); } if (strstr (value, "W") || strstr (value, "D")) { g_file_info_set_attribute_boolean (info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, TRUE); } } else if (strcmp (name, "group-perm") == 0) { /* Ignore for now */ d(g_print ("Group permissions: '%s'\n", value)); } else if (strcmp (name, "other-perm") == 0) { /* Ignore for now */ d(g_print ("Other permissions: '%s'\n", value)); } else if (strcmp (name, "owner") == 0) { /* Ignore for now */ d(g_print ("Owner: '%s'\n", value)); } else if (strcmp (name, "group") == 0) { /* Ignore for now */ d(g_print ("Group: '%s'\n", value)); } else if (strcmp (name, "type") == 0) { g_file_info_set_content_type (info, value); d(g_print ("Mime-Type: '%s'\n", value)); } else if (strcmp (name, "xml:lang") == 0) { d(g_print ("Lang: '%s'\n", value)); } else if (strcmp (name, "mem-type") == 0) { guint device; if (value == NULL || value[0] == '\0') continue; device = om_mem_type_id_from_string (value); g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_RDEV, device); d(g_print ("Mem-Type: '%s' (%d)\n", value, device)); } else { d(g_print ("Unknown Attribute: %s = %s\n", name, value)); } } if (g_file_info_get_name (info) == NULL) { /* Required attribute */ /* Set error */ return FALSE; } return TRUE; }
gboolean ostree_content_stream_parse (gboolean compressed, GInputStream *input, guint64 input_length, gboolean trusted, GInputStream **out_input, GFileInfo **out_file_info, GVariant **out_xattrs, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; guint32 archive_header_size; guchar dummy[4]; gsize bytes_read; ot_lobj GInputStream *ret_input = NULL; ot_lobj GFileInfo *content_file_info = NULL; ot_lobj GFileInfo *ret_file_info = NULL; ot_lvariant GVariant *ret_xattrs = NULL; ot_lvariant GVariant *file_header = NULL; ot_lfree guchar *buf = NULL; if (!g_input_stream_read_all (input, &archive_header_size, 4, &bytes_read, cancellable, error)) goto out; archive_header_size = GUINT32_FROM_BE (archive_header_size); if (archive_header_size > input_length) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "File header size %u exceeds size %" G_GUINT64_FORMAT, (guint)archive_header_size, input_length); goto out; } if (archive_header_size == 0) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "File header size is zero"); goto out; } /* Skip over padding */ if (!g_input_stream_read_all (input, dummy, 4, &bytes_read, cancellable, error)) goto out; buf = g_malloc (archive_header_size); if (!g_input_stream_read_all (input, buf, archive_header_size, &bytes_read, cancellable, error)) goto out; file_header = g_variant_new_from_data (compressed ? OSTREE_ZLIB_FILE_HEADER_GVARIANT_FORMAT : OSTREE_FILE_HEADER_GVARIANT_FORMAT, buf, archive_header_size, trusted, g_free, buf); buf = NULL; if (compressed) { if (!ostree_zlib_file_header_parse (file_header, out_file_info ? &ret_file_info : NULL, out_xattrs ? &ret_xattrs : NULL, error)) goto out; } else { if (!ostree_file_header_parse (file_header, out_file_info ? &ret_file_info : NULL, out_xattrs ? &ret_xattrs : NULL, error)) goto out; if (ret_file_info) g_file_info_set_size (ret_file_info, input_length - archive_header_size - 8); } if (g_file_info_get_file_type (ret_file_info) == G_FILE_TYPE_REGULAR && out_input) { /* Give the input stream at its current position as return value; * assuming the caller doesn't seek, this should be fine. We might * want to wrap it though in a non-seekable stream. **/ if (compressed) { ot_lobj GConverter *zlib_decomp = (GConverter*)g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_RAW); ret_input = g_converter_input_stream_new (input, zlib_decomp); } else ret_input = g_object_ref (input); } ret = TRUE; ot_transfer_out_value (out_input, &ret_input); ot_transfer_out_value (out_file_info, &ret_file_info); ot_transfer_out_value (out_xattrs, &ret_xattrs); out: return ret; }
static gboolean g_vfs_ftp_dir_cache_funcs_process (GInputStream * stream, int debug_id, const GVfsFtpFile * dir, GVfsFtpDirCacheEntry *entry, gboolean is_unix, GCancellable * cancellable, GError ** error) { struct list_state state = { NULL, }; GDataInputStream *data; GFileInfo *info; int type; GVfsFtpFile *file; char *line, *s; gsize length; /* protect against code reorg - in current code, error never is NULL */ g_assert (error != NULL); g_assert (*error == NULL); data = g_data_input_stream_new (stream); /* we use LF only, because the mozilla code can handle lines ending in CR */ g_data_input_stream_set_newline_type (data, G_DATA_STREAM_NEWLINE_TYPE_LF); while ((line = g_data_input_stream_read_line (data, &length, cancellable, error))) { struct list_result result = { 0, }; GFileType file_type = G_FILE_TYPE_UNKNOWN; GTimeVal tv = { 0, 0 }; /* strip trailing \r - ParseFTPList only removes it if the line ends in \r\n, * but we stripped the \n already. */ if (length > 0 && line[length - 1] == '\r') line[--length] = '\0'; g_debug ("<<%2d << %s\n", debug_id, line); type = ParseFTPList (line, &state, &result); if (type != 'd' && type != 'f' && type != 'l') { g_free (line); continue; } /* don't list . and .. directories * Let's hope they're not important files on some ftp servers */ if (result.fe_fnlen == 1 && result.fe_fname[0] == '.') { g_free (line); continue; } if (result.fe_fnlen == 2 && result.fe_fname[0] == '.' && result.fe_fname[1] == '.') { g_free (line); continue; } s = g_strndup (result.fe_fname, result.fe_fnlen); file = g_vfs_ftp_file_new_child (dir, s, NULL); g_free (s); if (file == NULL) { g_debug ("# invalid filename, skipping"); g_free (line); continue; } info = g_file_info_new (); s = g_path_get_basename (g_vfs_ftp_file_get_gvfs_path (file)); g_file_info_set_name (info, s); g_free (s); if (type == 'l') { char *link; link = g_strndup (result.fe_lname, result.fe_lnlen); g_file_info_set_symlink_target (info, link); g_file_info_set_is_symlink (info, TRUE); g_free (link); } g_file_info_set_size (info, g_ascii_strtoull (result.fe_size, NULL, 10)); /* If unix format then parse the attributes */ if (state.lstyle == 'U') { char file_mode[10], uid[64], gid[64]; guint32 mode; /* POSIX ls -l form: mode, links, owner, group */ if (sscanf(line, "%10c %*u %63s %63s", file_mode, uid, gid) == 3) { if (g_vfs_ftp_parse_mode (file_mode, &mode, &file_type)) { g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_UNIX_MODE, mode); g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_USER, uid); g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_OWNER_GROUP, gid); } } else g_debug ("# unknown listing format\n"); } if (file_type == G_FILE_TYPE_UNKNOWN) { file_type = type == 'f' ? G_FILE_TYPE_REGULAR : type == 'l' ? G_FILE_TYPE_SYMBOLIC_LINK : G_FILE_TYPE_DIRECTORY; } gvfs_file_info_populate_default (info, g_vfs_ftp_file_get_gvfs_path (file), file_type); if (is_unix) g_file_info_set_is_hidden (info, result.fe_fnlen > 0 && result.fe_fname[0] == '.'); /* Workaround: * result.fetime.tm_year contains actual year instead of offset-from-1900, * which mktime expects. */ if (result.fe_time.tm_year >= 1900) result.fe_time.tm_year -= 1900; tv.tv_sec = mktime (&result.fe_time); if (tv.tv_sec != -1) g_file_info_set_modification_time (info, &tv); g_vfs_ftp_dir_cache_entry_add (entry, file, info); g_free (line); } g_object_unref (data); return *error != NULL; }
static GFileInfo * g_vfs_ftp_dir_cache_funcs_lookup_uncached (GVfsFtpTask * task, const GVfsFtpFile *file) { GFileInfo *info; char **reply; if (g_vfs_ftp_file_is_root (file)) return create_root_file_info (task->backend); /* the directory cache fails when the parent directory of the file is not readable. * This cannot happen on Unix, but it can happen on FTP. * In this case we try to figure out as much as possible about the file (does it even exist?) * using standard ftp commands. */ if (g_vfs_ftp_task_send (task, 0, "CWD %s", g_vfs_ftp_file_get_ftp_path (file))) { char *tmp; info = g_file_info_new (); tmp = g_path_get_basename (g_vfs_ftp_file_get_gvfs_path (file)); g_file_info_set_name (info, tmp); g_free (tmp); gvfs_file_info_populate_default (info, g_vfs_ftp_file_get_gvfs_path (file), G_FILE_TYPE_DIRECTORY); g_file_info_set_is_hidden (info, TRUE); return info; } g_vfs_ftp_task_clear_error (task); if (g_vfs_ftp_task_send_and_check (task, 0, NULL, NULL, &reply, "SIZE %s", g_vfs_ftp_file_get_ftp_path (file))) { char *tmp; info = g_file_info_new (); tmp = g_path_get_basename (g_vfs_ftp_file_get_gvfs_path (file)); g_file_info_set_name (info, tmp); g_free (tmp); gvfs_file_info_populate_default (info, g_vfs_ftp_file_get_gvfs_path (file), G_FILE_TYPE_REGULAR); g_file_info_set_size (info, g_ascii_strtoull (reply[0] + 4, NULL, 0)); g_strfreev (reply); g_file_info_set_is_hidden (info, TRUE); return info; } g_vfs_ftp_task_clear_error (task); /* note that there might still be a file/directory, we just have * no way to figure this out (in particular on ftp servers that * don't support SIZE. * If you have ways to improve file detection, patches are welcome. */ return NULL; }