add.c 5.44 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");
110
		virtdep = apk_dep_from_pkg(&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

Timo Teräs's avatar
Timo Teräs committed
122 123 124
			apk_sign_ctx_init(&sctx, APK_SIGN_VERIFY);
			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;
			}

130 131 132 133
			dep = apk_dep_from_pkg(&db, pkg);
		} else
			dep = apk_dep_from_str(&db, argv[i]);

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

142
	if (virtpkg) {
143
		apk_deps_add(&pkgs, &virtdep);
144 145
		apk_deps_add(&db.world, &virtdep);
	}
146

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

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

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

APK_DEFINE_APPLET(apk_add);