extract.c revision 23109
11553Srgrimes#ifndef lint
21553Srgrimesstatic const char *rcsid = "$Id: extract.c,v 1.11 1997/02/22 16:09:16 peter Exp $";
31553Srgrimes#endif
41553Srgrimes
51553Srgrimes/*
61553Srgrimes * FreeBSD install - a package for the installation and maintainance
71553Srgrimes * of non-core utilities.
81553Srgrimes *
91553Srgrimes * Redistribution and use in source and binary forms, with or without
101553Srgrimes * modification, are permitted provided that the following conditions
111553Srgrimes * are met:
121553Srgrimes * 1. Redistributions of source code must retain the above copyright
131553Srgrimes *    notice, this list of conditions and the following disclaimer.
141553Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
151553Srgrimes *    notice, this list of conditions and the following disclaimer in the
161553Srgrimes *    documentation and/or other materials provided with the distribution.
171553Srgrimes *
181553Srgrimes * Jordan K. Hubbard
191553Srgrimes * 18 July 1993
201553Srgrimes *
211553Srgrimes * This is the package extraction code for the add module.
221553Srgrimes *
231553Srgrimes */
241553Srgrimes
251553Srgrimes#include "lib.h"
261553Srgrimes#include "add.h"
271553Srgrimes
281553Srgrimes
291553Srgrimes#define STARTSTRING "tar cf - "
30133249Simp#define TOOBIG(str) ((strlen(str) + 22 + strlen(home) + where_count > maxargs) \
311553Srgrimes		|| (strlen(str) + 6 + strlen(home) + perm_count > maxargs))
321553Srgrimes
331553Srgrimes#define PUSHOUT(todir) /* push out string */ \
341553Srgrimes        if (where_count > sizeof(STARTSTRING)-1) { \
351553Srgrimes		    strcat(where_args, "|tar xf - -C "); \
361553Srgrimes		    strcat(where_args, todir); \
37		    if (system(where_args)) \
38			barf("can not invoke %d byte tar pipeline: %s", strlen(where_args), where_args); \
39		    strcpy(where_args, STARTSTRING); \
40		    where_count = sizeof(STARTSTRING)-1; \
41	} \
42	if (perm_count) { \
43		    apply_perms(todir, perm_args); \
44		    perm_args[0] = 0;\
45		    perm_count = 0; \
46	}
47
48void
49extract_plist(char *home, Package *pkg)
50{
51    PackingList p = pkg->head;
52    char *last_file;
53    char *where_args, *perm_args, *last_chdir;
54    int maxargs, where_count = 0, perm_count = 0, add_count;
55
56    maxargs = sysconf(_SC_ARG_MAX) / 2;	/* Just use half the argument space */
57    where_args = alloca(maxargs);
58    if (!where_args)
59	barf("can't get argument list space");
60    perm_args = alloca(maxargs);
61    if (!perm_args)
62	barf("can't get argument list space");
63
64    strcpy(where_args, STARTSTRING);
65    where_count = sizeof(STARTSTRING)-1;
66    perm_args[0] = 0;
67
68    last_chdir = 0;
69
70    /* Reset the world */
71    Owner = NULL;
72    Group = NULL;
73    Mode = NULL;
74    last_file = NULL;
75    Directory = home;
76
77    /* Do it */
78    while (p) {
79	char cmd[FILENAME_MAX];
80
81	switch(p->type) {
82	case PLIST_NAME:
83	    PkgName = p->name;
84	    if (Verbose)
85		printf("extract: Package name is %s\n", p->name);
86	    break;
87
88	case PLIST_FILE:
89	    last_file = p->name;
90	    if (Verbose)
91		printf("extract: %s/%s\n", Directory, p->name);
92	    if (!Fake) {
93		char try[FILENAME_MAX];
94
95		/* first try to rename it into place */
96		sprintf(try, "%s/%s", Directory, p->name);
97		if (rename(p->name, try) == 0) {
98		    /* try to add to list of perms to be changed and run in bulk. */
99		    if (p->name[0] == '/' || TOOBIG(p->name)) {
100			PUSHOUT(Directory);
101		    }
102		    add_count = snprintf(&perm_args[perm_count],
103					 maxargs - perm_count,
104					 "%s ", p->name);
105		    if (add_count > maxargs - perm_count)
106			barf("oops, miscounted strings!");
107		    perm_count += add_count;
108		}
109		else {
110		    /* rename failed, try copying with a big tar command */
111		    if (last_chdir != Directory) {
112			PUSHOUT(last_chdir);
113			last_chdir = Directory;
114		    }
115		    else if (p->name[0] == '/' || TOOBIG(p->name)) {
116			PUSHOUT(Directory);
117		    }
118		    add_count = snprintf(&where_args[where_count],
119					 maxargs - where_count,
120					 " %s", p->name);
121		    if (add_count > maxargs - where_count)
122			barf("oops, miscounted strings!");
123		    where_count += add_count;
124		    add_count = snprintf(&perm_args[perm_count],
125					 maxargs - perm_count,
126					 "%s ", p->name);
127		    if (add_count > maxargs - perm_count)
128			barf("oops, miscounted strings!");
129		    perm_count += add_count;
130		}
131	    }
132	    break;
133
134	case PLIST_CWD:
135	    if (Verbose)
136		printf("extract: CWD to %s\n", p->name);
137	    PUSHOUT(Directory);
138	    if (strcmp(p->name, ".")) {
139		if (!Fake && make_hierarchy(p->name) == FAIL)
140		    barf("Unable make directory '%s'.", p->name);
141		Directory = p->name;
142	    }
143	    else
144		Directory = home;
145	    break;
146
147	case PLIST_CMD:
148	    format_cmd(cmd, p->name, Directory, last_file);
149	    PUSHOUT(Directory);
150	    if (Verbose)
151		printf("extract: execute '%s'\n", cmd);
152	    if (!Fake && system(cmd))
153		whinge("Command '%s' failed.", cmd);
154	    break;
155
156	case PLIST_CHMOD:
157	    PUSHOUT(Directory);
158	    Mode = p->name;
159	    break;
160
161	case PLIST_CHOWN:
162	    PUSHOUT(Directory);
163	    Owner = p->name;
164	    break;
165
166	case PLIST_CHGRP:
167	    PUSHOUT(Directory);
168	    Group = p->name;
169	    break;
170
171	case PLIST_COMMENT:
172	    break;
173
174	case PLIST_IGNORE:
175	    p = p->next;
176	    break;
177	}
178	p = p->next;
179    }
180    PUSHOUT(Directory);
181}
182