ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/src/trunk/lib/libmport/bundle_read_install_pkg.c
Revision: 12115
Committed: Tue Oct 30 01:59:04 2018 UTC (5 years, 6 months ago) by laffer1
Content type: text/plain
File size: 29190 byte(s)
Log Message:
fix debug

File Contents

# Content
1 /*-
2 * Copyright (c) 2013-2015 Lucas Holt
3 * Copyright (c) 2007-2009 Chris Reinhardt
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28 #include <sys/cdefs.h>
29 __MBSDID("$MidnightBSD$");
30
31 #include "mport.h"
32 #include "mport_private.h"
33
34 #include <sys/stat.h>
35 #include <libgen.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <errno.h>
39 #include <unistd.h>
40 #include <syslog.h>
41 #include <stdarg.h>
42 #include <archive_entry.h>
43
44
45 enum phase { PREINSTALL, ACTUALINSTALL, POSTINSTALL};
46
47 static int do_pre_install(mportInstance *, mportBundleRead *, mportPackageMeta *);
48 static int do_actual_install(mportInstance *, mportBundleRead *, mportPackageMeta *);
49 static int do_post_install(mportInstance *, mportBundleRead *, mportPackageMeta *);
50 static int run_postexec(mportInstance *, mportPackageMeta *);
51 static int run_pkg_install(mportInstance *, mportBundleRead *, mportPackageMeta *, const char *);
52 static int run_mtree(mportInstance *, mportBundleRead *, mportPackageMeta *);
53 static int display_pkg_msg(mportInstance *, mportBundleRead *, mportPackageMeta *);
54 static int get_file_count(mportInstance *, char *, int *);
55 static int create_package_row(mportInstance *, mportPackageMeta *);
56 static int create_categories(mportInstance *mport, mportPackageMeta *pkg);
57 static int create_depends(mportInstance *mport, mportPackageMeta *pkg);
58 static int create_sample_file(mportInstance *mport, char *cwd, const char *file);
59 static char** parse_sample(char *input);
60 static int mark_complete(mportInstance *, mportPackageMeta *);
61 static int mport_bundle_read_get_assetlist(mportInstance *mport, mportPackageMeta *pkg, mportAssetList **alist_p, enum phase);
62
63 /**
64 * This is a wrapper for all bund read install operations
65 */
66 int
67 mport_bundle_read_install_pkg(mportInstance *mport, mportBundleRead *bundle, mportPackageMeta *pkg)
68 {
69 if (do_pre_install(mport, bundle, pkg) != MPORT_OK) {
70 RETURN_CURRENT_ERROR;
71 }
72
73 if (do_actual_install(mport, bundle, pkg) != MPORT_OK) {
74 RETURN_CURRENT_ERROR;
75 }
76
77 if (do_post_install(mport, bundle, pkg) != MPORT_OK) {
78 RETURN_CURRENT_ERROR;
79 }
80
81 syslog(LOG_NOTICE, "%s-%s installed", pkg->name, pkg->version);
82
83 return MPORT_OK;
84 }
85
86
87 /* This does everything that has to happen before we start installing files.
88 * We run mtree, pkg-install PRE-INSTALL, etc...
89 */
90 static int
91 do_pre_install(mportInstance *mport, mportBundleRead *bundle, mportPackageMeta *pkg)
92 {
93 char cwd[FILENAME_MAX];
94 char file[FILENAME_MAX];
95 mportAssetList *alist;
96 mportAssetListEntry *e = NULL;
97
98 /* run mtree */
99 if (run_mtree(mport, bundle, pkg) != MPORT_OK)
100 RETURN_CURRENT_ERROR;
101
102 /* run pkg-install PRE-INSTALL */
103 if (run_pkg_install(mport, bundle, pkg, "PRE-INSTALL") != MPORT_OK)
104 RETURN_CURRENT_ERROR;
105
106 /* Process @preexec steps */
107 if (mport_bundle_read_get_assetlist(mport, pkg, &alist, PREINSTALL) != MPORT_OK)
108 goto ERROR;
109
110 (void) strlcpy(cwd, pkg->prefix, sizeof(cwd));
111
112 if (mport_chdir(mport, cwd) != MPORT_OK)
113 goto ERROR;
114
115 STAILQ_FOREACH(e, alist, next) {
116 switch (e->type) {
117 case ASSET_CWD:
118 (void) strlcpy(cwd, e->data == NULL ? pkg->prefix : e->data, sizeof(cwd));
119 if (mport_chdir(mport, cwd) != MPORT_OK)
120 goto ERROR;
121
122 break;
123 case ASSET_PREEXEC:
124 if (mport_run_asset_exec(mport, e->data, cwd, file) != MPORT_OK)
125 goto ERROR;
126 break;
127 default:
128 /* do nothing */
129 break;
130 }
131 }
132
133 mport_assetlist_free(alist);
134 mport_pkgmeta_logevent(mport, pkg, "preexec");
135
136 return MPORT_OK;
137
138 ERROR:
139 // TODO: asset list free
140 RETURN_CURRENT_ERROR;
141 }
142
143 /* get the file count for the progress meter */
144 static int
145 get_file_count(mportInstance *mport, char *pkg_name, int *file_total)
146 {
147 __block sqlite3_stmt *count;
148 __block int result = MPORT_OK;
149 __block char *err;
150
151 if (mport_db_prepare(mport->db, &count,
152 "SELECT COUNT(*) FROM stub.assets WHERE (type=%i or type=%i or type=%i or type=%i) AND pkg=%Q",
153 ASSET_FILE, ASSET_SAMPLE, ASSET_SHELL, ASSET_FILE_OWNER_MODE, pkg_name) != MPORT_OK) {
154 sqlite3_finalize(count);
155 RETURN_CURRENT_ERROR;
156 }
157
158 dispatch_sync(mportSQLSerial, ^{
159 switch (sqlite3_step(count)) {
160 case SQLITE_ROW:
161 *file_total = sqlite3_column_int(count, 0);
162 sqlite3_finalize(count);
163 break;
164 default:
165 err = (char *) sqlite3_errmsg(mport->db);
166 result = MPORT_ERR_FATAL;
167 sqlite3_finalize(count);
168 }
169 });
170
171 if (result == MPORT_ERR_FATAL)
172 SET_ERRORX(result, "Error reading file count %s", err);
173 return result;
174 }
175
176 static int
177 create_package_row(mportInstance *mport, mportPackageMeta *pkg)
178 {
179 /* Insert the package meta row into the packages table (We use pack here because things might have been twiddled) */
180 /* Note that this will be marked as dirty by default */
181 if (mport_db_do(mport->db,
182 "INSERT INTO packages (pkg, version, origin, prefix, lang, options, comment, os_release, cpe, locked, deprecated, expiration_date, no_provide_shlib, flavor) VALUES (%Q,%Q,%Q,%Q,%Q,%Q,%Q,%Q,%Q,0,%Q,%ld,%d,%Q)",
183 pkg->name, pkg->version, pkg->origin, pkg->prefix, pkg->lang, pkg->options, pkg->comment,
184 pkg->os_release, pkg->cpe, pkg->deprecated, pkg->expiration_date, pkg->no_provide_shlib, pkg->flavor) != MPORT_OK)
185 RETURN_CURRENT_ERROR;
186
187 return MPORT_OK;
188 }
189
190 static int
191 create_depends(mportInstance *mport, mportPackageMeta *pkg)
192 {
193 /* Insert the depends into the master table */
194 if (mport_db_do(mport->db,
195 "INSERT INTO depends (pkg, depend_pkgname, depend_pkgversion, depend_port) SELECT pkg,depend_pkgname,depend_pkgversion,depend_port FROM stub.depends WHERE pkg=%Q",
196 pkg->name) != MPORT_OK)
197 RETURN_CURRENT_ERROR;
198
199 return MPORT_OK;
200 }
201
202 static int
203 create_categories(mportInstance *mport, mportPackageMeta *pkg)
204 {
205 /* Insert the categories into the master table */
206 if (mport_db_do(mport->db,
207 "INSERT INTO categories (pkg, category) SELECT pkg, category FROM stub.categories WHERE pkg=%Q",
208 pkg->name) != MPORT_OK)
209 RETURN_CURRENT_ERROR;
210
211 return MPORT_OK;
212 }
213
214 static char**
215 parse_sample(char *input)
216 {
217 char **ap, **argv;
218 argv = calloc(3, sizeof(char *));
219
220 if (argv == NULL)
221 return NULL;
222
223 for (ap = argv; (*ap = strsep(&input, " \t")) != NULL;) {
224 if (**ap != '\0') {
225 if (++ap >= &argv[3])
226 break;
227 }
228 }
229
230 return argv;
231 }
232
233 static int
234 create_sample_file(mportInstance *mport, char *cwd, const char *file)
235 {
236 char nonSample[FILENAME_MAX * 2];
237 char secondFile[FILENAME_MAX];
238
239 strlcpy(nonSample, file, FILENAME_MAX * 2);
240 (void) snprintf(nonSample, FILENAME_MAX, "%s%s/%s", mport->root, cwd, file);
241 char** fileargv = parse_sample(nonSample);
242
243 if (fileargv[1] != '\0') {
244 if (fileargv[1][0] == '/')
245 strlcpy(secondFile, fileargv[1], FILENAME_MAX);
246 else
247 (void) snprintf(secondFile, FILENAME_MAX, "%s%s/%s", mport->root, cwd, fileargv[1]);
248
249 if (!mport_file_exists(secondFile)) {
250 if (mport_copy_file(fileargv[0], secondFile) != MPORT_OK)
251 RETURN_CURRENT_ERROR;
252 }
253 } else {
254 /* single file */
255 char *sptr = strcasestr(nonSample, ".sample");
256 if (sptr != NULL) {
257 sptr[0] = '\0'; /* hack off .sample */
258 if (!mport_file_exists(nonSample)) {
259 if (mport_copy_file(file, nonSample) != MPORT_OK)
260 RETURN_CURRENT_ERROR;
261 }
262 }
263 }
264
265 free(fileargv);
266
267 return MPORT_OK;
268 }
269
270 /**
271 * Get the list of assets (plist entries) from the stub attached database (package we are installing)
272 * filtered on entries that are not pre/post exec.
273 */
274 static int
275 mport_bundle_read_get_assetlist(mportInstance *mport, mportPackageMeta *pkg, mportAssetList **alist_p, enum phase state)
276 {
277 __block mportAssetList *alist;
278 __block sqlite3_stmt *stmt = NULL;
279 __block int result = MPORT_OK;
280 __block char *err;
281
282 if ((alist = mport_assetlist_new()) == NULL)
283 RETURN_ERROR(MPORT_ERR_FATAL, "Out of memory.");
284
285 *alist_p = alist;
286
287 if (state == PREINSTALL) {
288 if (mport_db_prepare(mport->db, &stmt,
289 "SELECT type,data,checksum,owner,grp,mode FROM stub.assets WHERE pkg=%Q and type in (%d, %d)",
290 pkg->name, ASSET_CWD, ASSET_PREEXEC) != MPORT_OK) {
291 sqlite3_finalize(stmt);
292 RETURN_CURRENT_ERROR;
293 }
294 } else if (state == ACTUALINSTALL) {
295 if (mport_db_prepare(mport->db, &stmt,
296 "SELECT type,data,checksum,owner,grp,mode FROM stub.assets WHERE pkg=%Q and type not in (%d, %d)",
297 pkg->name, ASSET_PREEXEC, ASSET_POSTEXEC) != MPORT_OK) {
298 sqlite3_finalize(stmt);
299 RETURN_CURRENT_ERROR;
300 }
301 } else if (state == POSTINSTALL) {
302 if (mport_db_prepare(mport->db, &stmt,
303 "SELECT type,data,checksum,owner,grp,mode FROM stub.assets WHERE pkg=%Q and type in (%d, %d)",
304 pkg->name, ASSET_CWD, ASSET_POSTEXEC) != MPORT_OK) {
305 sqlite3_finalize(stmt);
306 RETURN_CURRENT_ERROR;
307 }
308 }
309
310 if (stmt == NULL) {
311 RETURN_ERROR(MPORT_ERR_FATAL, "Statement was null");
312 }
313
314 dispatch_sync(mportSQLSerial, ^{
315 while (1) {
316 mportAssetListEntry *e;
317
318 int ret = sqlite3_step(stmt);
319
320 if (ret == SQLITE_BUSY || ret == SQLITE_LOCKED) {
321 sleep(1);
322 ret = sqlite3_step(stmt);
323 }
324
325 if (ret == SQLITE_DONE)
326 break;
327
328 if (ret != SQLITE_ROW) {
329 err = (char *) sqlite3_errmsg(mport->db);
330 result = MPORT_ERR_FATAL;
331 break; // we finalize below
332 }
333
334 e = (mportAssetListEntry *) calloc(1, sizeof(mportAssetListEntry));
335
336 if (e == NULL) {
337 err = "Out of memory";
338 result = MPORT_ERR_FATAL;
339 break; // we finalize below
340 }
341
342 e->type = (mportAssetListEntryType) sqlite3_column_int(stmt, 0);
343 const unsigned char *data = sqlite3_column_text(stmt, 1);
344 const unsigned char *checksum = sqlite3_column_text(stmt, 2);
345 const unsigned char *owner = sqlite3_column_text(stmt, 3);
346 const unsigned char *group = sqlite3_column_text(stmt, 4);
347 const unsigned char *mode = sqlite3_column_text(stmt, 5);
348
349 e->data = data == NULL ? NULL : strdup((char *) data);
350 if (checksum != NULL)
351 e->checksum = strdup((char *) checksum);
352 if (owner != NULL)
353 e->owner = strdup((char *) owner);
354 if (group != NULL)
355 e->group = strdup((char *) group);
356 if (mode != NULL)
357 e->mode = strdup((char *) mode);
358
359 STAILQ_INSERT_TAIL(alist, e, next);
360 }
361
362 sqlite3_finalize(stmt);
363 });
364
365 if (result == MPORT_ERR_FATAL)
366 SET_ERRORX(result, "Error reading assets %s", err);
367 return result;
368 }
369
370 static int
371 do_actual_install(mportInstance *mport, mportBundleRead *bundle, mportPackageMeta *pkg)
372 {
373 mportAssetList *alist = NULL;
374 __block mportAssetListEntry *e = NULL;
375 int file_total;
376 int file_count = 0;
377 struct archive_entry *entry;
378 char *orig_cwd = NULL;
379 uid_t owner = 0; /* root */
380 gid_t group = 0; /* wheel */
381 mode_t *set = NULL;
382 mode_t newmode;
383 mode_t *dirset = NULL;
384 mode_t dirnewmode;
385 char *mode = NULL;
386 char *mkdirp = NULL;
387 struct stat sb;
388 __block char file[FILENAME_MAX], cwd[FILENAME_MAX];
389 __block sqlite3_stmt *insert = NULL;
390
391 /* sadly, we can't just use abs pathnames, because it will break hardlinks */
392 orig_cwd = getcwd(NULL, 0);
393
394 if (get_file_count(mport, pkg->name, &file_total) != MPORT_OK)
395 goto ERROR;
396
397 mport_call_progress_init_cb(mport, "Installing %s-%s", pkg->name, pkg->version);
398
399 if (mport_bundle_read_get_assetlist(mport, pkg, &alist, ACTUALINSTALL) != MPORT_OK)
400 goto ERROR;
401
402 if (create_package_row(mport, pkg) != MPORT_OK)
403 goto ERROR;
404
405 if (create_depends(mport, pkg) != MPORT_OK)
406 goto ERROR;
407
408 if (create_categories(mport, pkg) != MPORT_OK)
409 goto ERROR;
410
411 /* Insert the assets into the master table (We do this one by one because we want to insert file
412 * assets as absolute paths. */
413 if (mport_db_prepare(mport->db, &insert,
414 "INSERT INTO assets (pkg, type, data, checksum, owner, grp, mode) values (%Q,?,?,?,?,?,?)",
415 pkg->name) != MPORT_OK)
416 goto ERROR;
417
418 (void) strlcpy(cwd, pkg->prefix, sizeof(cwd));
419
420 if (mport_chdir(mport, cwd) != MPORT_OK)
421 goto ERROR;
422
423 mport_db_do(mport->db, "BEGIN TRANSACTION");
424
425 STAILQ_FOREACH(e, alist, next) {
426 switch (e->type) {
427 case ASSET_CWD:
428 (void) strlcpy(cwd, e->data == NULL ? pkg->prefix : e->data, sizeof(cwd));
429 if (mport_chdir(mport, cwd) != MPORT_OK)
430 goto ERROR;
431 break;
432 case ASSET_CHMOD:
433 if (mode != NULL)
434 free(mode);
435 /* TODO: should we reset the mode rather than NULL here */
436 if (e->data == NULL)
437 mode = NULL;
438 else
439 mode = strdup(e->data);
440 break;
441 case ASSET_CHOWN:
442 owner = mport_get_uid(e->data);
443 break;
444 case ASSET_CHGRP:
445 group = mport_get_gid(e->data);
446 break;
447 case ASSET_DIR:
448 case ASSET_DIRRM:
449 case ASSET_DIRRMTRY:
450 case ASSET_DIR_OWNER_MODE:
451 mkdirp = strdup( e->data == NULL ? "" : e->data); /* need a char * here */
452 if (mkdirp == NULL || mport_mkdirp(mkdirp, S_IRWXU | S_IRWXG | S_IRWXO) == 0) {
453 free(mkdirp);
454 SET_ERRORX(MPORT_ERR_FATAL, "Unable to create directory %s", e->data);
455 goto ERROR;
456 }
457 free(mkdirp);
458
459 if (e->mode != NULL && e->mode[0] != '\0') {
460 if ((dirset = setmode(e->mode)) == NULL)
461 goto ERROR;
462 dirnewmode = getmode(dirset, sb.st_mode);
463 free(dirset);
464 if (chmod(e->data, dirnewmode))
465 goto ERROR;
466 }
467 if (e->owner != NULL && e->group != NULL && e->owner[0] != '\0' &&
468 e->group[0] != '\0') {
469 if (chown(e->data, mport_get_uid(e->owner), mport_get_gid(e->group)) == -1) {
470 SET_ERROR(MPORT_ERR_FATAL, "Unable to change owner");
471 goto ERROR;
472 }
473 } else if (e->owner != NULL && e->owner[0] != '\0') {
474 if (chown(e->data, mport_get_uid(e->owner), group) == -1) {
475 SET_ERROR(MPORT_ERR_FATAL, "Unable to change owner");
476 goto ERROR;
477 }
478 } else if (e->group != NULL && e->group[0] != '\0') {
479 if (chown(e->data, owner, mport_get_gid(e->group)) == -1) {
480 SET_ERROR(MPORT_ERR_FATAL, "Unable to change owner");
481 goto ERROR;
482 }
483 }
484
485 break;
486 case ASSET_EXEC:
487 if (mport_run_asset_exec(mport, e->data, cwd, file) != MPORT_OK)
488 goto ERROR;
489 break;
490 case ASSET_FILE_OWNER_MODE:
491 /* FALLS THROUGH */
492 case ASSET_FILE:
493 /* FALLS THROUGH */
494 case ASSET_SHELL:
495 /* FALLS THROUGH */
496 case ASSET_SAMPLE:
497 if (mport_bundle_read_next_entry(bundle, &entry) != MPORT_OK)
498 goto ERROR;
499
500 (void) snprintf(file, FILENAME_MAX, "%s%s/%s", mport->root, cwd, e->data);
501
502 if (e->type == ASSET_SAMPLE)
503 for (int ch = 0; ch < FILENAME_MAX; ch++) {
504 if (file[ch] == '\0')
505 break;
506 if (file[ch] == ' ' || file[ch] == '\t') {
507 file[ch] = '\0';
508 break;
509 }
510 }
511
512 if (entry == NULL) {
513 SET_ERROR(MPORT_ERR_FATAL, "Unexpected EOF with archive file");
514 goto ERROR;
515 }
516
517 archive_entry_set_pathname(entry, file);
518
519 if (mport_bundle_read_extract_next_file(bundle, entry) != MPORT_OK)
520 goto ERROR;
521
522 if (lstat(file, &sb)) {
523 SET_ERRORX(MPORT_ERR_FATAL, "Unable to stat file %s", file);
524 goto ERROR;
525 }
526
527 if (S_ISREG(sb.st_mode)) {
528 if (e->type == ASSET_FILE_OWNER_MODE) {
529 /* Test for owner and group settings, otherwise roll with our default. */
530 if (e->owner != NULL && e->group != NULL && e->owner[0] != '\0' &&
531 e->group[0] != '\0') {
532 #ifdef DEBUG
533 fprintf(stderr, "owner %s and group %s\n", e->owner, e->group);
534 #endif
535 if (chown(file, mport_get_uid(e->owner),
536 mport_get_gid(e->group)) == -1) {
537 SET_ERROR(MPORT_ERR_FATAL, "Unable to change owner");
538 goto ERROR;
539 }
540 } else if (e->owner != NULL && e->owner[0] != '\0') {
541 #ifdef DEBUG
542 fprintf(stderr, "owner %s\n", e->owner);
543 #endif
544 if (chown(file, mport_get_uid(e->owner), group) == -1) {
545 SET_ERROR(MPORT_ERR_FATAL, "Unable to change owner");
546 goto ERROR;
547 }
548 } else if (e->group != NULL && e->group[0] != '\0') {
549 #ifdef DEBUG
550 fprintf(stderr, "group %s\n", e->group);
551 #endif
552 if (chown(file, owner, mport_get_gid(e->group)) == -1) {
553 SET_ERROR(MPORT_ERR_FATAL, "Unable to change owner");
554 goto ERROR;
555 }
556 } else {
557 // use default.
558 if (chown(file, owner, group) == -1) {
559 SET_ERROR(MPORT_ERR_FATAL, "Unable to change owner");
560 goto ERROR;
561 }
562 }
563 } else {
564 /* Set the owner and group */
565 if (chown(file, owner, group) == -1) {
566 SET_ERRORX(MPORT_ERR_FATAL,
567 "Unable to set permissions on file %s", file);
568 goto ERROR;
569 }
570 }
571
572 /* Set the file permissions, assumes non NFSv4 */
573 if (mode != NULL) {
574 if (stat(file, &sb)) {
575 SET_ERRORX(MPORT_ERR_FATAL, "Unable to stat file %s", file);
576 goto ERROR;
577 }
578 if (e->type == ASSET_FILE_OWNER_MODE && e->mode != NULL) {
579 if ((set = setmode(e->mode)) == NULL) {
580 SET_ERROR(MPORT_ERR_FATAL, "Unable to set mode");
581 goto ERROR;
582 }
583 } else {
584 if ((set = setmode(mode)) == NULL) {
585 SET_ERROR(MPORT_ERR_FATAL, "Unable to set mode");
586 goto ERROR;
587 }
588 }
589 newmode = getmode(set, sb.st_mode);
590 free(set);
591 if (chmod(file, newmode)) {
592 SET_ERROR(MPORT_ERR_FATAL, "Unable to set file permissions");
593 goto ERROR;
594 }
595 }
596
597 /* shell registration */
598 if (e->type == ASSET_SHELL && mport_shell_register(file) != MPORT_OK) {
599 goto ERROR;
600 }
601
602 /* for sample files, if we don't have an existing file, make a new one */
603 if (e->type == ASSET_SAMPLE && create_sample_file(mport, cwd, e->data) != MPORT_OK) {
604 SET_ERRORX(MPORT_ERR_FATAL, "Unable to create sample file from %s",
605 file);
606 goto ERROR;
607 }
608 }
609
610 (mport->progress_step_cb)(++file_count, file_total, file);
611
612 break;
613 default:
614 /* do nothing */
615 break;
616 }
617
618 /* insert this asset into the master database */
619 __block int code = MPORT_OK;
620 __block const char *err;
621 __block char *filePtr = strdup(file);
622 __block char *cwdPtr = strdup(cwd);
623 dispatch_sync(mportSQLSerial, ^{
624 char dir[FILENAME_MAX];
625 if (sqlite3_bind_int(insert, 1, (int) e->type) != SQLITE_OK) {
626 code = MPORT_ERR_FATAL;
627 err = sqlite3_errmsg(mport->db);
628 return;
629 }
630 if (e->type == ASSET_FILE || e->type == ASSET_SAMPLE || e->type == ASSET_SHELL ||
631 e->type == ASSET_FILE_OWNER_MODE) {
632 /* don't put the root in the database! */
633 if (sqlite3_bind_text(insert, 2, filePtr + strlen(mport->root), -1, SQLITE_STATIC) !=
634 SQLITE_OK) {
635 code = MPORT_ERR_FATAL;
636 err = sqlite3_errmsg(mport->db);
637 return;
638 }
639
640 if (sqlite3_bind_text(insert, 3, e->checksum, -1, SQLITE_STATIC) != SQLITE_OK) {
641 code = MPORT_ERR_FATAL;
642 err = sqlite3_errmsg(mport->db);
643 return;
644 }
645
646 if (e->owner != NULL) {
647 if (sqlite3_bind_text(insert, 4, e->owner, -1, SQLITE_STATIC) != SQLITE_OK) {
648 code = MPORT_ERR_FATAL;
649 err = sqlite3_errmsg(mport->db);
650 return;
651 }
652 } else {
653 if (sqlite3_bind_null(insert, 4) != SQLITE_OK) {
654 code = MPORT_ERR_FATAL;
655 err = sqlite3_errmsg(mport->db);
656 return;
657 }
658 }
659
660 if (e->group != NULL) {
661 if (sqlite3_bind_text(insert, 5, e->group, -1, SQLITE_STATIC) != SQLITE_OK) {
662 code = MPORT_ERR_FATAL;
663 err = sqlite3_errmsg(mport->db);
664 return;
665 }
666 } else {
667 if (sqlite3_bind_null(insert, 5) != SQLITE_OK) {
668 code = MPORT_ERR_FATAL;
669 err = sqlite3_errmsg(mport->db);
670 return;
671 }
672 }
673
674 if (e->mode != NULL) {
675 if (sqlite3_bind_text(insert, 6, e->mode, -1, SQLITE_STATIC) != SQLITE_OK) {
676 code = MPORT_ERR_FATAL;
677 err = sqlite3_errmsg(mport->db);
678 return;
679 }
680 } else {
681 if (sqlite3_bind_null(insert, 6) != SQLITE_OK) {
682 code = MPORT_ERR_FATAL;
683 err = sqlite3_errmsg(mport->db);
684 return;
685 }
686 }
687 } else if (e->type == ASSET_DIR || e->type == ASSET_DIRRM || e->type == ASSET_DIRRMTRY) {
688 /* if data starts with /, it's most likely an absolute path. Don't prepend cwd */
689 if (e->data != NULL && e->data[0] == '/')
690 (void) snprintf(dir, FILENAME_MAX, "%s", e->data);
691 else
692 (void) snprintf(dir, FILENAME_MAX, "%s/%s", cwdPtr, e->data);
693
694 if (sqlite3_bind_text(insert, 2, dir, -1, SQLITE_STATIC) != SQLITE_OK) {
695 code = MPORT_ERR_FATAL;
696 err = sqlite3_errmsg(mport->db);
697 return;
698 }
699
700 if (sqlite3_bind_null(insert, 3) != SQLITE_OK) {
701 code = MPORT_ERR_FATAL;
702 err = sqlite3_errmsg(mport->db);
703 return;
704 }
705
706 if (sqlite3_bind_null(insert, 4) != SQLITE_OK) {
707 code = MPORT_ERR_FATAL;
708 err = sqlite3_errmsg(mport->db);
709 return;
710 }
711
712 if (sqlite3_bind_null(insert, 5) != SQLITE_OK) {
713 code = MPORT_ERR_FATAL;
714 err = sqlite3_errmsg(mport->db);
715 return;
716 }
717
718 if (sqlite3_bind_null(insert, 6) != SQLITE_OK) {
719 code = MPORT_ERR_FATAL;
720 err = sqlite3_errmsg(mport->db);
721 return;
722 }
723 } else {
724 if (sqlite3_bind_text(insert, 2, e->data, -1, SQLITE_STATIC) != SQLITE_OK) {
725 code = MPORT_ERR_FATAL;
726 err = sqlite3_errmsg(mport->db);
727 return;
728 }
729
730 if (sqlite3_bind_null(insert, 3) != SQLITE_OK) {
731 code = MPORT_ERR_FATAL;
732 err = sqlite3_errmsg(mport->db);
733 return;
734 }
735
736 if (sqlite3_bind_null(insert, 4) != SQLITE_OK) {
737 code = MPORT_ERR_FATAL;
738 err = sqlite3_errmsg(mport->db);
739 return;
740 }
741
742 if (sqlite3_bind_null(insert, 5) != SQLITE_OK) {
743 code = MPORT_ERR_FATAL;
744 err = sqlite3_errmsg(mport->db);
745 return;
746 }
747
748 if (sqlite3_bind_null(insert, 6) != SQLITE_OK) {
749 code = MPORT_ERR_FATAL;
750 err = sqlite3_errmsg(mport->db);
751 return;
752 }
753 }
754
755 if (sqlite3_step(insert) != SQLITE_DONE) {
756 code = MPORT_ERR_FATAL;
757 err = sqlite3_errmsg(mport->db);
758 return;
759 }
760
761 sqlite3_reset(insert);
762 });
763
764 free(filePtr);
765 free(cwdPtr);
766 if (code != MPORT_OK) {
767 SET_ERROR(code, err);
768 goto ERROR;
769 }
770 }
771
772 if (mport_db_do(mport->db, "COMMIT") != MPORT_OK) {
773 SET_ERROR(MPORT_ERR_FATAL, sqlite3_errmsg(mport->db));
774 goto ERROR;
775 }
776 sqlite3_finalize(insert);
777
778 mport_pkgmeta_logevent(mport, pkg, "Installed");
779
780 (mport->progress_free_cb)();
781 (void) mport_chdir(NULL, orig_cwd);
782 free(orig_cwd);
783 mport_assetlist_free(alist);
784 return (MPORT_OK);
785
786 ERROR:
787 sqlite3_finalize(insert);
788 (mport->progress_free_cb)();
789 free(orig_cwd);
790 mport_assetlist_free(alist);
791 RETURN_CURRENT_ERROR;
792 }
793
794
795 #define COPY_METAFILE(TYPE) (void)snprintf(from, FILENAME_MAX, "%s/%s/%s-%s/%s", bundle->tmpdir, MPORT_STUB_INFRA_DIR, pkg->name, pkg->version, TYPE); \
796 if (mport_file_exists(from)) { \
797 (void)snprintf(to, FILENAME_MAX, "%s%s/%s-%s/%s", mport->root, MPORT_INST_INFRA_DIR, pkg->name, pkg->version, TYPE); \
798 if (mport_mkdir(dirname(to)) != MPORT_OK) \
799 RETURN_CURRENT_ERROR; \
800 if (mport_copy_file(from, to) != MPORT_OK) \
801 RETURN_CURRENT_ERROR; \
802 }
803
804 static int
805 mark_complete(mportInstance *mport, mportPackageMeta *pkg)
806 {
807 if (mport_db_do(mport->db, "UPDATE packages SET status='clean' WHERE pkg=%Q", pkg->name) != MPORT_OK) {
808 SET_ERROR(MPORT_ERR_FATAL, "Unable to mark package clean");
809 RETURN_CURRENT_ERROR;
810 }
811
812 return MPORT_OK;
813 }
814
815
816 static int
817 do_post_install(mportInstance *mport, mportBundleRead *bundle, mportPackageMeta *pkg)
818 {
819 char to[FILENAME_MAX], from[FILENAME_MAX]; /* keep these for COPY_METAFILE */
820
821 COPY_METAFILE(MPORT_MTREE_FILE);
822 COPY_METAFILE(MPORT_INSTALL_FILE);
823 COPY_METAFILE(MPORT_DEINSTALL_FILE);
824 COPY_METAFILE(MPORT_MESSAGE_FILE);
825
826 if (run_postexec(mport, pkg) != MPORT_OK)
827 RETURN_CURRENT_ERROR;
828
829 if (display_pkg_msg(mport, bundle, pkg) != MPORT_OK)
830 RETURN_CURRENT_ERROR;
831
832 if (run_pkg_install(mport, bundle, pkg, "POST-INSTALL") != MPORT_OK)
833 RETURN_CURRENT_ERROR;
834
835 return mark_complete(mport, pkg);
836 }
837
838
839 static int
840 run_postexec(mportInstance *mport, mportPackageMeta *pkg)
841 {
842 mportAssetList *alist;
843 mportAssetListEntry *e = NULL;
844 char cwd[FILENAME_MAX];
845
846 /* Process @postexec steps */
847 if (mport_bundle_read_get_assetlist(mport, pkg, &alist, POSTINSTALL) != MPORT_OK)
848 goto ERROR;
849
850 (void) strlcpy(cwd, pkg->prefix, sizeof(cwd));
851
852 if (mport_chdir(mport, cwd) != MPORT_OK)
853 goto ERROR;
854
855 STAILQ_FOREACH(e, alist, next) {
856 char file[FILENAME_MAX];
857 if (e->data == NULL) {
858 snprintf(file, sizeof(file), "%s", mport->root);
859 } else if (e->data[0] == '/') {
860 snprintf(file, sizeof(file), "%s%s", mport->root, e->data);
861 } else {
862 snprintf(file, sizeof(file), "%s%s/%s", mport->root, pkg->prefix, e->data);
863 }
864
865 switch (e->type) {
866 case ASSET_CWD:
867 (void) strlcpy(cwd, e->data == NULL ? pkg->prefix : e->data, sizeof(cwd));
868 if (mport_chdir(mport, cwd) != MPORT_OK)
869 goto ERROR;
870 break;
871 case ASSET_POSTEXEC:
872 if (mport_run_asset_exec(mport, e->data, cwd, file) != MPORT_OK)
873 goto ERROR;
874 break;
875 default:
876 /* do nothing */
877 break;
878 }
879 }
880
881 mport_assetlist_free(alist);
882 mport_pkgmeta_logevent(mport, pkg, "postexec");
883
884 return MPORT_OK;
885
886 ERROR:
887 // TODO: asset list free
888 RETURN_CURRENT_ERROR;
889 }
890
891
892 static int
893 run_mtree(mportInstance *mport, mportBundleRead *bundle, mportPackageMeta *pkg)
894 {
895 char file[FILENAME_MAX];
896 int ret;
897
898 (void) snprintf(file, FILENAME_MAX, "%s/%s/%s-%s/%s", bundle->tmpdir, MPORT_STUB_INFRA_DIR, pkg->name,
899 pkg->version,
900 MPORT_MTREE_FILE);
901
902 if (mport_file_exists(file)) {
903 if ((ret = mport_xsystem(mport, "%s -U -f %s -d -e -p %s >/dev/null", MPORT_MTREE_BIN, file,
904 pkg->prefix)) != 0)
905 RETURN_ERRORX(MPORT_ERR_FATAL, "%s returned non-zero: %i", MPORT_MTREE_BIN, ret);
906 }
907
908 return MPORT_OK;
909 }
910
911
912 static int
913 run_pkg_install(mportInstance *mport, mportBundleRead *bundle, mportPackageMeta *pkg, const char *mode)
914 {
915 char file[FILENAME_MAX];
916 int ret;
917
918 (void) snprintf(file, FILENAME_MAX, "%s/%s/%s-%s/%s", bundle->tmpdir, MPORT_STUB_INFRA_DIR, pkg->name,
919 pkg->version,
920 MPORT_INSTALL_FILE);
921
922 if (mport_file_exists(file)) {
923 if (chmod(file, 755) != 0)
924 RETURN_ERRORX(MPORT_ERR_FATAL, "chmod(%s, 755): %s", file, strerror(errno));
925
926 if ((ret = mport_xsystem(mport, "PKG_PREFIX=%s %s %s %s", pkg->prefix, file, pkg->name, mode)) != 0)
927 RETURN_ERRORX(MPORT_ERR_FATAL, "%s %s returned non-zero: %i", MPORT_INSTALL_FILE, mode, ret);
928 }
929
930 return MPORT_OK;
931 }
932
933
934 static int
935 display_pkg_msg(mportInstance *mport, mportBundleRead *bundle, mportPackageMeta *pkg)
936 {
937 char filename[FILENAME_MAX];
938 char *buf;
939 struct stat st;
940 FILE *file;
941
942 (void) snprintf(filename, FILENAME_MAX, "%s/%s/%s-%s/%s", bundle->tmpdir, MPORT_STUB_INFRA_DIR, pkg->name,
943 pkg->version, MPORT_MESSAGE_FILE);
944
945 if (stat(filename, &st) == -1)
946 /* if we couldn't stat the file, we assume there isn't a pkg-msg */
947 return MPORT_OK;
948
949 if ((file = fopen(filename, "r")) == NULL)
950 RETURN_ERRORX(MPORT_ERR_FATAL, "Couldn't open %s: %s", filename, strerror(errno));
951
952 if ((buf = (char *) calloc((size_t) (st.st_size + 1), sizeof(char))) == NULL)
953 RETURN_ERROR(MPORT_ERR_FATAL, "Out of memory.");
954
955 if (fread(buf, 1, (size_t) st.st_size, file) != (size_t) st.st_size) {
956 free(buf);
957 RETURN_ERRORX(MPORT_ERR_FATAL, "Read error: %s", strerror(errno));
958 }
959
960 buf[st.st_size] = 0;
961
962 mport_call_msg_cb(mport, buf);
963
964 free(buf);
965
966 return MPORT_OK;
967 }

Properties

Name Value
svn:keywords MidnightBSD=%H