Deleted Added
full compact
pl.c (96388) pl.c (96392)
1/*
2 * FreeBSD install - a package for the installation and maintainance
3 * of non-core utilities.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * Jordan K. Hubbard
15 * 18 July 1993
16 *
17 * Routines for dealing with the packing list.
18 *
19 */
20
21#include <sys/cdefs.h>
1/*
2 * FreeBSD install - a package for the installation and maintainance
3 * of non-core utilities.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * Jordan K. Hubbard
15 * 18 July 1993
16 *
17 * Routines for dealing with the packing list.
18 *
19 */
20
21#include <sys/cdefs.h>
22__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/create/pl.c 96388 2002-05-11 03:48:49Z alfred $");
22__FBSDID("$FreeBSD: head/usr.sbin/pkg_install/create/pl.c 96392 2002-05-11 04:17:55Z alfred $");
23
24#include "lib.h"
25#include "create.h"
26#include <errno.h>
27#include <err.h>
28#include <md5.h>
29
30/* Check a list for files that require preconversion */
31void
32check_list(const char *home, Package *pkg)
33{
34 const char *where = home;
35 const char *there = NULL;
36 char *cp, name[FILENAME_MAX], buf[33];
37 PackingList p;
38
39 for (p = pkg->head; p != NULL; p = p->next)
40 switch (p->type) {
41 case PLIST_CWD:
42 where = p->name;
43 break;
44 case PLIST_IGNORE:
45 p = p->next;
46 break;
47 case PLIST_SRC:
48 there = p->name;
49 break;
50 case PLIST_FILE:
51 cp = NULL;
52 sprintf(name, "%s/%s", there ? there : where, p->name);
53 if (issymlink(name)) {
54 int len;
55 char lnk[FILENAME_MAX];
56
57 if ((len = readlink(name, lnk, FILENAME_MAX)) > 0)
58 cp = MD5Data((unsigned char *)lnk, len, buf);
59 } else if (isfile(name)) {
60 /* Don't record MD5 checksum for device nodes and such */
61 cp = MD5File(name, buf);
62 }
63
64 if (cp != NULL) {
65 PackingList tmp = new_plist_entry();
66
67 tmp->name = copy_string(strconcat("MD5:", cp));
68 tmp->type = PLIST_COMMENT;
69 tmp->next = p->next;
70 tmp->prev = p;
71 p->next = tmp;
72 if (pkg->tail == p)
73 pkg->tail = tmp;
74 p = tmp;
75 }
76 break;
77 default:
78 break;
79 }
80}
81
82static int
83trylink(const char *from, const char *to)
84{
85 if (link(from, to) == 0)
86 return 0;
87 if (errno == ENOENT) {
88 /* try making the container directory */
89 char *cp = strrchr(to, '/');
90 if (cp)
91 vsystem("mkdir -p %.*s", cp - to,
92 to);
93 return link(from, to);
94 }
95 return -1;
96}
97
98#define STARTSTRING "tar cf -"
99#define TOOBIG(str) (int)strlen(str) + 6 + (int)strlen(home) + where_count > maxargs
100#define PUSHOUT() /* push out string */ \
101 if (where_count > (int)sizeof(STARTSTRING)-1) { \
102 strcat(where_args, "|tar xpf -"); \
103 if (system(where_args)) { \
104 cleanup(0); \
23
24#include "lib.h"
25#include "create.h"
26#include <errno.h>
27#include <err.h>
28#include <md5.h>
29
30/* Check a list for files that require preconversion */
31void
32check_list(const char *home, Package *pkg)
33{
34 const char *where = home;
35 const char *there = NULL;
36 char *cp, name[FILENAME_MAX], buf[33];
37 PackingList p;
38
39 for (p = pkg->head; p != NULL; p = p->next)
40 switch (p->type) {
41 case PLIST_CWD:
42 where = p->name;
43 break;
44 case PLIST_IGNORE:
45 p = p->next;
46 break;
47 case PLIST_SRC:
48 there = p->name;
49 break;
50 case PLIST_FILE:
51 cp = NULL;
52 sprintf(name, "%s/%s", there ? there : where, p->name);
53 if (issymlink(name)) {
54 int len;
55 char lnk[FILENAME_MAX];
56
57 if ((len = readlink(name, lnk, FILENAME_MAX)) > 0)
58 cp = MD5Data((unsigned char *)lnk, len, buf);
59 } else if (isfile(name)) {
60 /* Don't record MD5 checksum for device nodes and such */
61 cp = MD5File(name, buf);
62 }
63
64 if (cp != NULL) {
65 PackingList tmp = new_plist_entry();
66
67 tmp->name = copy_string(strconcat("MD5:", cp));
68 tmp->type = PLIST_COMMENT;
69 tmp->next = p->next;
70 tmp->prev = p;
71 p->next = tmp;
72 if (pkg->tail == p)
73 pkg->tail = tmp;
74 p = tmp;
75 }
76 break;
77 default:
78 break;
79 }
80}
81
82static int
83trylink(const char *from, const char *to)
84{
85 if (link(from, to) == 0)
86 return 0;
87 if (errno == ENOENT) {
88 /* try making the container directory */
89 char *cp = strrchr(to, '/');
90 if (cp)
91 vsystem("mkdir -p %.*s", cp - to,
92 to);
93 return link(from, to);
94 }
95 return -1;
96}
97
98#define STARTSTRING "tar cf -"
99#define TOOBIG(str) (int)strlen(str) + 6 + (int)strlen(home) + where_count > maxargs
100#define PUSHOUT() /* push out string */ \
101 if (where_count > (int)sizeof(STARTSTRING)-1) { \
102 strcat(where_args, "|tar xpf -"); \
103 if (system(where_args)) { \
104 cleanup(0); \
105 errx(2, "%s: can't invoke tar pipeline", __FUNCTION__); \
105 errx(2, "%s: can't invoke tar pipeline", __func__); \
106 } \
107 memset(where_args, 0, maxargs); \
108 last_chdir = NULL; \
109 strcpy(where_args, STARTSTRING); \
110 where_count = sizeof(STARTSTRING)-1; \
111 }
112
113/*
114 * Copy unmarked files in packing list to playpen - marked files
115 * have already been copied in an earlier pass through the list.
116 */
117void
118copy_plist(const char *home, Package *plist)
119{
120 PackingList p = plist->head;
121 const char *where = home;
122 const char *there = NULL, *mythere;
123 char *where_args;
124 const char *last_chdir, *root = "/";
125 int maxargs, where_count = 0, add_count;
126 struct stat stb;
127 dev_t curdir;
128
129 maxargs = sysconf(_SC_ARG_MAX);
130 maxargs -= 64; /*
131 * Some slop for the tar cmd text,
132 * and sh -c
133 */
134 where_args = malloc(maxargs);
135 if (!where_args) {
136 cleanup(0);
106 } \
107 memset(where_args, 0, maxargs); \
108 last_chdir = NULL; \
109 strcpy(where_args, STARTSTRING); \
110 where_count = sizeof(STARTSTRING)-1; \
111 }
112
113/*
114 * Copy unmarked files in packing list to playpen - marked files
115 * have already been copied in an earlier pass through the list.
116 */
117void
118copy_plist(const char *home, Package *plist)
119{
120 PackingList p = plist->head;
121 const char *where = home;
122 const char *there = NULL, *mythere;
123 char *where_args;
124 const char *last_chdir, *root = "/";
125 int maxargs, where_count = 0, add_count;
126 struct stat stb;
127 dev_t curdir;
128
129 maxargs = sysconf(_SC_ARG_MAX);
130 maxargs -= 64; /*
131 * Some slop for the tar cmd text,
132 * and sh -c
133 */
134 where_args = malloc(maxargs);
135 if (!where_args) {
136 cleanup(0);
137 errx(2, "%s: can't get argument list space", __FUNCTION__);
137 errx(2, "%s: can't get argument list space", __func__);
138 }
139
140 memset(where_args, 0, maxargs);
141 strcpy(where_args, STARTSTRING);
142 where_count = sizeof(STARTSTRING)-1;
143 last_chdir = 0;
144
145 if (stat(".", &stb) == 0)
146 curdir = stb.st_dev;
147 else
148 curdir = (dev_t) -1; /*
149 * It's ok if this is a valid dev_t;
150 * this is just a hint for an
151 * optimization.
152 */
153
154 while (p) {
155 if (p->type == PLIST_CWD)
156 where = p->name;
157 else if (p->type == PLIST_SRC)
158 there = p->name;
159 else if (p->type == PLIST_IGNORE)
160 p = p->next;
161 else if (p->type == PLIST_FILE && !p->marked) {
162 char fn[FILENAME_MAX];
163
164
165 /* First, look for it in the "home" dir */
166 sprintf(fn, "%s/%s", home, p->name);
167 if (fexists(fn)) {
168 if (lstat(fn, &stb) == 0 && stb.st_dev == curdir &&
169 S_ISREG(stb.st_mode)) {
170 /*
171 * If we can link it to the playpen, that avoids a copy
172 * and saves time.
173 */
174 if (p->name[0] != '/') {
175 /*
176 * Don't link abspn stuff--it doesn't come from
177 * local dir!
178 */
179 if (trylink(fn, p->name) == 0) {
180 p = p->next;
181 continue;
182 }
183 }
184 }
185 if (TOOBIG(fn)) {
186 PUSHOUT();
187 }
188 if (p->name[0] == '/') {
189 add_count = snprintf(&where_args[where_count],
190 maxargs - where_count,
191 " %s %s",
192 last_chdir == root ? "" : "-C /",
193 p->name);
194 last_chdir = root;
195 } else {
196 add_count = snprintf(&where_args[where_count],
197 maxargs - where_count,
198 " %s%s %s",
199 last_chdir == home ? "" : "-C ",
200 last_chdir == home ? "" : home,
201 p->name);
202 last_chdir = home;
203 }
204 if (add_count < 0 || add_count > maxargs - where_count) {
205 cleanup(0);
138 }
139
140 memset(where_args, 0, maxargs);
141 strcpy(where_args, STARTSTRING);
142 where_count = sizeof(STARTSTRING)-1;
143 last_chdir = 0;
144
145 if (stat(".", &stb) == 0)
146 curdir = stb.st_dev;
147 else
148 curdir = (dev_t) -1; /*
149 * It's ok if this is a valid dev_t;
150 * this is just a hint for an
151 * optimization.
152 */
153
154 while (p) {
155 if (p->type == PLIST_CWD)
156 where = p->name;
157 else if (p->type == PLIST_SRC)
158 there = p->name;
159 else if (p->type == PLIST_IGNORE)
160 p = p->next;
161 else if (p->type == PLIST_FILE && !p->marked) {
162 char fn[FILENAME_MAX];
163
164
165 /* First, look for it in the "home" dir */
166 sprintf(fn, "%s/%s", home, p->name);
167 if (fexists(fn)) {
168 if (lstat(fn, &stb) == 0 && stb.st_dev == curdir &&
169 S_ISREG(stb.st_mode)) {
170 /*
171 * If we can link it to the playpen, that avoids a copy
172 * and saves time.
173 */
174 if (p->name[0] != '/') {
175 /*
176 * Don't link abspn stuff--it doesn't come from
177 * local dir!
178 */
179 if (trylink(fn, p->name) == 0) {
180 p = p->next;
181 continue;
182 }
183 }
184 }
185 if (TOOBIG(fn)) {
186 PUSHOUT();
187 }
188 if (p->name[0] == '/') {
189 add_count = snprintf(&where_args[where_count],
190 maxargs - where_count,
191 " %s %s",
192 last_chdir == root ? "" : "-C /",
193 p->name);
194 last_chdir = root;
195 } else {
196 add_count = snprintf(&where_args[where_count],
197 maxargs - where_count,
198 " %s%s %s",
199 last_chdir == home ? "" : "-C ",
200 last_chdir == home ? "" : home,
201 p->name);
202 last_chdir = home;
203 }
204 if (add_count < 0 || add_count > maxargs - where_count) {
205 cleanup(0);
206 errx(2, "%s: oops, miscounted strings!", __FUNCTION__);
206 errx(2, "%s: oops, miscounted strings!", __func__);
207 }
208 where_count += add_count;
209 }
210 /*
211 * Otherwise, try along the actual extraction path..
212 */
213 else {
214 if (p->name[0] == '/')
215 mythere = root;
216 else mythere = there;
217 sprintf(fn, "%s/%s", mythere ? mythere : where, p->name);
218 if (lstat(fn, &stb) == 0 && stb.st_dev == curdir &&
219 S_ISREG(stb.st_mode)) {
220 /*
221 * If we can link it to the playpen, that avoids a copy
222 * and saves time.
223 */
224 if (trylink(fn, p->name) == 0) {
225 p = p->next;
226 continue;
227 }
228 }
229 if (TOOBIG(p->name)) {
230 PUSHOUT();
231 }
232 if (last_chdir == (mythere ? mythere : where))
233 add_count = snprintf(&where_args[where_count],
234 maxargs - where_count,
235 " %s", p->name);
236 else
237 add_count = snprintf(&where_args[where_count],
238 maxargs - where_count,
239 " -C %s %s",
240 mythere ? mythere : where,
241 p->name);
242 if (add_count < 0 || add_count > maxargs - where_count) {
243 cleanup(0);
207 }
208 where_count += add_count;
209 }
210 /*
211 * Otherwise, try along the actual extraction path..
212 */
213 else {
214 if (p->name[0] == '/')
215 mythere = root;
216 else mythere = there;
217 sprintf(fn, "%s/%s", mythere ? mythere : where, p->name);
218 if (lstat(fn, &stb) == 0 && stb.st_dev == curdir &&
219 S_ISREG(stb.st_mode)) {
220 /*
221 * If we can link it to the playpen, that avoids a copy
222 * and saves time.
223 */
224 if (trylink(fn, p->name) == 0) {
225 p = p->next;
226 continue;
227 }
228 }
229 if (TOOBIG(p->name)) {
230 PUSHOUT();
231 }
232 if (last_chdir == (mythere ? mythere : where))
233 add_count = snprintf(&where_args[where_count],
234 maxargs - where_count,
235 " %s", p->name);
236 else
237 add_count = snprintf(&where_args[where_count],
238 maxargs - where_count,
239 " -C %s %s",
240 mythere ? mythere : where,
241 p->name);
242 if (add_count < 0 || add_count > maxargs - where_count) {
243 cleanup(0);
244 errx(2, "%s: oops, miscounted strings!", __FUNCTION__);
244 errx(2, "%s: oops, miscounted strings!", __func__);
245 }
246 where_count += add_count;
247 last_chdir = (mythere ? mythere : where);
248 }
249 }
250 p = p->next;
251 }
252 PUSHOUT();
253 free(where_args);
254}
245 }
246 where_count += add_count;
247 last_chdir = (mythere ? mythere : where);
248 }
249 }
250 p = p->next;
251 }
252 PUSHOUT();
253 free(where_args);
254}