/** * gs_plugin_file_to_app: */ gboolean gs_plugin_file_to_app (GsPlugin *plugin, GList **list, GFile *file, GCancellable *cancellable, GError **error) { g_autofree gchar *content_type = NULL; g_autofree gchar *id_prefixed = NULL; g_autoptr(GBytes) appstream_gz = NULL; g_autoptr(GBytes) icon_data = NULL; g_autoptr(GBytes) metadata = NULL; g_autoptr(GsApp) app = NULL; g_autoptr(XdgAppBundleRef) xref_bundle = NULL; const gchar *mimetypes[] = { "application/vnd.xdgapp", NULL }; /* does this match any of the mimetypes we support */ content_type = gs_utils_get_content_type (file, cancellable, error); if (content_type == NULL) return FALSE; if (!g_strv_contains (mimetypes, content_type)) return TRUE; /* load bundle */ xref_bundle = xdg_app_bundle_ref_new (file, error); if (xref_bundle == NULL) { g_prefix_error (error, "error loading bundle: "); return FALSE; } /* create a virtual ID */ id_prefixed = gs_plugin_xdg_app_build_id (XDG_APP_REF (xref_bundle)); /* load metadata */ app = gs_app_new (id_prefixed); gs_app_set_kind (app, AS_APP_KIND_DESKTOP); gs_app_set_state (app, AS_APP_STATE_AVAILABLE_LOCAL); gs_app_set_size_installed (app, xdg_app_bundle_ref_get_installed_size (xref_bundle)); gs_plugin_xdg_app_set_metadata (app, XDG_APP_REF (xref_bundle)); metadata = xdg_app_bundle_ref_get_metadata (xref_bundle); if (!gs_plugin_xdg_app_set_app_metadata (app, g_bytes_get_data (metadata, NULL), g_bytes_get_size (metadata), error)) return FALSE; /* load AppStream */ appstream_gz = xdg_app_bundle_ref_get_appstream (xref_bundle); if (appstream_gz != NULL) { g_autoptr(GZlibDecompressor) decompressor = NULL; g_autoptr(GInputStream) stream_gz = NULL; g_autoptr(GInputStream) stream_data = NULL; g_autoptr(GBytes) appstream = NULL; g_autoptr(AsStore) store = NULL; g_autofree gchar *id = NULL; AsApp *item; /* decompress data */ decompressor = g_zlib_decompressor_new (G_ZLIB_COMPRESSOR_FORMAT_GZIP); stream_gz = g_memory_input_stream_new_from_bytes (appstream_gz); if (stream_gz == NULL) return FALSE; stream_data = g_converter_input_stream_new (stream_gz, G_CONVERTER (decompressor)); appstream = g_input_stream_read_bytes (stream_data, 0x100000, /* 1Mb */ cancellable, error); if (appstream == NULL) return FALSE; store = as_store_new (); if (!as_store_from_bytes (store, appstream, cancellable, error)) return FALSE; /* find app */ id = g_strdup_printf ("%s.desktop", gs_app_get_xdgapp_name (app)); item = as_store_get_app_by_id (store, id); if (item == NULL) { g_set_error (error, GS_PLUGIN_ERROR, GS_PLUGIN_ERROR_FAILED, "application %s not found", id); return FALSE; } /* copy details from AppStream to app */ if (!gs_appstream_refine_app (plugin, app, item, error)) return FALSE; } /* load icon */ icon_data = xdg_app_bundle_ref_get_icon (xref_bundle, 64 * gs_plugin_get_scale (plugin)); if (icon_data == NULL) icon_data = xdg_app_bundle_ref_get_icon (xref_bundle, 64); if (icon_data != NULL) { g_autoptr(GInputStream) stream_icon = NULL; g_autoptr(GdkPixbuf) pixbuf = NULL; stream_icon = g_memory_input_stream_new_from_bytes (icon_data); pixbuf = gdk_pixbuf_new_from_stream (stream_icon, cancellable, error); if (pixbuf == NULL) return FALSE; gs_app_set_pixbuf (app, pixbuf); } else { g_autoptr(AsIcon) icon = NULL; icon = as_icon_new (); as_icon_set_kind (icon, AS_ICON_KIND_STOCK); as_icon_set_name (icon, "application-x-executable"); gs_app_set_icon (app, icon); } /* not quite true: this just means we can update this specific app */ if (xdg_app_bundle_ref_get_origin (xref_bundle)) gs_app_add_quirk (app, AS_APP_QUIRK_HAS_SOURCE); g_debug ("created local app: %s", gs_app_to_string (app)); gs_app_list_add (list, app); return TRUE; }
/** * fu_provider_schedule_update: **/ static gboolean fu_provider_schedule_update (FuProvider *provider, FuDevice *device, GInputStream *stream, GError **error) { gchar tmpname[] = {"XXXXXX.cap"}; guint i; _cleanup_bytes_unref_ GBytes *fwbin = NULL; _cleanup_free_ gchar *dirname = NULL; _cleanup_free_ gchar *filename = NULL; _cleanup_object_unref_ FuDevice *device_tmp = NULL; _cleanup_object_unref_ FuPending *pending = NULL; _cleanup_object_unref_ GFile *file = NULL; /* id already exists */ pending = fu_pending_new (); device_tmp = fu_pending_get_device (pending, fu_device_get_id (device), NULL); if (device_tmp != NULL) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_ALREADY_PENDING, "%s is already scheduled to be updated", fu_device_get_id (device)); return FALSE; } /* create directory */ dirname = g_build_filename (LOCALSTATEDIR, "lib", "fwupd", NULL); file = g_file_new_for_path (dirname); if (!g_file_query_exists (file, NULL)) { if (!g_file_make_directory_with_parents (file, NULL, error)) return FALSE; } /* get a random filename */ for (i = 0; i < 6; i++) tmpname[i] = g_random_int_range ('A', 'Z'); filename = g_build_filename (dirname, tmpname, NULL); /* just copy to the temp file */ fu_provider_set_status (provider, FWUPD_STATUS_SCHEDULING); if (!g_seekable_seek (G_SEEKABLE (stream), 0, G_SEEK_SET, NULL, error)) return FALSE; fwbin = g_input_stream_read_bytes (stream, FU_PROVIDER_FIRMWARE_MAX, NULL, error); if (fwbin == NULL) return FALSE; if (!g_file_set_contents (filename, g_bytes_get_data (fwbin, NULL), g_bytes_get_size (fwbin), error)) return FALSE; /* schedule for next boot */ g_debug ("schedule %s to be installed to %s on next boot", filename, fu_device_get_id (device)); fu_device_set_metadata (device, FU_DEVICE_KEY_FILENAME_CAB, filename); /* add to database */ if (!fu_pending_add_device (pending, device, error)) return FALSE; /* next boot we run offline */ return fu_provider_offline_setup (error); }
gboolean as_store_cab_from_file (AsStore *store, GFile *file, GCancellable *cancellable, GError **error) { guint64 size; g_autoptr(GBytes) bytes = NULL; g_autoptr(GError) error_local = NULL; g_autoptr(GFileInfo) info = NULL; g_autoptr(GInputStream) input_stream = NULL; g_autofree gchar *filename = NULL; g_autofree gchar *origin = NULL; /* set origin */ origin = g_file_get_basename (file); as_store_set_origin (store, origin); /* open file */ input_stream = G_INPUT_STREAM (g_file_read (file, cancellable, &error_local)); if (input_stream == NULL) { filename = g_file_get_path (file); g_set_error (error, AS_STORE_ERROR, AS_STORE_ERROR_FAILED, "Failed to open %s: %s", filename, error_local->message); return FALSE; } /* get size */ info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_SIZE, G_FILE_QUERY_INFO_NONE, cancellable, &error_local); if (info == NULL) { filename = g_file_get_path (file); g_set_error (error, AS_STORE_ERROR, AS_STORE_ERROR_FAILED, "Failed to get info from %s: %s", filename, error_local->message); return FALSE; } /* slurp it all */ size = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE); bytes = g_input_stream_read_bytes (input_stream, (gsize) size, cancellable, &error_local); if (bytes == NULL) { filename = g_file_get_path (file); g_set_error (error, AS_STORE_ERROR, AS_STORE_ERROR_FAILED, "Failed to read %s: %s", filename, error_local->message); return FALSE; } /* parse */ return as_store_cab_from_bytes_with_origin (store, bytes, origin, cancellable, error); }