add.c 5.79 KB
Newer Older
1 2 3 4 5 6
/* add.c - Alpine Package Keeper (APK)
 *
 * Copyright (C) 2005-2008 Natanael Copa <n@tanael.org>
 * Copyright (C) 2008 Timo Teräs <timo.teras@iki.fi>
 * All rights reserved.
 *
Timo Teräs's avatar
Timo Teräs committed
7
 * This program is free software; you can redistribute it and/or modify it
8 9 10 11
 * under the terms of the GNU General Public License version 2 as published
 * by the Free Software Foundation. See http://www.gnu.org/ for details.
 */

12
#include <errno.h>
13
#include <stdio.h>
14
#include <zlib.h>
15 16
#include "apk_applet.h"
#include "apk_database.h"
17
#include "apk_state.h"
18

19
struct add_ctx {
20
	unsigned int open_flags;
21
	const char *virtpkg;
22 23 24 25 26 27 28 29
};

static int add_parse(void *ctx, int optch, int optindex, const char *optarg)
{
	struct add_ctx *actx = (struct add_ctx *) ctx;

	switch (optch) {
	case 0x10000:
30
		actx->open_flags |= APK_OPENF_CREATE;
31
		break;
32
	case 'u':
33
		apk_flags |= APK_UPGRADE;
34
		break;
35 36 37
	case 't':
		actx->virtpkg = optarg;
		break;
38 39 40 41 42 43
	default:
		return -1;
	}
	return 0;
}

44 45
static int cup(void)
{
Timo Teräs's avatar
Timo Teräs committed
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70
	/* compressed/uncompressed size is 259/1213 */
	static unsigned char z[] = {
		0x78,0x9c,0x9d,0x94,0x3d,0x8e,0xc4,0x20,0x0c,0x85,0xfb,0x9c,
		0xc2,0x72,0x43,0x46,0x8a,0x4d,0x3f,0x67,0x89,0x64,0x77,0x2b,
		0x6d,0xbb,0x6d,0x0e,0x3f,0xc6,0x84,0x4d,0x08,0x84,0x55,0xd6,
		0xa2,0xe0,0xef,0x7b,0x36,0xe1,0x11,0x80,0x6e,0xcc,0x53,0x7f,
		0x3e,0xc5,0xeb,0xcf,0x1d,0x20,0x22,0xcc,0x3c,0x53,0x8e,0x17,
		0xd9,0x80,0x6d,0xee,0x0e,0x61,0x42,0x3c,0x8b,0xcf,0xc7,0x12,
		0x22,0x71,0x8b,0x31,0x05,0xd5,0xb0,0x11,0x4b,0xa7,0x32,0x2f,
		0x80,0x69,0x6b,0xb0,0x98,0x40,0xe2,0xcd,0xba,0x6a,0xba,0xe4,
		0x65,0xed,0x61,0x23,0x44,0xb5,0x95,0x06,0x8b,0xde,0x6c,0x61,
		0x70,0xde,0x0e,0xb6,0xed,0xc4,0x43,0x0c,0x56,0x6f,0x8f,0x31,
		0xd0,0x35,0xb5,0xc7,0x58,0x06,0xff,0x81,0x49,0x84,0xb8,0x0e,
		0xb1,0xd8,0xc1,0x66,0x31,0x0e,0x46,0x5c,0x43,0xc9,0xef,0xe5,
		0xdc,0x63,0xb1,0xdc,0x67,0x6d,0x31,0xb3,0xc9,0x69,0x74,0x87,
		0xc7,0xa3,0x1b,0x6a,0xb3,0xbd,0x2f,0x3b,0xd5,0x0c,0x57,0x3b,
		0xce,0x7c,0x5e,0xe5,0x48,0xd0,0x48,0x01,0x92,0x49,0x8b,0xf7,
		0xfc,0x58,0x67,0xb3,0xf7,0x14,0x20,0x5c,0x4c,0x9e,0xcc,0xeb,
		0x78,0x7e,0x64,0xa6,0xa1,0xf5,0xb2,0x70,0x38,0x09,0x7c,0x7f,
		0xfd,0xc0,0x8a,0x4e,0xc8,0x55,0xe8,0x12,0xe2,0x9f,0x1a,0xb1,
		0xb9,0x82,0x52,0x02,0x7a,0xe5,0xf9,0xd9,0x88,0x47,0x79,0x3b,
		0x46,0x61,0x27,0xf9,0x51,0xb1,0x17,0xb0,0x2c,0x0e,0xd5,0x39,
		0x2d,0x96,0x25,0x27,0xd6,0xd1,0x3f,0xa5,0x08,0xe1,0x9e,0x4e,
		0xa7,0xe9,0x03,0xb1,0x0a,0xb6,0x75
	};
71
	unsigned char buf[1213];
Timo Teräs's avatar
Timo Teräs committed
72 73
	unsigned long len = sizeof(buf);

74 75
	uncompress(buf, &len, z, sizeof(z));
	write(STDOUT_FILENO, buf, len);
Timo Teräs's avatar
Timo Teräs committed
76

77 78 79
	return 0;
}

Timo Teräs's avatar
Timo Teräs committed
80

