package.c revision 11553
111499Sjkh/* 211499Sjkh * The new sysinstall program. 311499Sjkh * 411499Sjkh * This is probably the last program in the `sysinstall' line - the next 511499Sjkh * generation being essentially a complete rewrite. 611499Sjkh * 711553Sjkh * $Id: package.c,v 1.2 1995/10/16 15:14:21 jkh Exp $ 811499Sjkh * 911499Sjkh * Copyright (c) 1995 1011499Sjkh * Jordan Hubbard. All rights reserved. 1111499Sjkh * 1211499Sjkh * Redistribution and use in source and binary forms, with or without 1311499Sjkh * modification, are permitted provided that the following conditions 1411499Sjkh * are met: 1511499Sjkh * 1. Redistributions of source code must retain the above copyright 1611499Sjkh * notice, this list of conditions and the following disclaimer, 1711499Sjkh * verbatim and that no modifications are made prior to this 1811499Sjkh * point in the file. 1911499Sjkh * 2. Redistributions in binary form must reproduce the above copyright 2011499Sjkh * notice, this list of conditions and the following disclaimer in the 2111499Sjkh * documentation and/or other materials provided with the distribution. 2211499Sjkh * 3. All advertising materials mentioning features or use of this software 2311499Sjkh * must display the following acknowledgement: 2411499Sjkh * This product includes software developed by Jordan Hubbard 2511499Sjkh * for the FreeBSD Project. 2611499Sjkh * 4. The name of Jordan Hubbard or the FreeBSD project may not be used to 2711499Sjkh * endorse or promote products derived from this software without specific 2811499Sjkh * prior written permission. 2911499Sjkh * 3011499Sjkh * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 3111499Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 3211499Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 3311499Sjkh * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 3411499Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3511499Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3611499Sjkh * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 3711499Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3811499Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3911499Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 4011499Sjkh * SUCH DAMAGE. 4111499Sjkh * 4211499Sjkh */ 4311499Sjkh 4411499Sjkh#include <stdio.h> 4511499Sjkh#include <string.h> 4611499Sjkh#include <stdlib.h> 4711499Sjkh#include <sys/errno.h> 4811499Sjkh#include <sys/param.h> 4911499Sjkh#include <sys/mount.h> 5011499Sjkh#include <sys/stat.h> 5111499Sjkh#include "sysinstall.h" 5211499Sjkh 5311499Sjkhstatic char *make_playpen(char *pen, size_t sz); 5411499Sjkh 5511499Sjkh/* Extract a package based on a namespec and a media device */ 5611499Sjkhint 5711499Sjkhpackage_extract(Device *dev, char *name) 5811499Sjkh{ 5911499Sjkh char path[511]; 6011499Sjkh char pen[FILENAME_MAX]; 6111499Sjkh char *where; 6211499Sjkh int i, fd, ret; 6311499Sjkh 6411536Sjkh /* Check to make sure it's not already there */ 6511553Sjkh if (!vsystem("pkg_info -e %s", name)) 6611536Sjkh return RET_SUCCESS; 6711536Sjkh 6811553Sjkh if (!dev->init(dev)) { 6911553Sjkh msgConfirm("Unable to initialize media type for package add."); 7011499Sjkh return RET_FAIL; 7111553Sjkh } 7211499Sjkh 7311499Sjkh ret = RET_FAIL; 7411553Sjkh sprintf(path, "packages/All/%s%s", name, strstr(name, ".tgz") ? "" : ".tgz"); 7511553Sjkh msgDebug("pkg_extract: Attempting to fetch %s\n", path); 7611553Sjkh fd = dev->get(dev, path, TRUE); 7711499Sjkh if (fd >= 0) { 7811499Sjkh pid_t tpid; 7911499Sjkh 8011553Sjkh msgNotify("Fetching %s from %s\n", path, dev->name); 8111499Sjkh pen[0] = '\0'; 8211499Sjkh if ((where = make_playpen(pen, 0)) != NULL) { 8311499Sjkh if (isDebug()) 8411499Sjkh msgDebug("Working in temporary directory %s, will return to %s\n", pen, where); 8511499Sjkh tpid = fork(); 8611499Sjkh if (!tpid) { 8711499Sjkh dup2(fd, 0); 8811499Sjkh i = vsystem("tar %s-xzf -", !strcmp(variable_get(CPIO_VERBOSITY_LEVEL), "high") ? "-v " : ""); 8911499Sjkh if (isDebug()) 9011499Sjkh msgDebug("tar command returns %d status\n", i); 9111499Sjkh exit(i); 9211499Sjkh } 9311499Sjkh else { 9411499Sjkh int pstat; 9511499Sjkh 9611499Sjkh close(fd); 9711499Sjkh tpid = waitpid(tpid, &pstat, 0); 9811499Sjkh if (vsystem("(pwd; cat +CONTENTS) | pkg_add %s-S", 9911536Sjkh !strcmp(variable_get(CPIO_VERBOSITY_LEVEL), "high") ? "-v " : "")) 10011499Sjkh msgConfirm("An error occurred while trying to pkg_add %s.\n" 10111499Sjkh "Please check debugging screen for possible further details.", path); 10211499Sjkh else 10311499Sjkh ret = RET_SUCCESS; 10411499Sjkh } 10511499Sjkh if (chdir(where) == -1) 10611499Sjkh msgFatal("Unable to get back to where I was before, Jojo!\n(That was: %s)\n", where); 10711499Sjkh vsystem("rm -rf %s", pen); 10811499Sjkh if (isDebug()) 10911499Sjkh msgDebug("Nuked pen: %s\n", pen); 11011499Sjkh } 11111499Sjkh else 11211499Sjkh msgConfirm("Unable to find a temporary location to unpack this stuff in.\n" 11311499Sjkh "You must simply not have enough space or you've configured your\n" 11411499Sjkh "system oddly. Sorry!"); 11511499Sjkh dev->close(dev, fd); 11611499Sjkh if (dev->type == DEVICE_TYPE_TAPE) 11711499Sjkh unlink(path); 11811499Sjkh } 11911553Sjkh else 12011553Sjkh msgDebug("pkg_extract: get operation returned %d\n", fd); 12111499Sjkh return ret; 12211499Sjkh} 12311499Sjkh 12411499Sjkhstatic size_t 12511499Sjkhmin_free(char *tmpdir) 12611499Sjkh{ 12711499Sjkh struct statfs buf; 12811499Sjkh 12911499Sjkh if (statfs(tmpdir, &buf) != 0) { 13011499Sjkh msgDebug("Error in statfs, errno = %d\n", errno); 13111499Sjkh return -1; 13211499Sjkh } 13311499Sjkh return buf.f_bavail * buf.f_bsize; 13411499Sjkh} 13511499Sjkh 13611499Sjkh/* Find a good place to play. */ 13711499Sjkhstatic char * 13811499Sjkhfind_play_pen(char *pen, size_t sz) 13911499Sjkh{ 14011499Sjkh struct stat sb; 14111499Sjkh 14211499Sjkh if (pen[0] && stat(pen, &sb) != RET_FAIL && (min_free(pen) >= sz)) 14311499Sjkh return pen; 14411499Sjkh else if (stat("/var/tmp", &sb) != RET_FAIL && min_free("/var/tmp") >= sz) 14511499Sjkh strcpy(pen, "/var/tmp/instmp.XXXXXX"); 14611499Sjkh else if (stat("/tmp", &sb) != RET_FAIL && min_free("/tmp") >= sz) 14711499Sjkh strcpy(pen, "/tmp/instmp.XXXXXX"); 14811499Sjkh else if ((stat("/usr/tmp", &sb) == RET_SUCCESS || mkdir("/usr/tmp", 01777) == RET_SUCCESS) && 14911499Sjkh min_free("/usr/tmp") >= sz) 15011499Sjkh strcpy(pen, "/usr/tmp/instmp.XXXXXX"); 15111499Sjkh else { 15211499Sjkh msgConfirm("Can't find enough temporary space to extract the files, please try\n" 15311499Sjkh "This again after your system is up (you can run /stand/sysinstall\n" 15411499Sjkh "directly) and you've had a chance to point /var/tmp somewhere with\n" 15511499Sjkh "sufficient temporary space available."); 15611499Sjkh return NULL; 15711499Sjkh } 15811499Sjkh return pen; 15911499Sjkh} 16011499Sjkh 16111499Sjkh/* 16211499Sjkh * Make a temporary directory to play in and chdir() to it, returning 16311499Sjkh * pathname of previous working directory. 16411499Sjkh */ 16511499Sjkhstatic char * 16611499Sjkhmake_playpen(char *pen, size_t sz) 16711499Sjkh{ 16811499Sjkh static char Previous[FILENAME_MAX]; 16911499Sjkh 17011499Sjkh if (!find_play_pen(pen, sz)) 17111499Sjkh return NULL; 17211499Sjkh 17311499Sjkh if (!mktemp(pen)) { 17411499Sjkh msgConfirm("Can't mktemp '%s'.", pen); 17511499Sjkh return NULL; 17611499Sjkh } 17711499Sjkh if (mkdir(pen, 0755) == RET_FAIL) { 17811499Sjkh msgConfirm("Can't mkdir '%s'.", pen); 17911499Sjkh return NULL; 18011499Sjkh } 18111499Sjkh if (isDebug()) { 18211499Sjkh if (sz) 18311499Sjkh msgDebug("Requested space: %d bytes, free space: %d bytes in %s\n", (int)sz, min_free(pen), pen); 18411499Sjkh } 18511499Sjkh if (min_free(pen) < sz) { 18611499Sjkh rmdir(pen); 18711499Sjkh msgConfirm("Not enough free space to create: `%s'\n" 18811499Sjkh "Please try this again after your system is up (you can run\n" 18911499Sjkh "/stand/sysinstall directly) and you've had a chance to point\n" 19011499Sjkh "/var/tmp somewhere with sufficient temporary space available."); 19111499Sjkh return NULL; 19211499Sjkh } 19311499Sjkh if (!getcwd(Previous, FILENAME_MAX)) { 19411499Sjkh msgConfirm("getcwd"); 19511499Sjkh return NULL; 19611499Sjkh } 19711499Sjkh if (chdir(pen) == RET_FAIL) 19811499Sjkh msgConfirm("Can't chdir to '%s'.", pen); 19911499Sjkh return Previous; 20011499Sjkh} 201