Branch data Line data Source code
1 : : /*-
2 : : * Copyright (c) 2011-2020 Baptiste Daroussin <bapt@FreeBSD.org>
3 : : * Copyright (c) 2011-2012 Julien Laffaye <jlaffaye@FreeBSD.org>
4 : : * Copyright (c) 2014-2015 Matthew Seaman <matthew@FreeBSD.org>
5 : : * Copyright (c) 2014 Vsevolod Stakhov <vsevolod@FreeBSD.org>
6 : : * All rights reserved.
7 : : *
8 : : * Redistribution and use in source and binary forms, with or without
9 : : * modification, are permitted provided that the following conditions
10 : : * are met:
11 : : * 1. Redistributions of source code must retain the above copyright
12 : : * notice, this list of conditions and the following disclaimer
13 : : * in this position and unchanged.
14 : : * 2. Redistributions in binary form must reproduce the above copyright
15 : : * notice, this list of conditions and the following disclaimer in the
16 : : * documentation and/or other materials provided with the distribution.
17 : : *
18 : : * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
19 : : * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20 : : * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21 : : * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
22 : : * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23 : : * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24 : : * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25 : : * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 : : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 : : * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28 : : */
29 : :
30 : : #include <sys/stat.h>
31 : :
32 : : #include <errno.h>
33 : : #include <regex.h>
34 : : #include <fcntl.h>
35 : :
36 : : #include <bsd_compat.h>
37 : :
38 : : #include "pkg.h"
39 : : #include "private/event.h"
40 : : #include "private/pkg.h"
41 : :
42 : : #define TICK 100
43 : :
44 : : static int load_metadata(struct pkg *pkg, const char *metadata, const char *plist,
45 : : const char *rootdir);
46 : : static void fixup_abi(struct pkg *pkg, const char *rootdir, bool testing);
47 : : static void counter_init(const char *what, int64_t max);
48 : : static void counter_count(void);
49 : : static void counter_end(void);
50 : :
51 : : extern struct pkg_ctx ctx;
52 : :
53 : : static int
54 : 996 : pkg_create_from_dir(struct pkg *pkg, const char *root,
55 : : struct pkg_create *pc, struct packing *pkg_archive)
56 : : {
57 : : char fpath[MAXPATHLEN];
58 : 996 : struct pkg_file *file = NULL;
59 : 996 : struct pkg_dir *dir = NULL;
60 : : int ret;
61 : : struct stat st;
62 : 996 : int64_t flatsize = 0;
63 : : int64_t nfiles;
64 : : const char *relocation;
65 : : hardlinks_t *hardlinks;
66 : :
67 [ - + ]: 996 : if (pkg_is_valid(pkg) != EPKG_OK) {
68 : 0 : pkg_emit_error("the package is not valid");
69 : 0 : return (EPKG_FATAL);
70 : : }
71 : :
72 : 996 : relocation = pkg_kv_get(&pkg->annotations, "relocated");
73 [ - + ]: 996 : if (relocation == NULL)
74 : 996 : relocation = "";
75 [ + - ]: 996 : if (ctx.pkg_rootdir != NULL)
76 : 0 : relocation = ctx.pkg_rootdir;
77 : :
78 : : /*
79 : : * Get / compute size / checksum if not provided in the manifest
80 : : */
81 : :
82 : 996 : nfiles = pkghash_count(pkg->filehash);
83 : 996 : counter_init("file sizes/checksums", nfiles);
84 : :
85 : 996 : hardlinks = kh_init_hardlinks();
86 [ + + ]: 1749 : while (pkg_files(pkg, &file) == EPKG_OK) {
87 : :
88 [ + + ]: 757 : snprintf(fpath, sizeof(fpath), "%s%s%s", root ? root : "",
89 : 757 : relocation, file->path);
90 : :
91 [ + - ]: 757 : if (lstat(fpath, &st) == -1) {
92 : 0 : pkg_emit_error("file '%s' is missing", fpath);
93 : 0 : kh_destroy_hardlinks(hardlinks);
94 : 0 : return (EPKG_FATAL);
95 : : }
96 : :
97 [ + + + + ]: 757 : if (!(S_ISREG(st.st_mode) || S_ISLNK(st.st_mode))) {
98 : 4 : pkg_emit_error("file '%s' is not a regular file or symlink", fpath);
99 : 4 : kh_destroy_hardlinks(hardlinks);
100 : 4 : return (EPKG_FATAL);
101 : : }
102 : :
103 [ - + ]: 753 : if (file->size == 0)
104 : 753 : file->size = (int64_t)st.st_size;
105 : :
106 [ + + + + ]: 753 : if (st.st_nlink == 1 || !check_for_hardlink(hardlinks, &st)) {
107 : 730 : flatsize += file->size;
108 : 730 : }
109 : :
110 : 753 : file->sum = pkg_checksum_generate_file(fpath,
111 : : PKG_HASH_TYPE_SHA256_HEX);
112 [ + - ]: 753 : if (file->sum == NULL) {
113 : 0 : kh_destroy_hardlinks(hardlinks);
114 : 0 : return (EPKG_FATAL);
115 : : }
116 : :
117 : 753 : counter_count();
118 : : }
119 : 992 : kh_destroy_hardlinks(hardlinks);
120 : :
121 : 992 : counter_end();
122 : :
123 : 992 : pkg->flatsize = flatsize;
124 : :
125 [ - + ]: 992 : if (pkg->type == PKG_OLD_FILE) {
126 : 0 : pkg_emit_error("Cannot create an old format package");
127 : 0 : return (EPKG_FATAL);
128 : : }
129 : : /*
130 : : * Register shared libraries used by the package if
131 : : * SHLIBS enabled in conf. Deletes shlib info if not.
132 : : */
133 : 992 : xstring *b = xstring_new();
134 : :
135 : 992 : pkg_emit_manifest_buf(pkg, b, PKG_MANIFEST_EMIT_COMPACT, NULL);
136 : 992 : fflush(b->fp);
137 : 992 : packing_append_buffer(pkg_archive, b->buf, "+COMPACT_MANIFEST", strlen(b->buf));
138 : 992 : xstring_reset(b);
139 [ - + ]: 992 : if (pc->expand_manifest)
140 : 0 : pkg_emit_manifest_buf(pkg, b, PKG_MANIFEST_EMIT_UCL, NULL);
141 : : else
142 : 992 : pkg_emit_manifest_buf(pkg, b, 0, NULL);
143 : 992 : fflush(b->fp);
144 : 992 : packing_append_buffer(pkg_archive, b->buf, "+MANIFEST", strlen(b->buf));
145 : 992 : xstring_free(b);
146 : :
147 : 992 : counter_init("packing files", nfiles);
148 : :
149 [ + + ]: 1741 : while (pkg_files(pkg, &file) == EPKG_OK) {
150 : :
151 [ + + ]: 749 : snprintf(fpath, sizeof(fpath), "%s%s%s", root ? root : "",
152 : 749 : relocation, file->path);
153 : :
154 : 1498 : ret = packing_append_file_attr(pkg_archive, fpath, file->path,
155 : 749 : file->uname, file->gname, file->perm, file->fflags);
156 [ - + # # ]: 749 : if (ctx.developer_mode && ret != EPKG_OK)
157 : 0 : return (ret);
158 : 749 : counter_count();
159 : : }
160 : :
161 : 992 : counter_end();
162 : :
163 : 992 : nfiles = pkghash_count(pkg->dirhash);
164 : 992 : counter_init("packing directories", nfiles);
165 : :
166 [ + + ]: 1024 : while (pkg_dirs(pkg, &dir) == EPKG_OK) {
167 [ + + ]: 32 : snprintf(fpath, sizeof(fpath), "%s%s%s", root ? root : "",
168 : 32 : relocation, dir->path);
169 : :
170 : 64 : ret = packing_append_file_attr(pkg_archive, fpath, dir->path,
171 : 32 : dir->uname, dir->gname, dir->perm, dir->fflags);
172 [ - + # # ]: 32 : if (ctx.developer_mode && ret != EPKG_OK)
173 : 0 : return (ret);
174 : 32 : counter_count();
175 : : }
176 : :
177 : 992 : counter_end();
178 : :
179 : 992 : return (EPKG_OK);
180 : 996 : }
181 : :
182 : : static struct packing *
183 : 1000 : pkg_create_archive(struct pkg *pkg, struct pkg_create *pc, unsigned required_flags)
184 : : {
185 : 1000 : char *pkg_path = NULL;
186 : 1000 : struct packing *pkg_archive = NULL;
187 : :
188 : : /*
189 : : * Ensure that we have all the information we need
190 : : */
191 [ - + ]: 1000 : if (pkg->type != PKG_OLD_FILE)
192 [ + - ]: 1000 : assert((pkg->flags & required_flags) == required_flags);
193 : :
194 [ - + ]: 1000 : if (mkdirs(pc->outdir) != EPKG_OK)
195 : 0 : return NULL;
196 : :
197 [ + - ]: 1000 : if (pkg_asprintf(&pkg_path, "%S/%n-%v", pc->outdir, pkg, pkg) == -1) {
198 : 0 : pkg_emit_errno("pkg_asprintf", "");
199 : 0 : return (NULL);
200 : : }
201 : :
202 [ + + + + : 3000 : if (packing_init(&pkg_archive, pkg_path, pc->format,
+ + ]
203 : 2000 : pc->compression_level, pc->timestamp, pc->overwrite, false) != EPKG_OK) {
204 : 4 : pkg_archive = NULL;
205 : 4 : }
206 : :
207 : 1000 : free(pkg_path);
208 : :
209 : 1000 : return pkg_archive;
210 : 1000 : }
211 : :
212 : : static const char * const scripts[] = {
213 : : "+INSTALL",
214 : : "+PRE_INSTALL",
215 : : "+POST_INSTALL",
216 : : "+POST_INSTALL",
217 : : "+DEINSTALL",
218 : : "+PRE_DEINSTALL",
219 : : "+POST_DEINSTALL",
220 : : "pkg-install",
221 : : "pkg-pre-install",
222 : : "pkg-post-install",
223 : : "pkg-deinstall",
224 : : "pkg-pre-deinstall",
225 : : "pkg-post-deinstall",
226 : : NULL
227 : : };
228 : :
229 : : static const char * const lua_scripts[] = {
230 : : "pkg-pre-install.lua",
231 : : "pkg-post-install.lua",
232 : : "pkg-pre-deinstall.lua",
233 : : "pkg-post-deinstall.lua",
234 : : NULL
235 : : };
236 : :
237 : : struct pkg_create *
238 : 1077 : pkg_create_new(void)
239 : : {
240 : : struct pkg_create *pc;
241 : :
242 : 1077 : pc = xcalloc(1, sizeof(*pc));
243 : 1077 : pc->format = DEFAULT_COMPRESSION;
244 : 1077 : pc->compression_level = ctx.compression_level;
245 : 1077 : pc->timestamp = (time_t) -1;
246 : 1077 : pc->overwrite = true;
247 : 1077 : pc->expand_manifest = false;
248 : :
249 : 1077 : return (pc);
250 : : }
251 : :
252 : : void
253 : 1077 : pkg_create_free(struct pkg_create *pc)
254 : : {
255 : 1077 : free(pc);
256 : 1077 : }
257 : :
258 : : bool
259 : 12 : pkg_create_set_format(struct pkg_create *pc, const char *format)
260 : : {
261 [ + - ]: 12 : if (strcmp(format, "tzst") == 0)
262 : 0 : pc->format = TZS;
263 [ + + ]: 12 : else if (strcmp(format, "txz") == 0)
264 : 8 : pc->format = TXZ;
265 [ + - ]: 4 : else if (strcmp(format, "tbz") == 0)
266 : 0 : pc->format = TBZ;
267 [ + - ]: 4 : else if (strcmp(format, "tgz") == 0)
268 : 0 : pc->format = TGZ;
269 [ + - ]: 4 : else if (strcmp(format, "tar") == 0)
270 : 4 : pc->format = TAR;
271 : : else
272 : 0 : return (false);
273 : 12 : return (true);
274 : 12 : }
275 : :
276 : : void
277 : 1077 : pkg_create_set_compression_level(struct pkg_create *pc, int clevel)
278 : : {
279 : 1077 : pc->compression_level = clevel;
280 : 1077 : }
281 : :
282 : : void
283 : 1077 : pkg_create_set_expand_manifest(struct pkg_create *pc, bool expand)
284 : : {
285 : 1077 : pc->expand_manifest = expand;
286 : 1077 : }
287 : :
288 : : void
289 : 1077 : pkg_create_set_rootdir(struct pkg_create *pc, const char *rootdir)
290 : : {
291 : 1077 : pc->rootdir = rootdir;
292 : 1077 : }
293 : :
294 : : void
295 : 1077 : pkg_create_set_output_dir(struct pkg_create *pc, const char *outdir)
296 : : {
297 : 1077 : pc->outdir = outdir;
298 : 1077 : }
299 : :
300 : : void
301 : 8 : pkg_create_set_timestamp(struct pkg_create *pc, time_t timestamp)
302 : : {
303 : 8 : pc->timestamp = timestamp;
304 : 8 : }
305 : :
306 : : void
307 : 1077 : pkg_create_set_overwrite(struct pkg_create *pc, bool overwrite)
308 : : {
309 : 1077 : pc->overwrite = overwrite;
310 : 1077 : }
311 : :
312 : : static int
313 : 4 : hash_file(struct pkg_create *pc, struct pkg *pkg)
314 : : {
315 : : char hash_dest[MAXPATHLEN];
316 : : char filename[MAXPATHLEN];
317 : :
318 : : /* Find the hash and rename the file and create a symlink */
319 : 8 : pkg_snprintf(filename, sizeof(filename), "%n-%v.pkg",
320 : 4 : pkg, pkg);
321 : 4 : pkg->sum = pkg_checksum_file(filename,
322 : : PKG_HASH_TYPE_SHA256_HEX);
323 : 8 : pkg_snprintf(hash_dest, sizeof(hash_dest), "%n-%v-%z.pkg",
324 : 4 : pkg, pkg, pkg);
325 : :
326 : 4 : pkg_debug(1, "Rename the pkg file from: %s to: %s",
327 : 4 : filename, hash_dest);
328 [ + - ]: 4 : if (rename(filename, hash_dest) == -1) {
329 : 0 : pkg_emit_errno("rename", hash_dest);
330 : 0 : unlink(hash_dest);
331 : 0 : return (EPKG_FATAL);
332 : : }
333 [ - + ]: 4 : if (symlink(hash_dest, filename) == -1) {
334 : 0 : pkg_emit_errno("symlink", hash_dest);
335 : 0 : return (EPKG_FATAL);
336 : : }
337 : 4 : return (EPKG_OK);
338 : 4 : }
339 : :
340 : : int
341 : 0 : pkg_create_i(struct pkg_create *pc, struct pkg *pkg, bool hash)
342 : : {
343 : 0 : struct packing *pkg_archive = NULL;
344 : : int ret;
345 : :
346 : 0 : unsigned required_flags = PKG_LOAD_DEPS | PKG_LOAD_FILES |
347 : : PKG_LOAD_CATEGORIES | PKG_LOAD_DIRS | PKG_LOAD_SCRIPTS |
348 : : PKG_LOAD_OPTIONS | PKG_LOAD_LICENSES | PKG_LOAD_LUA_SCRIPTS;
349 : :
350 [ # # # # ]: 0 : assert(pkg->type == PKG_INSTALLED || pkg->type == PKG_OLD_FILE);
351 : :
352 : 0 : pkg_archive = pkg_create_archive(pkg, pc, required_flags);
353 [ # # ]: 0 : if (pkg_archive == NULL) {
354 [ # # ]: 0 : if (errno == EEXIST)
355 : 0 : return (EPKG_EXIST);
356 : 0 : pkg_emit_error("unable to create archive");
357 : 0 : return (EPKG_FATAL);
358 : : }
359 : :
360 [ # # ]: 0 : if ((ret = pkg_create_from_dir(pkg, NULL, pc, pkg_archive)) != EPKG_OK) {
361 : 0 : pkg_emit_error("package creation failed");
362 : 0 : }
363 : 0 : packing_finish(pkg_archive);
364 : :
365 [ # # # # ]: 0 : if (hash && ret == EPKG_OK)
366 : 0 : ret = hash_file(pc, pkg);
367 : :
368 : 0 : return (ret);
369 : 0 : }
370 : :
371 : : int
372 : 1077 : pkg_create(struct pkg_create *pc, const char *metadata, const char *plist,
373 : : bool hash)
374 : : {
375 : 1077 : struct pkg *pkg = NULL;
376 : 1077 : struct packing *pkg_archive = NULL;
377 : 1077 : int ret = ENOMEM;
378 : :
379 : 1077 : pkg_debug(1, "Creating package");
380 [ - + ]: 1077 : if (pkg_new(&pkg, PKG_FILE) != EPKG_OK) {
381 : 0 : return (EPKG_FATAL);
382 : : }
383 : :
384 [ + + ]: 1077 : if (load_metadata(pkg, metadata, plist, pc->rootdir) != EPKG_OK) {
385 : 77 : pkg_free(pkg);
386 : 77 : return (EPKG_FATAL);
387 : : }
388 : 1000 : fixup_abi(pkg, pc->rootdir, false);
389 : :
390 : 1000 : pkg_archive = pkg_create_archive(pkg, pc, 0);
391 [ + + ]: 1000 : if (pkg_archive == NULL) {
392 [ + - ]: 4 : if (errno == EEXIST) {
393 : 4 : pkg_emit_notice("%s-%s already packaged, skipping...\n",
394 : 4 : pkg->name, pkg->version);
395 : 4 : pkg_free(pkg);
396 : 4 : return (EPKG_EXIST);
397 : : }
398 : 0 : pkg_free(pkg);
399 : 0 : return (EPKG_FATAL);
400 : : }
401 : :
402 [ + + ]: 996 : if ((ret = pkg_create_from_dir(pkg, pc->rootdir, pc, pkg_archive)) != EPKG_OK)
403 : 4 : pkg_emit_error("package creation failed");
404 : :
405 : 996 : packing_finish(pkg_archive);
406 [ + + + - ]: 996 : if (hash && ret == EPKG_OK)
407 : 4 : ret = hash_file(pc, pkg);
408 : :
409 : 996 : pkg_free(pkg);
410 : 996 : return (ret);
411 : 1077 : }
412 : :
413 : : /* The "no concessions to old pkg_tools" variant: just get everything
414 : : * from the manifest */
415 : : int
416 : 0 : pkg_create_from_manifest(const char *outdir, pkg_formats format,
417 : : const char *rootdir, const char *manifest, const char *plist)
418 : : {
419 : : struct pkg_create *pc;
420 : : int ret;
421 : :
422 : 0 : pc = pkg_create_new();
423 : 0 : pc->format = format;
424 : 0 : pkg_create_set_rootdir(pc, rootdir);
425 : 0 : pkg_create_set_output_dir(pc, outdir);
426 : :
427 : 0 : ret = pkg_create(pc, manifest, plist, false);
428 : 0 : pkg_create_free(pc);
429 : 0 : return (ret);
430 : : }
431 : :
432 : : static int
433 : 128 : pkg_load_message_from_file(int fd, struct pkg *pkg, const char *path)
434 : : {
435 : 128 : char *buf = NULL;
436 : 128 : off_t size = 0;
437 : : int ret;
438 : : ucl_object_t *obj;
439 : :
440 [ + - ]: 128 : assert(pkg != NULL);
441 [ - + ]: 128 : assert(path != NULL);
442 : :
443 [ + + ]: 128 : if (faccessat(fd, path, F_OK, 0) == -1) {
444 : 108 : return (EPKG_FATAL);
445 : : }
446 : :
447 : 20 : pkg_debug(1, "Reading message: '%s'", path);
448 [ - + ]: 20 : if ((ret = file_to_bufferat(fd, path, &buf, &size)) != EPKG_OK) {
449 : 0 : return (ret);
450 : : }
451 : :
452 [ + + ]: 20 : if (*buf == '[') {
453 : 8 : ret = pkg_message_from_str(pkg, buf, size);
454 : 8 : free(buf);
455 : 8 : return (ret);
456 : : }
457 : 12 : obj = ucl_object_fromstring_common(buf, size,
458 : : UCL_STRING_RAW|UCL_STRING_TRIM);
459 : 12 : ret = pkg_message_from_ucl(pkg, obj);
460 : 12 : ucl_object_unref(obj);
461 : 12 : free(buf);
462 : :
463 : 12 : return (ret);
464 : 128 : }
465 : :
466 : : /* TODO use file descriptor for rootdir */
467 : : static int
468 : 1321 : load_manifest(struct pkg *pkg, const char *metadata, const char *plist,
469 : : struct pkg_manifest_key *keys, const char *rootdir)
470 : : {
471 : : int ret;
472 : :
473 : 1321 : ret = pkg_parse_manifest_file(pkg, metadata, keys);
474 : :
475 [ + + + + ]: 1321 : if (ret == EPKG_OK && plist != NULL)
476 : 135 : ret = ports_parse_plist(pkg, plist, rootdir);
477 : 1321 : return (ret);
478 : : }
479 : :
480 : : /* TODO use file descriptor for rootdir */
481 : : static int
482 : 1462 : load_metadata(struct pkg *pkg, const char *metadata, const char *plist,
483 : : const char *rootdir)
484 : : {
485 : 1462 : struct pkg_manifest_key *keys = NULL;
486 : : regex_t preg;
487 : : regmatch_t pmatch[2];
488 : : size_t size;
489 : : int fd, i;
490 : :
491 : 1462 : pkg_manifest_keys_new(&keys);
492 : :
493 : : /* Let's see if we have a directory or a manifest */
494 [ + + ]: 1462 : if ((fd = open(metadata, O_DIRECTORY|O_CLOEXEC)) == -1) {
495 [ + - ]: 1321 : if (errno == ENOTDIR)
496 : 1321 : return (load_manifest(pkg, metadata, plist, keys, rootdir));
497 : 0 : pkg_emit_errno("open", metadata);
498 : 0 : pkg_manifest_keys_free(keys);
499 : 0 : return (EPKG_FATAL);
500 : : }
501 : :
502 [ + + ]: 141 : if ((pkg_parse_manifest_fileat(fd, pkg, "+MANIFEST", keys)) != EPKG_OK) {
503 : 13 : pkg_manifest_keys_free(keys);
504 : 13 : close(fd);
505 : 13 : return (EPKG_FATAL);
506 : : }
507 : 128 : pkg_manifest_keys_free(keys);
508 : :
509 : 128 : pkg_load_message_from_file(fd, pkg, "+DISPLAY");
510 [ - + ]: 128 : if (pkg->desc == NULL)
511 : 0 : pkg_set_from_fileat(fd, pkg, PKG_DESC, "+DESC", false);
512 : :
513 [ + + ]: 1792 : for (i = 0; scripts[i] != NULL; i++) {
514 [ + - ]: 1664 : if (faccessat(fd, scripts[i], F_OK, 0) == 0)
515 : 0 : pkg_addscript_fileat(fd, pkg, scripts[i]);
516 : 1664 : }
517 : :
518 [ + + ]: 640 : for (i = 0; lua_scripts[i] != NULL; i++) {
519 [ + - ]: 512 : if (faccessat(fd, lua_scripts[i], F_OK, 0) == 0)
520 : 0 : pkg_addluascript_fileat(fd, pkg, lua_scripts[i]);
521 : 512 : }
522 : :
523 [ + + + + ]: 128 : if (plist != NULL && ports_parse_plist(pkg, plist, rootdir) != EPKG_OK) {
524 : 48 : return (EPKG_FATAL);
525 : : }
526 : 80 : close(fd);
527 : :
528 [ + - ]: 80 : if (pkg->www == NULL) {
529 [ # # ]: 0 : if (pkg->desc == NULL) {
530 : 0 : pkg_emit_error("No www or desc defined in manifest");
531 : 0 : return (EPKG_FATAL);
532 : : }
533 : 0 : regcomp(&preg, "^WWW:[[:space:]]*(.*)$",
534 : : REG_EXTENDED|REG_ICASE|REG_NEWLINE);
535 [ # # ]: 0 : if (regexec(&preg, pkg->desc, 2, pmatch, 0) == 0) {
536 : 0 : size = pmatch[1].rm_eo - pmatch[1].rm_so;
537 : 0 : pkg->www = xstrndup(&pkg->desc[pmatch[1].rm_so], size);
538 : 0 : } else {
539 : 0 : pkg->www = xstrdup("UNKNOWN");
540 : : }
541 : 0 : regfree(&preg);
542 : 0 : }
543 : :
544 : 80 : return (EPKG_OK);
545 : 1462 : }
546 : :
547 : : static void
548 : 1381 : fixup_abi(struct pkg *pkg, const char *rootdir, bool testing)
549 : : {
550 : 1381 : bool defaultarch = false;
551 : : const char *arch;
552 : :
553 : : /* if no arch autodetermine it */
554 [ + + ]: 1381 : if (pkg->abi == NULL) {
555 : : #ifdef __FreeBSD__
556 : : char *osversion;
557 : 1020 : xasprintf(&osversion, "%d", ctx.osversion);
558 : 1020 : pkg_kv_add(&pkg->annotations, "FreeBSD_version", osversion, "annotation");
559 : : #endif
560 : 1020 : arch = pkg_object_string(pkg_config_get("ABI"));
561 : 1020 : pkg->abi = xstrdup(arch);
562 : 1020 : defaultarch = true;
563 : 1020 : }
564 : :
565 [ + + ]: 1381 : if (!testing)
566 : 1323 : pkg_analyse_files(NULL, pkg, rootdir);
567 : :
568 [ + - ]: 1381 : if (ctx.developer_mode)
569 : 0 : suggest_arch(pkg, defaultarch);
570 : 1381 : }
571 : :
572 : : int
573 : 385 : pkg_load_metadata(struct pkg *pkg, const char *mfile, const char *md_dir,
574 : : const char *plist, const char *rootdir, bool testing)
575 : : {
576 : : int ret;
577 : :
578 [ + + ]: 385 : ret = load_metadata(pkg, md_dir != NULL ? md_dir: mfile, plist, rootdir);
579 [ + + ]: 385 : if (ret != EPKG_OK)
580 : 4 : return (ret);
581 : :
582 : 381 : fixup_abi(pkg, rootdir, testing);
583 : 381 : return (ret);
584 : 385 : }
585 : :
586 : : int
587 : 0 : pkg_create_staged(const char *outdir, pkg_formats format, const char *rootdir,
588 : : const char *md_dir, char *plist, bool hash)
589 : : {
590 : : struct pkg_create *pc;
591 : : int ret;
592 : :
593 : 0 : pc = pkg_create_new();
594 : 0 : pc->format = format;
595 : 0 : pkg_create_set_rootdir(pc, rootdir);
596 : 0 : pkg_create_set_output_dir(pc, outdir);
597 : :
598 : 0 : ret = pkg_create(pc, md_dir, plist, hash);
599 : 0 : pkg_create_free(pc);
600 : 0 : return (ret);
601 : : }
602 : :
603 : : int
604 : 0 : pkg_create_installed(const char *outdir, pkg_formats format, struct pkg *pkg)
605 : : {
606 : : struct pkg_create *pc;
607 : : int ret;
608 : :
609 : 0 : pc = pkg_create_new();
610 : 0 : pc->format = format;
611 : 0 : pkg_create_set_output_dir(pc, outdir);
612 : :
613 : 0 : ret = pkg_create_i(pc, pkg, false);
614 : 0 : pkg_create_free(pc);
615 : 0 : return (ret);
616 : : }
617 : :
618 : : static int64_t count;
619 : : static int64_t maxcount;
620 : : static const char *what;
621 : :
622 : 2980 : static int magnitude(int64_t num)
623 : : {
624 : : int oom;
625 : :
626 [ + + ]: 2980 : if (num == 0)
627 : 1712 : return (1);
628 [ - + ]: 1268 : if (num < 0)
629 : 0 : num = -num;
630 : :
631 [ - + ]: 1268 : for (oom = 1; num >= 10; oom++)
632 : 0 : num /= 10;
633 : :
634 : 1268 : return (oom);
635 : 2980 : }
636 : :
637 : : static void
638 : 2980 : counter_init(const char *count_what, int64_t max)
639 : : {
640 : 2980 : count = 0;
641 : 2980 : what = count_what;
642 : 2980 : maxcount = max;
643 : 5960 : pkg_emit_progress_start("%-20s%*s[%jd]", what,
644 : 2980 : 6 - magnitude(maxcount), " ", (intmax_t)maxcount);
645 : :
646 : 2980 : return;
647 : : }
648 : :
649 : : static void
650 : 1534 : counter_count(void)
651 : : {
652 : 1534 : count++;
653 : :
654 [ - + ]: 1534 : if (count % TICK == 0)
655 : 0 : pkg_emit_progress_tick(count, maxcount);
656 : :
657 : 1534 : return;
658 : : }
659 : :
660 : : static void
661 : 2976 : counter_end(void)
662 : : {
663 : 2976 : pkg_emit_progress_tick(count, maxcount);
664 : 2976 : return;
665 : : }
|