Timo Teräs's avatar
Timo Teräs committed
81
static int add_main(void *ctx, int argc, char **argv)
82
{
83
	struct add_ctx *actx = (struct add_ctx *) ctx;
84
	struct apk_database db;
85
	struct apk_state *state = NULL;
86 87
	struct apk_dependency_array *pkgs = NULL;
	struct apk_package *virtpkg = NULL;
88
	struct apk_dependency virtdep;
89
	int i, r;
90

Timo Teräs's avatar
Timo Teräs committed
91
	if ((argc > 0) && (apk_verbosity > 1) &&
92 93
	    (strcmp(argv[0], "coffee") == 0))
		return cup();
94

95 96 97
	r = apk_db_open(&db, apk_root, actx->open_flags | APK_OPENF_WRITE);
	if (r != 0)
		return r;
Timo Teräs's avatar
Timo Teräs committed
98

99 100 101 102 103 104
	if (actx->virtpkg) {
		virtpkg = apk_pkg_new();
		if (virtpkg == NULL) {
			apk_error("Failed to allocate virtual meta package");
			goto err;
		}
Timo Teräs's avatar
Timo Teräs committed
105
		virtpkg->name = apk_db_get_name(&db, APK_BLOB_STR(actx->virtpkg));
Timo Teräs's avatar
Timo Teräs committed
106 107
		apk_blob_checksum(APK_BLOB_STR(virtpkg->name->name),
				  apk_default_checksum(), &virtpkg->csum);
108 109
		virtpkg->version = strdup("0");
		virtpkg->description = strdup("virtual meta package");
Timo Teräs's avatar
Timo Teräs committed
110
		apk_dep_from_pkg(&virtdep, &db, virtpkg);
111
		virtdep.name->flags |= APK_NAME_TOPLEVEL | APK_NAME_VIRTUAL;
112 113
		virtpkg = apk_db_pkg_add(&db, virtpkg);
	}
114

115
	for (i = 0; i < argc; i++) {
116 117 118
		struct apk_dependency dep;

		if (strstr(argv[i], ".apk") != NULL) {
119
			struct apk_package *pkg = NULL;
Timo Teräs's avatar
Timo Teräs committed
120
			struct apk_sign_ctx sctx;
121

122 123 124 125 126 127 128 129 130 131 132
			if (!apk_db_cache_active(&db) &&
			    !apk_db_permanent(&db) &&
			    !(apk_flags & APK_FORCE)) {
				apk_error("Use --force or enable package "
					  "caching to install non-repository "
					  "packages.");
				goto err;
			}

			/* FIXME: should verify the package too */
			apk_sign_ctx_init(&sctx, APK_SIGN_GENERATE, NULL);
133
			r = apk_pkg_read(&db, argv[i], &sctx, &pkg);
Timo Teräs's avatar
Timo Teräs committed
134
			apk_sign_ctx_free(&sctx);
135 136
			if (r != 0) {
				apk_error("%s: %s", argv[i], apk_error_str(r));
137 138
				goto err;

139
			}
Timo Teräs's avatar
Timo Teräs committed
140 141 142 143 144 145
			apk_dep_from_pkg(&dep, &db, pkg);
		} else {
			r = apk_dep_from_blob(&dep, &db, APK_BLOB_STR(argv[i]));
			if (r != 0)
				goto err;
		}
146

147 148 149 150 151
		if (virtpkg) {
			apk_deps_add(&virtpkg->depends, &dep);
		} else {
			dep.name->flags |= APK_NAME_TOPLEVEL;
		}
152
		apk_deps_add(&pkgs, &dep);
153
	}
154

155
	if (virtpkg) {
156
		apk_deps_add(&pkgs, &virtdep);
157 158
		apk_deps_add(&db.world, &virtdep);
	}
159

160
	state = apk_state_new(&db);
161
	for (i = 0; (pkgs != NULL) && i < pkgs->num; i++) {
162
		r = apk_state_lock_dependency(state, &pkgs->item[i]);
163
		if (r != 0) {
164
			apk_error("Unable to install '%s'", pkgs->item[i].name->name);
165 166
			if (!(apk_flags & APK_FORCE))
				goto err;
167
		}
168 169
		if (!virtpkg)
			apk_deps_add(&db.world, &pkgs->item[i]);
170
	}
171
	r = apk_state_commit(state, &db);
172
err:
173 174
	if (state != NULL)
		apk_state_unref(state);
175
	apk_db_close(&db);
176
	return r;
177 178
}

Timo Teräs's avatar
Timo Teräs committed
179 180 181 182 183 184 185 186
static struct apk_option add_options[] = {
	{ 0x10000,	"initdb",	"Initialize database" },
	{ 'u',		"upgrade",	"Prefer to upgrade package" },
	{ 't',		"virtual",
	  "Instead of adding all the packages to 'world', create a new virtual "
	  "package with the listed dependencies and add that to 'world'. The "
	  "actions of the command are easily reverted by deleting the virtual "
	  "package.", required_argument, "NAME" },
187 188
};

189 190
static struct apk_applet apk_add = {
	.name = "add",
Timo Teräs's avatar
Timo Teräs committed
191 192 193
	.help = "Add (or update) PACKAGEs to main dependencies and install "
		"them, while ensuring that all dependencies are met.",
	.arguments = "PACKAGE...",
194 195 196 197
	.context_size = sizeof(struct add_ctx),
	.num_options = ARRAY_SIZE(add_options),
	.options = add_options,
	.parse = add_parse,
198 199 200 201 202
	.main = add_main,
};

APK_DEFINE_APPLET(apk_add);