add.c 5.5 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 119
		struct apk_dependency dep;

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

122
			apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY, NULL);
Timo Teräs's avatar
Timo Teräs committed
123 124
			pkg = apk_pkg_read(&db, argv[i], &sctx);
			apk_sign_ctx_free(&sctx);
125 126 127 128 129
			if (pkg == NULL) {
				apk_error("Unable to read '%s'", argv[i]);
				goto err;
			}

Timo Teräs's avatar
Timo Teräs committed
130 131 132 133 134 135
			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;
		}
136

137 138 139 140 141
		if (virtpkg) {
			apk_deps_add(&virtpkg->depends, &dep);
		} else {
			dep.name->flags |= APK_NAME_TOPLEVEL;
		}
142
		apk_deps_add(&pkgs, &dep);
143
	}
144

145
	if (virtpkg) {
146
		apk_deps_add(&pkgs, &virtdep);
147 148
		apk_deps_add(&db.world, &virtdep);
	}
149

150
	state = apk_state_new(&db);
151
	for (i = 0; (pkgs != NULL) && i < pkgs->num; i++) {
152
		r = apk_state_lock_dependency(state, &pkgs->item[i]);
153
		if (r != 0) {
154
			apk_error("Unable to install '%s'", pkgs->item[i].name->name);
155 156
			if (!(apk_flags & APK_FORCE))
				goto err;
157
		}
158 159
		if (!virtpkg)
			apk_deps_add(&db.world, &pkgs->item[i]);
160
	}
161
	r = apk_state_commit(state, &db);
162
err:
163 164
	if (state != NULL)
		apk_state_unref(state);
165
	apk_db_close(&db);
166
	return r;
167 168
}

Timo Teräs's avatar
Timo Teräs committed
169 170 171 172 173 174 175 176
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" },
177 178
};

179 180
static struct apk_applet apk_add = {
	.name = "add",
Timo Teräs's avatar
Timo Teräs committed
181 182 183
	.help = "Add (or update) PACKAGEs to main dependencies and install "
		"them, while ensuring that all dependencies are met.",
	.arguments = "PACKAGE...",
184 185 186 187
	.context_size = sizeof(struct add_ctx),
	.num_options = ARRAY_SIZE(add_options),
	.options = add_options,
	.parse = add_parse,
188 189 190 191 192
	.main = add_main,
};

APK_DEFINE_APPLET(apk_add);