2 * FreeBSD install - a package for the installation and maintainance
3 * of non-core utilities.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
17 * Routines for dealing with the packing list.
19 * $FreeBSD: src/usr.sbin/pkg_install/create/pl.c,v 1.27 2004/06/29 19:06:41 eik Exp $
20 * $DragonFly: src/usr.sbin/pkg_install/create/Attic/pl.c,v 1.3 2004/07/30 04:46:12 dillon Exp $
29 /* Add an MD5 checksum entry for a file or link */
31 add_cksum(Package *pkg, PackingList p, const char *fname)
33 char *cp = NULL, buf[33];
35 if (issymlink(fname)) {
37 char lnk[FILENAME_MAX];
39 if ((len = readlink(fname, lnk, FILENAME_MAX)) > 0)
40 cp = MD5Data((unsigned char *)lnk, len, buf);
41 } else if (isfile(fname)) {
42 /* Don't record MD5 checksum for device nodes and such */
43 cp = MD5File(fname, buf);
47 PackingList tmp = new_plist_entry();
49 tmp->name = copy_string(strconcat("MD5:", cp));
50 tmp->type = PLIST_COMMENT;
59 /* Check a list for files that require preconversion */
61 check_list(const char *home, Package *pkg)
63 const char *where = home;
64 const char *there = NULL;
65 char name[FILENAME_MAX];
68 for (p = pkg->head; p != NULL; p = p->next)
84 snprintf(name, sizeof(name), "%s/%s", there, p->name);
86 snprintf(name, sizeof(name), "%s%s/%s",
87 BaseDir && where && where[0] == '/' ? BaseDir : "", where, p->name);
89 add_cksum(pkg, p, name);
97 trylink(const char *from, const char *to)
99 if (link(from, to) == 0)
101 if (errno == ENOENT) {
102 /* try making the container directory */
103 char *cp = strrchr(to, '/');
105 vsystem("/bin/mkdir -p %.*s", cp - to,
107 return link(from, to);
112 #define STARTSTRING "/usr/bin/tar cf -"
113 #define TOOBIG(str) (int)strlen(str) + 6 + (int)strlen(home) + where_count > maxargs
114 #define PUSHOUT() /* push out string */ \
115 if (where_count > (int)sizeof(STARTSTRING)-1) { \
116 strcat(where_args, "|/usr/bin/tar xpf -"); \
117 if (system(where_args)) { \
119 errx(2, "%s: can't invoke tar pipeline", __func__); \
121 memset(where_args, 0, maxargs); \
123 strcpy(where_args, STARTSTRING); \
124 where_count = sizeof(STARTSTRING)-1; \
128 * Copy unmarked files in packing list to playpen - marked files
129 * have already been copied in an earlier pass through the list.
132 copy_plist(const char *home, Package *plist)
134 PackingList p = plist->head;
135 const char *where = home;
136 const char *there = NULL, *mythere;
138 const char *last_chdir, *root = "/";
139 int maxargs, where_count = 0, add_count;
143 maxargs = sysconf(_SC_ARG_MAX);
145 * Some slop for the tar cmd text,
148 where_args = malloc(maxargs);
151 errx(2, "%s: can't get argument list space", __func__);
154 memset(where_args, 0, maxargs);
155 strcpy(where_args, STARTSTRING);
156 where_count = sizeof(STARTSTRING)-1;
159 if (stat(".", &stb) == 0)
162 curdir = (dev_t) -1; /*
163 * It's ok if this is a valid dev_t;
164 * this is just a hint for an
169 if (p->type == PLIST_CWD)
171 else if (p->type == PLIST_SRC)
173 else if (p->type == PLIST_IGNORE)
175 else if (p->type == PLIST_FILE && !p->marked) {
176 char fn[FILENAME_MAX];
179 /* First, look for it in the "home" dir */
180 sprintf(fn, "%s/%s", home, p->name);
182 if (lstat(fn, &stb) == 0 && stb.st_dev == curdir &&
183 S_ISREG(stb.st_mode)) {
185 * If we can link it to the playpen, that avoids a copy
188 if (p->name[0] != '/') {
190 * Don't link abspn stuff--it doesn't come from
193 if (trylink(fn, p->name) == 0) {
202 if (p->name[0] == '/') {
203 add_count = snprintf(&where_args[where_count],
204 maxargs - where_count,
206 last_chdir == root ? "" : "-C /",
210 add_count = snprintf(&where_args[where_count],
211 maxargs - where_count,
213 last_chdir == home ? "" : "-C ",
214 last_chdir == home ? "" : home,
218 if (add_count < 0 || add_count >= maxargs - where_count) {
220 errx(2, "%s: oops, miscounted strings!", __func__);
222 where_count += add_count;
225 * Otherwise, try along the actual extraction path..
228 if (p->name[0] == '/')
230 else mythere = there;
232 snprintf(fn, sizeof(fn), "%s/%s", mythere, p->name);
234 snprintf(fn, sizeof(fn), "%s%s/%s",
235 BaseDir && where && where[0] == '/' ? BaseDir : "", where, p->name);
236 if (lstat(fn, &stb) == 0 && stb.st_dev == curdir &&
237 S_ISREG(stb.st_mode)) {
239 * If we can link it to the playpen, that avoids a copy
242 if (trylink(fn, p->name) == 0) {
247 if (TOOBIG(p->name)) {
250 if (last_chdir == (mythere ? mythere : where))
251 add_count = snprintf(&where_args[where_count],
252 maxargs - where_count,
255 add_count = snprintf(&where_args[where_count],
256 maxargs - where_count,
258 mythere ? mythere : where,
260 if (add_count < 0 || add_count >= maxargs - where_count) {
262 errx(2, "%s: oops, miscounted strings!", __func__);
264 where_count += add_count;
265 last_chdir = (mythere ? mythere : where);