1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/app-manager/localdistributions.c Tue Apr 25 17:41:00 2023 +0100
1.3 @@ -0,0 +1,372 @@
1.4 +/*
1.5 + * Copyright (C) 2000 Red Hat, Inc., Jonathan Blandford <jrb@redhat.com>
1.6 + * Copyright (C) 2023 J. Ali Harlow <ali@juiblex.co.uk>
1.7 + *
1.8 + * This program is free software; you can redistribute it and/or modify
1.9 + * it under the terms of the GNU General Public License as published by
1.10 + * the Free Software Foundation; either version 2 of the License, or
1.11 + * (at your option) any later version.
1.12 + *
1.13 + * This program is distributed in the hope that it will be useful,
1.14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1.15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1.16 + * GNU General Public License for more details.
1.17 + *
1.18 + * You should have received a copy of the GNU General Public License along
1.19 + * with this program; if not, write to the Free Software Foundation, Inc.,
1.20 + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
1.21 + */
1.22 +
1.23 +#include "config.h"
1.24 +#include <stdlib.h>
1.25 +#include <string.h>
1.26 +#include <glib-object.h>
1.27 +#include <gtk/gtk.h>
1.28 +#include <plover/plover.h>
1.29 +#include "localdistributions.h"
1.30 +
1.31 +#define VALID_ITER(iter,local) ((iter) && (iter)->user_data && \
1.32 + PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local)->stamp==(iter)->stamp)
1.33 +
1.34 +static GType column_types[PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS];
1.35 +
1.36 +static void
1.37 + plover_local_distributions_tree_model_init(GtkTreeModelIface *iface);
1.38 +
1.39 +G_DEFINE_TYPE_WITH_CODE(PloverLocalDistributions,plover_local_distributions,
1.40 + G_TYPE_OBJECT,G_IMPLEMENT_INTERFACE(GTK_TYPE_TREE_MODEL,
1.41 + plover_local_distributions_tree_model_init));
1.42 +
1.43 +typedef struct _PloverLocalDistribution {
1.44 + gchar *vendor,*distribution,*prefix,*user_friendly,*database_uri;
1.45 +} PloverLocalDistribution;
1.46 +
1.47 +typedef struct _PloverLocalDistributionsPrivate {
1.48 + GList *distributions;
1.49 + int stamp;
1.50 +} PloverLocalDistributionsPrivate;
1.51 +
1.52 +#define PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(obj)\
1.53 + G_TYPE_INSTANCE_GET_PRIVATE(obj,\
1.54 + PLOVER_TYPE_LOCAL_DISTRIBUTIONS,\
1.55 + PloverLocalDistributionsPrivate)
1.56 +
1.57 +PloverLocalDistribution *plover_local_distribution_new(const char *vendor,
1.58 + const char *distribution)
1.59 +{
1.60 + gchar *s;
1.61 + struct comps *comps;
1.62 + PloverLocalDistribution *ld;
1.63 + ld=g_new0(PloverLocalDistribution,1);
1.64 + ld->vendor=g_strdup(vendor);
1.65 + if (distribution)
1.66 + {
1.67 + ld->distribution=g_strdup(distribution);
1.68 + ld->user_friendly=g_strdup_printf("%s (%s)",distribution,vendor);
1.69 + }
1.70 + else
1.71 + ld->user_friendly=g_strdup(vendor);
1.72 + comps=plover_comps_new();
1.73 + plover_comps_set_vendor(comps,vendor);
1.74 + if (distribution)
1.75 + plover_comps_set_distribution(comps,distribution);
1.76 + ld->prefix=plover_comps_get_default_prefix(comps);
1.77 + plover_comps_free(comps);
1.78 + s=g_build_filename(ld->prefix,"var","lib","razor",NULL);
1.79 + ld->database_uri=razor_path_to_uri(s);
1.80 + g_free(s);
1.81 + return ld;
1.82 +}
1.83 +
1.84 +void plover_local_distribution_free(PloverLocalDistribution *ld)
1.85 +{
1.86 + if (ld)
1.87 + {
1.88 + g_free(ld->vendor);
1.89 + g_free(ld->distribution);
1.90 + g_free(ld->prefix);
1.91 + g_free(ld->user_friendly);
1.92 + g_free(ld->database_uri);
1.93 + g_free(ld);
1.94 + }
1.95 +}
1.96 +
1.97 +static void plover_local_distributions_finalize(GObject *obj)
1.98 +{
1.99 + PloverLocalDistributionsPrivate *priv;
1.100 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(obj);
1.101 + g_list_foreach(priv->distributions,(GFunc)plover_local_distribution_free,
1.102 + NULL);
1.103 + g_list_free(priv->distributions);
1.104 + if (G_OBJECT_CLASS(plover_local_distributions_parent_class)->finalize)
1.105 + G_OBJECT_CLASS(plover_local_distributions_parent_class)->finalize(obj);
1.106 +}
1.107 +
1.108 +static void
1.109 + plover_local_distributions_class_init(PloverLocalDistributionsClass *klass)
1.110 +{
1.111 + GObjectClass *oclass=G_OBJECT_CLASS(klass);
1.112 + oclass->finalize=plover_local_distributions_finalize;
1.113 + g_type_class_add_private(klass,sizeof(PloverLocalDistributionsPrivate));
1.114 + column_types[PLOVER_LOCAL_DISTRIBUTIONS_VENDOR_COLUMN]=G_TYPE_STRING;
1.115 + column_types[PLOVER_LOCAL_DISTRIBUTIONS_DISTRIBUTION_COLUMN]=G_TYPE_STRING;
1.116 + column_types[PLOVER_LOCAL_DISTRIBUTIONS_PREFIX_COLUMN]=G_TYPE_STRING;
1.117 + column_types[PLOVER_LOCAL_DISTRIBUTIONS_USER_FRIENDLY_COLUMN]=G_TYPE_STRING;
1.118 + column_types[PLOVER_LOCAL_DISTRIBUTIONS_DATABASE_URI_COLUMN]=G_TYPE_STRING;
1.119 +}
1.120 +
1.121 +static GtkTreeModelFlags
1.122 +plover_local_distributions_get_flags(GtkTreeModel *tree_model)
1.123 +{
1.124 + return GTK_TREE_MODEL_ITERS_PERSIST|GTK_TREE_MODEL_LIST_ONLY;
1.125 +}
1.126 +
1.127 +static gint plover_local_distributions_get_n_columns(GtkTreeModel *tree_model)
1.128 +{
1.129 + return PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS;
1.130 +}
1.131 +
1.132 +static GType
1.133 + plover_local_distributions_get_column_type(GtkTreeModel *tree_model,gint indx)
1.134 +{
1.135 + g_return_val_if_fail(indx>=0 && indx<PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS,
1.136 + G_TYPE_INVALID);
1.137 + return column_types[indx];
1.138 +}
1.139 +
1.140 +static gboolean plover_local_distributions_get_iter(GtkTreeModel *tree_model,
1.141 + GtkTreeIter *iter,GtkTreePath *path)
1.142 +{
1.143 + int i;
1.144 + PloverLocalDistributionsPrivate *priv;
1.145 + PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model;
1.146 + PloverLocalDistribution *ld;
1.147 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local);
1.148 + i=gtk_tree_path_get_indices(path)[0];
1.149 + ld=g_list_nth_data(priv->distributions,i);
1.150 + if (!ld)
1.151 + return FALSE;
1.152 + iter->stamp=priv->stamp;
1.153 + iter->user_data=ld;
1.154 + return TRUE;
1.155 +}
1.156 +
1.157 +static GtkTreePath *
1.158 + plover_local_distributions_get_path(GtkTreeModel *tree_model,
1.159 + GtkTreeIter *iter)
1.160 +{
1.161 + GtkTreePath *path;
1.162 + PloverLocalDistributionsPrivate *priv;
1.163 + PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model;
1.164 + g_return_val_if_fail(VALID_ITER(iter,tree_model),NULL);
1.165 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local);
1.166 + path=gtk_tree_path_new();
1.167 + gtk_tree_path_append_index(path,
1.168 + g_list_index(priv->distributions,iter->user_data));
1.169 + return path;
1.170 +}
1.171 +
1.172 +static void plover_local_distributions_get_value(GtkTreeModel *tree_model,
1.173 + GtkTreeIter *iter,gint column,GValue *value)
1.174 +{
1.175 + gchar *s;
1.176 + PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model;
1.177 + PloverLocalDistribution *ld;
1.178 + g_return_if_fail(column>=0 && column<PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS);
1.179 + g_return_if_fail(VALID_ITER(iter,local));
1.180 + ld=iter->user_data;
1.181 + g_value_init(value,column_types[column]);
1.182 + switch((PloverLocalDistributionsColumn)column)
1.183 + {
1.184 + case PLOVER_LOCAL_DISTRIBUTIONS_VENDOR_COLUMN:
1.185 + g_value_set_string(value,ld->vendor);
1.186 + break;
1.187 + case PLOVER_LOCAL_DISTRIBUTIONS_DISTRIBUTION_COLUMN:
1.188 + g_value_set_string(value,ld->distribution);
1.189 + break;
1.190 + case PLOVER_LOCAL_DISTRIBUTIONS_PREFIX_COLUMN:
1.191 + g_value_set_string(value,ld->prefix);
1.192 + break;
1.193 + case PLOVER_LOCAL_DISTRIBUTIONS_USER_FRIENDLY_COLUMN:
1.194 + g_value_set_string(value,ld->user_friendly);
1.195 + break;
1.196 + case PLOVER_LOCAL_DISTRIBUTIONS_DATABASE_URI_COLUMN:
1.197 + g_value_set_string(value,ld->database_uri);
1.198 + break;
1.199 + case PLOVER_LOCAL_DISTRIBUTIONS_NO_COLUMNS:
1.200 + /* Quieten compiler warning */
1.201 + break;
1.202 + }
1.203 +}
1.204 +
1.205 +static gboolean
1.206 + plover_local_distributions_iter_next(GtkTreeModel *tree_model,
1.207 + GtkTreeIter *iter)
1.208 +{
1.209 + GList *lnk;
1.210 + PloverLocalDistributions *local=(PloverLocalDistributions *)tree_model;
1.211 + PloverLocalDistributionsPrivate *priv;
1.212 + g_return_val_if_fail(VALID_ITER(iter,tree_model),FALSE);
1.213 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(local);
1.214 + lnk=g_list_find(priv->distributions,iter->user_data);
1.215 + iter->user_data=lnk->next?lnk->next->data:NULL;
1.216 + return !!iter->user_data;
1.217 +}
1.218 +
1.219 +static gboolean
1.220 + plover_local_distributions_iter_children(GtkTreeModel *tree_model,
1.221 + GtkTreeIter *iter,GtkTreeIter *parent)
1.222 +{
1.223 + PloverLocalDistributionsPrivate *priv;
1.224 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model);
1.225 + /* this is a list, nodes have no children */
1.226 + if (parent)
1.227 + return FALSE;
1.228 + if (priv->distributions)
1.229 + {
1.230 + iter->stamp=priv->stamp;
1.231 + iter->user_data=priv->distributions->data;
1.232 + return TRUE;
1.233 + }
1.234 + else
1.235 + return FALSE;
1.236 +}
1.237 +
1.238 +static gboolean
1.239 + plover_local_distributions_iter_has_child(GtkTreeModel *tree_model,
1.240 + GtkTreeIter *iter)
1.241 +{
1.242 + PloverLocalDistributionsPrivate *priv;
1.243 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model);
1.244 + return !!priv->distributions;
1.245 +}
1.246 +
1.247 +static gint plover_local_distributions_iter_n_children(GtkTreeModel *tree_model,
1.248 + GtkTreeIter *iter)
1.249 +{
1.250 + PloverLocalDistributionsPrivate *priv;
1.251 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model);
1.252 + if (!iter)
1.253 + return g_list_length(priv->distributions);
1.254 + g_return_val_if_fail(VALID_ITER(iter,tree_model),-1);
1.255 + return 0;
1.256 +}
1.257 +
1.258 +static gboolean
1.259 + plover_local_distributions_iter_nth_child(GtkTreeModel *tree_model,
1.260 + GtkTreeIter *iter,GtkTreeIter *parent,gint n)
1.261 +{
1.262 + GList *lnk;
1.263 + PloverLocalDistributionsPrivate *priv;
1.264 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(tree_model);
1.265 + if (parent)
1.266 + return FALSE;
1.267 + lnk=g_list_nth(priv->distributions,n);
1.268 + if (!lnk)
1.269 + return FALSE;
1.270 + iter->stamp=priv->stamp;
1.271 + iter->user_data=lnk->data;
1.272 + return TRUE;
1.273 +}
1.274 +
1.275 +static gboolean plover_local_distributions_iter_parent(GtkTreeModel *tree_model,
1.276 + GtkTreeIter *iter,GtkTreeIter *child)
1.277 +{
1.278 + return FALSE;
1.279 +}
1.280 +
1.281 +static void plover_local_distributions_tree_model_init(GtkTreeModelIface *iface)
1.282 +{
1.283 + iface->get_flags=plover_local_distributions_get_flags;
1.284 + iface->get_n_columns=plover_local_distributions_get_n_columns;
1.285 + iface->get_column_type=plover_local_distributions_get_column_type;
1.286 + iface->get_iter=plover_local_distributions_get_iter;
1.287 + iface->get_path=plover_local_distributions_get_path;
1.288 + iface->get_value=plover_local_distributions_get_value;
1.289 + iface->iter_next=plover_local_distributions_iter_next;
1.290 + iface->iter_children=plover_local_distributions_iter_children;
1.291 + iface->iter_has_child=plover_local_distributions_iter_has_child;
1.292 + iface->iter_n_children=plover_local_distributions_iter_n_children;
1.293 + iface->iter_nth_child=plover_local_distributions_iter_nth_child;
1.294 + iface->iter_parent=plover_local_distributions_iter_parent;
1.295 +}
1.296 +
1.297 +static void plover_local_distributions_init(PloverLocalDistributions *store)
1.298 +{
1.299 + gchar *s;
1.300 + const char *vendor_prefix,*vendor,*distribution;
1.301 + GDir *vendor_dir,*distribution_dir,*database_dir;
1.302 + PloverLocalDistributionsPrivate *priv;
1.303 + PloverLocalDistribution *ld;
1.304 + priv=PLOVER_LOCAL_DISTRIBUTIONS_GET_PRIVATE(store);
1.305 + /*
1.306 + * local distribution databases may be found in
1.307 + * <vendor-prefix>/$VENDOR/$DISTRIBUTION/var/lib/razor and
1.308 + * <vendor-prefix>/$VENDOR/var/lib/razor
1.309 + */
1.310 + vendor_prefix=plover_get_vendor_prefix();
1.311 + g_message("Vendor prefix is %s",vendor_prefix);
1.312 + vendor_dir=g_dir_open(vendor_prefix,0,NULL);
1.313 + if (!vendor_dir)
1.314 + {
1.315 + g_warning("Failed to open %s",vendor_prefix);
1.316 + return;
1.317 + }
1.318 + while((vendor=g_dir_read_name(vendor_dir)))
1.319 + {
1.320 + g_message("Candidate for vendor is %s",vendor);
1.321 + s=g_build_filename(vendor_prefix,vendor,NULL);
1.322 + distribution_dir=g_dir_open(s,0,NULL);
1.323 + g_free(s);
1.324 + if (!distribution_dir)
1.325 + {
1.326 + g_warning("Failed to open %s/%s",vendor_prefix,vendor);
1.327 + continue;
1.328 + }
1.329 + while((distribution=g_dir_read_name(distribution_dir)))
1.330 + {
1.331 + g_message("Candidate for distribution is %s",distribution);
1.332 + if (!strcmp(distribution,"var"))
1.333 + {
1.334 + s=g_build_filename(vendor_prefix,vendor,"var","lib","razor",
1.335 + NULL);
1.336 + database_dir=g_dir_open(s,0,NULL);
1.337 + g_free(s);
1.338 + if (database_dir)
1.339 + {
1.340 + ld=plover_local_distribution_new(vendor,NULL);
1.341 + g_message("Found vendor-specific razor database at %s",
1.342 + ld->database_uri);
1.343 + priv->distributions=g_list_prepend(priv->distributions,ld);
1.344 + g_dir_close(database_dir);
1.345 + }
1.346 + else
1.347 + g_warning("Failed to open %s/%s/var/lib/razor",
1.348 + vendor_prefix,vendor);
1.349 + }
1.350 + s=g_build_filename(vendor_prefix,vendor,distribution,
1.351 + "var","lib","razor",NULL);
1.352 + database_dir=g_dir_open(s,0,NULL);
1.353 + g_free(s);
1.354 + if (database_dir)
1.355 + {
1.356 + ld=plover_local_distribution_new(vendor,distribution);
1.357 + g_message("Found local-distribution razor database at %s",
1.358 + ld->database_uri);
1.359 + priv->distributions=g_list_prepend(priv->distributions,ld);
1.360 + g_dir_close(database_dir);
1.361 + }
1.362 + else
1.363 + g_warning("Failed to open %s/%s/%s/var/lib/razor",
1.364 + vendor_prefix,vendor,distribution);
1.365 + }
1.366 + g_dir_close(distribution_dir);
1.367 + }
1.368 + g_dir_close(vendor_dir);
1.369 + priv->stamp=g_random_int();
1.370 +}
1.371 +
1.372 +PloverLocalDistributions *plover_local_distributions_new(void)
1.373 +{
1.374 + return g_object_new(PLOVER_TYPE_LOCAL_DISTRIBUTIONS,NULL);
1.375 +}