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
45static void
46sanity_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
56static void
57register_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 */
94static char   *
95fileGetContents(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 */
122static void
123get_dash_string(char **s)
124{
125	if (**s == '-')
126		*s = xstrdup(*s + 1);
127	else
128		*s = fileGetContents(*s);
129}
130
131int
132pkg_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