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}
|