2 * FreeBSD install - a package for the installation and maintainance
3 * of non-core utilities.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
17 * This is the main body of the create module.
21 #include <sys/cdefs.h>
22 __FBSDID("$FreeBSD: src/usr.sbin/pkg_install/create/perform.c,v 1.49.2.18 2002/08/31 19:25:54 obrien Exp $");
31 #include <sys/syslimits.h>
35 static void sanity_check(void);
36 static void make_dist(const char *, const char *, const char *, Package *);
37 static int create_from_installed(const char *, const char *);
42 pkg_perform(char **pkgs)
44 char *pkg = *pkgs; /* Only one arg to create */
51 /* Preliminary setup */
52 if (InstalledPkg == NULL)
54 if (Verbose && !PlistOnly)
55 printf("Creating package %s\n", pkg);
57 /* chop suffix off if already specified, remembering if we want to compress */
60 if (!strcmp(&pkg[len - 4], ".tbz")) {
64 else if (!strcmp(&pkg[len - 4], ".tgz")) {
68 else if (!strcmp(&pkg[len - 4], ".tar")) {
73 if (Zipper == BZIP2) {
75 setenv("BZIP2", "--best", 0);
76 } else if (Zipper == GZIP) {
78 setenv("GZIP", "-9", 0);
82 if (InstalledPkg != NULL)
83 return (create_from_installed(pkg, suf));
85 get_dash_string(&Comment);
86 get_dash_string(&Desc);
87 if (!strcmp(Contents, "-"))
90 pkg_in = fopen(Contents, "r");
93 errx(2, "%s: unable to open contents file '%s' for input",
97 plist.head = plist.tail = NULL;
99 /* Stick the dependencies, if any, at the top */
101 char **deps, *deporigin;
105 if (Verbose && !PlistOnly)
106 printf("Registering depends:");
108 /* Count number of dependencies */
109 for (cp = Pkgdeps; cp != NULL && *cp != '\0';
110 cp = strpbrk(++cp, " \t\n")) {
115 /* Create easy to use NULL-terminated list */
116 deps = alloca(sizeof(*deps) * ndeps + 1);
118 errx(2, "%s: alloca() failed", __func__);
121 for (i = 0; Pkgdeps;) {
122 cp = strsep(&Pkgdeps, " \t\n");
132 for (i = 0; i < ndeps; i++) {
133 deporigin = strchr(deps[i], ':');
134 if (deporigin != NULL) {
136 add_plist_top(&plist, PLIST_DEPORIGIN, ++deporigin);
138 add_plist_top(&plist, PLIST_PKGDEP, deps[i]);
139 if (Verbose && !PlistOnly)
140 printf(" %s", deps[i]);
144 if (Verbose && !PlistOnly)
148 /* If a SrcDir override is set, add it now */
150 if (Verbose && !PlistOnly)
151 printf("Using SrcDir value of %s\n", SrcDir);
152 add_plist(&plist, PLIST_SRC, SrcDir);
155 /* Slurp in the packing list */
156 read_plist(&plist, pkg_in);
158 /* Prefix should add an @cwd to the packing list */
160 add_plist_top(&plist, PLIST_CWD, Prefix);
162 /* Add the origin if asked, at the top */
164 add_plist_top(&plist, PLIST_ORIGIN, Origin);
167 * Run down the list and see if we've named it, if not stick in a name
170 if (find_plist(&plist, PLIST_NAME) == NULL)
171 add_plist_top(&plist, PLIST_NAME, basename(pkg));
173 if (asprintf(&cp, "PKG_FORMAT_REVISION:%d.%d", PLIST_FMT_VER_MAJOR,
174 PLIST_FMT_VER_MINOR) == -1) {
175 errx(2, "%s: asprintf() failed", __func__);
177 add_plist_top(&plist, PLIST_COMMENT, cp);
181 * We're just here for to dump out a revised plist for the FreeBSD ports
182 * hack. It's not a real create in progress.
185 check_list(home, &plist);
186 write_plist(&plist, stdout);
190 /* Make a directory to stomp around in */
191 home = make_playpen(PlayPen, 0);
192 signal(SIGINT, cleanup);
193 signal(SIGHUP, cleanup);
195 /* Make first "real contents" pass over it */
196 check_list(home, &plist);
197 (void) umask(022); /*
198 * Make sure gen'ed directories, files don't have
199 * group or other write bits.
201 /* copy_plist(home, &plist); */
202 /* mark_plist(&plist); */
204 /* Now put the release specific items in */
205 add_plist(&plist, PLIST_CWD, ".");
206 write_file(COMMENT_FNAME, Comment);
207 add_plist(&plist, PLIST_IGNORE, NULL);
208 add_plist(&plist, PLIST_FILE, COMMENT_FNAME);
209 write_file(DESC_FNAME, Desc);
210 add_plist(&plist, PLIST_IGNORE, NULL);
211 add_plist(&plist, PLIST_FILE, DESC_FNAME);
214 copy_file(home, Install, INSTALL_FNAME);
215 add_plist(&plist, PLIST_IGNORE, NULL);
216 add_plist(&plist, PLIST_FILE, INSTALL_FNAME);
219 copy_file(home, PostInstall, POST_INSTALL_FNAME);
220 add_plist(&plist, PLIST_IGNORE, NULL);
221 add_plist(&plist, PLIST_FILE, POST_INSTALL_FNAME);
224 copy_file(home, DeInstall, DEINSTALL_FNAME);
225 add_plist(&plist, PLIST_IGNORE, NULL);
226 add_plist(&plist, PLIST_FILE, DEINSTALL_FNAME);
229 copy_file(home, PostDeInstall, POST_DEINSTALL_FNAME);
230 add_plist(&plist, PLIST_IGNORE, NULL);
231 add_plist(&plist, PLIST_FILE, POST_DEINSTALL_FNAME);
234 copy_file(home, Require, REQUIRE_FNAME);
235 add_plist(&plist, PLIST_IGNORE, NULL);
236 add_plist(&plist, PLIST_FILE, REQUIRE_FNAME);
239 copy_file(home, Display, DISPLAY_FNAME);
240 add_plist(&plist, PLIST_IGNORE, NULL);
241 add_plist(&plist, PLIST_FILE, DISPLAY_FNAME);
242 add_plist(&plist, PLIST_DISPLAY, DISPLAY_FNAME);
245 copy_file(home, Mtree, MTREE_FNAME);
246 add_plist(&plist, PLIST_IGNORE, NULL);
247 add_plist(&plist, PLIST_FILE, MTREE_FNAME);
248 add_plist(&plist, PLIST_MTREE, MTREE_FNAME);
251 /* Finally, write out the packing list */
252 fp = fopen(CONTENTS_FNAME, "w");
255 errx(2, "%s: can't open file %s for writing",
256 __func__, CONTENTS_FNAME);
258 write_plist(&plist, fp);
261 errx(2, "%s: error while closing %s",
262 __func__, CONTENTS_FNAME);
265 /* And stick it into a tar ball */
266 make_dist(home, pkg, suf, &plist);
273 return TRUE; /* Success */
277 make_dist(const char *homedir, const char *pkg, const char *suff, Package *plist)
279 char tball[FILENAME_MAX];
282 const char *args[50]; /* Much more than enough. */
289 args[nargs++] = "tar"; /* argv[0] */
292 snprintf(tball, FILENAME_MAX, "%s.%s", pkg, suff);
294 snprintf(tball, FILENAME_MAX, "%s/%s.%s", homedir, pkg, suff);
296 args[nargs++] = "-c";
297 args[nargs++] = "-f";
298 args[nargs++] = tball;
299 if (strchr(suff, 'z')) { /* Compress/gzip/bzip2? */
300 if (Zipper == BZIP2) {
301 args[nargs++] = "-j";
305 args[nargs++] = "-z";
312 args[nargs++] = "-h";
314 args[nargs++] = "-X";
315 args[nargs++] = ExcludeFrom;
317 args[nargs++] = "-T"; /* Take filenames from file instead of args. */
318 args[nargs++] = "-"; /* Use stdin for the file. */
322 printf("Creating %star ball in '%s'\n", cname, tball);
324 /* Set up a pipe for passing the filenames, and fork off a tar process. */
325 if (pipe(pipefds) == -1) {
327 errx(2, "%s: cannot create pipe", __func__);
329 if ((pid = fork()) == -1) {
331 errx(2, "%s: cannot fork process for tar", __func__);
333 if (pid == 0) { /* The child */
337 execv("/usr/bin/tar", (char * const *)(uintptr_t)args);
339 errx(2, "%s: failed to execute tar command", __func__);
342 /* Meanwhile, back in the parent process ... */
344 if ((totar = fdopen(pipefds[1], "w")) == NULL) {
346 errx(2, "%s: fdopen failed", __func__);
349 fprintf(totar, "%s\n", CONTENTS_FNAME);
350 fprintf(totar, "%s\n", COMMENT_FNAME);
351 fprintf(totar, "%s\n", DESC_FNAME);
354 fprintf(totar, "%s\n", INSTALL_FNAME);
356 fprintf(totar, "%s\n", POST_INSTALL_FNAME);
358 fprintf(totar, "%s\n", DEINSTALL_FNAME);
360 fprintf(totar, "%s\n", POST_DEINSTALL_FNAME);
362 fprintf(totar, "%s\n", REQUIRE_FNAME);
364 fprintf(totar, "%s\n", DISPLAY_FNAME);
366 fprintf(totar, "%s\n", MTREE_FNAME);
368 for (p = plist->head; p; p = p->next) {
369 if (p->type == PLIST_FILE)
370 fprintf(totar, "%s\n", p->name);
371 else if (p->type == PLIST_CWD || p->type == PLIST_SRC)
372 fprintf(totar, "-C\n%s\n", p->name);
373 else if (p->type == PLIST_IGNORE)
379 /* assume either signal or bad exit is enough for us */
382 errx(2, "%s: tar command failed with code %d", __func__, ret);
391 errx(2, "%s: required package comment string is missing (-c comment)",
396 errx(2, "%s: required package description string is missing (-d desc)",
401 errx(2, "%s: required package contents list is missing (-f [-]file)",
407 /* Clean up those things that would otherwise hang around */
422 create_from_installed(const char *pkg, const char *suf)
426 char homedir[MAXPATHLEN], log_dir[FILENAME_MAX];
428 snprintf(log_dir, sizeof(log_dir), "%s/%s", LOG_DIR, InstalledPkg);
429 if (!fexists(log_dir)) {
430 warnx("can't find package '%s' installed!", InstalledPkg);
433 getcwd(homedir, sizeof(homedir));
434 if (chdir(log_dir) == FAIL) {
435 warnx("can't change directory to '%s'!", log_dir);
438 /* Suck in the contents list */
439 plist.head = plist.tail = NULL;
440 fp = fopen(CONTENTS_FNAME, "r");
442 warnx("unable to open %s file", CONTENTS_FNAME);
445 read_plist(&plist, fp);
448 (const char *)Install = isfile(INSTALL_FNAME) ? INSTALL_FNAME : NULL;
449 (const char *)PostInstall = isfile(POST_INSTALL_FNAME) ? POST_INSTALL_FNAME : NULL;
450 (const char *)DeInstall = isfile(DEINSTALL_FNAME) ? DEINSTALL_FNAME : NULL;
451 (const char *)PostDeInstall = isfile(POST_DEINSTALL_FNAME) ? POST_DEINSTALL_FNAME : NULL;
452 (const char *)Require = isfile(REQUIRE_FNAME) ? REQUIRE_FNAME : NULL;
453 (const char *)Display = isfile(DISPLAY_FNAME) ? DISPLAY_FNAME : NULL;
454 (const char *)Mtree = isfile(MTREE_FNAME) ? MTREE_FNAME : NULL;
456 make_dist(homedir, pkg, suf, &plist);