xref: /netbsd-src/external/bsd/pkg_install/dist/create/perform.c (revision f46918ca2125b9b1e7ca5a22c07d1414c618e467)
1 /*	$NetBSD: perform.c,v 1.4 2021/04/10 19:49:59 nia Exp $	*/
2 
3 #if HAVE_CONFIG_H
4 #include "config.h"
5 #endif
6 #include <nbcompat.h>
7 #if HAVE_SYS_CDEFS_H
8 #include <sys/cdefs.h>
9 #endif
10 __RCSID("$NetBSD: perform.c,v 1.4 2021/04/10 19:49:59 nia Exp $");
11 
12 /*
13  * FreeBSD install - a package for the installation and maintainance
14  * of non-core utilities.
15  *
16  * Redistribution and use in source and binary forms, with or without
17  * modification, are permitted provided that the following conditions
18  * are met:
19  * 1. Redistributions of source code must retain the above copyright
20  *    notice, this list of conditions and the following disclaimer.
21  * 2. Redistributions in binary form must reproduce the above copyright
22  *    notice, this list of conditions and the following disclaimer in the
23  *    documentation and/or other materials provided with the distribution.
24  *
25  * Jordan K. Hubbard
26  * 18 July 1993
27  *
28  * This is the main body of the create module.
29  *
30  */
31 
32 #include "lib.h"
33 #include "create.h"
34 
35 #if HAVE_ERR_H
36 #include <err.h>
37 #endif
38 #if HAVE_FCNTL_H
39 #include <fcntl.h>
40 #endif
41 #if HAVE_UNISTD_H
42 #include <unistd.h>
43 #endif
44 
45 static void
sanity_check(void)46 sanity_check(void)
47 {
48 	if (!Comment)
49 		errx(2, "required package comment string is missing (-c comment)");
50 	if (!Desc)
51 		errx(2, "required package description string is missing (-d desc)");
52 	if (!Contents)
53 		errx(2, "required package contents list is missing (-f [-]file)");
54 }
55 
56 static void
register_depends(package_t * plist,char * deps,int build_only)57 register_depends(package_t *plist, char *deps, int build_only)
58 {
59 	char *cp;
60 
61 	if (Verbose && !PlistOnly) {
62 		if (build_only)
63 			printf("Registering build depends:");
64 		else
65 			printf("Registering depends:");
66 	}
67 	while (deps) {
68 		cp = strsep(&deps, " \t\n");
69 		if (*cp) {
70 			char *best_installed;
71 			best_installed = find_best_matching_installed_pkg(cp, 1);
72 			if (best_installed != NULL) {
73 				add_plist(plist, PLIST_BLDDEP, best_installed);
74 				if (Verbose && !PlistOnly && build_only)
75 					printf(" %s", cp);
76 			} else
77 				warnx("No matching package installed for %s", cp);
78 			free(best_installed);
79 			if (!build_only) {
80 				add_plist(plist, PLIST_PKGDEP, cp);
81 				if (Verbose && !PlistOnly)
82 					printf(" %s", cp);
83 			}
84 		}
85 	}
86 	if (Verbose && !PlistOnly)
87 		printf(".\n");
88 }
89 
90 /*
91  *  Expect "fname" to point at a file, and read it into
92  *  the buffer returned.
93  */
94 static char   *
fileGetContents(char * fname)95 fileGetContents(char *fname)
96 {
97 	char   *contents;
98 	struct stat sb;
99 	int     fd;
100 
101 	if (stat(fname, &sb) == FAIL) {
102 		errx(2, "can't stat '%s'", fname);
103 	}
104 
105 	contents = xmalloc((size_t) (sb.st_size) + 1);
106 	fd = open(fname, O_RDONLY, 0);
107 	if (fd == FAIL) {
108 		errx(2, "unable to open '%s' for reading", fname);
109 	}
110 	if (read(fd, contents, (size_t) sb.st_size) != (ssize_t) sb.st_size) {
111 		errx(2, "short read on '%s' - did not get %lld bytes",
112 		    fname, (long long) sb.st_size);
113 	}
114 	close(fd);
115 	contents[(size_t) sb.st_size] = '\0';
116 	return contents;
117 }
118 
119 /*
120  * Get a string parameter as a file spec or as a "contents follow -" spec
121  */
122 static void
get_dash_string(char ** s)123 get_dash_string(char **s)
124 {
125 	if (**s == '-')
126 		*s = xstrdup(*s + 1);
127 	else
128 		*s = fileGetContents(*s);
129 }
130 
131 int
pkg_perform(const char * pkg)132 pkg_perform(const char *pkg)
133 {
134 	char   *cp;
135 	FILE   *pkg_in;
136 	package_t plist;
137 	const char *full_pkg, *suffix;
138 	char *allocated_pkg;
139 	int retval;
140 
141 	/* Break the package name into base and desired suffix (if any) */
142 	if ((cp = strrchr(pkg, '.')) != NULL) {
143 		allocated_pkg = xmalloc(cp - pkg + 1);
144 		memcpy(allocated_pkg, pkg, cp - pkg);
145 		allocated_pkg[cp - pkg] = '\0';
146 		suffix = cp + 1;
147 		full_pkg = pkg;
148 		pkg = allocated_pkg;
149 	} else {
150 		allocated_pkg = NULL;
151 		full_pkg = pkg;
152 		suffix = "tgz";
153 	}
154 
155 	/* Preliminary setup */
156 	sanity_check();
157 	if (Verbose && !PlistOnly)
158 		printf("Creating package %s\n", pkg);
159 	get_dash_string(&Comment);
160 	get_dash_string(&Desc);
161 	if (IS_STDIN(Contents))
162 		pkg_in = stdin;
163 	else {
164 		pkg_in = fopen(Contents, "r");
165 		if (!pkg_in)
166 			errx(2, "unable to open contents file '%s' for input", Contents);
167 	}
168 
169 	plist.head = plist.tail = NULL;
170 
171 	/* Stick the dependencies, if any, at the top */
172 	if (Pkgdeps)
173 		register_depends(&plist, Pkgdeps, 0);
174 
175 	/*
176 	 * Put the build dependencies after the dependencies.
177 	 * This works due to the evaluation order in pkg_add.
178 	 */
179 	if (BuildPkgdeps)
180 		register_depends(&plist, BuildPkgdeps, 1);
181 
182 	/* Put the conflicts directly after the dependencies, if any */
183 	if (Pkgcfl) {
184 		if (Verbose && !PlistOnly)
185 			printf("Registering conflicts:");
186 		while (Pkgcfl) {
187 			cp = strsep(&Pkgcfl, " \t\n");
188 			if (*cp) {
189 				add_plist(&plist, PLIST_PKGCFL, cp);
190 				if (Verbose && !PlistOnly)
191 					printf(" %s", cp);
192 			}
193 		}
194 		if (Verbose && !PlistOnly)
195 			printf(".\n");
196 	}
197 
198 	/* Slurp in the packing list */
199 	append_plist(&plist, pkg_in);
200 
201 	if (pkg_in != stdin)
202 		fclose(pkg_in);
203 
204 	/* Prefix should override the packing list */
205 	if (Prefix) {
206 		delete_plist(&plist, FALSE, PLIST_CWD, NULL);
207 		add_plist_top(&plist, PLIST_CWD, Prefix);
208 	}
209 	/*
210          * Run down the list and see if we've named it, if not stick in a name
211          * at the top.
212          */
213 	if (find_plist(&plist, PLIST_NAME) == NULL) {
214 		add_plist_top(&plist, PLIST_NAME, basename_of(pkg));
215 	}
216 
217 	/* Make first "real contents" pass over it */
218 	check_list(&plist, basename_of(pkg));
219 
220 	/*
221          * We're just here for to dump out a revised plist for the FreeBSD ports
222          * hack.  It's not a real create in progress.
223          */
224 	if (PlistOnly) {
225 		write_plist(&plist, stdout, realprefix);
226 		retval = TRUE;
227 	} else {
228 		retval = pkg_build(pkg, full_pkg, suffix, &plist);
229 	}
230 
231 	/* Cleanup */
232 	free(Comment);
233 	free(Desc);
234 	free_plist(&plist);
235 
236 	free(allocated_pkg);
237 
238 	return retval;
239 }
240