static OstreeRepoCommitFilterResult commit_filter (OstreeRepo *self, const char *path, GFileInfo *file_info, gpointer user_data) { GHashTable *mode_adds = user_data; gpointer value; if (opt_owner_uid >= 0) g_file_info_set_attribute_uint32 (file_info, "unix::uid", opt_owner_uid); if (opt_owner_gid >= 0) g_file_info_set_attribute_uint32 (file_info, "unix::gid", opt_owner_gid); if (mode_adds && g_hash_table_lookup_extended (mode_adds, path, NULL, &value)) { guint current_mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode"); guint mode_add = GPOINTER_TO_UINT (value); g_file_info_set_attribute_uint32 (file_info, "unix::mode", current_mode | mode_add); g_hash_table_remove (mode_adds, path); } return OSTREE_REPO_COMMIT_FILTER_ALLOW; }
static OstreeRepoCommitFilterResult commit_filter (OstreeRepo *repo, const char *path, GFileInfo *file_info, gpointer user_data) { guint current_mode; /* No user info */ g_file_info_set_attribute_uint32 (file_info, "unix::uid", 0); g_file_info_set_attribute_uint32 (file_info, "unix::gid", 0); /* No setuid */ current_mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode"); g_file_info_set_attribute_uint32 (file_info, "unix::mode", current_mode & ~07000); if (g_str_equal (path, "/") || g_str_equal (path, "/metadata") || g_str_has_prefix (path, "/files") || g_str_has_prefix (path, "/export")) { g_debug ("commit filter, allow: %s", path); return OSTREE_REPO_COMMIT_FILTER_ALLOW; } else { g_debug ("commit filter, skip: %s", path); return OSTREE_REPO_COMMIT_FILTER_SKIP; } }
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 OstreeRepoCommitFilterResult commit_filter (OstreeRepo *repo, const char *path, GFileInfo *file_info, CommitData *commit_data) { guint mode; /* No user info */ g_file_info_set_attribute_uint32 (file_info, "unix::uid", 0); g_file_info_set_attribute_uint32 (file_info, "unix::gid", 0); mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode"); /* No setuid */ mode = mode & ~07000; /* All files readable */ mode = mode | 0444; g_file_info_set_attribute_uint32 (file_info, "unix::mode", mode); if (matches_patterns (commit_data->exclude, path) && !matches_patterns (commit_data->include, path)) { g_debug ("Excluding %s", path); return OSTREE_REPO_COMMIT_FILTER_SKIP; } return OSTREE_REPO_COMMIT_FILTER_ALLOW; }
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 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 add_file_to_mtree (GFile *file, const char *name, OstreeRepo *repo, OstreeMutableTree *mtree, GCancellable *cancellable, GError **error) { g_autoptr(GFileInfo) file_info = NULL; g_autoptr(GInputStream) raw_input = NULL; g_autoptr(GInputStream) input = NULL; guint64 length; g_autofree guchar *child_file_csum = NULL; g_autofree char *tmp_checksum = NULL; file_info = g_file_query_info (file, "standard::size", 0, cancellable, error); if (file_info == NULL) return FALSE; g_file_info_set_name (file_info, name); g_file_info_set_file_type (file_info, G_FILE_TYPE_REGULAR); g_file_info_set_attribute_uint32 (file_info, "unix::uid", 0); g_file_info_set_attribute_uint32 (file_info, "unix::gid", 0); g_file_info_set_attribute_uint32 (file_info, "unix::mode", 0100644); raw_input = (GInputStream *) g_file_read (file, cancellable, error); if (raw_input == NULL) return FALSE; if (!ostree_raw_file_to_content_stream (raw_input, file_info, NULL, &input, &length, cancellable, error)) return FALSE; if (!ostree_repo_write_content (repo, NULL, input, length, &child_file_csum, cancellable, error)) return FALSE; tmp_checksum = ostree_checksum_from_bytes (child_file_csum); if (!ostree_mutable_tree_replace_file (mtree, name, tmp_checksum, error)) return FALSE; return TRUE; }
/** * Set unix mode of a file * @param fileinfo : a GFileInfo pointer obtained from an opened file * (GFile *) * @param meta : meta_data_t * structure that contains all meta data for * the corresponding file. */ void set_file_mode_to_gfile(GFileInfo *fileinfo, meta_data_t *meta) { if (fileinfo != NULL && meta != NULL) { print_debug(_("Setting mode: %d\n"), meta->mode); g_file_info_set_attribute_uint32(fileinfo, G_FILE_ATTRIBUTE_UNIX_MODE, meta->mode); } }
static OstreeRepoCommitFilterResult commit_filter (OstreeRepo *repo, const char *path, GFileInfo *file_info, CommitData *commit_data) { guint mode; /* No user info */ g_file_info_set_attribute_uint32 (file_info, "unix::uid", 0); g_file_info_set_attribute_uint32 (file_info, "unix::gid", 0); /* In flatpak, there is no real reason for files to have different * permissions based on the group or user really, everything is * always used readonly for everyone. Having things be writeable * for anyone but the user just causes risks for the system-installed * case. So, we canonicalize the mode to writable only by the user, * readable to all, and executable for all for directories and * files that the user can execute. */ mode = g_file_info_get_attribute_uint32 (file_info, "unix::mode"); if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_DIRECTORY) mode = 0755 | S_IFDIR; else if (g_file_info_get_file_type (file_info) == G_FILE_TYPE_REGULAR) { /* If use can execute, make executable by all */ if (mode & S_IXUSR) mode = 0755 | S_IFREG; else /* otherwise executable by none */ mode = 0644 | S_IFREG; } g_file_info_set_attribute_uint32 (file_info, "unix::mode", mode); if (matches_patterns (commit_data->exclude, path) && !matches_patterns (commit_data->include, path)) { g_debug ("Excluding %s", path); return OSTREE_REPO_COMMIT_FILTER_SKIP; } return OSTREE_REPO_COMMIT_FILTER_ALLOW; }
static GConverterResult g_zlib_decompressor_convert (GConverter *converter, const void *inbuf, gsize inbuf_size, void *outbuf, gsize outbuf_size, GConverterFlags flags, gsize *bytes_read, gsize *bytes_written, GError **error) { GZlibDecompressor *decompressor; int res; decompressor = G_ZLIB_DECOMPRESSOR (converter); decompressor->zstream.next_in = (void *)inbuf; decompressor->zstream.avail_in = inbuf_size; decompressor->zstream.next_out = outbuf; decompressor->zstream.avail_out = outbuf_size; res = inflate (&decompressor->zstream, Z_NO_FLUSH); if (res == Z_DATA_ERROR || res == Z_NEED_DICT) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_INVALID_DATA, _("Invalid compressed data")); return G_CONVERTER_ERROR; } if (res == Z_MEM_ERROR) { g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Not enough memory")); return G_CONVERTER_ERROR; } if (res == Z_STREAM_ERROR) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Internal error: %s"), decompressor->zstream.msg); return G_CONVERTER_ERROR; } if (res == Z_BUF_ERROR) { if (flags & G_CONVERTER_FLUSH) return G_CONVERTER_FLUSHED; /* Z_FINISH not set, so this means no progress could be made */ /* We do have output space, so this should only happen if we have no input but need some */ g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_PARTIAL_INPUT, _("Need more input")); return G_CONVERTER_ERROR; } g_assert (res == Z_OK || res == Z_STREAM_END); *bytes_read = inbuf_size - decompressor->zstream.avail_in; *bytes_written = outbuf_size - decompressor->zstream.avail_out; #if !defined (G_OS_WIN32) || ZLIB_VERNUM >= 0x1240 if (decompressor->header_data != NULL && decompressor->header_data->gzheader.done == 1) { HeaderData *data = decompressor->header_data; /* So we don't notify again */ data->gzheader.done = 2; data->file_info = g_file_info_new (); g_file_info_set_attribute_uint64 (data->file_info, G_FILE_ATTRIBUTE_TIME_MODIFIED, data->gzheader.time); g_file_info_set_attribute_uint32 (data->file_info, G_FILE_ATTRIBUTE_TIME_MODIFIED_USEC, 0); if (data->filename[0] != '\0') g_file_info_set_attribute_byte_string (data->file_info, G_FILE_ATTRIBUTE_STANDARD_NAME, data->filename); g_object_notify (G_OBJECT (decompressor), "file-info"); } #endif /* !G_OS_WIN32 || ZLIB >= 1.2.4 */ if (res == Z_STREAM_END) return G_CONVERTER_FINISHED; return G_CONVERTER_CONVERTED; }
static gboolean trash_backend_query_info (GVfsBackend *vfs_backend, GVfsJobQueryInfo *job, const char *filename, GFileQueryInfoFlags flags, GFileInfo *info, GFileAttributeMatcher *matcher) { GVfsBackendTrash *backend = G_VFS_BACKEND_TRASH (vfs_backend); g_assert (filename[0] == '/'); if (filename[1]) { GError *error = NULL; gboolean is_toplevel; TrashItem *item; GFile *real; real = trash_backend_get_file (backend, filename, &item, &is_toplevel, &error); if (real) { GFileInfo *real_info; real_info = g_file_query_info (real, job->attributes, flags, G_VFS_JOB (job)->cancellable, &error); g_object_unref (real); if (real_info) { g_file_info_copy_into (real_info, info); trash_backend_add_info (item, info, is_toplevel); g_vfs_job_succeeded (G_VFS_JOB (job)); trash_item_unref (item); g_object_unref (real_info); return TRUE; } trash_item_unref (item); } g_vfs_job_failed_from_error (G_VFS_JOB (job), error); g_error_free (error); } else { GIcon *icon; int n_items; n_items = trash_root_get_n_items (backend->root); g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY); g_file_info_set_name (info, "/"); /* Translators: this is the display name of the backend */ g_file_info_set_display_name (info, _("Trash")); g_file_info_set_content_type (info, "inode/directory"); icon = g_themed_icon_new (n_items ? "user-trash-full" : "user-trash"); g_file_info_set_icon (info, icon); g_object_unref (icon); icon = g_themed_icon_new (n_items ? "user-trash-full-symbolic" : "user-trash-symbolic"); g_file_info_set_symbolic_icon (info, icon); g_object_unref (icon); g_file_info_set_attribute_uint32 (info, G_FILE_ATTRIBUTE_TRASH_ITEM_COUNT, n_items); g_vfs_job_succeeded (G_VFS_JOB (job)); } return TRUE; }
/** * ostree_diff_dirs_with_options: * @flags: Flags * @a: First directory path, or %NULL * @b: First directory path * @modified: (element-type OstreeDiffItem): Modified files * @removed: (element-type Gio.File): Removed files * @added: (element-type Gio.File): Added files * @cancellable: Cancellable * @options: (allow-none): Options * @error: Error * * Compute the difference between directory @a and @b as 3 separate * sets of #OstreeDiffItem in @modified, @removed, and @added. */ gboolean ostree_diff_dirs_with_options (OstreeDiffFlags flags, GFile *a, GFile *b, GPtrArray *modified, GPtrArray *removed, GPtrArray *added, OstreeDiffDirsOptions *options, GCancellable *cancellable, GError **error) { gboolean ret = FALSE; GError *temp_error = NULL; g_autoptr(GFileEnumerator) dir_enum = NULL; g_autoptr(GFile) child_a = NULL; g_autoptr(GFile) child_b = NULL; g_autoptr(GFileInfo) child_a_info = NULL; g_autoptr(GFileInfo) child_b_info = NULL; OstreeDiffDirsOptions default_opts = OSTREE_DIFF_DIRS_OPTIONS_INIT; if (!options) options = &default_opts; /* If we're diffing versus a repo, and either of them have xattrs disabled, * then disable for both. */ OstreeRepo *repo; if (OSTREE_IS_REPO_FILE (a)) repo = ostree_repo_file_get_repo ((OstreeRepoFile*)a); else if (OSTREE_IS_REPO_FILE (b)) repo = ostree_repo_file_get_repo ((OstreeRepoFile*)b); else repo = NULL; if (repo != NULL && repo->disable_xattrs) flags |= OSTREE_DIFF_FLAGS_IGNORE_XATTRS; if (a == NULL) { if (!diff_add_dir_recurse (b, added, cancellable, error)) goto out; ret = TRUE; goto out; } child_a_info = g_file_query_info (a, OSTREE_GIO_FAST_QUERYINFO, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, error); if (!child_a_info) goto out; child_b_info = g_file_query_info (b, OSTREE_GIO_FAST_QUERYINFO, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, error); if (!child_b_info) goto out; /* Fast path test for unmodified directories */ if (g_file_info_get_file_type (child_a_info) == G_FILE_TYPE_DIRECTORY && g_file_info_get_file_type (child_b_info) == G_FILE_TYPE_DIRECTORY && OSTREE_IS_REPO_FILE (a) && OSTREE_IS_REPO_FILE (b)) { OstreeRepoFile *a_repof = (OstreeRepoFile*) a; OstreeRepoFile *b_repof = (OstreeRepoFile*) b; if (strcmp (ostree_repo_file_tree_get_contents_checksum (a_repof), ostree_repo_file_tree_get_contents_checksum (b_repof)) == 0) { ret = TRUE; goto out; } } g_clear_object (&child_a_info); g_clear_object (&child_b_info); dir_enum = g_file_enumerate_children (a, OSTREE_GIO_FAST_QUERYINFO, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, error); if (!dir_enum) goto out; while ((child_a_info = g_file_enumerator_next_file (dir_enum, cancellable, &temp_error)) != NULL) { const char *name; GFileType child_a_type; GFileType child_b_type; name = g_file_info_get_name (child_a_info); g_clear_object (&child_a); child_a = g_file_get_child (a, name); child_a_type = g_file_info_get_file_type (child_a_info); g_clear_object (&child_b); child_b = g_file_get_child (b, name); g_clear_object (&child_b_info); child_b_info = g_file_query_info (child_b, OSTREE_GIO_FAST_QUERYINFO, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, &temp_error); if (!child_b_info) { if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { g_clear_error (&temp_error); g_ptr_array_add (removed, g_object_ref (child_a)); } else { g_propagate_error (error, temp_error); goto out; } } else { if (options->owner_uid >= 0) g_file_info_set_attribute_uint32 (child_b_info, "unix::uid", options->owner_uid); if (options->owner_gid >= 0) g_file_info_set_attribute_uint32 (child_b_info, "unix::gid", options->owner_gid); child_b_type = g_file_info_get_file_type (child_b_info); if (child_a_type != child_b_type) { OstreeDiffItem *diff_item = diff_item_new (child_a, child_a_info, child_b, child_b_info, NULL, NULL); g_ptr_array_add (modified, diff_item); } else { OstreeDiffItem *diff_item = NULL; if (!diff_files (flags, child_a, child_a_info, child_b, child_b_info, &diff_item, cancellable, error)) goto out; if (diff_item) g_ptr_array_add (modified, diff_item); /* Transfer ownership */ if (child_a_type == G_FILE_TYPE_DIRECTORY) { if (!ostree_diff_dirs_with_options (flags, child_a, child_b, modified, removed, added, options, cancellable, error)) goto out; } } } g_clear_object (&child_a_info); } if (temp_error != NULL) { g_propagate_error (error, temp_error); goto out; } g_clear_object (&dir_enum); dir_enum = g_file_enumerate_children (b, OSTREE_GIO_FAST_QUERYINFO, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, error); if (!dir_enum) goto out; g_clear_object (&child_b_info); while ((child_b_info = g_file_enumerator_next_file (dir_enum, cancellable, &temp_error)) != NULL) { const char *name; name = g_file_info_get_name (child_b_info); g_clear_object (&child_a); child_a = g_file_get_child (a, name); g_clear_object (&child_b); child_b = g_file_get_child (b, name); g_clear_object (&child_a_info); child_a_info = g_file_query_info (child_a, OSTREE_GIO_FAST_QUERYINFO, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, cancellable, &temp_error); if (!child_a_info) { if (g_error_matches (temp_error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { g_clear_error (&temp_error); g_ptr_array_add (added, g_object_ref (child_b)); if (g_file_info_get_file_type (child_b_info) == G_FILE_TYPE_DIRECTORY) { if (!diff_add_dir_recurse (child_b, added, cancellable, error)) goto out; } } else { g_propagate_error (error, temp_error); goto out; } } g_clear_object (&child_b_info); } if (temp_error != NULL) { g_propagate_error (error, temp_error); goto out; } ret = TRUE; out: return ret; }
GFileInfo * gvfs_file_info_demarshal (char *data, gsize size) { guint32 num_attrs, i; GInputStream *memstream; GDataInputStream *in; GFileInfo *info; char *attr, *str, **strv; GFileAttributeType type; GFileAttributeStatus status; GObject *obj; int objtype; memstream = g_memory_input_stream_new_from_data (data, size, NULL); in = g_data_input_stream_new (memstream); g_object_unref (memstream); info = g_file_info_new (); num_attrs = g_data_input_stream_read_uint32 (in, NULL, NULL); for (i = 0; i < num_attrs; i++) { attr = read_string (in); type = g_data_input_stream_read_byte (in, NULL, NULL); status = g_data_input_stream_read_byte (in, NULL, NULL); switch (type) { case G_FILE_ATTRIBUTE_TYPE_STRING: str = read_string (in); g_file_info_set_attribute_string (info, attr, str); g_free (str); break; case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING: str = read_string (in); g_file_info_set_attribute_byte_string (info, attr, str); g_free (str); break; case G_FILE_ATTRIBUTE_TYPE_STRINGV: strv = read_stringv (in); g_file_info_set_attribute_stringv (info, attr, strv); g_strfreev (strv); break; case G_FILE_ATTRIBUTE_TYPE_BOOLEAN: g_file_info_set_attribute_boolean (info, attr, g_data_input_stream_read_byte (in, NULL, NULL)); break; case G_FILE_ATTRIBUTE_TYPE_UINT32: g_file_info_set_attribute_uint32 (info, attr, g_data_input_stream_read_uint32 (in, NULL, NULL)); break; case G_FILE_ATTRIBUTE_TYPE_INT32: g_file_info_set_attribute_int32 (info, attr, g_data_input_stream_read_int32 (in, NULL, NULL)); break; case G_FILE_ATTRIBUTE_TYPE_UINT64: g_file_info_set_attribute_uint64 (info, attr, g_data_input_stream_read_uint64 (in, NULL, NULL)); break; case G_FILE_ATTRIBUTE_TYPE_INT64: g_file_info_set_attribute_int64 (info, attr, g_data_input_stream_read_int64 (in, NULL, NULL)); break; case G_FILE_ATTRIBUTE_TYPE_OBJECT: objtype = g_data_input_stream_read_byte (in, NULL, NULL); obj = NULL; if (objtype == 1) { char *icon_str; icon_str = read_string (in); obj = (GObject *)g_icon_new_for_string (icon_str, NULL); g_free (icon_str); } else { g_warning ("Unsupported GFileInfo object type %d\n", objtype); g_free (attr); goto out; } g_file_info_set_attribute_object (info, attr, obj); if (obj) g_object_unref (obj); break; case G_FILE_ATTRIBUTE_TYPE_INVALID: break; default: g_warning ("Unsupported GFileInfo attribute type %d\n", type); g_free (attr); goto out; break; } g_file_info_set_attribute_status (info, attr, status); g_free (attr); } out: g_object_unref (in); return info; }
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; }
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; }