pen.c revision 33427
1132720Skan#ifndef lint 2132720Skanstatic const char rcsid[] = 3169691Skan "$Id: pen.c,v 1.26 1998/01/09 14:52:18 jkh Exp $"; 4132720Skan#endif 5132720Skan 6132720Skan/* 7132720Skan * FreeBSD install - a package for the installation and maintainance 8132720Skan * of non-core utilities. 9132720Skan * 10132720Skan * Redistribution and use in source and binary forms, with or without 11132720Skan * modification, are permitted provided that the following conditions 12132720Skan * are met: 13132720Skan * 1. Redistributions of source code must retain the above copyright 14132720Skan * notice, this list of conditions and the following disclaimer. 15132720Skan * 2. Redistributions in binary form must reproduce the above copyright 16132720Skan * notice, this list of conditions and the following disclaimer in the 17132720Skan * documentation and/or other materials provided with the distribution. 18169691Skan * 19132720Skan * Jordan K. Hubbard 20132720Skan * 18 July 1993 21132720Skan * 22132720Skan * Routines for managing the "play pen". 23132720Skan * 24132720Skan */ 25132720Skan 26132720Skan#include <err.h> 27132720Skan#include "lib.h" 28132720Skan#include <sys/signal.h> 29132720Skan#include <sys/param.h> 30132720Skan#include <sys/mount.h> 31132720Skan 32132720Skan/* For keeping track of where we are */ 33132720Skanstatic char PenLocation[FILENAME_MAX]; 34132720Skanstatic char Previous[FILENAME_MAX]; 35132720Skan 36132720Skanchar * 37132720Skanwhere_playpen(void) 38132720Skan{ 39132720Skan return PenLocation; 40132720Skan} 41132720Skan 42132720Skan/* Find a good place to play. */ 43132720Skanstatic char * 44132720Skanfind_play_pen(char *pen, size_t sz) 45132720Skan{ 46132720Skan char *cp; 47132720Skan struct stat sb; 48132720Skan 49132720Skan if (pen[0] && stat(pen, &sb) != FAIL && (min_free(pen) >= sz)) 50132720Skan return pen; 51169691Skan else if ((cp = getenv("PKG_TMPDIR")) != NULL && stat(cp, &sb) != FAIL && (min_free(cp) >= sz)) 52132720Skan sprintf(pen, "%s/instmp.XXXXXX", cp); 53169691Skan else if ((cp = getenv("TMPDIR")) != NULL && stat(cp, &sb) != FAIL && (min_free(cp) >= sz)) 54169691Skan sprintf(pen, "%s/instmp.XXXXXX", cp); 55169691Skan else if (stat("/var/tmp", &sb) != FAIL && min_free("/var/tmp") >= sz) 56169691Skan strcpy(pen, "/var/tmp/instmp.XXXXXX"); 57132720Skan else if (stat("/tmp", &sb) != FAIL && min_free("/tmp") >= sz) 58132720Skan strcpy(pen, "/tmp/instmp.XXXXXX"); 59132720Skan else if ((stat("/usr/tmp", &sb) == SUCCESS || mkdir("/usr/tmp", 01777) == SUCCESS) && min_free("/usr/tmp") >= sz) 60132720Skan strcpy(pen, "/usr/tmp/instmp.XXXXXX"); 61132720Skan else { 62132720Skan cleanup(0); 63132720Skan errx(2, 64132720Skan"can't find enough temporary space to extract the files, please set your\n" 65132720Skan"PKG_TMPDIR environment variable to a location with at least %d bytes\n" 66132720Skan"free", sz); 67132720Skan return NULL; 68132720Skan } 69132720Skan return pen; 70132720Skan} 71132720Skan 72132720Skan/* 73132720Skan * Make a temporary directory to play in and chdir() to it, returning 74132720Skan * pathname of previous working directory. 75132720Skan */ 76132720Skanchar * 77132720Skanmake_playpen(char *pen, size_t sz) 78132720Skan{ 79132720Skan if (PenLocation[0]) { 80132720Skan errx(2, "make_playpen() called before closing previous pen: %s", pen); 81132720Skan return NULL; 82132720Skan } 83132720Skan if (!find_play_pen(pen, sz)) 84132720Skan return NULL; 85132720Skan 86132720Skan if (!mktemp(pen)) { 87132720Skan cleanup(0); 88132720Skan errx(2, "can't mktemp '%s'", pen); 89132720Skan } 90132720Skan if (mkdir(pen, 0755) == FAIL) { 91132720Skan cleanup(0); 92132720Skan errx(2, "can't mkdir '%s'", pen); 93132720Skan } 94132720Skan if (Verbose) { 95132720Skan if (sz) 96132720Skan fprintf(stderr, "Requested space: %d bytes, free space: %qd bytes in %s\n", (int)sz, min_free(pen), pen); 97132720Skan } 98132720Skan if (min_free(pen) < sz) { 99132720Skan rmdir(pen); 100132720Skan cleanup(0); 101132720Skan errx(2, "not enough free space to create '%s'.\n" 102132720Skan "Please set your PKG_TMPDIR environment variable to a location\n" 103132720Skan "with more space and\ntry the command again", pen); 104132720Skan } 105132720Skan if (!getcwd(Previous, FILENAME_MAX)) { 106132720Skan upchuck("getcwd"); 107132720Skan return NULL; 108132720Skan } 109132720Skan if (chdir(pen) == FAIL) 110132720Skan cleanup(0), errx(2, "can't chdir to '%s'", pen); 111169691Skan strcpy(PenLocation, pen); 112169691Skan return Previous; 113169691Skan} 114169691Skan 115169691Skan/* Convenience routine for getting out of playpen */ 116169691Skanvoid 117169691Skanleave_playpen() 118169691Skan{ 119169691Skan void (*oldsig)(int); 120169691Skan 121169691Skan /* Don't interrupt while we're cleaning up */ 122169691Skan oldsig = signal(SIGINT, SIG_IGN); 123132720Skan if (Previous[0] && chdir(Previous) == FAIL) 124132720Skan cleanup(0), errx(2, "can't chdir back to '%s'", Previous); 125132720Skan else if (PenLocation[0]) { 126169691Skan if (PenLocation[0] == '/' && vsystem("rm -rf %s", PenLocation)) 127169691Skan warnx("couldn't remove temporary dir '%s'", PenLocation); 128132720Skan } 129 Previous[0] = PenLocation[0] = '\0'; 130 signal(SIGINT, oldsig); 131} 132 133off_t 134min_free(char *tmpdir) 135{ 136 struct statfs buf; 137 138 if (statfs(tmpdir, &buf) != 0) { 139 warn("statfs"); 140 return -1; 141 } 142 return (off_t)buf.f_bavail * (off_t)buf.f_bsize; 143} 144