XBPS Library API  0.19
The X Binary Package System
plist.c
1 /*-
2  * Copyright (c) 2008-2012 Juan Romero Pardines.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
15  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
16  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
17  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
18  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
19  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
21  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 
26 #include <stdio.h>
27 #include <stdbool.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <errno.h>
31 
32 #include "xbps_api_impl.h"
33 
34 /**
35  * @file lib/plist.c
36  * @brief PropertyList generic routines
37  * @defgroup plist PropertyList generic functions
38  *
39  * These functions manipulate plist files and objects shared by almost
40  * all library functions.
41  */
42 bool HIDDEN
43 xbps_add_obj_to_dict(prop_dictionary_t dict, prop_object_t obj,
44  const char *key)
45 {
46  assert(prop_object_type(dict) == PROP_TYPE_DICTIONARY);
47  assert(obj != NULL);
48  assert(key != NULL);
49 
50  if (!prop_dictionary_set(dict, key, obj)) {
51  prop_object_release(dict);
52  errno = EINVAL;
53  return false;
54  }
55 
56  prop_object_release(obj);
57  return true;
58 }
59 
60 bool HIDDEN
61 xbps_add_obj_to_array(prop_array_t array, prop_object_t obj)
62 {
63  assert(prop_object_type(array) == PROP_TYPE_ARRAY);
64  assert(obj != NULL);
65 
66  if (!prop_array_add(array, obj)) {
67  prop_object_release(array);
68  errno = EINVAL;
69  return false;
70  }
71 
72  prop_object_release(obj);
73  return true;
74 }
75 
76 int
78  prop_array_t array,
79  int (*fn)(struct xbps_handle *, prop_object_t, void *, bool *),
80  void *arg)
81 {
82  prop_object_t obj;
83  prop_object_iterator_t iter;
84  int rv = 0;
85  bool loop_done = false;
86 
87  assert(prop_object_type(array) == PROP_TYPE_ARRAY);
88  assert(fn != NULL);
89 
90  iter = prop_array_iterator(array);
91  if (iter == NULL)
92  return ENOMEM;
93 
94  while ((obj = prop_object_iterator_next(iter)) != NULL) {
95  rv = (*fn)(xhp, obj, arg, &loop_done);
96  if (rv != 0 || loop_done)
97  break;
98  }
99  prop_object_iterator_release(iter);
100 
101  return rv;
102 }
103 
104 int
106  prop_dictionary_t dict,
107  const char *key,
108  int (*fn)(struct xbps_handle *, prop_object_t, void *, bool *),
109  void *arg)
110 {
111  prop_object_t obj;
112  prop_array_t array;
113  size_t i;
114  int rv = 0;
115  bool cbloop_done = false;
116 
117  assert(prop_object_type(dict) == PROP_TYPE_DICTIONARY);
118  assert(xhp != NULL);
119  assert(key != NULL);
120  assert(fn != NULL);
121 
122  array = prop_dictionary_get(dict, key);
123  if (prop_object_type(array) != PROP_TYPE_ARRAY)
124  return EINVAL;
125 
126  for (i = 0; i < prop_array_count(array); i++) {
127  obj = prop_array_get(array, i);
128  if (obj == NULL)
129  continue;
130  rv = (*fn)(xhp, obj, arg, &cbloop_done);
131  if (rv != 0 || cbloop_done)
132  break;
133  }
134 
135  return rv;
136 }
137 
138 int
140  prop_array_t array,
141  int (*fn)(struct xbps_handle *, prop_object_t, void *, bool *),
142  void *arg)
143 {
144  prop_object_t obj;
145  unsigned int cnt;
146  int rv;
147  bool loop_done = false;
148 
149  assert(prop_object_type(array) == PROP_TYPE_ARRAY);
150  assert(fn != NULL);
151  assert(xhp != NULL);
152 
153  if ((cnt = prop_array_count(array)) == 0)
154  return 0;
155 
156  while (cnt--) {
157  obj = prop_array_get(array, cnt);
158  if (obj == NULL)
159  continue;
160  rv = (*fn)(xhp, obj, arg, &loop_done);
161  if (rv != 0 || loop_done)
162  break;
163  }
164 
165  return rv;
166 }
167 
168 int
170  prop_dictionary_t dict,
171  const char *key,
172  int (*fn)(struct xbps_handle *, prop_object_t, void *, bool *),
173  void *arg)
174 {
175  prop_array_t array;
176 
177  assert(prop_object_type(dict) == PROP_TYPE_DICTIONARY);
178  assert(key != NULL);
179  assert(fn != NULL);
180  assert(xhp != NULL);
181 
182  array = prop_dictionary_get(dict, key);
183  if (prop_object_type(array) != PROP_TYPE_ARRAY) {
184  xbps_dbg_printf(xhp, "invalid key '%s' for dictionary", key);
185  return EINVAL;
186  }
187 
188  return xbps_callback_array_iter_reverse(xhp, array, fn, arg);
189 }
190 
191 prop_object_iterator_t
192 xbps_array_iter_from_dict(prop_dictionary_t dict, const char *key)
193 {
194  prop_array_t array;
195 
196  assert(prop_object_type(dict) == PROP_TYPE_DICTIONARY);
197  assert(key != NULL);
198 
199  array = prop_dictionary_get(dict, key);
200  if (prop_object_type(array) != PROP_TYPE_ARRAY) {
201  errno = EINVAL;
202  return NULL;
203  }
204 
205  return prop_array_iterator(array);
206 }
207 
208 static int
209 array_replace_dict(prop_array_t array,
210  prop_dictionary_t dict,
211  const char *str,
212  bool bypattern)
213 {
214  prop_object_t obj;
215  size_t i;
216  const char *curpkgname;
217 
218  assert(prop_object_type(array) == PROP_TYPE_ARRAY);
219  assert(prop_object_type(dict) == PROP_TYPE_DICTIONARY);
220  assert(str != NULL);
221 
222  for (i = 0; i < prop_array_count(array); i++) {
223  obj = prop_array_get(array, i);
224  if (obj == NULL)
225  continue;
226  if (bypattern) {
227  /* pkgpattern match */
228  prop_dictionary_get_cstring_nocopy(obj,
229  "pkgver", &curpkgname);
230  if (xbps_pkgpattern_match(curpkgname, str)) {
231  if (!prop_array_set(array, i, dict))
232  return EINVAL;
233 
234  return 0;
235  }
236  } else {
237  /* pkgname match */
238  prop_dictionary_get_cstring_nocopy(obj,
239  "pkgname", &curpkgname);
240  if (strcmp(curpkgname, str) == 0) {
241  if (!prop_array_set(array, i, dict))
242  return EINVAL;
243 
244  return 0;
245  }
246  }
247  }
248  /* no match */
249  return ENOENT;
250 }
251 
252 int HIDDEN
253 xbps_array_replace_dict_by_name(prop_array_t array,
254  prop_dictionary_t dict,
255  const char *pkgname)
256 {
257  return array_replace_dict(array, dict, pkgname, false);
258 }
259 
260 int HIDDEN
261 xbps_array_replace_dict_by_pattern(prop_array_t array,
262  prop_dictionary_t dict,
263  const char *pattern)
264 {
265  return array_replace_dict(array, dict, pattern, true);
266 }