/** * Sets file attributes * @param file is a GFile pointer and must not be null * @param meta is the structure that contains all meta data for the * file that we want to set. */ void set_file_attributes(GFile *file, meta_data_t *meta) { GError *error = NULL; GFileInfo *fileinfo = NULL; if (file != NULL && meta != NULL) { fileinfo = g_file_query_info(file, "*", G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error); if (fileinfo == NULL || error != NULL) { print_error(__FILE__, __LINE__, _("Error while getting file information: %s\n"), error->message); error = free_error(error); } else { set_file_mode_to_gfile(fileinfo, meta); set_dates_to_gfile(fileinfo, meta); if (g_file_set_attributes_from_info(file, fileinfo, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, &error) == FALSE && error != NULL) { print_error(__FILE__, __LINE__, _("Error or warning for file (%s): %s\n"), meta->name, error->message); free_error(error); } free_object(fileinfo); } } else { /* To translators : do not translate this ! */ print_error(__FILE__, __LINE__, "set_file_attribute(file = %p, meta = %p)\n", file, meta); } }
static gboolean convert_file (ConvertData *data) { GFile *file; DocItem *item; const gchar *uri; xmlNodePtr node; xmlNodePtr cur; gint total, current; gchar *text; if (!data->current) return FALSE; item = (DocItem *) data->current->data; uri = (const gchar *)item->uri; node = item->cur; data->current = g_list_next (data->current); /* Update progress information */ total = g_list_length (data->items); current = ++(data->n_item); text = g_strdup_printf (_("Converting %s"), uri); gtk_label_set_text (GTK_LABEL (data->label), text); g_free (text); text = g_strdup_printf (_("%d of %d documents converted"), current, total); gtk_progress_bar_set_text (GTK_PROGRESS_BAR (data->progress), text); g_free (text); gtk_progress_bar_set_fraction (GTK_PROGRESS_BAR (data->progress), (gdouble)(current - 1) / total); file = g_file_new_for_uri (uri); if (!g_file_query_exists (file, NULL)) { g_printerr ("Uri %s does not exist\n", uri); g_object_unref (file); return data->current != NULL; } for (cur = node->xmlChildrenNode; cur != NULL; cur = cur->next) { xmlChar *key; xmlChar *value; if (xmlStrcmp (cur->name, (const xmlChar *)"entry") != 0) continue; key = xmlGetProp (cur, (const xmlChar *)"key"); value = xmlGetProp (cur, (const xmlChar *)"value"); if (key && value) { GFileInfo *info; gchar *gio_key; GError *error = NULL; info = g_file_info_new (); gio_key = g_strconcat (EV_METADATA_NAMESPACE"::", key, NULL); g_file_info_set_attribute_string (info, gio_key, (const gchar *)value); g_free (gio_key); if (!g_file_set_attributes_from_info (file, info, 0, NULL, &error)) { g_printerr ("Error setting metadata for %s: %s\n", uri, error->message); g_error_free (error); } g_object_unref (info); } if (key) xmlFree (key); if (value) xmlFree (value); } g_object_unref (file); return data->current != NULL; }
static void parse_xml_node (GFile *file, xmlNodePtr filenode) { xmlNodePtr node; xmlAttrPtr attr; xmlChar *property; const char *new_key; GHashTable *list_keys; GList *keys, *l; GHashTableIter iter; GFileInfo *info; int i; char **strv; GError *error; info = g_file_info_new (); for (attr = filenode->properties; attr != NULL; attr = attr->next) { if (strcmp ((char *)attr->name, "name") == 0 || strcmp ((char *)attr->name, "timestamp") == 0) { continue; } new_key = convert_key_name (attr->name); if (new_key) { property = xmlGetProp (filenode, attr->name); if (property) { g_file_info_set_attribute_string (info, new_key, property); xmlFree (property); } } } list_keys = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, NULL); for (node = filenode->children; node != NULL; node = node->next) { for (attr = node->properties; attr != NULL; attr = attr->next) { new_key = convert_key_name (node->name); if (new_key) { property = xmlGetProp (node, attr->name); if (property) { keys = g_hash_table_lookup (list_keys, new_key); keys = g_list_append (keys, property); g_hash_table_replace (list_keys, (char *)new_key, keys); } } } } g_hash_table_iter_init (&iter, list_keys); while (g_hash_table_iter_next (&iter, (void **)&new_key, (void **)&keys)) { strv = g_new0 (char *, g_list_length (keys) + 1); for (l = keys, i = 0; l != NULL; l = l->next, i++) { strv[i] = l->data; } g_file_info_set_attribute_stringv (info, new_key, strv); g_free (strv); g_list_foreach (keys, (GFunc)xmlFree, NULL); g_list_free (keys); } g_hash_table_destroy (list_keys); if (info) { error = NULL; if (!g_file_set_attributes_from_info (file, info, 0, NULL, &error)) { char *uri; uri = g_file_get_uri (file); if (!quiet) { g_print ("error setting info for %s: %s\n", uri, error->message); } g_free (uri); g_error_free (error); } g_object_unref (info); } }
/** * gedit_document_set_metadata: * @doc: a #GeditDocument * @first_key: name of the first key to set * @...: (allow-none): value for the first key, followed optionally by more key/value pairs, * followed by %NULL. * * Sets metadata on a document. */ void gedit_document_set_metadata (GeditDocument *doc, const gchar *first_key, ...) { GeditDocumentPrivate *priv; GFile *location; const gchar *key; va_list var_args; GFileInfo *info = NULL; g_return_if_fail (GEDIT_IS_DOCUMENT (doc)); g_return_if_fail (first_key != NULL); priv = gedit_document_get_instance_private (doc); location = gtk_source_file_get_location (priv->file); /* With the metadata manager, can't set metadata for untitled documents. * With GVFS metadata, if the location is NULL the metadata is stored in * priv->metadata_info, so that it can be saved later if the document is * saved. */ if (!priv->use_gvfs_metadata && location == NULL) { return; } if (priv->use_gvfs_metadata) { info = g_file_info_new (); } va_start (var_args, first_key); for (key = first_key; key; key = va_arg (var_args, const gchar *)) { const gchar *value = va_arg (var_args, const gchar *); if (priv->use_gvfs_metadata) { /* Collect the metadata into @info. */ set_gvfs_metadata (doc, info, key, value); } else { gedit_metadata_manager_set (location, key, value); } } va_end (var_args); if (priv->use_gvfs_metadata && location != NULL) { GError *error = NULL; /* We save synchronously since metadata is always local so it * should be fast. Moreover this function can be called on * application shutdown, when the main loop has already exited, * so an async operation would not terminate. * https://bugzilla.gnome.org/show_bug.cgi?id=736591 */ g_file_set_attributes_from_info (location, info, G_FILE_QUERY_INFO_NONE, NULL, &error); if (error != NULL) { /* Do not complain about metadata if we are closing a * document for a non existing file. */ if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT) && !g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_FOUND)) { g_warning ("Set document metadata failed: %s", error->message); } g_error_free (error); } } g_clear_object (&info); }
static gboolean tracker_writeback_file_update_metadata (TrackerWriteback *writeback, GPtrArray *values, TrackerSparqlConnection *connection, GCancellable *cancellable, GError **error) { TrackerWritebackFileClass *writeback_file_class; gboolean retval; GFile *file, *tmp_file; GFileInfo *file_info; GStrv row; const gchar * const *content_types; const gchar *mime_type; guint n; GError *n_error = NULL; writeback_file_class = TRACKER_WRITEBACK_FILE_GET_CLASS (writeback); if (!writeback_file_class->update_file_metadata) { g_critical ("%s doesn't implement update_file_metadata()", G_OBJECT_TYPE_NAME (writeback)); g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s doesn't implement update_file_metadata()", G_OBJECT_TYPE_NAME (writeback)); return FALSE; } if (!writeback_file_class->content_types) { g_critical ("%s doesn't implement content_types()", G_OBJECT_TYPE_NAME (writeback)); g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s doesn't implement content_types()", G_OBJECT_TYPE_NAME (writeback)); return FALSE; } /* Get the file from the row */ row = g_ptr_array_index (values, 0); file = g_file_new_for_uri (row[0]); file_info = g_file_query_info (file, G_FILE_ATTRIBUTE_UNIX_MODE "," G_FILE_ATTRIBUTE_STANDARD_CONTENT_TYPE "," G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE, G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, NULL, NULL); if (!file_info) { g_object_unref (file); g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s doesn't exist", row[0]); return FALSE; } if (!g_file_info_get_attribute_boolean (file_info, G_FILE_ATTRIBUTE_ACCESS_CAN_WRITE)) { g_object_unref (file_info); g_object_unref (file); g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "%s not writable", row[0]); return FALSE; } mime_type = g_file_info_get_content_type (file_info); content_types = (writeback_file_class->content_types) (TRACKER_WRITEBACK_FILE (writeback)); retval = FALSE; for (n = 0; content_types[n] != NULL; n++) { if (g_strcmp0 (mime_type, content_types[n]) == 0) { retval = TRUE; break; } } if (!retval) { /* module does not support writeback for this file */ g_object_unref (file_info); g_object_unref (file); g_set_error_literal (error, TRACKER_DBUS_ERROR, TRACKER_DBUS_ERROR_UNSUPPORTED, "Module does not support writeback for this file"); return FALSE; } /* Copy to a temporary file so we can perform an atomic write on move */ tmp_file = create_temporary_file (file, file_info, &n_error); if (!tmp_file) { g_object_unref (file); g_propagate_error (error, n_error); g_object_unref (file_info); return FALSE; } retval = (writeback_file_class->update_file_metadata) (TRACKER_WRITEBACK_FILE (writeback), tmp_file, values, connection, cancellable, &n_error); if (!retval) { /* Delete the temporary file and preserve original */ g_file_delete (tmp_file, NULL, NULL); } else { GError *m_error = NULL; /* Move back the modified file to the original location */ g_file_move (tmp_file, file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, NULL); /* Set file attributes on tmp_file using file_info of original file */ g_file_set_attributes_from_info (tmp_file, file_info, 0, NULL, &m_error); if (m_error) { g_warning ("Can't restore permissions of original file for %s", row[0]); g_error_free (m_error); } } g_object_unref (file_info); g_object_unref (tmp_file); g_object_unref (file); if (n_error) { g_propagate_error (error, n_error); } return retval; }
/* Note: This function does not report errors as a GError because there’s no * harm in the stamp file not being updated: it just means we’re going to check * again for updates sooner than otherwise. */ static void update_stamp_file (guint64 last_successful_update_secs, guint update_interval_days, guint randomized_delay_days) { const gchar *stamp_dir = get_stamp_dir (); g_autofree gchar *stamp_path = NULL; g_autoptr(GFile) stamp_file = NULL; g_autoptr(GError) error = NULL; GTimeVal mtime; g_autofree gchar *next_update = NULL; g_autoptr(GFileInfo) file_info = NULL; if (g_mkdir_with_parents (stamp_dir, 0755) != 0) { int saved_errno = errno; const char *err_str = g_strerror (saved_errno); critical (EOS_UPDATER_CONFIGURATION_ERROR_MSGID, "Failed to create updater timestamp directory: %s", err_str); return; } /* This will be subject to year 2038 problems on 32-bit architectures. * FIXME: Fix that by dropping use of #GTimeVal. */ mtime.tv_sec = (glong) last_successful_update_secs; mtime.tv_usec = 0; stamp_path = g_build_filename (stamp_dir, UPDATE_STAMP_NAME, NULL); stamp_file = g_file_new_for_path (stamp_path); g_file_replace_contents (stamp_file, "", 0, NULL, FALSE, G_FILE_CREATE_NONE, NULL, NULL, &error); if (error) { critical (EOS_UPDATER_STAMP_ERROR_MSGID, "Failed to write updater stamp file: %s", error->message); return; } /* Set the file’s mtime to include the randomised delay. This will result in * the mtime either being now, or some number of days in the future. Setting * the mtime to the future should not be a problem, as the stamp file is only * accessed by eos-autoupdater, so the semantics of the mtime are clear. */ file_info = g_file_query_info (stamp_file, G_FILE_ATTRIBUTE_TIME_MODIFIED, G_FILE_QUERY_INFO_NONE, NULL, &error); if (error != NULL) { critical (EOS_UPDATER_STAMP_ERROR_MSGID, "Failed to get stamp file info: %s", error->message); return; } if (randomized_delay_days > 0) { gint32 actual_delay_days = g_random_int_range (0, (gint32) randomized_delay_days + 1); mtime.tv_sec += (glong) actual_delay_days * (glong) SEC_PER_DAY; } g_file_info_set_modification_time (file_info, &mtime); g_file_set_attributes_from_info (stamp_file, file_info, G_FILE_QUERY_INFO_NONE, NULL, &error); if (error != NULL) { critical (EOS_UPDATER_STAMP_ERROR_MSGID, "Failed to set stamp file info: %s", error->message); return; } /* A little bit of help for debuggers. */ mtime.tv_sec += (glong) update_interval_days * (glong) SEC_PER_DAY; next_update = g_time_val_to_iso8601 (&mtime); g_debug ("Wrote stamp file. Next update at %s", next_update); }
static gboolean project_import_generate_file (AnjutaPluginDescription *backend, ProjectImportDialog *import_dialog, GFile *project_file) { /* Of course we could do some more intelligent stuff here * and check which plugins are really needed */ GFile* source_file = NULL; gchar *backend_id = NULL; GError* error = NULL; if (!anjuta_plugin_description_get_string (backend, "Project", "Supported-Project-Types", &backend_id)) { if (!strcmp (backend_id, "automake")) source_file = g_file_new_for_path (AM_PROJECT_FILE); else if (!strcmp (backend_id, "make")) source_file = g_file_new_for_path (MKFILE_PROJECT_FILE); else if (!strcmp (backend_id, "directory")) source_file = g_file_new_for_path (DIRECTORY_PROJECT_FILE); } g_free (backend_id); if (source_file != NULL) { /* Use a default project file */ if (!g_file_copy (source_file, project_file, G_FILE_COPY_NONE, NULL, NULL, NULL, &error)) { if (error->domain == G_IO_ERROR && error->code == G_IO_ERROR_EXISTS) { gchar *prjfile = g_file_get_parse_name (project_file); if (anjuta_util_dialog_boolean_question (GTK_WINDOW (import_dialog), FALSE, _("A file named \"%s\" already exists. " "Do you want to replace it?"), prjfile)) { g_error_free (error); error = NULL; g_file_copy (source_file, project_file, G_FILE_COPY_OVERWRITE, NULL, NULL, NULL, &error); } g_free (prjfile); } } if (!error) { time_t ctime = time(NULL); GFileInfo* file_info = g_file_info_new(); g_file_info_set_attribute_uint64(file_info, "time::modified", ctime); g_file_info_set_attribute_uint64(file_info, "time::created", ctime); g_file_info_set_attribute_uint64(file_info, "time::access", ctime); g_file_set_attributes_from_info (project_file, file_info, G_FILE_QUERY_INFO_NONE, NULL, NULL); g_object_unref (G_OBJECT(file_info));; } } else { /* For unknown project backend we use the directory project file and * replace the backend plugin with the right one */ gchar *content; gsize length; source_file = g_file_new_for_path (DIRECTORY_PROJECT_FILE); if (g_file_load_contents (source_file, NULL, &content, &length, NULL, &error)) { GString *buffer; const gchar *pos; const gchar *plugin; const gchar *end_plugin; gssize len; buffer = g_string_new_len (content, length); pos = buffer->str; len = buffer->len; for (;;) { plugin = g_strstr_len (pos, len, "<plugin "); if (plugin == NULL) break; end_plugin = g_strstr_len (plugin, len - (plugin - pos), "</plugin>"); if (end_plugin == NULL) break; if (g_strstr_len (plugin, end_plugin - plugin, "\"IAnjutaProjectBackend\"") != NULL) break; pos = end_plugin + 9; len -= (end_plugin + 9 - pos); } if ((plugin == NULL) || (end_plugin == NULL)) { g_set_error (&error, ianjuta_project_backend_error_quark(),0, "Unable to find backend plugin"); } else { /* Replace directory backend with right one */ GString *str; GFileOutputStream *stream; gchar *name = NULL; gchar *plugin_id = NULL; anjuta_plugin_description_get_string (backend, "Anjuta Plugin", "Name", &name); anjuta_plugin_description_get_string (backend, "Anjuta Plugin", "Location", &plugin_id); str = g_string_new (NULL); g_string_printf (str, "<plugin name= \"%s\"\n" " mandatory=\"yes\">\n" " <require group=\"Anjuta Plugin\"\n" " attribute=\"Location\"\n" " value=\"%s\"/>\n" " <require group=\"Anjuta Plugin\"\n" " attribute=\"Interfaces\"\n" " value=\"IAnjutaProjectBackend\"/>\n" " ", name, plugin_id); g_string_erase (buffer, plugin - buffer->str, end_plugin - plugin); g_string_insert_len (buffer, plugin - buffer->str, str->str, str->len); g_string_free (str, TRUE); stream = g_file_create (project_file, G_FILE_CREATE_NONE, NULL, &error); if (stream == NULL && error->domain == G_IO_ERROR && error->code == G_IO_ERROR_EXISTS) { gchar *prjfile = g_file_get_parse_name (project_file); if (anjuta_util_dialog_boolean_question (GTK_WINDOW (import_dialog), FALSE, _("A file named \"%s\" already exists. " "Do you want to replace it?"), prjfile)) { g_error_free (error); error = NULL; stream = g_file_replace (project_file, NULL, FALSE, G_FILE_CREATE_REPLACE_DESTINATION, NULL, &error); } g_free (prjfile); } if (stream != NULL) { gsize written; g_output_stream_write_all (G_OUTPUT_STREAM (stream), buffer->str, buffer->len, &written, NULL, &error); g_output_stream_close (G_OUTPUT_STREAM (stream), NULL, NULL); } } g_string_free (buffer, TRUE); g_free (content); } } g_object_unref (source_file); if (error) { gchar *prjfile; prjfile = g_file_get_parse_name (project_file); /* show the dialog since it may be hidden */ gtk_widget_show (GTK_WIDGET (import_dialog)); anjuta_util_dialog_error (GTK_WINDOW (import_dialog), _("A file named \"%s\" cannot be written: %s. " "Check if you have write access to the project directory."), prjfile, error->message); g_free (prjfile); g_error_free (error); return FALSE; } return TRUE; }