diff -r 000000000000 -r 2947214c450e app-manager/localdistributions.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/app-manager/localdistributions.c Tue Apr 25 17:41:00 2023 +0100 @@ -0,0 +1,372 @@ +/* + * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford + * Copyright (C) 2023 J. Ali Harlow + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include "localdistributions.h" + +#define VALID_ITER(iter,local) ((iter) && (iter)->user_data && \ + PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local)->stamp==(iter)->stamp) + +static GType column_types[PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS]; + +static void + plover_local_distributions_tree_model_init(GtkTreeModelIface *iface); + +G_DEFINE_TYPE_WITH_CODE(PloverLocalDistributions,plover_local_distributions, + G_TYPE_OBJECT,G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL, + plover_local_distributions_tree_model_init)); + +typedef struct _PloverLocalDistribution { + gchar *vendor,*distribution,*prefix,*user_friendly,*database_uri; +} PloverLocalDistribution; + +typedef struct _PloverLocalDistributionsPrivate { + GList *distributions; + int stamp; +} PloverLocalDistributionsPrivate; + +#define PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(obj)\ + G_TYPE_INSTANCE_GET_PRIVATE(obj,\ + PLOVER_TYPE_LOCAL_DISTRIBUTIONS,\ + PloverLocalDistributionsPrivate) + +PloverLocalDistribution *plover_local_distribution_new(const char *vendor, + const char *distribution) +{ + gchar *s; + struct comps *comps; + PloverLocalDistribution *ld; + ld=g_new0(PloverLocalDistribution,1); + ld->vendor=g_strdup(vendor); + if (distribution) + { + ld->distribution=g_strdup(distribution); + ld->user_friendly=g_strdup_printf("%s (%s)",distribution,vendor); + } + else + ld->user_friendly=g_strdup(vendor); + comps=plover_comps_new(); + plover_comps_set_vendor(comps,vendor); + if (distribution) + plover_comps_set_distribution(comps,distribution); + ld->prefix=plover_comps_get_default_prefix(comps); + plover_comps_free(comps); + s=g_build_filename(ld->prefix,"var","lib","razor",NULL); + ld->database_uri=razor_path_to_uri(s); + g_free(s); + return ld; +} + +void plover_local_distribution_free(PloverLocalDistribution *ld) +{ + if (ld) + { + g_free(ld->vendor); + g_free(ld->distribution); + g_free(ld->prefix); + g_free(ld->user_friendly); + g_free(ld->database_uri); + g_free(ld); + } +} + +static void plover_local_distributions_finalize(GObject *obj) +{ + PloverLocalDistributionsPrivate *priv; + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(obj); + g_list_foreach(priv->distributions,(GFunc)plover_local_distribution_free, + NULL); + g_list_free(priv->distributions); + if (G_OBJECT_CLASS(plover_local_distributions_parent_class)->finalize) + G_OBJECT_CLASS(plover_local_distributions_parent_class)->finalize(obj); +} + +static void + plover_local_distributions_class_init(PloverLocalDistributionsClass *klass) +{ + GObjectClass *oclass=G_OBJECT_CLASS(klass); + oclass->finalize=plover_local_distributions_finalize; + g_type_class_add_private(klass,sizeof(PloverLocalDistributionsPrivate)); + column_types[PLOVER_LOCAL_DISTRIBUTIONS_VENDOR_COLUMN]=G_TYPE_STRING; + column_types[PLOVER_LOCAL_DISTRIBUTIONS_DISTRIBUTION_COLUMN]=G_TYPE_STRING; + column_types[PLOVER_LOCAL_DISTRIBUTIONS_PREFIX_COLUMN]=G_TYPE_STRING; + column_types[PLOVER_LOCAL_DISTRIBUTIONS_USER_FRIENDLY_COLUMN]=G_TYPE_STRING; + column_types[PLOVER_LOCAL_DISTRIBUTIONS_DATABASE_URI_COLUMN]=G_TYPE_STRING; +} + +static GtkTreeModelFlags +plover_local_distributions_get_flags(GtkTreeModel *tree_model) +{ + return GTK_TREE_MODEL_ITERS_PERSIST|GTK_TREE_MODEL_LIST_ONLY; +} + +static gint plover_local_distributions_get_n_columns(GtkTreeModel *tree_model) +{ + return PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS; +} + +static GType + plover_local_distributions_get_column_type(GtkTreeModel *tree_model,gint indx) +{ + g_return_val_if_fail(indx>=0 && indxdistributions,i); + if (!ld) + return FALSE; + iter->stamp=priv->stamp; + iter->user_data=ld; + return TRUE; +} + +static GtkTreePath * + plover_local_distributions_get_path(GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + GtkTreePath *path; + PloverLocalDistributionsPrivate *priv; + PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model; + g_return_val_if_fail(VALID_ITER(iter,tree_model),NULL); + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local); + path=gtk_tree_path_new(); + gtk_tree_path_append_index(path, + g_list_index(priv->distributions,iter->user_data)); + return path; +} + +static void plover_local_distributions_get_value(GtkTreeModel *tree_model, + GtkTreeIter *iter,gint column,GValue *value) +{ + gchar *s; + PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model; + PloverLocalDistribution *ld; + g_return_if_fail(column>=0 && columnuser_data; + g_value_init(value,column_types[column]); + switch((PloverLocalDistributionsColumn)column) + { + case PLOVER_LOCAL_DISTRIBUTIONS_VENDOR_COLUMN: + g_value_set_string(value,ld->vendor); + break; + case PLOVER_LOCAL_DISTRIBUTIONS_DISTRIBUTION_COLUMN: + g_value_set_string(value,ld->distribution); + break; + case PLOVER_LOCAL_DISTRIBUTIONS_PREFIX_COLUMN: + g_value_set_string(value,ld->prefix); + break; + case PLOVER_LOCAL_DISTRIBUTIONS_USER_FRIENDLY_COLUMN: + g_value_set_string(value,ld->user_friendly); + break; + case PLOVER_LOCAL_DISTRIBUTIONS_DATABASE_URI_COLUMN: + g_value_set_string(value,ld->database_uri); + break; + case PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS: + /* Quieten compiler warning */ + break; + } +} + +static gboolean + plover_local_distributions_iter_next(GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + GList *lnk; + PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model; + PloverLocalDistributionsPrivate *priv; + g_return_val_if_fail(VALID_ITER(iter,tree_model),FALSE); + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local); + lnk=g_list_find(priv->distributions,iter->user_data); + iter->user_data=lnk->next?lnk->next->data:NULL; + return !!iter->user_data; +} + +static gboolean + plover_local_distributions_iter_children(GtkTreeModel *tree_model, + GtkTreeIter *iter,GtkTreeIter *parent) +{ + PloverLocalDistributionsPrivate *priv; + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model); + /* this is a list, nodes have no children */ + if (parent) + return FALSE; + if (priv->distributions) + { + iter->stamp=priv->stamp; + iter->user_data=priv->distributions->data; + return TRUE; + } + else + return FALSE; +} + +static gboolean + plover_local_distributions_iter_has_child(GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + PloverLocalDistributionsPrivate *priv; + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model); + return !!priv->distributions; +} + +static gint plover_local_distributions_iter_n_children(GtkTreeModel *tree_model, + GtkTreeIter *iter) +{ + PloverLocalDistributionsPrivate *priv; + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model); + if (!iter) + return g_list_length(priv->distributions); + g_return_val_if_fail(VALID_ITER(iter,tree_model),-1); + return 0; +} + +static gboolean + plover_local_distributions_iter_nth_child(GtkTreeModel *tree_model, + GtkTreeIter *iter,GtkTreeIter *parent,gint n) +{ + GList *lnk; + PloverLocalDistributionsPrivate *priv; + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model); + if (parent) + return FALSE; + lnk=g_list_nth(priv->distributions,n); + if (!lnk) + return FALSE; + iter->stamp=priv->stamp; + iter->user_data=lnk->data; + return TRUE; +} + +static gboolean plover_local_distributions_iter_parent(GtkTreeModel *tree_model, + GtkTreeIter *iter,GtkTreeIter *child) +{ + return FALSE; +} + +static void plover_local_distributions_tree_model_init(GtkTreeModelIface *iface) +{ + iface->get_flags=plover_local_distributions_get_flags; + iface->get_n_columns=plover_local_distributions_get_n_columns; + iface->get_column_type=plover_local_distributions_get_column_type; + iface->get_iter=plover_local_distributions_get_iter; + iface->get_path=plover_local_distributions_get_path; + iface->get_value=plover_local_distributions_get_value; + iface->iter_next=plover_local_distributions_iter_next; + iface->iter_children=plover_local_distributions_iter_children; + iface->iter_has_child=plover_local_distributions_iter_has_child; + iface->iter_n_children=plover_local_distributions_iter_n_children; + iface->iter_nth_child=plover_local_distributions_iter_nth_child; + iface->iter_parent=plover_local_distributions_iter_parent; +} + +static void plover_local_distributions_init(PloverLocalDistributions *store) +{ + gchar *s; + const char *vendor_prefix,*vendor,*distribution; + GDir *vendor_dir,*distribution_dir,*database_dir; + PloverLocalDistributionsPrivate *priv; + PloverLocalDistribution *ld; + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(store); + /* + * local distribution databases may be found in + * /$VENDOR/$DISTRIBUTION/var/lib/razor and + * /$VENDOR/var/lib/razor + */ + vendor_prefix=plover_get_vendor_prefix(); + g_message("Vendor prefix is %s",vendor_prefix); + vendor_dir=g_dir_open(vendor_prefix,0,NULL); + if (!vendor_dir) + { + g_warning("Failed to open %s",vendor_prefix); + return; + } + while((vendor=g_dir_read_name(vendor_dir))) + { + g_message("Candidate for vendor is %s",vendor); + s=g_build_filename(vendor_prefix,vendor,NULL); + distribution_dir=g_dir_open(s,0,NULL); + g_free(s); + if (!distribution_dir) + { + g_warning("Failed to open %s/%s",vendor_prefix,vendor); + continue; + } + while((distribution=g_dir_read_name(distribution_dir))) + { + g_message("Candidate for distribution is %s",distribution); + if (!strcmp(distribution,"var")) + { + s=g_build_filename(vendor_prefix,vendor,"var","lib","razor", + NULL); + database_dir=g_dir_open(s,0,NULL); + g_free(s); + if (database_dir) + { + ld=plover_local_distribution_new(vendor,NULL); + g_message("Found vendor-specific razor database at %s", + ld->database_uri); + priv->distributions=g_list_prepend(priv->distributions,ld); + g_dir_close(database_dir); + } + else + g_warning("Failed to open %s/%s/var/lib/razor", + vendor_prefix,vendor); + } + s=g_build_filename(vendor_prefix,vendor,distribution, + "var","lib","razor",NULL); + database_dir=g_dir_open(s,0,NULL); + g_free(s); + if (database_dir) + { + ld=plover_local_distribution_new(vendor,distribution); + g_message("Found local-distribution razor database at %s", + ld->database_uri); + priv->distributions=g_list_prepend(priv->distributions,ld); + g_dir_close(database_dir); + } + else + g_warning("Failed to open %s/%s/%s/var/lib/razor", + vendor_prefix,vendor,distribution); + } + g_dir_close(distribution_dir); + } + g_dir_close(vendor_dir); + priv->stamp=g_random_int(); +} + +PloverLocalDistributions *plover_local_distributions_new(void) +{ + return g_object_new(PLOVER_TYPE_LOCAL_DISTRIBUTIONS,NULL); +}