1993-08-26 01:19:55 +00:00
|
|
|
#ifndef lint
|
1997-10-08 07:48:21 +00:00
|
|
|
static const char rcsid[] =
|
1999-08-28 01:35:59 +00:00
|
|
|
"$FreeBSD$";
|
1993-08-26 01:19:55 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/*
|
|
|
|
* FreeBSD install - a package for the installation and maintainance
|
|
|
|
* of non-core utilities.
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted provided that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* Jordan K. Hubbard
|
|
|
|
* 18 July 1993
|
|
|
|
*
|
|
|
|
* Routines for dealing with the packing list.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "lib.h"
|
|
|
|
#include "create.h"
|
1994-12-06 00:51:50 +00:00
|
|
|
#include <errno.h>
|
1997-10-08 07:48:21 +00:00
|
|
|
#include <err.h>
|
1996-07-30 10:48:20 +00:00
|
|
|
#include <md5.h>
|
1993-08-26 01:19:55 +00:00
|
|
|
|
|
|
|
/* Check a list for files that require preconversion */
|
|
|
|
void
|
2001-10-10 06:58:42 +00:00
|
|
|
check_list(const char *home, Package *pkg)
|
1993-08-26 01:19:55 +00:00
|
|
|
{
|
2001-10-10 06:58:42 +00:00
|
|
|
const char *where = home;
|
|
|
|
const char *there = NULL;
|
2001-01-12 11:36:12 +00:00
|
|
|
char *cp, name[FILENAME_MAX], buf[33];
|
|
|
|
PackingList p;
|
1993-08-26 01:19:55 +00:00
|
|
|
|
2001-01-12 11:36:12 +00:00
|
|
|
for (p = pkg->head; p != NULL; p = p->next)
|
|
|
|
switch (p->type) {
|
|
|
|
case PLIST_CWD:
|
1993-08-26 01:19:55 +00:00
|
|
|
where = p->name;
|
2001-01-12 11:36:12 +00:00
|
|
|
break;
|
|
|
|
case PLIST_IGNORE:
|
1993-08-26 01:19:55 +00:00
|
|
|
p = p->next;
|
2001-01-12 11:36:12 +00:00
|
|
|
break;
|
|
|
|
case PLIST_SRC:
|
1994-08-29 16:31:38 +00:00
|
|
|
there = p->name;
|
2001-01-12 11:36:12 +00:00
|
|
|
break;
|
|
|
|
case PLIST_FILE:
|
2001-10-10 08:21:41 +00:00
|
|
|
cp = NULL;
|
1994-08-29 16:31:38 +00:00
|
|
|
sprintf(name, "%s/%s", there ? there : where, p->name);
|
2001-10-10 08:21:41 +00:00
|
|
|
if (issymlink(name)) {
|
|
|
|
int len;
|
|
|
|
char lnk[FILENAME_MAX];
|
|
|
|
|
|
|
|
if ((len = readlink(name, lnk, FILENAME_MAX)) > 0)
|
|
|
|
cp = MD5Data((unsigned char *)lnk, len, buf);
|
|
|
|
} else if (isfile(name)) {
|
|
|
|
/* Don't record MD5 checksum for device nodes and such */
|
|
|
|
cp = MD5File(name, buf);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cp != NULL) {
|
1996-07-30 10:48:20 +00:00
|
|
|
PackingList tmp = new_plist_entry();
|
1993-08-26 01:19:55 +00:00
|
|
|
|
1996-07-30 10:48:20 +00:00
|
|
|
tmp->name = copy_string(strconcat("MD5:", cp));
|
|
|
|
tmp->type = PLIST_COMMENT;
|
|
|
|
tmp->next = p->next;
|
|
|
|
tmp->prev = p;
|
|
|
|
p->next = tmp;
|
2001-01-12 11:36:12 +00:00
|
|
|
if (pkg->tail == p)
|
|
|
|
pkg->tail = tmp;
|
1996-07-30 10:48:20 +00:00
|
|
|
p = tmp;
|
1993-08-26 01:19:55 +00:00
|
|
|
}
|
2001-01-12 11:36:12 +00:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
break;
|
1993-08-26 01:19:55 +00:00
|
|
|
}
|
1995-05-30 03:57:47 +00:00
|
|
|
}
|
1993-08-26 01:19:55 +00:00
|
|
|
|
1994-12-06 00:51:50 +00:00
|
|
|
static int
|
|
|
|
trylink(const char *from, const char *to)
|
|
|
|
{
|
|
|
|
if (link(from, to) == 0)
|
|
|
|
return 0;
|
|
|
|
if (errno == ENOENT) {
|
|
|
|
/* try making the container directory */
|
|
|
|
char *cp = strrchr(to, '/');
|
|
|
|
if (cp)
|
|
|
|
vsystem("mkdir -p %.*s", cp - to,
|
|
|
|
to);
|
|
|
|
return link(from, to);
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define STARTSTRING "tar cf -"
|
2001-10-10 06:58:42 +00:00
|
|
|
#define TOOBIG(str) (int)strlen(str) + 6 + (int)strlen(home) + where_count > maxargs
|
1994-12-06 00:51:50 +00:00
|
|
|
#define PUSHOUT() /* push out string */ \
|
2001-10-10 06:58:42 +00:00
|
|
|
if (where_count > (int)sizeof(STARTSTRING)-1) { \
|
1994-12-06 00:51:50 +00:00
|
|
|
strcat(where_args, "|tar xpf -"); \
|
1998-09-11 07:26:58 +00:00
|
|
|
if (system(where_args)) { \
|
|
|
|
cleanup(0); \
|
2000-10-22 09:53:27 +00:00
|
|
|
errx(2, __FUNCTION__ ": can't invoke tar pipeline"); \
|
1998-09-11 07:26:58 +00:00
|
|
|
} \
|
1994-12-06 00:51:50 +00:00
|
|
|
memset(where_args, 0, maxargs); \
|
|
|
|
last_chdir = NULL; \
|
|
|
|
strcpy(where_args, STARTSTRING); \
|
|
|
|
where_count = sizeof(STARTSTRING)-1; \
|
|
|
|
}
|
|
|
|
|
1993-08-26 01:19:55 +00:00
|
|
|
/*
|
|
|
|
* Copy unmarked files in packing list to playpen - marked files
|
|
|
|
* have already been copied in an earlier pass through the list.
|
|
|
|
*/
|
|
|
|
void
|
2001-10-10 06:58:42 +00:00
|
|
|
copy_plist(const char *home, Package *plist)
|
1993-08-26 01:19:55 +00:00
|
|
|
{
|
|
|
|
PackingList p = plist->head;
|
2001-10-10 06:58:42 +00:00
|
|
|
const char *where = home;
|
|
|
|
const char *there = NULL, *mythere;
|
|
|
|
char *where_args;
|
|
|
|
const char *last_chdir, *root = "/";
|
1994-12-06 00:51:50 +00:00
|
|
|
int maxargs, where_count = 0, add_count;
|
|
|
|
struct stat stb;
|
|
|
|
dev_t curdir;
|
|
|
|
|
|
|
|
maxargs = sysconf(_SC_ARG_MAX);
|
2001-05-17 10:12:45 +00:00
|
|
|
maxargs -= 64; /*
|
|
|
|
* Some slop for the tar cmd text,
|
|
|
|
* and sh -c
|
|
|
|
*/
|
1994-12-06 00:51:50 +00:00
|
|
|
where_args = malloc(maxargs);
|
1998-09-11 07:26:58 +00:00
|
|
|
if (!where_args) {
|
|
|
|
cleanup(0);
|
2000-10-22 09:53:27 +00:00
|
|
|
errx(2, __FUNCTION__ ": can't get argument list space");
|
1998-09-11 07:26:58 +00:00
|
|
|
}
|
1994-12-06 00:51:50 +00:00
|
|
|
|
|
|
|
memset(where_args, 0, maxargs);
|
|
|
|
strcpy(where_args, STARTSTRING);
|
|
|
|
where_count = sizeof(STARTSTRING)-1;
|
|
|
|
last_chdir = 0;
|
|
|
|
|
|
|
|
if (stat(".", &stb) == 0)
|
|
|
|
curdir = stb.st_dev;
|
|
|
|
else
|
2001-05-17 10:12:45 +00:00
|
|
|
curdir = (dev_t) -1; /*
|
|
|
|
* It's ok if this is a valid dev_t;
|
|
|
|
* this is just a hint for an
|
|
|
|
* optimization.
|
|
|
|
*/
|
1993-08-26 01:19:55 +00:00
|
|
|
|
|
|
|
while (p) {
|
|
|
|
if (p->type == PLIST_CWD)
|
|
|
|
where = p->name;
|
1994-08-28 14:15:30 +00:00
|
|
|
else if (p->type == PLIST_SRC)
|
1994-08-29 16:31:38 +00:00
|
|
|
there = p->name;
|
1993-08-26 01:19:55 +00:00
|
|
|
else if (p->type == PLIST_IGNORE)
|
|
|
|
p = p->next;
|
|
|
|
else if (p->type == PLIST_FILE && !p->marked) {
|
|
|
|
char fn[FILENAME_MAX];
|
|
|
|
|
1994-12-06 00:51:50 +00:00
|
|
|
|
1993-08-26 01:19:55 +00:00
|
|
|
/* First, look for it in the "home" dir */
|
|
|
|
sprintf(fn, "%s/%s", home, p->name);
|
1994-12-06 00:51:50 +00:00
|
|
|
if (fexists(fn)) {
|
|
|
|
if (lstat(fn, &stb) == 0 && stb.st_dev == curdir &&
|
|
|
|
S_ISREG(stb.st_mode)) {
|
2001-05-17 10:12:45 +00:00
|
|
|
/*
|
|
|
|
* If we can link it to the playpen, that avoids a copy
|
|
|
|
* and saves time.
|
|
|
|
*/
|
1994-12-06 00:51:50 +00:00
|
|
|
if (p->name[0] != '/') {
|
2001-05-17 10:12:45 +00:00
|
|
|
/*
|
|
|
|
* Don't link abspn stuff--it doesn't come from
|
|
|
|
* local dir!
|
|
|
|
*/
|
1994-12-06 00:51:50 +00:00
|
|
|
if (trylink(fn, p->name) == 0) {
|
|
|
|
p = p->next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (TOOBIG(fn)) {
|
|
|
|
PUSHOUT();
|
|
|
|
}
|
|
|
|
if (p->name[0] == '/') {
|
|
|
|
add_count = snprintf(&where_args[where_count],
|
|
|
|
maxargs - where_count,
|
|
|
|
" %s %s",
|
|
|
|
last_chdir == root ? "" : "-C /",
|
|
|
|
p->name);
|
|
|
|
last_chdir = root;
|
|
|
|
} else {
|
|
|
|
add_count = snprintf(&where_args[where_count],
|
|
|
|
maxargs - where_count,
|
1995-05-30 03:57:47 +00:00
|
|
|
" %s%s %s",
|
1994-12-06 00:51:50 +00:00
|
|
|
last_chdir == home ? "" : "-C ",
|
|
|
|
last_chdir == home ? "" : home,
|
|
|
|
p->name);
|
|
|
|
last_chdir = home;
|
|
|
|
}
|
2001-08-20 15:09:34 +00:00
|
|
|
if (add_count < 0 || add_count > maxargs - where_count) {
|
1998-09-11 07:26:58 +00:00
|
|
|
cleanup(0);
|
2000-10-22 09:53:27 +00:00
|
|
|
errx(2, __FUNCTION__ ": oops, miscounted strings!");
|
1998-09-11 07:26:58 +00:00
|
|
|
}
|
1994-12-06 00:51:50 +00:00
|
|
|
where_count += add_count;
|
|
|
|
}
|
1993-08-26 01:19:55 +00:00
|
|
|
/*
|
|
|
|
* Otherwise, try along the actual extraction path..
|
|
|
|
*/
|
1994-12-06 00:51:50 +00:00
|
|
|
else {
|
|
|
|
if (p->name[0] == '/')
|
|
|
|
mythere = root;
|
|
|
|
else mythere = there;
|
|
|
|
sprintf(fn, "%s/%s", mythere ? mythere : where, p->name);
|
|
|
|
if (lstat(fn, &stb) == 0 && stb.st_dev == curdir &&
|
|
|
|
S_ISREG(stb.st_mode)) {
|
2001-05-17 10:12:45 +00:00
|
|
|
/*
|
|
|
|
* If we can link it to the playpen, that avoids a copy
|
|
|
|
* and saves time.
|
|
|
|
*/
|
1994-12-06 00:51:50 +00:00
|
|
|
if (trylink(fn, p->name) == 0) {
|
|
|
|
p = p->next;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (TOOBIG(p->name)) {
|
|
|
|
PUSHOUT();
|
|
|
|
}
|
|
|
|
if (last_chdir == (mythere ? mythere : where))
|
|
|
|
add_count = snprintf(&where_args[where_count],
|
|
|
|
maxargs - where_count,
|
|
|
|
" %s", p->name);
|
|
|
|
else
|
|
|
|
add_count = snprintf(&where_args[where_count],
|
|
|
|
maxargs - where_count,
|
|
|
|
" -C %s %s",
|
|
|
|
mythere ? mythere : where,
|
|
|
|
p->name);
|
2001-08-20 15:09:34 +00:00
|
|
|
if (add_count < 0 || add_count > maxargs - where_count) {
|
1998-09-11 07:26:58 +00:00
|
|
|
cleanup(0);
|
2000-10-22 09:53:27 +00:00
|
|
|
errx(2, __FUNCTION__ ": oops, miscounted strings!");
|
1998-09-11 07:26:58 +00:00
|
|
|
}
|
1994-12-06 00:51:50 +00:00
|
|
|
where_count += add_count;
|
|
|
|
last_chdir = (mythere ? mythere : where);
|
|
|
|
}
|
1993-08-26 01:19:55 +00:00
|
|
|
}
|
|
|
|
p = p->next;
|
|
|
|
}
|
1994-12-06 00:51:50 +00:00
|
|
|
PUSHOUT();
|
|
|
|
free(where_args);
|
1993-08-26 01:19:55 +00:00
|
|
|
}
|