1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2014 Fabien Bourigault <bourigaultfabien@gmail.com>
4 *
5 * SPDX-License-Identifier: LGPL-2.1+
6 */
7
8 /**
9 * SECTION:asb-package-alpm
10 * @short_description: Object representing a .tar.xz (pacman) package file.
11 * @stability: Unstable
12 *
13 * This object represents one .tar.xz (pacman) package file.
14 */
15
16 #include "config.h"
17
18 #include <limits.h>
19
20 #include <alpm.h>
21
22 #include "asb-package-alpm.h"
23 #include "asb-plugin.h"
24
25 typedef struct
26 {
27 alpm_handle_t *handle;
28 alpm_pkg_t *package;
29 } AsbPackageAlpmPrivate;
30
G_DEFINE_TYPE_WITH_PRIVATE(AsbPackageAlpm,asb_package_alpm,ASB_TYPE_PACKAGE)31 G_DEFINE_TYPE_WITH_PRIVATE (AsbPackageAlpm, asb_package_alpm, ASB_TYPE_PACKAGE)
32
33 #define GET_PRIVATE(o) (asb_package_alpm_get_instance_private (o))
34
35 static void
36 asb_package_alpm_finalize (GObject *object)
37 {
38 AsbPackageAlpm *pkg = ASB_PACKAGE_ALPM (object);
39 AsbPackageAlpmPrivate *priv = GET_PRIVATE (pkg);
40
41 /* TODO: handle errors */
42 alpm_pkg_free (priv->package);
43 alpm_release (priv->handle);
44
45 G_OBJECT_CLASS (asb_package_alpm_parent_class)->finalize (object);
46 }
47
48 static void
asb_package_alpm_init(AsbPackageAlpm * pkg)49 asb_package_alpm_init (AsbPackageAlpm *pkg)
50 {
51 }
52
53 static GPtrArray *
asb_package_alpm_list_to_array(alpm_list_t * list)54 asb_package_alpm_list_to_array (alpm_list_t *list)
55 {
56 alpm_list_t *current;
57 GPtrArray *array = g_ptr_array_new_with_free_func (g_free);
58
59 for (current = list; current; current = alpm_list_next (current)) {
60 g_ptr_array_add (array, g_strdup (current->data));
61 }
62 g_ptr_array_add (array, NULL);
63
64 return array;
65 }
66
67 static gboolean
asb_package_alpm_ensure_license(AsbPackage * pkg,GError ** error)68 asb_package_alpm_ensure_license (AsbPackage *pkg, GError **error)
69 {
70 AsbPackageAlpm *pkg_alpm = ASB_PACKAGE_ALPM (pkg);
71 AsbPackageAlpmPrivate *priv = GET_PRIVATE (pkg_alpm);
72
73 alpm_list_t *alpm_licenses;
74 GPtrArray *licenses;
75 gchar *license;
76
77 alpm_licenses = alpm_pkg_get_licenses (priv->package);
78 licenses = asb_package_alpm_list_to_array (alpm_licenses);
79 /* TODO: translate licenses to SPDX licenses (makes licenses clickable
80 * is GNOME Software) */
81 license = g_strjoinv (" AND ", (gchar **)(licenses->pdata));
82
83 asb_package_set_license (pkg, license);
84
85 g_ptr_array_free (licenses, TRUE);
86 return TRUE;
87 }
88
89 static void
asb_package_alpm_ensure_version(AsbPackage * pkg,GError ** error)90 asb_package_alpm_ensure_version (AsbPackage *pkg, GError **error)
91 {
92 AsbPackageAlpm *pkg_alpm = ASB_PACKAGE_ALPM (pkg);
93 AsbPackageAlpmPrivate *priv = GET_PRIVATE (pkg_alpm);
94
95 g_auto(GStrv) split = NULL;
96
97 split = g_strsplit (alpm_pkg_get_version (priv->package), ":-", 3);
98
99 /* epoch:version:release */
100 if (g_strv_length (split) == 3) {
101 asb_package_set_epoch (pkg, (guint) g_ascii_strtoull (split[0], NULL, 0));
102 asb_package_set_version (pkg, split[1]);
103 asb_package_set_release (pkg, split[2]);
104 } else {/* version:release */
105 asb_package_set_version (pkg, split[0]);
106 asb_package_set_release (pkg, split[1]);
107 }
108 }
109
110 #if 0
111 static gboolean
112 asb_package_alpm_ensure_releases (AsbPackage *pkg, GError **error)
113 {
114 AsbPackageAlpm *pkg_alpm = ASB_PACKAGE_ALPM (pkg);
115 AsbPackageAlpmPrivate *priv = GET_PRIVATE (pkg_alpm);
116 return TRUE;
117 }
118 #endif
119
120 static gboolean
asb_package_alpm_ensure_depends(AsbPackage * pkg,GError ** error)121 asb_package_alpm_ensure_depends (AsbPackage *pkg, GError **error)
122 {
123 AsbPackageAlpm *pkg_alpm = ASB_PACKAGE_ALPM (pkg);
124 AsbPackageAlpmPrivate *priv = GET_PRIVATE (pkg_alpm);
125 alpm_list_t *alpm_depends;
126 alpm_list_t *current;
127
128 alpm_depends = alpm_pkg_get_depends (priv->package);
129 for (current = alpm_depends; current; current = alpm_list_next (current))
130 asb_package_add_dep (pkg, current->data);
131
132 return TRUE;
133 }
134
135 static gboolean
asb_package_alpm_ensure_filelists(AsbPackage * pkg,GError ** error)136 asb_package_alpm_ensure_filelists (AsbPackage *pkg, GError **error)
137 {
138 AsbPackageAlpm *pkg_alpm = ASB_PACKAGE_ALPM (pkg);
139 AsbPackageAlpmPrivate *priv = GET_PRIVATE (pkg_alpm);
140
141 alpm_filelist_t *pkgfiles = alpm_pkg_get_files (priv->package);
142 guint i;
143 GPtrArray *filelist = g_ptr_array_new_with_free_func (g_free);
144
145 for (i = 0; i < pkgfiles->count; i++) {
146 const alpm_file_t *file = pkgfiles->files + i;
147 g_ptr_array_add (filelist, g_strconcat ("/", file->name, NULL));
148 }
149 g_ptr_array_add (filelist, NULL);
150
151 asb_package_set_filelist (pkg, (gchar **)(filelist->pdata));
152
153 g_ptr_array_free (filelist, TRUE);
154 return TRUE;
155 }
156
157 static gboolean
asb_package_alpm_open(AsbPackage * pkg,const gchar * filename,GError ** error)158 asb_package_alpm_open (AsbPackage *pkg, const gchar *filename, GError **error)
159 {
160 AsbPackageAlpm *pkg_alpm = ASB_PACKAGE_ALPM (pkg);
161 AsbPackageAlpmPrivate *priv = GET_PRIVATE (pkg_alpm);
162
163 alpm_errno_t alpm_error;
164
165 /* initialize the alpm library */
166 priv->handle = alpm_initialize ("/", "/tmp", &alpm_error);
167 if (priv->handle == NULL) {
168 g_set_error (error,
169 ASB_PLUGIN_ERROR,
170 ASB_PLUGIN_ERROR_FAILED,
171 "libalpm initialization failed %s (%u) for %s",
172 alpm_strerror (alpm_error),
173 alpm_error,
174 filename);
175 return FALSE;
176 }
177
178 /* open the package */
179 if (alpm_pkg_load (priv->handle, filename, TRUE, 0, &priv->package) == -1) {
180 g_set_error (error,
181 ASB_PLUGIN_ERROR,
182 ASB_PLUGIN_ERROR_FAILED,
183 "Failed to load package %s : %s (%u)",
184 filename,
185 alpm_strerror (alpm_errno (priv->handle)),
186 alpm_errno (priv->handle));
187 alpm_release (priv->handle);
188 return FALSE;
189 }
190
191 asb_package_set_name (pkg, alpm_pkg_get_name (priv->package));
192 asb_package_set_url (pkg, alpm_pkg_get_url (priv->package));
193 asb_package_set_arch (pkg, alpm_pkg_get_arch (priv->package));
194 asb_package_alpm_ensure_version (pkg, error);
195
196 return TRUE;
197 }
198
199 static gint
asb_package_alpm_compare(AsbPackage * pkg1,AsbPackage * pkg2)200 asb_package_alpm_compare (AsbPackage *pkg1, AsbPackage *pkg2)
201 {
202 AsbPackageAlpm *pkg_alpm1 = ASB_PACKAGE_ALPM (pkg1);
203 AsbPackageAlpmPrivate *priv1 = GET_PRIVATE (pkg_alpm1);
204
205 AsbPackageAlpm *pkg_alpm2 = ASB_PACKAGE_ALPM (pkg2);
206 AsbPackageAlpmPrivate *priv2 = GET_PRIVATE (pkg_alpm2);
207
208 const gchar *pkg1_version = alpm_pkg_get_version (priv1->package);
209 const gchar *pkg2_version = alpm_pkg_get_version (priv2->package);
210
211 return alpm_pkg_vercmp (pkg1_version, pkg2_version);
212 }
213
214 static gboolean
asb_package_alpm_ensure(AsbPackage * pkg,AsbPackageEnsureFlags flags,GError ** error)215 asb_package_alpm_ensure (AsbPackage *pkg,
216 AsbPackageEnsureFlags flags,
217 GError **error)
218 {
219 if ((flags & ASB_PACKAGE_ENSURE_DEPS) > 0) {
220 if (!asb_package_alpm_ensure_depends (pkg, error))
221 return FALSE;
222 }
223 if ((flags & ASB_PACKAGE_ENSURE_FILES) > 0) {
224 if (!asb_package_alpm_ensure_filelists (pkg, error))
225 return FALSE;
226 }
227 if ((flags & ASB_PACKAGE_ENSURE_LICENSE) > 0) {
228 if (!asb_package_alpm_ensure_license (pkg, error))
229 return FALSE;
230 }
231 return TRUE;
232 }
233
234 static void
asb_package_alpm_class_init(AsbPackageAlpmClass * klass)235 asb_package_alpm_class_init (AsbPackageAlpmClass *klass)
236 {
237 AsbPackageClass *package_class = ASB_PACKAGE_CLASS (klass);
238 GObjectClass *object_class = G_OBJECT_CLASS (klass);
239
240 object_class->finalize = asb_package_alpm_finalize;
241 package_class->open = asb_package_alpm_open;
242 package_class->ensure = asb_package_alpm_ensure;
243 package_class->compare = asb_package_alpm_compare;
244 }
245
246 AsbPackage *
asb_package_alpm_new(void)247 asb_package_alpm_new (void)
248 {
249 AsbPackage *pkg;
250 pkg = g_object_new (ASB_TYPE_PACKAGE_ALPM, NULL);
251 return ASB_PACKAGE (pkg);
252 }
253