modules: pull in most of FreeBSD's module linker changes
[dragonfly.git] / usr.sbin / installer / libinstaller / package.c
blob6a1a76948509e1b466a4ba063a14b673496a0220
1 /*
2 * Copyright (c)2004 The DragonFly Project. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
8 * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in
13 * the documentation and/or other materials provided with the
14 * distribution.
16 * Neither the name of the DragonFly Project nor the names of its
17 * contributors may be used to endorse or promote products derived
18 * from this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
31 * OF THE POSSIBILITY OF SUCH DAMAGE.
35 * package.c
36 * Manage installation etc of packages.
37 * $Id: package.c,v 1.24 2005/02/06 21:05:18 cpressey Exp $
40 #include <ctype.h>
41 #include <stdarg.h>
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
46 #include "libaura/dict.h"
47 #include "libaura/fspred.h"
48 #include "libaura/popen.h"
50 #include "libdfui/dfui.h"
52 #include "commands.h"
53 #include "diskutil.h"
54 #include "functions.h"
55 #include "uiutil.h"
56 #include "package.h"
59 * Determine whether a package is installed on a DragonFly HDD.
61 int
62 pkg_exists(struct i_fn_args *a, const char *pkg)
64 return(is_dir("%smnt/var/db/pkg/%s", a->os_root, pkg));
67 int
68 pkg_clean(struct i_fn_args *a, struct commands *cmds)
70 command_add(cmds, "%s%s %smnt/ /%s '*'",
71 a->os_root, cmd_name(a, "CHROOT"),
72 a->os_root, cmd_name(a, "PKG_DELETE"));
73 return(1);
77 * Copy a package from an installation CD onto a DragonFly HDD.
79 int
80 pkg_copy(struct i_fn_args *a, struct commands *cmds, const char *pkg_name,
81 struct aura_dict *seen)
83 FILE *pipe;
84 char *rpkg_name;
85 char line[256];
86 char pkg_suffix[256];
89 * Get all the packages that this package depends on, and
90 * recursively pkg_copy them first, if they're not already there.
92 * XXX We should be sending this command through a command chain
93 * right now so that we can get an accurate idea of what is being
94 * run and so that it will be logged. But unfortunately that's
95 * not feasible, since this function is building another command
96 * chain for later use. So we use a pipe.
98 if ((pipe = aura_popen("%s%s -r %s", "r",
99 a->os_root, cmd_name(a, "PKG_INFO"), pkg_name)) == NULL)
100 return(0);
102 while (fgets(line, 255, pipe) != NULL) {
104 * Only look at lines that begin with 'Dependency:'.
106 if (strncmp(line, "Dependency:", 11) != 0)
107 continue;
108 rpkg_name = &line[12];
111 * Strip any trailing whitespace.
113 while (strlen(rpkg_name) > 0 &&
114 isspace(rpkg_name[strlen(rpkg_name) - 1])) {
115 rpkg_name[strlen(rpkg_name) - 1] = '\0';
118 if (!pkg_exists(a, rpkg_name)) {
119 if (!pkg_copy(a, cmds, rpkg_name, seen)) {
120 aura_pclose(pipe);
121 return(0);
125 aura_pclose(pipe);
126 snprintf(pkg_suffix, 256, "tgz");
127 if (!pkg_exists(a, pkg_name) &&
128 !aura_dict_exists(seen, pkg_name, strlen(pkg_name))) {
129 aura_dict_store(seen,
130 pkg_name, strlen(pkg_name), "", 0);
131 command_add(cmds, "%s%s -b %s %smnt/tmp/%s.%s",
132 a->os_root, cmd_name(a, "PKG_CREATE"),
133 pkg_name, a->os_root, pkg_name, pkg_suffix);
134 command_add(cmds, "%s%s %smnt/ /%s /tmp/%s.%s",
135 a->os_root, cmd_name(a, "CHROOT"),
136 a->os_root, cmd_name(a, "PKG_ADD"),
137 pkg_name, pkg_suffix);
138 command_add(cmds, "%s%s %smnt/tmp/%s.%s",
139 a->os_root, cmd_name(a, "RM"),
140 a->os_root, pkg_name, pkg_suffix);
143 return(1);
147 * Remove a package from a DragonFly HDD.
150 pkg_remove(struct i_fn_args *a, struct commands *cmds, const char *pkg_name,
151 struct aura_dict *seen)
153 FILE *pipe;
154 char *command, *rpkg_name;
155 char line[256];
156 int seen_required_by = 0;
159 * Get all the packages that this package depends on, and
160 * recursively pkg_copy them first, if they're not already there.
162 asprintf(&command,
163 "%s%s %smnt/ /%s -R %s",
164 a->os_root, cmd_name(a, "CHROOT"),
165 a->os_root, cmd_name(a, "PKG_INFO"),
166 pkg_name);
167 pipe = popen(command, "r");
168 free(command);
169 if (pipe == NULL)
170 return(0);
172 while (fgets(line, 255, pipe) != NULL) {
174 * Only look at lines that follow the "Required by:" line.
176 if (seen_required_by) {
177 rpkg_name = line;
179 * Strip any trailing whitespace.
181 while (strlen(rpkg_name) > 0 &&
182 isspace(rpkg_name[strlen(rpkg_name) - 1])) {
183 rpkg_name[strlen(rpkg_name) - 1] = '\0';
186 if (strlen(rpkg_name) > 0 && pkg_exists(a, rpkg_name)) {
187 if (!pkg_remove(a, cmds, rpkg_name, seen)) {
188 pclose(pipe);
189 return(0);
192 } else {
193 if (strncmp(line, "Required by:", 12) != 0) {
194 seen_required_by = 1;
198 pclose(pipe);
200 if (pkg_exists(a, pkg_name) &&
201 !aura_dict_exists(seen, pkg_name, strlen(pkg_name))) {
202 aura_dict_store(seen,
203 pkg_name, strlen(pkg_name), "", 0);
204 command_add(cmds, "%s%s %smnt/ /%s %s",
205 a->os_root, cmd_name(a, "CHROOT"),
206 a->os_root, cmd_name(a, "PKG_DELETE"),
207 pkg_name);
210 return(1);