]> git.ipfire.org Git - pakfire.git/blame - src/libpakfire/buildservice.c
buildservice: Log a message when we initialized properly
[pakfire.git] / src / libpakfire / buildservice.c
CommitLineData
931d97a0
MT
1/*#############################################################################
2# #
3# Pakfire - The IPFire package management system #
4# Copyright (C) 2021 Pakfire development team #
5# #
6# This program is free software: you can redistribute it and/or modify #
7# it under the terms of the GNU General Public License as published by #
8# the Free Software Foundation, either version 3 of the License, or #
9# (at your option) any later version. #
10# #
11# This program is distributed in the hope that it will be useful, #
12# but WITHOUT ANY WARRANTY; without even the implied warranty of #
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
14# GNU General Public License for more details. #
15# #
16# You should have received a copy of the GNU General Public License #
17# along with this program. If not, see <http://www.gnu.org/licenses/>. #
18# #
19#############################################################################*/
20
21#include <errno.h>
3d2cc9e6 22#include <limits.h>
931d97a0
MT
23#include <stdlib.h>
24
57a8b2d4
MT
25#include <json.h>
26
931d97a0 27#include <pakfire/buildservice.h>
3d2cc9e6 28#include <pakfire/config.h>
931d97a0 29#include <pakfire/ctx.h>
01840335 30#include <pakfire/digest.h>
10db1fae 31#include <pakfire/httpclient.h>
3d2cc9e6 32#include <pakfire/logging.h>
01840335 33#include <pakfire/path.h>
931d97a0 34#include <pakfire/private.h>
3d2cc9e6 35#include <pakfire/string.h>
57a8b2d4 36#include <pakfire/util.h>
c26aca37 37#include <pakfire/xfer.h>
931d97a0 38
ff5cb6ba
MT
39#include <krb5/krb5.h>
40
1e4b70d0
MT
41#define DEFAULT_KEYTAB "/etc/krb5.keytab"
42
931d97a0
MT
43struct pakfire_buildservice {
44 struct pakfire_ctx* ctx;
45 int nrefs;
3d2cc9e6 46
d188b602 47 // Configuration
3d2cc9e6 48 char url[PATH_MAX];
1e4b70d0 49 char keytab[PATH_MAX];
d188b602
MT
50
51 // A HTTP Client
10db1fae 52 struct pakfire_httpclient* httpclient;
ff5cb6ba
MT
53
54 // Kerberos Context
55 krb5_context krb5_ctx;
931d97a0
MT
56};
57
ff5cb6ba
MT
58static int pakfire_buildservice_setup_auth(struct pakfire_buildservice* service) {
59 const char* error = NULL;
60 int r;
61
62 // Setup a Kerberos context
63 r = krb5_init_context(&service->krb5_ctx);
64 if (r) {
65 error = krb5_get_error_message(service->krb5_ctx, r);
66
67 CTX_ERROR(service->ctx, "Could not initialize Kerberos: %s\n", error);
68 krb5_free_error_message(service->krb5_ctx, error);
69
70 goto ERROR;
71 }
72
73ERROR:
74 return r;
75}
76
3d2cc9e6
MT
77static int pakfire_buildservice_setup(struct pakfire_buildservice* service) {
78 struct pakfire_config* config = NULL;
79 const char* url = NULL;
1e4b70d0 80 const char* keytab = NULL;
3d2cc9e6
MT
81 int r;
82
83 // Fetch the configuration
84 config = pakfire_ctx_get_config(service->ctx);
85 if (!config) {
86 r = 1;
87 goto ERROR;
88 }
89
90 // Fetch the URL
91 url = pakfire_config_get(config, "client", "url", NULL);
92 if (!url) {
93 CTX_ERROR(service->ctx, "Build Service URL is not configured\n");
94 r = 1;
95 goto ERROR;
96 }
97
98 // Store the URL
99 r = pakfire_string_set(service->url, url);
100 if (r)
101 goto ERROR;
102
1e4b70d0
MT
103 // Fetch the keytab
104 keytab = pakfire_config_get(config, "client", "keytab", DEFAULT_KEYTAB);
105
106 // Store the keytab
107 r = pakfire_string_set(service->keytab, keytab);
108 if (r)
109 goto ERROR;
110
10db1fae
MT
111 // Setup the HTTP client
112 r = pakfire_httpclient_create(&service->httpclient, service->ctx);
d188b602
MT
113 if (r)
114 goto ERROR;
115
ff5cb6ba
MT
116 // Setup authentication
117 r = pakfire_buildservice_setup_auth(service);
118 if (r)
119 goto ERROR;
120
3d2cc9e6
MT
121ERROR:
122 if (config)
123 pakfire_config_unref(config);
124
125 return r;
126}
127
931d97a0 128static void pakfire_buildservice_free(struct pakfire_buildservice* service) {
ff5cb6ba
MT
129 if (service->krb5_ctx)
130 krb5_free_context(service->krb5_ctx);
d188b602 131 if (service->httpclient)
10db1fae 132 pakfire_httpclient_unref(service->httpclient);
931d97a0
MT
133 if (service->ctx)
134 pakfire_ctx_unref(service->ctx);
135
136 free(service);
137}
138
139PAKFIRE_EXPORT int pakfire_buildservice_create(
140 struct pakfire_buildservice** service, struct pakfire_ctx* ctx) {
141 struct pakfire_buildservice* s = NULL;
3d2cc9e6 142 int r;
931d97a0
MT
143
144 // Allocate some memory
145 s = calloc(1, sizeof(*s));
146 if (!s)
147 return -errno;
148
149 // Store a reference to the context
150 s->ctx = pakfire_ctx_ref(ctx);
151
152 // Initialize the reference counter
153 s->nrefs = 1;
154
3d2cc9e6
MT
155 // Setup everything
156 r = pakfire_buildservice_setup(s);
157 if (r)
158 goto ERROR;
159
bc10d86d
MT
160 CTX_DEBUG(s->ctx, "Pakfire Build Service initialized for %s\n", s->url);
161
931d97a0
MT
162 // Return the pointer
163 *service = s;
164
165 return 0;
3d2cc9e6
MT
166
167ERROR:
168 pakfire_buildservice_free(s);
169
170 return r;
931d97a0
MT
171}
172
173PAKFIRE_EXPORT struct pakfire_buildservice* pakfire_buildservice_ref(
174 struct pakfire_buildservice* service) {
175 ++service->nrefs;
176
177 return service;
178}
179
180PAKFIRE_EXPORT struct pakfire_buildservice* pakfire_buildservice_unref(
181 struct pakfire_buildservice* service) {
182 if (--service->nrefs > 0)
183 return service;
184
185 pakfire_buildservice_free(service);
186 return NULL;
187}
57a8b2d4 188
04cc2479
MT
189PAKFIRE_EXPORT const char* pakfire_buildservice_get_url(struct pakfire_buildservice* service) {
190 return service->url;
191}
192
c26aca37 193static int pakfire_buildservice_create_xfer(struct pakfire_xfer** xfer,
57a8b2d4 194 struct pakfire_buildservice* service, const char* url) {
c26aca37 195 struct pakfire_xfer* t = NULL;
57a8b2d4
MT
196 int r;
197
c26aca37 198 // Create a new xfer
10db1fae 199 r = pakfire_httpclient_create_xfer(&t, service->httpclient, url);
57a8b2d4
MT
200 if (r)
201 goto ERROR;
202
203 // Set the base URL
c26aca37 204 r = pakfire_xfer_set_baseurl(t, service->url);
57a8b2d4
MT
205 if (r)
206 goto ERROR;
207
c26aca37
MT
208 // Return the new xfer
209 *xfer = pakfire_xfer_ref(t);
57a8b2d4
MT
210
211ERROR:
212 if (t)
c26aca37 213 pakfire_xfer_unref(t);
57a8b2d4
MT
214
215 return r;
216}
217
33de78f2 218static int pakfire_buildservice_handle_error(struct pakfire_buildservice* service,
c26aca37 219 struct pakfire_xfer* xfer, const struct json_object* error) {
33de78f2
MT
220 struct json_object* message = NULL;
221 struct json_object* code = NULL;
222 const char* m = NULL;
223 unsigned int c = 0;
224
225 // Fetch the URL
c26aca37 226 const char* url = pakfire_xfer_get_effective_url(xfer);
33de78f2
MT
227
228 // Fetch the code
229 if (!json_object_object_get_ex(error, "code", &code))
230 return -EBADMSG;
231
232 // Check if the code is an integer
233 if (!json_object_is_type(code, json_type_int))
234 return -EBADMSG;
235
236 // Fetch the message
237 if (!json_object_object_get_ex(error, "message", &message))
238 return -EBADMSG;
239
240 // Check if the message is a string
241 if (!json_object_is_type(message, json_type_string))
242 return -EBADMSG;
243
244 c = json_object_get_uint64(code);
245 m = json_object_get_string(message);
246
247 // Log the error
605615a2
MT
248 CTX_ERROR(service->ctx, "%s responded with error %u (%s):\n %s\n",
249 url, c, strerror(c), m);
33de78f2 250
605615a2 251 return -c;
33de78f2
MT
252}
253
254/*
255 This function parses an API response
256*/
257static int pakfire_buildservice_parse_response(struct pakfire_buildservice* service,
c26aca37 258 struct pakfire_xfer* xfer, const char* buffer, const size_t length,
33de78f2
MT
259 struct json_object** object) {
260 struct json_object* error = NULL;
261 struct json_object* o = NULL;
262 int r;
263
cc2371c1
MT
264 // Check if we received any data
265 if (!length) {
266 CTX_ERROR(service->ctx, "Received an empty response\n");
267 r = -EBADMSG;
268 goto ERROR;
269 }
270
33de78f2
MT
271 // XXX Maybe fetch the parser's error message here?!
272
273 // Parse the buffer
274 o = pakfire_json_parse(service->ctx, buffer, length);
275 if (!o) {
276 CTX_ERROR(service->ctx, "Could not parse the response\n");
277 r = -EBADMSG;
278 goto ERROR;
279 }
280
281 // Check if the response is a dictionary
282 if (!json_object_is_type(o, json_type_object)) {
283 CTX_ERROR(service->ctx, "The received object is not a JSON dict\n");
284 r = -EBADMSG;
285 goto ERROR;
286 }
287
288 // Fetch error
289 r = json_object_object_get_ex(o, "error", &error);
290 if (r) {
c26aca37 291 r = pakfire_buildservice_handle_error(service, xfer, error);
33de78f2
MT
292 goto ERROR;
293 }
294
295 // Return the object
296 *object = o;
297
298 return 0;
299
300ERROR:
301 if (o)
302 json_object_put(o);
303
304 return r;
305}
306
27629aaf
MT
307// Build
308
309int pakfire_buildservice_build(struct pakfire_buildservice* service, const char* upload,
310 const char* repo, const char** arches, int flags) {
c26aca37 311 struct pakfire_xfer* xfer = NULL;
27629aaf
MT
312 struct json_object* response = NULL;
313 char* buffer = NULL;
314 size_t length = 0;
315 int r;
316
c26aca37
MT
317 // Create a new xfer
318 r = pakfire_buildservice_create_xfer(&xfer, service, "/api/v1/builds");
27629aaf
MT
319 if (r)
320 goto ERROR;
321
322 // Enable authentication
c26aca37 323 r = pakfire_xfer_auth(xfer);
27629aaf
MT
324 if (r)
325 goto ERROR;
326
327 // Add the upload parameter
c26aca37 328 r = pakfire_xfer_add_param(xfer, "upload", "%s", upload);
27629aaf
MT
329 if (r)
330 goto ERROR;
331
332 // Add the repo parameter
c26aca37 333 r = pakfire_xfer_add_param(xfer, "repo", "%s", repo);
27629aaf
MT
334 if (r)
335 goto ERROR;
336
337 // Add any arches
338 if (arches) {
339 for (const char** arch = arches; *arch; arch++) {
c26aca37 340 r = pakfire_xfer_add_param(xfer, "arch", "%s", *arch);
27629aaf
MT
341 if (r)
342 goto ERROR;
343 }
344 }
345
346 // Disable tests?
347 if (flags & PAKFIRE_BUILD_DISABLE_TESTS) {
c26aca37 348 r = pakfire_xfer_add_param(xfer, "disable_test_builds", "%s", "yes");
27629aaf
MT
349 if (r)
350 goto ERROR;
351 }
352
353 // Write the response to the buffer
c26aca37 354 r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length);
27629aaf
MT
355 if (r)
356 goto ERROR;
357
c26aca37
MT
358 // Run the xfer
359 r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS);
27629aaf
MT
360 if (r)
361 goto ERROR;
362
363 // Parse the response
c26aca37 364 r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response);
27629aaf
MT
365 if (r) {
366 CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r));
367 goto ERROR;
368 }
369
370ERROR:
c26aca37
MT
371 if (xfer)
372 pakfire_xfer_unref(xfer);
27629aaf
MT
373 if (response)
374 json_object_put(response);
375 if (buffer)
376 free(buffer);
377
378 return r;
379}
380
57a8b2d4
MT
381// Uploads
382
01840335
MT
383static int pakfire_buildservice_create_upload(struct pakfire_buildservice* service,
384 const char* path, const char* filename, FILE* f, char** uuid) {
c26aca37 385 struct pakfire_xfer* xfer = NULL;
27e7b6f6 386 struct pakfire_digests digests = {};
01840335
MT
387 struct json_object* response = NULL;
388 struct json_object* id = NULL;
01840335
MT
389 const char* __id = NULL;
390 char* hexdigest = NULL;
391 char* buffer = NULL;
392 size_t length = 0;
393 struct stat stat;
394 int r;
395
396 const int fd = fileno(f);
397
398 // Stat the file
399 r = fstat(fd, &stat);
400 if (r) {
401 CTX_ERROR(service->ctx, "Could not stat %s: %s\n", path, strerror(errno));
402 goto ERROR;
403 }
404
405 // Compute the digest
406 r = pakfire_digests_compute_from_file(service->ctx, &digests, PAKFIRE_DIGEST_BLAKE2B512, f);
407 if (r) {
408 CTX_ERROR(service->ctx, "Could not compute the digest of %s: %s\n",
409 path, strerror(-r));
410 goto ERROR;
411 }
412
413 // Convert the digest into hex format
414 hexdigest = pakfire_digest_get_hex(&digests, PAKFIRE_DIGEST_BLAKE2B512);
415 if (!hexdigest)
416 goto ERROR;
417
c26aca37
MT
418 // Create a new xfer
419 r = pakfire_buildservice_create_xfer(&xfer, service, "/api/v1/uploads");
01840335
MT
420 if (r)
421 goto ERROR;
422
423 // Enable authentication
c26aca37 424 r = pakfire_xfer_auth(xfer);
01840335
MT
425 if (r)
426 goto ERROR;
427
428 // Add the filename parameter
c26aca37 429 r = pakfire_xfer_add_param(xfer, "filename", "%s", filename);
01840335
MT
430 if (r)
431 goto ERROR;
432
433 // Add the size parameter
c26aca37 434 r = pakfire_xfer_add_param(xfer, "size", "%jd", stat.st_size);
01840335
MT
435 if (r)
436 goto ERROR;
437
438 // Add the hexdigest algo parameter
c26aca37 439 r = pakfire_xfer_add_param(xfer, "hexdigest_algo", "%s", "blake2b512");
01840335
MT
440 if (r)
441 goto ERROR;
442
443 // Add the hexdigest parameter
c26aca37 444 r = pakfire_xfer_add_param(xfer, "hexdigest", "%s", hexdigest);
01840335
MT
445 if (r)
446 goto ERROR;
447
448 // Write the response to the buffer
c26aca37 449 r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length);
01840335
MT
450 if (r)
451 goto ERROR;
452
c26aca37
MT
453 // Run the xfer
454 r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS);
01840335
MT
455 if (r)
456 goto ERROR;
457
33de78f2 458 // Parse the response
c26aca37 459 r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response);
33de78f2
MT
460 if (r) {
461 CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r));
01840335
MT
462 goto ERROR;
463 }
464
465 // Fetch the ID
466 r = json_object_object_get_ex(response, "id", &id);
467 if (r == 0) {
468 CTX_ERROR(service->ctx, "Could not fetch ID from response\n");
469 r = -EBADMSG;
470 goto ERROR;
471 }
472
473 // Extract the UUID
474 __id = json_object_get_string(id);
475 if (!__id) {
476 CTX_ERROR(service->ctx, "Could not fetch ID from response\n");
477 r = -EBADMSG;
478 goto ERROR;
479 }
480
481 // Return the UUID
482 *uuid = strdup(__id);
483 if (!*uuid) {
484 r = -errno;
485 goto ERROR;
486 }
487
488 // Success
489 r = 0;
490
491ERROR:
c26aca37
MT
492 if (xfer)
493 pakfire_xfer_unref(xfer);
01840335
MT
494 if (response)
495 json_object_put(response);
496 if (hexdigest)
497 free(hexdigest);
498 if (buffer)
499 free(buffer);
500
501 return r;
502}
503
504static int pakfire_buildservice_upload_payload(struct pakfire_buildservice* service,
505 const char* filename, const char* uuid, FILE* f) {
c26aca37 506 struct pakfire_xfer* xfer = NULL;
33de78f2
MT
507 struct json_object* response = NULL;
508 char* buffer = NULL;
509 size_t length = 0;
01840335
MT
510 char url[PATH_MAX];
511 int r;
512
513 // Make the URL
514 r = pakfire_string_format(url, "/api/v1/uploads/%s", uuid);
515 if (r)
516 goto ERROR;
517
c26aca37
MT
518 // Create a new xfer
519 r = pakfire_buildservice_create_xfer(&xfer, service, url);
01840335
MT
520 if (r)
521 goto ERROR;
522
523 // Set the title
c26aca37 524 r = pakfire_xfer_set_title(xfer, filename);
01840335
MT
525 if (r)
526 goto ERROR;
527
528 // Set source file
c26aca37 529 r = pakfire_xfer_set_input(xfer, f);
01840335
MT
530 if (r)
531 goto ERROR;
532
33de78f2 533 // Set the output buffer
c26aca37 534 r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length);
33de78f2
MT
535 if (r)
536 goto ERROR;
537
c26aca37
MT
538 // Run the xfer
539 r = pakfire_xfer_run(xfer, 0);
01840335
MT
540 if (r)
541 goto ERROR;
542
33de78f2 543 // Parse the response
c26aca37 544 r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response);
33de78f2
MT
545 if (r) {
546 CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r));
547 goto ERROR;
548 }
549
01840335 550ERROR:
c26aca37
MT
551 if (xfer)
552 pakfire_xfer_unref(xfer);
33de78f2
MT
553 if (response)
554 json_object_put(response);
01840335
MT
555
556 return r;
557}
558
559PAKFIRE_EXPORT int pakfire_buildservice_upload(struct pakfire_buildservice* service,
81adcd5c 560 const char* path, const char* filename, char** uuid) {
01840335 561 char basename[NAME_MAX];
01840335
MT
562 FILE* f = NULL;
563 int r;
564
565 // Compute the basename
566 r = pakfire_path_basename(basename, path);
567 if (r)
568 goto ERROR;
569
570 // Set the basename as default filename
571 if (!filename)
572 filename = basename;
573
574 // Open the source file
575 f = fopen(path, "r");
576 if (!f) {
577 CTX_ERROR(service->ctx, "Could not open file for upload %s: %m\n", path);
578 return -errno;
579 }
580
581 // Create a new upload
81adcd5c 582 r = pakfire_buildservice_create_upload(service, path, filename, f, uuid);
01840335
MT
583 if (r)
584 goto ERROR;
585
81adcd5c 586 CTX_DEBUG(service->ctx, "Created a new download (%s)\n", *uuid);
01840335
MT
587
588 // Send the payload
81adcd5c 589 r = pakfire_buildservice_upload_payload(service, filename, *uuid, f);
01840335
MT
590 if (r)
591 goto ERROR;
592
593ERROR:
81adcd5c
MT
594 if (r) {
595 if (*uuid)
596 free(*uuid);
597
598 *uuid = NULL;
599 }
01840335
MT
600 if (f)
601 fclose(f);
602
603 return r;
604}
605
57a8b2d4
MT
606PAKFIRE_EXPORT int pakfire_buildservice_list_uploads(
607 struct pakfire_buildservice* service, struct json_object** p) {
c26aca37 608 struct pakfire_xfer* xfer = NULL;
57a8b2d4
MT
609 struct json_object* response = NULL;
610 struct json_object* uploads = NULL;
611 char* buffer = NULL;
612 size_t length = 0;
613 int r;
614
c26aca37
MT
615 // Create a new xfer
616 r = pakfire_buildservice_create_xfer(&xfer, service, "/api/v1/uploads");
57a8b2d4
MT
617 if (r)
618 goto ERROR;
619
620 // Enable authentication
c26aca37 621 r = pakfire_xfer_auth(xfer);
57a8b2d4
MT
622 if (r)
623 goto ERROR;
624
625 // Write the response to the buffer
c26aca37 626 r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length);
57a8b2d4
MT
627 if (r)
628 goto ERROR;
629
c26aca37
MT
630 // Run the xfer
631 r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS);
57a8b2d4
MT
632 if (r)
633 goto ERROR;
634
57a8b2d4 635 // Parse the response
c26aca37 636 r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response);
33de78f2
MT
637 if (r) {
638 CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r));
57a8b2d4
MT
639 goto ERROR;
640 }
641
642 // Fetch the uploads
643 uploads = json_object_object_get(response, "uploads");
644 if (!uploads) {
645 CTX_ERROR(service->ctx, "Malformed response\n");
646 r = -EBADMSG;
647 goto ERROR;
648 }
649
650 // Return the pointer
651 *p = json_object_get(uploads);
652
653ERROR:
c26aca37
MT
654 if (xfer)
655 pakfire_xfer_unref(xfer);
57a8b2d4
MT
656 if (response)
657 json_object_put(response);
658 if (buffer)
659 free(buffer);
660
661 return r;
662}
c0b6198a
MT
663
664PAKFIRE_EXPORT int pakfire_buildservice_delete_upload(
665 struct pakfire_buildservice* service, const char* uuid) {
c26aca37 666 struct pakfire_xfer* xfer = NULL;
c0b6198a
MT
667 struct json_object* response = NULL;
668 char* buffer = NULL;
669 size_t length = 0;
670 char url[PATH_MAX];
671 int r;
672
673 // Compose the URL
674 r = pakfire_string_format(url, "/api/v1/uploads/%s", uuid);
675 if (r)
676 goto ERROR;
677
c26aca37
MT
678 // Create a new xfer
679 r = pakfire_buildservice_create_xfer(&xfer, service, url);
c0b6198a
MT
680 if (r)
681 goto ERROR;
682
683 // Ask to DELETE
c26aca37 684 r = pakfire_xfer_set_method(xfer, PAKFIRE_METHOD_DELETE);
c0b6198a
MT
685 if (r)
686 goto ERROR;
687
688 // Enable authentication
c26aca37 689 r = pakfire_xfer_auth(xfer);
c0b6198a
MT
690 if (r)
691 goto ERROR;
692
693 // Write the response to the buffer
c26aca37 694 r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length);
c0b6198a
MT
695 if (r)
696 goto ERROR;
697
c26aca37
MT
698 // Run the xfer
699 r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS);
c0b6198a
MT
700 if (r)
701 goto ERROR;
702
703 // Parse the response
c26aca37 704 r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response);
c0b6198a
MT
705 if (r) {
706 CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r));
707 goto ERROR;
708 }
709
710ERROR:
c26aca37
MT
711 if (xfer)
712 pakfire_xfer_unref(xfer);
c0b6198a
MT
713 if (response)
714 json_object_put(response);
715 if (buffer)
716 free(buffer);
717
718 return r;
719}
d554dcde
MT
720
721// Repositories
722
723PAKFIRE_EXPORT int pakfire_buildservice_list_repos(struct pakfire_buildservice* service,
724 const char* distro, struct json_object** p) {
c26aca37 725 struct pakfire_xfer* xfer = NULL;
d554dcde
MT
726 struct json_object* response = NULL;
727 struct json_object* repos = NULL;
728 char url[PATH_MAX];
729 char* buffer = NULL;
730 size_t length = 0;
731 int r;
732
733 // Check inputs
734 if (!distro)
735 return -EINVAL;
736
737 // Compose path
738 r = pakfire_string_format(url, "/api/v1/repos/%s", distro);
739 if (r)
740 goto ERROR;
741
c26aca37
MT
742 // Create a new xfer
743 r = pakfire_buildservice_create_xfer(&xfer, service, url);
d554dcde
MT
744 if (r)
745 goto ERROR;
746
747 // Enable authentication
c26aca37 748 r = pakfire_xfer_auth(xfer);
d554dcde
MT
749 if (r)
750 goto ERROR;
751
752 // Write the response to the buffer
c26aca37 753 r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length);
d554dcde
MT
754 if (r)
755 goto ERROR;
756
c26aca37
MT
757 // Run the xfer
758 r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS);
d554dcde
MT
759 if (r)
760 goto ERROR;
761
762 // Parse the response
c26aca37 763 r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response);
d554dcde
MT
764 if (r) {
765 CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r));
766 goto ERROR;
767 }
768
769 // Fetch the repos
770 if (!json_object_object_get_ex(response, "repos", &repos)) {
771 CTX_ERROR(service->ctx, "Malformed response\n");
772 r = -EBADMSG;
773 goto ERROR;
774 }
775
776 // Return the pointer
777 *p = json_object_get(repos);
778
779ERROR:
c26aca37
MT
780 if (xfer)
781 pakfire_xfer_unref(xfer);
d554dcde
MT
782 if (response)
783 json_object_put(response);
784 if (buffer)
785 free(buffer);
786
787 return r;
788}
9aa3397d
MT
789
790PAKFIRE_EXPORT int pakfire_buildservice_get_repo(struct pakfire_buildservice* service,
791 const char* distro, const char* name, struct json_object** p) {
c26aca37 792 struct pakfire_xfer* xfer = NULL;
9aa3397d
MT
793 struct json_object* response = NULL;
794 char url[PATH_MAX];
795 char* buffer = NULL;
796 size_t length = 0;
797 int r;
798
799 // Check inputs
800 if (!distro || !name)
801 return -EINVAL;
802
803 // Compose URL
804 r = pakfire_string_format(url, "/api/v1/repos/%s/%s", distro, name);
805 if (r)
806 goto ERROR;
807
c26aca37
MT
808 // Create a new xfer
809 r = pakfire_buildservice_create_xfer(&xfer, service, url);
9aa3397d
MT
810 if (r)
811 goto ERROR;
812
813 // Enable authentication
c26aca37 814 r = pakfire_xfer_auth(xfer);
9aa3397d
MT
815 if (r)
816 goto ERROR;
817
818 // Write the response to the buffer
c26aca37 819 r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length);
9aa3397d
MT
820 if (r)
821 goto ERROR;
822
c26aca37
MT
823 // Run the xfer
824 r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS);
9aa3397d
MT
825 if (r)
826 goto ERROR;
827
828 // Parse the response
c26aca37 829 r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response);
9aa3397d
MT
830 if (r) {
831 CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r));
832 goto ERROR;
833 }
834
835 // Return the pointer
836 *p = json_object_get(response);
837
838ERROR:
c26aca37
MT
839 if (xfer)
840 pakfire_xfer_unref(xfer);
9aa3397d
MT
841 if (response)
842 json_object_put(response);
843 if (buffer)
844 free(buffer);
845
846 return r;
847}
110ab7da
MT
848
849PAKFIRE_EXPORT int pakfire_buildservice_create_repo(struct pakfire_buildservice* service,
850 const char* distro, const char* name, const char* description, struct json_object** p) {
c26aca37 851 struct pakfire_xfer* xfer = NULL;
110ab7da
MT
852 struct json_object* response = NULL;
853 char url[PATH_MAX];
854 char* buffer = NULL;
855 size_t length = 0;
856 int r;
857
858 // Check inputs
859 if (!distro)
860 return -EINVAL;
861
862 // Compose path
863 r = pakfire_string_format(url, "/api/v1/repos/%s", distro);
864 if (r)
865 goto ERROR;
866
c26aca37
MT
867 // Create a new xfer
868 r = pakfire_buildservice_create_xfer(&xfer, service, url);
110ab7da
MT
869 if (r)
870 goto ERROR;
871
872 // Enable authentication
c26aca37 873 r = pakfire_xfer_auth(xfer);
110ab7da
MT
874 if (r)
875 goto ERROR;
876
877 // Set name
c26aca37 878 r = pakfire_xfer_add_param(xfer, "name", "%s", name);
110ab7da
MT
879 if (r)
880 goto ERROR;
881
882 // Set description
883 if (description) {
c26aca37 884 r = pakfire_xfer_add_param(xfer, "description", "%s", description);
110ab7da
MT
885 if (r)
886 goto ERROR;
887 }
888
889 // Write the response to the buffer
c26aca37 890 r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length);
110ab7da
MT
891 if (r)
892 goto ERROR;
893
c26aca37
MT
894 // Run the xfer
895 r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS);
110ab7da
MT
896 if (r)
897 goto ERROR;
898
899 // Parse the response
c26aca37 900 r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response);
110ab7da
MT
901 if (r) {
902 CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r));
903 goto ERROR;
904 }
905
906 // Return the pointer
907 if (p)
908 *p = json_object_get(response);
909
910ERROR:
c26aca37
MT
911 if (xfer)
912 pakfire_xfer_unref(xfer);
110ab7da
MT
913 if (response)
914 json_object_put(response);
915 if (buffer)
916 free(buffer);
917
918 return r;
919}
0948a9b6
MT
920
921PAKFIRE_EXPORT int pakfire_buildservice_delete_repo(struct pakfire_buildservice* service,
922 const char* distro, const char* name) {
c26aca37 923 struct pakfire_xfer* xfer = NULL;
0948a9b6
MT
924 struct json_object* response = NULL;
925 char* buffer = NULL;
926 size_t length = 0;
927 char url[PATH_MAX];
928 int r;
929
930 // Compose the URL
931 r = pakfire_string_format(url, "/api/v1/repos/%s/%s", distro, name);
932 if (r)
933 goto ERROR;
934
c26aca37
MT
935 // Create a new xfer
936 r = pakfire_buildservice_create_xfer(&xfer, service, url);
0948a9b6
MT
937 if (r)
938 goto ERROR;
939
940 // Ask to DELETE
c26aca37 941 r = pakfire_xfer_set_method(xfer, PAKFIRE_METHOD_DELETE);
0948a9b6
MT
942 if (r)
943 goto ERROR;
944
945 // Enable authentication
c26aca37 946 r = pakfire_xfer_auth(xfer);
0948a9b6
MT
947 if (r)
948 goto ERROR;
949
950 // Write the response to the buffer
c26aca37 951 r = pakfire_xfer_set_output_buffer(xfer, &buffer, &length);
0948a9b6
MT
952 if (r)
953 goto ERROR;
954
c26aca37
MT
955 // Run the xfer
956 r = pakfire_xfer_run(xfer, PAKFIRE_XFER_NO_PROGRESS);
0948a9b6
MT
957 if (r)
958 goto ERROR;
959
960 // Parse the response
c26aca37 961 r = pakfire_buildservice_parse_response(service, xfer, buffer, length, &response);
0948a9b6
MT
962 if (r) {
963 CTX_ERROR(service->ctx, "Could not parse the response: %s\n", strerror(-r));
964 goto ERROR;
965 }
966
967ERROR:
c26aca37
MT
968 if (xfer)
969 pakfire_xfer_unref(xfer);
0948a9b6
MT
970 if (response)
971 json_object_put(response);
972 if (buffer)
973 free(buffer);
974
975 return r;
976}