perform.c revision 67454
1#ifndef lint 2static const char rcsid[] = 3 "$FreeBSD: head/usr.sbin/pkg_install/create/perform.c 67454 2000-10-23 07:01:31Z sobomax $"; 4#endif 5 6/* 7 * FreeBSD install - a package for the installation and maintainance 8 * of non-core utilities. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * Jordan K. Hubbard 20 * 18 July 1993 21 * 22 * This is the main body of the create module. 23 * 24 */ 25 26#include "lib.h" 27#include "create.h" 28 29#include <err.h> 30#include <signal.h> 31#include <sys/syslimits.h> 32#include <sys/wait.h> 33#include <unistd.h> 34 35static void sanity_check(void); 36static void make_dist(char *, char *, char *, Package *); 37 38static char *home; 39 40int 41pkg_perform(char **pkgs) 42{ 43 char *pkg = *pkgs; /* Only one arg to create */ 44 char *cp; 45 FILE *pkg_in, *fp; 46 Package plist; 47 int len; 48 char *suf; 49 int compress = 0; 50 51 /* Preliminary setup */ 52 sanity_check(); 53 if (Verbose && !PlistOnly) 54 printf("Creating package %s\n", pkg); 55 get_dash_string(&Comment); 56 get_dash_string(&Desc); 57 if (!strcmp(Contents, "-")) 58 pkg_in = stdin; 59 else { 60 pkg_in = fopen(Contents, "r"); 61 if (!pkg_in) { 62 cleanup(0); 63 errx(2, __FUNCTION__ ": unable to open contents file '%s' for input", Contents); 64 } 65 } 66 plist.head = plist.tail = NULL; 67 68 /* chop suffix off if already specified, remembering if we want to compress */ 69 len = strlen(pkg); 70 if (len > 4) { 71 if (!strcmp(&pkg[len - 4], ".tgz")) { 72 compress = TRUE; 73 pkg[len - 4] = '\0'; 74 } 75 else if (!strcmp(&pkg[len - 4], ".tar")) { 76 compress = FALSE; 77 pkg[len - 4] = '\0'; 78 } 79 else 80 /* default is to compress packages */ 81 compress = TRUE; 82 } 83 if (compress) 84 suf = "tgz"; 85 else 86 suf = "tar"; 87 88 /* Add the origin if asked, at the top */ 89 if (Origin) 90 add_plist(&plist, PLIST_COMMENT, strconcat("ORIGIN:", Origin)); 91 92 /* Stick the dependencies, if any, at the top */ 93 if (Pkgdeps) { 94 if (Verbose && !PlistOnly) 95 printf("Registering depends:"); 96 while (Pkgdeps) { 97 cp = strsep(&Pkgdeps, " \t\n"); 98 if (*cp) { 99 add_plist_top(&plist, PLIST_PKGDEP, cp); 100 if (Verbose && !PlistOnly) 101 printf(" %s", cp); 102 } 103 } 104 if (Verbose && !PlistOnly) 105 printf(".\n"); 106 } 107 108 /* If a SrcDir override is set, add it now */ 109 if (SrcDir) { 110 if (Verbose && !PlistOnly) 111 printf("Using SrcDir value of %s\n", SrcDir); 112 add_plist(&plist, PLIST_SRC, SrcDir); 113 } 114 115 /* Slurp in the packing list */ 116 read_plist(&plist, pkg_in); 117 118 /* Prefix should add an @cwd to the packing list */ 119 if (Prefix) 120 add_plist_top(&plist, PLIST_CWD, Prefix); 121 /* 122 * Run down the list and see if we've named it, if not stick in a name 123 * at the top. 124 */ 125 if (find_plist(&plist, PLIST_NAME) == NULL) 126 add_plist_top(&plist, PLIST_NAME, basename_of(pkg)); 127 128 /* 129 * We're just here for to dump out a revised plist for the FreeBSD ports 130 * hack. It's not a real create in progress. 131 */ 132 if (PlistOnly) { 133 check_list(home, &plist); 134 write_plist(&plist, stdout); 135 exit(0); 136 } 137 138 /* Make a directory to stomp around in */ 139 home = make_playpen(PlayPen, 0); 140 signal(SIGINT, cleanup); 141 signal(SIGHUP, cleanup); 142 143 /* Make first "real contents" pass over it */ 144 check_list(home, &plist); 145 (void) umask(022); /* make sure gen'ed directories, files don't have 146 group or other write bits. */ 147 /* copy_plist(home, &plist); */ 148 /* mark_plist(&plist); */ 149 150 /* Now put the release specific items in */ 151 add_plist(&plist, PLIST_CWD, "."); 152 write_file(COMMENT_FNAME, Comment); 153 add_plist(&plist, PLIST_IGNORE, NULL); 154 add_plist(&plist, PLIST_FILE, COMMENT_FNAME); 155 write_file(DESC_FNAME, Desc); 156 add_plist(&plist, PLIST_IGNORE, NULL); 157 add_plist(&plist, PLIST_FILE, DESC_FNAME); 158 159 if (Install) { 160 copy_file(home, Install, INSTALL_FNAME); 161 add_plist(&plist, PLIST_IGNORE, NULL); 162 add_plist(&plist, PLIST_FILE, INSTALL_FNAME); 163 } 164 if (PostInstall) { 165 copy_file(home, PostInstall, POST_INSTALL_FNAME); 166 add_plist(&plist, PLIST_IGNORE, NULL); 167 add_plist(&plist, PLIST_FILE, POST_INSTALL_FNAME); 168 } 169 if (DeInstall) { 170 copy_file(home, DeInstall, DEINSTALL_FNAME); 171 add_plist(&plist, PLIST_IGNORE, NULL); 172 add_plist(&plist, PLIST_FILE, DEINSTALL_FNAME); 173 } 174 if (PostDeInstall) { 175 copy_file(home, PostDeInstall, POST_DEINSTALL_FNAME); 176 add_plist(&plist, PLIST_IGNORE, NULL); 177 add_plist(&plist, PLIST_FILE, POST_DEINSTALL_FNAME); 178 } 179 if (Require) { 180 copy_file(home, Require, REQUIRE_FNAME); 181 add_plist(&plist, PLIST_IGNORE, NULL); 182 add_plist(&plist, PLIST_FILE, REQUIRE_FNAME); 183 } 184 if (Display) { 185 copy_file(home, Display, DISPLAY_FNAME); 186 add_plist(&plist, PLIST_IGNORE, NULL); 187 add_plist(&plist, PLIST_FILE, DISPLAY_FNAME); 188 add_plist(&plist, PLIST_DISPLAY, DISPLAY_FNAME); 189 } 190 if (Mtree) { 191 copy_file(home, Mtree, MTREE_FNAME); 192 add_plist(&plist, PLIST_IGNORE, NULL); 193 add_plist(&plist, PLIST_FILE, MTREE_FNAME); 194 add_plist(&plist, PLIST_MTREE, MTREE_FNAME); 195 } 196 197 /* Finally, write out the packing list */ 198 fp = fopen(CONTENTS_FNAME, "w"); 199 if (!fp) { 200 cleanup(0); 201 errx(2, __FUNCTION__ ": can't open file %s for writing", CONTENTS_FNAME); 202 } 203 write_plist(&plist, fp); 204 if (fclose(fp)) { 205 cleanup(0); 206 errx(2, __FUNCTION__ ": error while closing %s", CONTENTS_FNAME); 207 } 208 209 /* And stick it into a tar ball */ 210 make_dist(home, pkg, suf, &plist); 211 212 /* Cleanup */ 213 free(Comment); 214 free(Desc); 215 free_plist(&plist); 216 leave_playpen(); 217 return TRUE; /* Success */ 218} 219 220static void 221make_dist(char *home, char *pkg, char *suffix, Package *plist) 222{ 223 char tball[FILENAME_MAX]; 224 PackingList p; 225 int ret; 226 char *args[50]; /* Much more than enough. */ 227 int nargs = 0; 228 int pipefds[2]; 229 FILE *totar; 230 pid_t pid; 231 232 args[nargs++] = "tar"; /* argv[0] */ 233 234 if (*pkg == '/') 235 snprintf(tball, FILENAME_MAX, "%s.%s", pkg, suffix); 236 else 237 snprintf(tball, FILENAME_MAX, "%s/%s.%s", home, pkg, suffix); 238 239 args[nargs++] = "-c"; 240 args[nargs++] = "-f"; 241 args[nargs++] = tball; 242 if (strchr(suffix, 'z')) /* Compress/gzip? */ 243 args[nargs++] = "-z"; 244 if (Dereference) 245 args[nargs++] = "-h"; 246 if (ExcludeFrom) { 247 args[nargs++] = "-X"; 248 args[nargs++] = ExcludeFrom; 249 } 250 args[nargs++] = "-T"; /* Take filenames from file instead of args. */ 251 args[nargs++] = "-"; /* Use stdin for the file. */ 252 args[nargs] = NULL; 253 254 if (Verbose) 255 printf("Creating gzip'd tar ball in '%s'\n", tball); 256 257 /* Set up a pipe for passing the filenames, and fork off a tar process. */ 258 if (pipe(pipefds) == -1) { 259 cleanup(0); 260 errx(2, __FUNCTION__ ": cannot create pipe"); 261 } 262 if ((pid = fork()) == -1) { 263 cleanup(0); 264 errx(2, __FUNCTION__ ": cannot fork process for tar"); 265 } 266 if (pid == 0) { /* The child */ 267 dup2(pipefds[0], 0); 268 close(pipefds[0]); 269 close(pipefds[1]); 270 execv("/usr/bin/tar", args); 271 cleanup(0); 272 errx(2, __FUNCTION__ ": failed to execute tar command"); 273 } 274 275 /* Meanwhile, back in the parent process ... */ 276 close(pipefds[0]); 277 if ((totar = fdopen(pipefds[1], "w")) == NULL) { 278 cleanup(0); 279 errx(2, __FUNCTION__ ": fdopen failed"); 280 } 281 282 fprintf(totar, "%s\n", CONTENTS_FNAME); 283 fprintf(totar, "%s\n", COMMENT_FNAME); 284 fprintf(totar, "%s\n", DESC_FNAME); 285 286 if (Install) 287 fprintf(totar, "%s\n", INSTALL_FNAME); 288 if (PostInstall) 289 fprintf(totar, "%s\n", POST_INSTALL_FNAME); 290 if (DeInstall) 291 fprintf(totar, "%s\n", DEINSTALL_FNAME); 292 if (PostDeInstall) 293 fprintf(totar, "%s\n", POST_DEINSTALL_FNAME); 294 if (Require) 295 fprintf(totar, "%s\n", REQUIRE_FNAME); 296 if (Display) 297 fprintf(totar, "%s\n", DISPLAY_FNAME); 298 if (Mtree) 299 fprintf(totar, "%s\n", MTREE_FNAME); 300 301 for (p = plist->head; p; p = p->next) { 302 if (p->type == PLIST_FILE) 303 fprintf(totar, "%s\n", p->name); 304 else if (p->type == PLIST_CWD || p->type == PLIST_SRC) 305 fprintf(totar, "-C\n%s\n", p->name); 306 else if (p->type == PLIST_IGNORE) 307 p = p->next; 308 } 309 310 fclose(totar); 311 wait(&ret); 312 /* assume either signal or bad exit is enough for us */ 313 if (ret) { 314 cleanup(0); 315 errx(2, __FUNCTION__ ": tar command failed with code %d", ret); 316 } 317} 318 319static void 320sanity_check() 321{ 322 if (!Comment) { 323 cleanup(0); 324 errx(2, __FUNCTION__ ": required package comment string is missing (-c comment)"); 325 } 326 if (!Desc) { 327 cleanup(0); 328 errx(2, __FUNCTION__ ": required package description string is missing (-d desc)"); 329 } 330 if (!Contents) { 331 cleanup(0); 332 errx(2, __FUNCTION__ ": required package contents list is missing (-f [-]file)"); 333 } 334} 335 336 337/* Clean up those things that would otherwise hang around */ 338void 339cleanup(int sig) 340{ 341 int in_cleanup = 0; 342 343 if (!in_cleanup) { 344 in_cleanup = 1; 345 leave_playpen(); 346 } 347 if (sig) 348 exit(1); 349} 350