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.79 2004/07/28 07:19:15 kan Exp $
20 * $DragonFly: src/usr.sbin/pkg_install/create/Attic/perform.c,v 1.4 2004/12/18 22:48:04 swildner 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 /* Put the conflicts directly after the dependencies, if any */
149 if (Verbose && !PlistOnly)
150 printf("Registering conflicts:");
152 cp = strsep(&Conflicts, " \t\n");
154 add_plist(&plist, PLIST_CONFLICTS, cp);
155 if (Verbose && !PlistOnly)
159 if (Verbose && !PlistOnly)
163 /* If a SrcDir override is set, add it now */
165 if (Verbose && !PlistOnly)
166 printf("Using SrcDir value of %s\n", SrcDir);
167 add_plist(&plist, PLIST_SRC, SrcDir);
170 /* Slurp in the packing list */
171 read_plist(&plist, pkg_in);
173 /* Prefix should add an @cwd to the packing list */
175 add_plist_top(&plist, PLIST_CWD, Prefix);
177 /* Add the origin if asked, at the top */
179 add_plist_top(&plist, PLIST_ORIGIN, Origin);
182 * Run down the list and see if we've named it, if not stick in a name
185 if (find_plist(&plist, PLIST_NAME) == NULL)
186 add_plist_top(&plist, PLIST_NAME, basename(pkg));
188 if (asprintf(&cp, "PKG_FORMAT_REVISION:%d.%d", PLIST_FMT_VER_MAJOR,
189 PLIST_FMT_VER_MINOR) == -1) {
190 errx(2, "%s: asprintf() failed", __func__);
192 add_plist_top(&plist, PLIST_COMMENT, cp);
196 * We're just here for to dump out a revised plist for the FreeBSD ports
197 * hack. It's not a real create in progress.
200 check_list(home, &plist);
201 write_plist(&plist, stdout);
205 /* Make a directory to stomp around in */
206 home = make_playpen(PlayPen, 0);
207 signal(SIGINT, cleanup);
208 signal(SIGHUP, cleanup);
210 /* Make first "real contents" pass over it */
211 check_list(home, &plist);
213 * Make sure gen'ed directories, files don't have
214 * group or other write bits.
216 /* copy_plist(home, &plist); */
217 /* mark_plist(&plist); */
219 /* Now put the release specific items in */
220 add_plist(&plist, PLIST_CWD, ".");
221 write_file(COMMENT_FNAME, Comment);
222 add_plist(&plist, PLIST_IGNORE, NULL);
223 add_plist(&plist, PLIST_FILE, COMMENT_FNAME);
224 add_cksum(&plist, plist.tail, COMMENT_FNAME);
225 write_file(DESC_FNAME, Desc);
226 add_plist(&plist, PLIST_IGNORE, NULL);
227 add_plist(&plist, PLIST_FILE, DESC_FNAME);
228 add_cksum(&plist, plist.tail, DESC_FNAME);
231 copy_file(home, Install, INSTALL_FNAME);
232 add_plist(&plist, PLIST_IGNORE, NULL);
233 add_plist(&plist, PLIST_FILE, INSTALL_FNAME);
234 add_cksum(&plist, plist.tail, INSTALL_FNAME);
237 copy_file(home, PostInstall, POST_INSTALL_FNAME);
238 add_plist(&plist, PLIST_IGNORE, NULL);
239 add_plist(&plist, PLIST_FILE, POST_INSTALL_FNAME);
240 add_cksum(&plist, plist.tail, POST_INSTALL_FNAME);
243 copy_file(home, DeInstall, DEINSTALL_FNAME);
244 add_plist(&plist, PLIST_IGNORE, NULL);
245 add_plist(&plist, PLIST_FILE, DEINSTALL_FNAME);
246 add_cksum(&plist, plist.tail, DEINSTALL_FNAME);
249 copy_file(home, PostDeInstall, POST_DEINSTALL_FNAME);
250 add_plist(&plist, PLIST_IGNORE, NULL);
251 add_plist(&plist, PLIST_FILE, POST_DEINSTALL_FNAME);
252 add_cksum(&plist, plist.tail, POST_DEINSTALL_FNAME);
255 copy_file(home, Require, REQUIRE_FNAME);
256 add_plist(&plist, PLIST_IGNORE, NULL);
257 add_plist(&plist, PLIST_FILE, REQUIRE_FNAME);
258 add_cksum(&plist, plist.tail, REQUIRE_FNAME);
261 copy_file(home, Display, DISPLAY_FNAME);
262 add_plist(&plist, PLIST_IGNORE, NULL);
263 add_plist(&plist, PLIST_FILE, DISPLAY_FNAME);
264 add_cksum(&plist, plist.tail, DISPLAY_FNAME);
265 add_plist(&plist, PLIST_DISPLAY, DISPLAY_FNAME);
268 copy_file(home, Mtree, MTREE_FNAME);
269 add_plist(&plist, PLIST_IGNORE, NULL);
270 add_plist(&plist, PLIST_FILE, MTREE_FNAME);
271 add_cksum(&plist, plist.tail, MTREE_FNAME);
272 add_plist(&plist, PLIST_MTREE, MTREE_FNAME);
275 /* Finally, write out the packing list */
276 fp = fopen(CONTENTS_FNAME, "w");
279 errx(2, "%s: can't open file %s for writing",
280 __func__, CONTENTS_FNAME);
282 write_plist(&plist, fp);
285 errx(2, "%s: error while closing %s",
286 __func__, CONTENTS_FNAME);
289 /* And stick it into a tar ball */
290 make_dist(home, pkg, suf, &plist);
297 return TRUE; /* Success */
301 make_dist(const char *homedir, const char *pkg, const char *suff, Package *plist)
303 char tball[FILENAME_MAX];
306 const char *args[50]; /* Much more than enough. */
313 args[nargs++] = "tar"; /* argv[0] */
316 snprintf(tball, FILENAME_MAX, "%s.%s", pkg, suff);
318 snprintf(tball, FILENAME_MAX, "%s/%s.%s", homedir, pkg, suff);
320 args[nargs++] = "-c";
321 args[nargs++] = "-f";
322 args[nargs++] = tball;
323 if (strchr(suff, 'z')) { /* Compress/gzip/bzip2? */
324 if (Zipper == BZIP2) {
325 args[nargs++] = "-j";
329 args[nargs++] = "-z";
336 args[nargs++] = "-h";
338 args[nargs++] = "-X";
339 args[nargs++] = ExcludeFrom;
341 args[nargs++] = "-T"; /* Take filenames from file instead of args. */
342 args[nargs++] = "-"; /* Use stdin for the file. */
346 printf("Creating %star ball in '%s'\n", cname, tball);
348 /* Set up a pipe for passing the filenames, and fork off a tar process. */
349 if (pipe(pipefds) == -1) {
351 errx(2, "%s: cannot create pipe", __func__);
353 if ((pid = fork()) == -1) {
355 errx(2, "%s: cannot fork process for tar", __func__);
357 if (pid == 0) { /* The child */
361 execv("/usr/bin/tar", (char * const *)(uintptr_t)args);
363 errx(2, "%s: failed to execute tar command", __func__);
366 /* Meanwhile, back in the parent process ... */
368 if ((totar = fdopen(pipefds[1], "w")) == NULL) {
370 errx(2, "%s: fdopen failed", __func__);
373 fprintf(totar, "%s\n", CONTENTS_FNAME);
374 fprintf(totar, "%s\n", COMMENT_FNAME);
375 fprintf(totar, "%s\n", DESC_FNAME);
378 fprintf(totar, "%s\n", INSTALL_FNAME);
380 fprintf(totar, "%s\n", POST_INSTALL_FNAME);
382 fprintf(totar, "%s\n", DEINSTALL_FNAME);
384 fprintf(totar, "%s\n", POST_DEINSTALL_FNAME);
386 fprintf(totar, "%s\n", REQUIRE_FNAME);
388 fprintf(totar, "%s\n", DISPLAY_FNAME);
390 fprintf(totar, "%s\n", MTREE_FNAME);
392 for (p = plist->head; p; p = p->next) {
393 if (p->type == PLIST_FILE)
394 fprintf(totar, "%s\n", p->name);
395 else if (p->type == PLIST_CWD && BaseDir && p->name && p->name[0] == '/')
396 fprintf(totar, "-C\n%s%s\n", BaseDir, p->name);
397 else if (p->type == PLIST_CWD || p->type == PLIST_SRC)
398 fprintf(totar, "-C\n%s\n", p->name);
399 else if (p->type == PLIST_IGNORE)
405 /* assume either signal or bad exit is enough for us */
408 errx(2, "%s: tar command failed with code %d", __func__, ret);
417 errx(2, "%s: required package comment string is missing (-c comment)",
422 errx(2, "%s: required package description string is missing (-d desc)",
427 errx(2, "%s: required package contents list is missing (-f [-]file)",
433 /* Clean up those things that would otherwise hang around */
448 create_from_installed(const char *pkg, const char *suf)
452 char homedir[MAXPATHLEN], log_dir[FILENAME_MAX];
454 snprintf(log_dir, sizeof(log_dir), "%s/%s", LOG_DIR, InstalledPkg);
455 if (!fexists(log_dir)) {
456 warnx("can't find package '%s' installed!", InstalledPkg);
459 getcwd(homedir, sizeof(homedir));
460 if (chdir(log_dir) == FAIL) {
461 warnx("can't change directory to '%s'!", log_dir);
464 /* Suck in the contents list */
465 plist.head = plist.tail = NULL;
466 fp = fopen(CONTENTS_FNAME, "r");
468 warnx("unable to open %s file", CONTENTS_FNAME);
471 read_plist(&plist, fp);
474 Install = isfile(INSTALL_FNAME) ? (char *)INSTALL_FNAME : NULL;
475 PostInstall = isfile(POST_INSTALL_FNAME) ?
476 (char *)POST_INSTALL_FNAME : NULL;
477 DeInstall = isfile(DEINSTALL_FNAME) ? (char *)DEINSTALL_FNAME : NULL;
478 PostDeInstall = isfile(POST_DEINSTALL_FNAME) ?
479 (char *)POST_DEINSTALL_FNAME : NULL;
480 Require = isfile(REQUIRE_FNAME) ? (char *)REQUIRE_FNAME : NULL;
481 Display = isfile(DISPLAY_FNAME) ? (char *)DISPLAY_FNAME : NULL;
482 Mtree = isfile(MTREE_FNAME) ? (char *)MTREE_FNAME : NULL;
484 make_dist(homedir, pkg, suf, &plist);