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.
19 * $FreeBSD: src/usr.sbin/pkg_install/create/perform.c,v 1.49.2.18 2002/08/31 19:25:54 obrien Exp $
20 * $DragonFly: src/usr.sbin/pkg_install/create/Attic/perform.c,v 1.2 2003/06/17 04:29:59 dillon Exp $
30 #include <sys/syslimits.h>
34 static void sanity_check(void);
35 static void make_dist(const char *, const char *, const char *, Package *);
36 static int create_from_installed(const char *, const char *);
41 pkg_perform(char **pkgs)
43 char *pkg = *pkgs; /* Only one arg to create */
50 /* Preliminary setup */
51 if (InstalledPkg == NULL)
53 if (Verbose && !PlistOnly)
54 printf("Creating package %s\n", pkg);
56 /* chop suffix off if already specified, remembering if we want to compress */
59 if (!strcmp(&pkg[len - 4], ".tbz")) {
63 else if (!strcmp(&pkg[len - 4], ".tgz")) {
67 else if (!strcmp(&pkg[len - 4], ".tar")) {
72 if (Zipper == BZIP2) {
74 setenv("BZIP2", "--best", 0);
75 } else if (Zipper == GZIP) {
77 setenv("GZIP", "-9", 0);
81 if (InstalledPkg != NULL)
82 return (create_from_installed(pkg, suf));
84 get_dash_string(&Comment);
85 get_dash_string(&Desc);
86 if (!strcmp(Contents, "-"))
89 pkg_in = fopen(Contents, "r");
92 errx(2, "%s: unable to open contents file '%s' for input",
96 plist.head = plist.tail = NULL;
98 /* Stick the dependencies, if any, at the top */
100 char **deps, *deporigin;
104 if (Verbose && !PlistOnly)
105 printf("Registering depends:");
107 /* Count number of dependencies */
108 for (cp = Pkgdeps; cp != NULL && *cp != '\0';
109 cp = strpbrk(++cp, " \t\n")) {
114 /* Create easy to use NULL-terminated list */
115 deps = alloca(sizeof(*deps) * ndeps + 1);
117 errx(2, "%s: alloca() failed", __func__);
120 for (i = 0; Pkgdeps;) {
121 cp = strsep(&Pkgdeps, " \t\n");
131 for (i = 0; i < ndeps; i++) {
132 deporigin = strchr(deps[i], ':');
133 if (deporigin != NULL) {
135 add_plist_top(&plist, PLIST_DEPORIGIN, ++deporigin);
137 add_plist_top(&plist, PLIST_PKGDEP, deps[i]);
138 if (Verbose && !PlistOnly)
139 printf(" %s", deps[i]);
143 if (Verbose && !PlistOnly)
147 /* If a SrcDir override is set, add it now */
149 if (Verbose && !PlistOnly)
150 printf("Using SrcDir value of %s\n", SrcDir);
151 add_plist(&plist, PLIST_SRC, SrcDir);
154 /* Slurp in the packing list */
155 read_plist(&plist, pkg_in);
157 /* Prefix should add an @cwd to the packing list */
159 add_plist_top(&plist, PLIST_CWD, Prefix);
161 /* Add the origin if asked, at the top */
163 add_plist_top(&plist, PLIST_ORIGIN, Origin);
166 * Run down the list and see if we've named it, if not stick in a name
169 if (find_plist(&plist, PLIST_NAME) == NULL)
170 add_plist_top(&plist, PLIST_NAME, basename(pkg));
172 if (asprintf(&cp, "PKG_FORMAT_REVISION:%d.%d", PLIST_FMT_VER_MAJOR,
173 PLIST_FMT_VER_MINOR) == -1) {
174 errx(2, "%s: asprintf() failed", __func__);
176 add_plist_top(&plist, PLIST_COMMENT, cp);
180 * We're just here for to dump out a revised plist for the FreeBSD ports
181 * hack. It's not a real create in progress.
184 check_list(home, &plist);
185 write_plist(&plist, stdout);
189 /* Make a directory to stomp around in */
190 home = make_playpen(PlayPen, 0);
191 signal(SIGINT, cleanup);
192 signal(SIGHUP, cleanup);
194 /* Make first "real contents" pass over it */
195 check_list(home, &plist);
196 (void) umask(022); /*
197 * Make sure gen'ed directories, files don't have
198 * group or other write bits.
200 /* copy_plist(home, &plist); */
201 /* mark_plist(&plist); */
203 /* Now put the release specific items in */
204 add_plist(&plist, PLIST_CWD, ".");
205 write_file(COMMENT_FNAME, Comment);
206 add_plist(&plist, PLIST_IGNORE, NULL);
207 add_plist(&plist, PLIST_FILE, COMMENT_FNAME);
208 write_file(DESC_FNAME, Desc);
209 add_plist(&plist, PLIST_IGNORE, NULL);
210 add_plist(&plist, PLIST_FILE, DESC_FNAME);
213 copy_file(home, Install, INSTALL_FNAME);
214 add_plist(&plist, PLIST_IGNORE, NULL);
215 add_plist(&plist, PLIST_FILE, INSTALL_FNAME);
218 copy_file(home, PostInstall, POST_INSTALL_FNAME);
219 add_plist(&plist, PLIST_IGNORE, NULL);
220 add_plist(&plist, PLIST_FILE, POST_INSTALL_FNAME);
223 copy_file(home, DeInstall, DEINSTALL_FNAME);
224 add_plist(&plist, PLIST_IGNORE, NULL);
225 add_plist(&plist, PLIST_FILE, DEINSTALL_FNAME);
228 copy_file(home, PostDeInstall, POST_DEINSTALL_FNAME);
229 add_plist(&plist, PLIST_IGNORE, NULL);
230 add_plist(&plist, PLIST_FILE, POST_DEINSTALL_FNAME);
233 copy_file(home, Require, REQUIRE_FNAME);
234 add_plist(&plist, PLIST_IGNORE, NULL);
235 add_plist(&plist, PLIST_FILE, REQUIRE_FNAME);
238 copy_file(home, Display, DISPLAY_FNAME);
239 add_plist(&plist, PLIST_IGNORE, NULL);
240 add_plist(&plist, PLIST_FILE, DISPLAY_FNAME);
241 add_plist(&plist, PLIST_DISPLAY, DISPLAY_FNAME);
244 copy_file(home, Mtree, MTREE_FNAME);
245 add_plist(&plist, PLIST_IGNORE, NULL);
246 add_plist(&plist, PLIST_FILE, MTREE_FNAME);
247 add_plist(&plist, PLIST_MTREE, MTREE_FNAME);
250 /* Finally, write out the packing list */
251 fp = fopen(CONTENTS_FNAME, "w");
254 errx(2, "%s: can't open file %s for writing",
255 __func__, CONTENTS_FNAME);
257 write_plist(&plist, fp);
260 errx(2, "%s: error while closing %s",
261 __func__, CONTENTS_FNAME);
264 /* And stick it into a tar ball */
265 make_dist(home, pkg, suf, &plist);
272 return TRUE; /* Success */
276 make_dist(const char *homedir, const char *pkg, const char *suff, Package *plist)
278 char tball[FILENAME_MAX];
281 const char *args[50]; /* Much more than enough. */
288 args[nargs++] = "tar"; /* argv[0] */
291 snprintf(tball, FILENAME_MAX, "%s.%s", pkg, suff);
293 snprintf(tball, FILENAME_MAX, "%s/%s.%s", homedir, pkg, suff);
295 args[nargs++] = "-c";
296 args[nargs++] = "-f";
297 args[nargs++] = tball;
298 if (strchr(suff, 'z')) { /* Compress/gzip/bzip2? */
299 if (Zipper == BZIP2) {
300 args[nargs++] = "-j";
304 args[nargs++] = "-z";
311 args[nargs++] = "-h";
313 args[nargs++] = "-X";
314 args[nargs++] = ExcludeFrom;
316 args[nargs++] = "-T"; /* Take filenames from file instead of args. */
317 args[nargs++] = "-"; /* Use stdin for the file. */
321 printf("Creating %star ball in '%s'\n", cname, tball);
323 /* Set up a pipe for passing the filenames, and fork off a tar process. */
324 if (pipe(pipefds) == -1) {
326 errx(2, "%s: cannot create pipe", __func__);
328 if ((pid = fork()) == -1) {
330 errx(2, "%s: cannot fork process for tar", __func__);
332 if (pid == 0) { /* The child */
336 execv("/usr/bin/tar", (char * const *)(uintptr_t)args);
338 errx(2, "%s: failed to execute tar command", __func__);
341 /* Meanwhile, back in the parent process ... */
343 if ((totar = fdopen(pipefds[1], "w")) == NULL) {
345 errx(2, "%s: fdopen failed", __func__);
348 fprintf(totar, "%s\n", CONTENTS_FNAME);
349 fprintf(totar, "%s\n", COMMENT_FNAME);
350 fprintf(totar, "%s\n", DESC_FNAME);
353 fprintf(totar, "%s\n", INSTALL_FNAME);
355 fprintf(totar, "%s\n", POST_INSTALL_FNAME);
357 fprintf(totar, "%s\n", DEINSTALL_FNAME);
359 fprintf(totar, "%s\n", POST_DEINSTALL_FNAME);
361 fprintf(totar, "%s\n", REQUIRE_FNAME);
363 fprintf(totar, "%s\n", DISPLAY_FNAME);
365 fprintf(totar, "%s\n", MTREE_FNAME);
367 for (p = plist->head; p; p = p->next) {
368 if (p->type == PLIST_FILE)
369 fprintf(totar, "%s\n", p->name);
370 else if (p->type == PLIST_CWD || p->type == PLIST_SRC)
371 fprintf(totar, "-C\n%s\n", p->name);
372 else if (p->type == PLIST_IGNORE)
378 /* assume either signal or bad exit is enough for us */
381 errx(2, "%s: tar command failed with code %d", __func__, ret);
390 errx(2, "%s: required package comment string is missing (-c comment)",
395 errx(2, "%s: required package description string is missing (-d desc)",
400 errx(2, "%s: required package contents list is missing (-f [-]file)",
406 /* Clean up those things that would otherwise hang around */
421 create_from_installed(const char *pkg, const char *suf)
425 char homedir[MAXPATHLEN], log_dir[FILENAME_MAX];
427 snprintf(log_dir, sizeof(log_dir), "%s/%s", LOG_DIR, InstalledPkg);
428 if (!fexists(log_dir)) {
429 warnx("can't find package '%s' installed!", InstalledPkg);
432 getcwd(homedir, sizeof(homedir));
433 if (chdir(log_dir) == FAIL) {
434 warnx("can't change directory to '%s'!", log_dir);
437 /* Suck in the contents list */
438 plist.head = plist.tail = NULL;
439 fp = fopen(CONTENTS_FNAME, "r");
441 warnx("unable to open %s file", CONTENTS_FNAME);
444 read_plist(&plist, fp);
447 (const char *)Install = isfile(INSTALL_FNAME) ? INSTALL_FNAME : NULL;
448 (const char *)PostInstall = isfile(POST_INSTALL_FNAME) ? POST_INSTALL_FNAME : NULL;
449 (const char *)DeInstall = isfile(DEINSTALL_FNAME) ? DEINSTALL_FNAME : NULL;
450 (const char *)PostDeInstall = isfile(POST_DEINSTALL_FNAME) ? POST_DEINSTALL_FNAME : NULL;
451 (const char *)Require = isfile(REQUIRE_FNAME) ? REQUIRE_FNAME : NULL;
452 (const char *)Display = isfile(DISPLAY_FNAME) ? DISPLAY_FNAME : NULL;
453 (const char *)Mtree = isfile(MTREE_FNAME) ? MTREE_FNAME : NULL;
455 make_dist(homedir, pkg, suf, &plist);