Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/archival
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- Location:
- branches/2.2.9/mindi-busybox/archival
- Files:
-
- 64 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/2.2.9/mindi-busybox/archival/Config.in
r1765 r2725 1 # DO NOT EDIT. This file is generated from Config.src 1 2 # 2 3 # For a description of the syntax of this configuration file, … … 6 7 menu "Archival Utilities" 7 8 9 10 11 config FEATURE_SEAMLESS_XZ 12 bool "Make tar, rpm, modprobe etc understand .xz data" 13 default y 14 help 15 Make tar, rpm, modprobe etc understand .xz data. 16 17 config FEATURE_SEAMLESS_LZMA 18 bool "Make tar, rpm, modprobe etc understand .lzma data" 19 default y 20 help 21 Make tar, rpm, modprobe etc understand .lzma data. 22 23 config FEATURE_SEAMLESS_BZ2 24 bool "Make tar, rpm, modprobe etc understand .bz2 data" 25 default y 26 help 27 Make tar, rpm, modprobe etc understand .bz2 data. 28 29 config FEATURE_SEAMLESS_GZ 30 bool "Make tar, rpm, modprobe etc understand .gz data" 31 default y 32 help 33 Make tar, rpm, modprobe etc understand .gz data. 34 35 config FEATURE_SEAMLESS_Z 36 bool "Make tar and gunzip understand .Z data" 37 default n 38 help 39 Make tar and gunzip understand .Z data. 40 8 41 config AR 9 42 bool "ar" 10 default n 43 default n # needs to be improved to be able to replace binutils ar 11 44 help 12 45 ar is an archival utility program used to create, modify, and 13 extract contents from archives. 46 extract contents from archives. An archive is a single file holding 14 47 a collection of other files in a structure that makes it possible to 15 48 retrieve the original individual files (called archive members). … … 30 63 31 64 config FEATURE_AR_LONG_FILENAMES 32 bool " Enable support for long filenames (not need for debs)"33 default n65 bool "Support for long filenames (not needed for debs)" 66 default y 34 67 depends on AR 35 68 help 36 By default the ar format can only store the first 15 characters of the37 filename, this option removes that limitation.69 By default the ar format can only store the first 15 characters 70 of the filename, this option removes that limitation. 38 71 It supports the GNU ar long filename method which moves multiple long 39 72 filenames into a the data section of a new ar entry. 40 73 74 config FEATURE_AR_CREATE 75 bool "Support archive creation" 76 default y 77 depends on AR 78 help 79 This enables archive creation (-c and -r) with busybox ar. 80 41 81 config BUNZIP2 42 82 bool "bunzip2" 43 default n83 default y 44 84 help 45 85 bunzip2 is a compression utility using the Burrows-Wheeler block 46 sorting text compression algorithm, and Huffman coding. 86 sorting text compression algorithm, and Huffman coding. Compression 47 87 is generally considerably better than that achieved by more 48 88 conventional LZ77/LZ78-based compressors, and approaches the 49 89 performance of the PPM family of statistical compressors. 50 90 51 The BusyBox bunzip2 applet is limited to de-compression only.52 On an x86 system, this applet adds about 11K.53 54 91 Unless you have a specific application which requires bunzip2, you 55 92 should probably say N here. 56 93 94 config BZIP2 95 bool "bzip2" 96 default y 97 help 98 bzip2 is a compression utility using the Burrows-Wheeler block 99 sorting text compression algorithm, and Huffman coding. Compression 100 is generally considerably better than that achieved by more 101 conventional LZ77/LZ78-based compressors, and approaches the 102 performance of the PPM family of statistical compressors. 103 104 Unless you have a specific application which requires bzip2, you 105 should probably say N here. 106 57 107 config CPIO 58 108 bool "cpio" 59 default n60 help 61 cpio is an archival utility program used to create, modify, and extract62 contents from archives.109 default y 110 help 111 cpio is an archival utility program used to create, modify, and 112 extract contents from archives. 63 113 cpio has 110 bytes of overheads for every stored file. 64 114 … … 66 116 "newc" or "crc" format, it cannot create or modify them. 67 117 68 Unless you have a specific application which requires cpio, you should 69 probably say N here. 118 Unless you have a specific application which requires cpio, you 119 should probably say N here. 120 121 config FEATURE_CPIO_O 122 bool "Support for archive creation" 123 default y 124 depends on CPIO 125 help 126 This implementation of cpio can create cpio archives in the "newc" 127 format only. 128 129 config FEATURE_CPIO_P 130 bool "Support for passthrough mode" 131 default y 132 depends on FEATURE_CPIO_O 133 help 134 Passthrough mode. Rarely used. 70 135 71 136 config DPKG 72 137 bool "dpkg" 73 138 default n 74 help 75 dpkg is a medium-level tool to install, build, remove and manage Debian packages. 76 77 This implementation of dpkg has a number of limitations, you should use the 78 official dpkg if possible. 139 select FEATURE_SEAMLESS_GZ 140 help 141 dpkg is a medium-level tool to install, build, remove and manage 142 Debian packages. 143 144 This implementation of dpkg has a number of limitations, 145 you should use the official dpkg if possible. 79 146 80 147 config DPKG_DEB 81 148 bool "dpkg_deb" 82 149 default n 83 help 84 dpkg-deb packs, unpacks and provides information about Debian archives. 150 select FEATURE_SEAMLESS_GZ 151 help 152 dpkg-deb unpacks and provides information about Debian archives. 85 153 86 154 This implementation of dpkg-deb cannot pack archives. 87 155 88 Unless you have a specific application which requires dpkg-deb, you should89 probablysay N here.156 Unless you have a specific application which requires dpkg-deb, 157 say N here. 90 158 91 159 config FEATURE_DPKG_DEB_EXTRACT_ONLY 92 bool " extract only (-x)"160 bool "Extract only (-x)" 93 161 default n 94 162 depends on DPKG_DEB 95 163 help 96 This reduces dpkg-deb to the equivalent of "ar -p <deb> data.tar.gz | tar -zx". 97 However it saves space as none of the extra dpkg-deb, ar or tar options are 98 needed, they are linked to internally. 164 This reduces dpkg-deb to the equivalent of 165 "ar -p <deb> data.tar.gz | tar -zx". However it saves space as none 166 of the extra dpkg-deb, ar or tar options are needed, they are linked 167 to internally. 99 168 100 169 config GUNZIP 101 170 bool "gunzip" 102 default n171 default y 103 172 help 104 173 gunzip is used to decompress archives created by gzip. … … 106 175 an archive, without decompressing it. 107 176 108 config FEATURE_GUNZIP_UNCOMPRESS109 bool "Uncompress support"110 default n111 depends on GUNZIP112 help113 Enable if you want gunzip to have the ability to decompress114 archives created by the program compress (not much115 used anymore).116 117 177 config GZIP 118 178 bool "gzip" 119 default n179 default y 120 180 help 121 181 gzip is used to compress files. 122 182 It's probably the most widely used UNIX compression program. 123 183 184 config FEATURE_GZIP_LONG_OPTIONS 185 bool "Enable long options" 186 default y 187 depends on GZIP && LONG_OPTS 188 help 189 Enable use of long options, increases size by about 106 Bytes 190 191 config LZOP 192 bool "lzop" 193 default y 194 help 195 Lzop compression/decompresion. 196 197 config LZOP_COMPR_HIGH 198 bool "lzop compression levels 7,8,9 (not very useful)" 199 default n 200 depends on LZOP 201 help 202 High levels (7,8,9) of lzop compression. These levels 203 are actually slower than gzip at equivalent compression ratios 204 and take up 3.2K of code. 205 124 206 config RPM2CPIO 125 207 bool "rpm2cpio" 126 default n127 help 128 Converts a nRPM file into a CPIO archive.208 default y 209 help 210 Converts a RPM file into a CPIO archive. 129 211 130 212 config RPM 131 213 bool "rpm" 132 default n214 default y 133 215 help 134 216 Mini RPM applet - queries and extracts RPM packages. 135 136 config FEATURE_RPM_BZ2137 bool "Enable handling of rpms with bzip2-compressed data inside"138 default n139 depends on RPM140 help141 Enable handling of rpms with bzip2-compressed data inside.142 217 143 218 config TAR 144 219 bool "tar" 145 default n220 default y 146 221 help 147 222 tar is an archiving program. It's commonly used with gzip to … … 157 232 tar archives using the `-c' option. 158 233 159 config FEATURE_TAR_BZIP2 160 bool "Enable -j option to handle .tar.bz2 files" 161 default n 162 depends on TAR 163 help 164 If you enable this option you'll be able to extract 165 archives compressed with bzip2. 166 167 config FEATURE_TAR_LZMA 168 bool "Enable -a option to handle .tar.lzma files" 169 default n 170 depends on TAR 171 help 172 If you enable this option you'll be able to extract 173 archives compressed with lzma. 234 config FEATURE_TAR_AUTODETECT 235 bool "Autodetect compressed tarballs" 236 default y 237 depends on TAR && (FEATURE_SEAMLESS_Z || FEATURE_SEAMLESS_GZ || FEATURE_SEAMLESS_BZ2 || FEATURE_SEAMLESS_LZMA || FEATURE_SEAMLESS_XZ) 238 help 239 With this option tar can automatically detect compressed 240 tarballs. Currently it works only on files (not pipes etc). 174 241 175 242 config FEATURE_TAR_FROM 176 243 bool "Enable -X (exclude from) and -T (include from) options)" 177 default n244 default y 178 245 depends on TAR 179 246 help … … 181 248 a list of files to include or exclude from an archive. 182 249 183 config FEATURE_TAR_GZIP184 bool "Enable -z option"185 default y186 depends on TAR187 help188 If you enable this option tar will be able to call gzip,189 when creating or extracting tar gziped archives.190 191 config FEATURE_TAR_COMPRESS192 bool "Enable -Z option"193 default n194 depends on TAR195 help196 If you enable this option tar will be able to call uncompress,197 when extracting .tar.Z archives.198 199 250 config FEATURE_TAR_OLDGNU_COMPATIBILITY 200 bool " Enable support for old tar header format"201 default N202 depends on TAR 251 bool "Support for old tar header format" 252 default y 253 depends on TAR || DPKG 203 254 help 204 255 This option is required to unpack archives created in … … 208 259 config FEATURE_TAR_OLDSUN_COMPATIBILITY 209 260 bool "Enable untarring of tarballs with checksums produced by buggy Sun tar" 210 default N211 depends on TAR 261 default y 262 depends on TAR || DPKG 212 263 help 213 264 This option is required to unpack archives created by some old 214 version of Sun's tar (it was calculating checksum using signed arithmetic). 215 It is said to be fixed in newer Sun tar, but "old" tarballs still exist. 265 version of Sun's tar (it was calculating checksum using signed 266 arithmetic). It is said to be fixed in newer Sun tar, but "old" 267 tarballs still exist. 216 268 217 269 config FEATURE_TAR_GNU_EXTENSIONS 218 bool " Enable support for some GNU tar extensions"219 default y 220 depends on TAR 270 bool "Support for GNU tar extensions (long filenames)" 271 default y 272 depends on TAR || DPKG 221 273 help 222 274 With this option busybox supports GNU long filenames and … … 225 277 config FEATURE_TAR_LONG_OPTIONS 226 278 bool "Enable long options" 227 default n 228 depends on TAR && GETOPT_LONG 229 help 230 Enable use of long options, increases size by about 400 Bytes 279 default y 280 depends on TAR && LONG_OPTS 281 help 282 Enable use of long options, increases size by about 400 Bytes 283 284 config FEATURE_TAR_TO_COMMAND 285 bool "Support for writing to an external program" 286 default y 287 depends on TAR && FEATURE_TAR_LONG_OPTIONS 288 help 289 If you enable this option you'll be able to instruct tar to send 290 the contents of each extracted file to the standard input of an 291 external program. 292 293 config FEATURE_TAR_UNAME_GNAME 294 bool "Enable use of user and group names" 295 default y 296 depends on TAR 297 help 298 Enables use of user and group names in tar. This affects contents 299 listings (-t) and preserving permissions when unpacking (-p). 300 +200 bytes. 301 302 config FEATURE_TAR_NOPRESERVE_TIME 303 bool "Enable -m (do not preserve time) option" 304 default y 305 depends on TAR 306 help 307 With this option busybox supports GNU tar -m 308 (do not preserve time) option. 309 310 config FEATURE_TAR_SELINUX 311 bool "Support for extracting SELinux labels" 312 default n 313 depends on TAR && SELINUX 314 help 315 With this option busybox supports restoring SELinux labels 316 when extracting files from tar archives. 231 317 232 318 config UNCOMPRESS … … 239 325 config UNLZMA 240 326 bool "unlzma" 241 default n327 default y 242 328 help 243 329 unlzma is a compression utility using the Lempel-Ziv-Markov chain 244 compression algorithm, and range coding. 330 compression algorithm, and range coding. Compression 245 331 is generally considerably better than that achieved by the bzip2 246 332 compressors. … … 253 339 254 340 config FEATURE_LZMA_FAST 255 bool "Optim ze unlzma for speed"256 default n341 bool "Optimize unlzma for speed" 342 default y 257 343 depends on UNLZMA 258 344 help 259 This option reduces decompression time by about 33% at the cost of 260 a 2K bigger binary. 345 This option reduces decompression time by about 25% at the cost of 346 a 1K bigger binary. 347 348 config LZMA 349 bool "Provide lzma alias which supports only unpacking" 350 default y 351 depends on UNLZMA 352 help 353 Enable this option if you want commands like "lzma -d" to work. 354 IOW: you'll get lzma applet, but it will always require -d option. 355 356 config UNXZ 357 bool "unxz" 358 default y 359 help 360 unxz is a unlzma successor. 361 362 config XZ 363 bool "Provide xz alias which supports only unpacking" 364 default y 365 depends on UNXZ 366 help 367 Enable this option if you want commands like "xz -d" to work. 368 IOW: you'll get xz applet, but it will always require -d option. 261 369 262 370 config UNZIP 263 371 bool "unzip" 264 default n372 default y 265 373 help 266 374 unzip will list or extract files from a ZIP archive, … … 270 378 directory of your choice. 271 379 272 comment "Common options for cpio and tar"273 depends on CPIO || TAR274 275 config FEATURE_UNARCHIVE_TAPE276 bool "Enable tape drive support"277 default n278 depends on CPIO || TAR279 help280 I don't think this is needed anymore.281 282 comment "Common options for dpkg and dpkg_deb"283 depends on DPKG || DPKG_DEB284 285 config FEATURE_DEB_TAR_GZ286 bool "gzip debian packages (normal)"287 default y if DPKG || DPKG_DEB288 depends on DPKG || DPKG_DEB289 help290 This is the default compression method inside the debian ar file.291 292 If you want compatibility with standard .deb's you should say yes here.293 294 config FEATURE_DEB_TAR_BZ2295 bool "bzip2 debian packages"296 default n297 depends on DPKG || DPKG_DEB298 help299 This allows dpkg and dpkg-deb to extract deb's that are compressed internally300 with bzip2 instead of gzip.301 302 You only want this if you are creating your own custom debian packages that303 use an internal control.tar.bz2 or data.tar.bz2.304 305 config FEATURE_DEB_TAR_LZMA306 bool "lzma debian packages"307 default n308 depends on DPKG || DPKG_DEB309 help310 This allows dpkg and dpkg-deb to extract deb's that are compressed311 internally with lzma instead of gzip.312 313 You only want this if you are creating your own custom debian314 packages that use an internal control.tar.lzma or data.tar.lzma.315 316 380 endmenu -
branches/2.2.9/mindi-busybox/archival/Kbuild
r1765 r2725 1 # DO NOT EDIT. This file is generated from Kbuild.src 1 2 # Makefile for busybox 2 3 # 3 4 # Copyright (C) 1999-2005 by Erik Andersen <andersen@codepoet.org> 4 5 # 5 # Licensed under the GPL v2, see the file LICENSE in this tarball.6 # Licensed under GPLv2, see file LICENSE in this source tree. 6 7 7 libs-y += lib unarchive/8 libs-y += libarchive/ 8 9 9 10 lib-y:= 11 12 13 10 14 lib-$(CONFIG_AR) += ar.o 11 lib-$(CONFIG_BUNZIP2) += bbunzip.o12 lib-$(CONFIG_UNLZMA) += bbunzip.o13 15 lib-$(CONFIG_CPIO) += cpio.o 14 16 lib-$(CONFIG_DPKG) += dpkg.o 15 17 lib-$(CONFIG_DPKG_DEB) += dpkg_deb.o 16 lib-$(CONFIG_GUNZIP) += bbunzip.o17 lib-$(CONFIG_GZIP) += gzip.o bbunzip.o18 18 lib-$(CONFIG_RPM2CPIO) += rpm2cpio.o 19 19 lib-$(CONFIG_RPM) += rpm.o 20 20 lib-$(CONFIG_TAR) += tar.o 21 lib-$(CONFIG_UNZIP) += unzip.o 22 23 lib-$(CONFIG_LZOP) += lzop.o bbunzip.o 24 lib-$(CONFIG_GZIP) += gzip.o bbunzip.o 25 lib-$(CONFIG_BZIP2) += bzip2.o bbunzip.o 26 27 lib-$(CONFIG_UNXZ) += bbunzip.o 28 lib-$(CONFIG_UNLZMA) += bbunzip.o 29 lib-$(CONFIG_BUNZIP2) += bbunzip.o 30 lib-$(CONFIG_GUNZIP) += bbunzip.o 21 31 lib-$(CONFIG_UNCOMPRESS) += bbunzip.o 22 lib-$(CONFIG_UNZIP) += unzip.o -
branches/2.2.9/mindi-busybox/archival/ar.c
r1765 r2725 4 4 * 5 5 * Copyright (C) 2000 by Glenn McGrath 6 * Written by Glenn McGrath <bug1@iinet.net.au> 1 June 20007 6 * 8 7 * Based in part on BusyBox tar, Debian dpkg-deb and GNU ar. 9 8 * 10 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 9 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 10 * 11 * Archive creation support: 12 * Copyright (C) 2010 Nokia Corporation. All rights reserved. 13 * Written by Alexander Shishkin. 11 14 * 12 15 * There is no single standard to adhere to so ar may not portable … … 16 19 17 20 #include "libbb.h" 18 #include "unarchive.h" 19 20 static void header_verbose_list_ar(const file_header_t *file_header) 21 #include "archive.h" 22 #include "ar.h" 23 24 #if ENABLE_FEATURE_AR_CREATE 25 /* filter out entries with same names as specified on the command line */ 26 static char FAST_FUNC filter_replaceable(archive_handle_t *handle) 27 { 28 if (find_list_entry(handle->accept, handle->file_header->name)) 29 return EXIT_FAILURE; 30 31 return EXIT_SUCCESS; 32 } 33 34 static void output_ar_header(archive_handle_t *handle) 35 { 36 /* GNU ar 2.19.51.0.14 creates malformed archives 37 * if input files are >10G. It also truncates files >4GB 38 * (uses "size mod 4G"). We abort in this case: 39 * We could add support for up to 10G files, but this is unlikely to be useful. 40 * Note that unpacking side limits all fields to "unsigned int" data type, 41 * and treats "all ones" as an error indicator. Thus max we allow here is UINT_MAX-1. 42 */ 43 enum { 44 /* for 2nd field: mtime */ 45 MAX11CHARS = UINT_MAX > 0xffffffff ? (unsigned)99999999999 : UINT_MAX-1, 46 /* for last field: filesize */ 47 MAX10CHARS = UINT_MAX > 0xffffffff ? (unsigned)9999999999 : UINT_MAX-1, 48 }; 49 50 struct file_header_t *fh = handle->file_header; 51 52 if (handle->offset & 1) { 53 xwrite(handle->src_fd, "\n", 1); 54 handle->offset++; 55 } 56 57 /* Careful! The widths should be exact. Fields must be separated */ 58 if (sizeof(off_t) > 4 && fh->size > (off_t)MAX10CHARS) { 59 bb_error_msg_and_die("'%s' is bigger than ar can handle", fh->name); 60 } 61 fdprintf(handle->src_fd, "%-16.16s%-12lu%-6u%-6u%-8o%-10"OFF_FMT"u`\n", 62 fh->name, 63 (sizeof(time_t) > 4 && fh->mtime > MAX11CHARS) ? (long)0 : (long)fh->mtime, 64 fh->uid > 99999 ? 0 : (int)fh->uid, 65 fh->gid > 99999 ? 0 : (int)fh->gid, 66 (int)fh->mode & 07777777, 67 fh->size 68 ); 69 70 handle->offset += AR_HEADER_LEN; 71 } 72 73 /* 74 * when replacing files in an existing archive, copy from the the 75 * original archive those files that are to be left intact 76 */ 77 static void FAST_FUNC copy_data(archive_handle_t *handle) 78 { 79 archive_handle_t *out_handle = handle->ar__out; 80 struct file_header_t *fh = handle->file_header; 81 82 out_handle->file_header = fh; 83 output_ar_header(out_handle); 84 85 bb_copyfd_exact_size(handle->src_fd, out_handle->src_fd, fh->size); 86 out_handle->offset += fh->size; 87 } 88 89 static int write_ar_header(archive_handle_t *handle) 90 { 91 char *fn; 92 char fn_h[17]; /* 15 + "/" + NUL */ 93 struct stat st; 94 int fd; 95 96 fn = llist_pop(&handle->accept); 97 if (!fn) 98 return -1; 99 100 xstat(fn, &st); 101 102 handle->file_header->mtime = st.st_mtime; 103 handle->file_header->uid = st.st_uid; 104 handle->file_header->gid = st.st_gid; 105 handle->file_header->mode = st.st_mode; 106 handle->file_header->size = st.st_size; 107 handle->file_header->name = fn_h; 108 //TODO: if ENABLE_FEATURE_AR_LONG_FILENAMES... 109 sprintf(fn_h, "%.15s/", bb_basename(fn)); 110 111 output_ar_header(handle); 112 113 fd = xopen(fn, O_RDONLY); 114 bb_copyfd_exact_size(fd, handle->src_fd, st.st_size); 115 close(fd); 116 handle->offset += st.st_size; 117 118 return 0; 119 } 120 121 static int write_ar_archive(archive_handle_t *handle) 122 { 123 struct stat st; 124 archive_handle_t *out_handle; 125 126 xfstat(handle->src_fd, &st, handle->ar__name); 127 128 /* if archive exists, create a new handle for output. 129 * we create it in place of the old one. 130 */ 131 if (st.st_size != 0) { 132 out_handle = init_handle(); 133 xunlink(handle->ar__name); 134 out_handle->src_fd = xopen(handle->ar__name, O_WRONLY | O_CREAT | O_TRUNC); 135 out_handle->accept = handle->accept; 136 } else { 137 out_handle = handle; 138 } 139 140 handle->ar__out = out_handle; 141 142 xwrite(out_handle->src_fd, AR_MAGIC "\n", AR_MAGIC_LEN + 1); 143 out_handle->offset += AR_MAGIC_LEN + 1; 144 145 /* skip to the end of the archive if we have to append stuff */ 146 if (st.st_size != 0) { 147 handle->filter = filter_replaceable; 148 handle->action_data = copy_data; 149 unpack_ar_archive(handle); 150 } 151 152 while (write_ar_header(out_handle) == 0) 153 continue; 154 155 /* optional, since we exit right after we return */ 156 if (ENABLE_FEATURE_CLEAN_UP) { 157 close(handle->src_fd); 158 if (out_handle->src_fd != handle->src_fd) 159 close(out_handle->src_fd); 160 } 161 162 return EXIT_SUCCESS; 163 } 164 #endif /* FEATURE_AR_CREATE */ 165 166 static void FAST_FUNC header_verbose_list_ar(const file_header_t *file_header) 21 167 { 22 168 const char *mode = bb_mode_string(file_header->mode); … … 27 173 memmove(&mtime[17], &mtime[20], 4); 28 174 mtime[21] = '\0'; 29 printf("%s %d/%d%7d %s %s\n", &mode[1], file_header->uid, file_header->gid, 30 (int) file_header->size, &mtime[4], file_header->name); 31 } 32 33 #define AR_CTX_PRINT 0x01 34 #define AR_CTX_LIST 0x02 35 #define AR_CTX_EXTRACT 0x04 36 #define AR_OPT_PRESERVE_DATE 0x08 37 #define AR_OPT_VERBOSE 0x10 38 #define AR_OPT_CREATE 0x20 39 #define AR_OPT_INSERT 0x40 40 41 int ar_main(int argc, char **argv); 42 int ar_main(int argc, char **argv) 43 { 44 static const char msg_unsupported_err[] ALIGN1 = 45 "archive %s is not supported"; 46 175 printf("%s %u/%u%7"OFF_FMT"u %s %s\n", &mode[1], 176 (int)file_header->uid, (int)file_header->gid, 177 file_header->size, 178 &mtime[4], file_header->name 179 ); 180 } 181 182 #define AR_OPT_VERBOSE (1 << 0) 183 #define AR_OPT_PRESERVE_DATE (1 << 1) 184 /* "ar r" implies create, but warns about it. c suppresses warning. 185 * bbox accepts but ignores it: */ 186 #define AR_OPT_CREATE (1 << 2) 187 188 #define AR_CMD_PRINT (1 << 3) 189 #define FIRST_CMD AR_CMD_PRINT 190 #define AR_CMD_LIST (1 << 4) 191 #define AR_CMD_EXTRACT (1 << 5) 192 #define AR_CMD_INSERT (1 << 6) 193 194 int ar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 195 int ar_main(int argc UNUSED_PARAM, char **argv) 196 { 47 197 archive_handle_t *archive_handle; 48 unsigned opt; 49 char magic[8]; 198 unsigned opt, t; 50 199 51 200 archive_handle = init_handle(); 52 201 53 /* Prepend '-' to the first argument if required */ 54 opt_complementary = "--:p:t:x:-1:p--tx:t--px:x--pt"; 55 opt = getopt32(argv, "ptxovcr"); 56 57 if (opt & AR_CTX_PRINT) { 202 /* --: prepend '-' to the first argument if required */ 203 /* -1: at least one param is reqd */ 204 /* one of p,t,x[,r] is required */ 205 opt_complementary = "--:-1:p:t:x"IF_FEATURE_AR_CREATE(":r"); 206 opt = getopt32(argv, "voc""ptx"IF_FEATURE_AR_CREATE("r")); 207 argv += optind; 208 209 t = opt / FIRST_CMD; 210 if (t & (t-1)) /* more than one of p,t,x[,r] are specified */ 211 bb_show_usage(); 212 213 if (opt & AR_CMD_PRINT) { 58 214 archive_handle->action_data = data_extract_to_stdout; 59 215 } 60 if (opt & AR_C TX_LIST) {216 if (opt & AR_CMD_LIST) { 61 217 archive_handle->action_header = header_list; 62 218 } 63 if (opt & AR_C TX_EXTRACT) {219 if (opt & AR_CMD_EXTRACT) { 64 220 archive_handle->action_data = data_extract_all; 65 221 } 66 222 if (opt & AR_OPT_PRESERVE_DATE) { 67 archive_handle-> flags |= ARCHIVE_PRESERVE_DATE;223 archive_handle->ah_flags |= ARCHIVE_RESTORE_DATE; 68 224 } 69 225 if (opt & AR_OPT_VERBOSE) { 70 226 archive_handle->action_header = header_verbose_list_ar; 71 227 } 72 if (opt & AR_OPT_CREATE) { 73 bb_error_msg_and_die(msg_unsupported_err, "creation");74 } 75 if (opt & AR_OPT_INSERT) {76 bb_error_msg_and_die(msg_unsupported_err, "insertion");77 }78 79 archive_handle->src_fd = xopen(argv[optind++], O_RDONLY);80 81 while (optind < argc) {228 #if ENABLE_FEATURE_AR_CREATE 229 archive_handle->ar__name = *argv; 230 #endif 231 archive_handle->src_fd = xopen(*argv++, 232 (opt & AR_CMD_INSERT) 233 ? O_RDWR | O_CREAT 234 : O_RDONLY 235 ); 236 237 if (*argv) 82 238 archive_handle->filter = filter_accept_list; 83 llist_add_to(&(archive_handle->accept), argv[optind++]); 84 } 85 86 xread(archive_handle->src_fd, magic, 7); 87 if (strncmp(magic, "!<arch>", 7) != 0) { 88 bb_error_msg_and_die("invalid ar magic"); 89 } 90 archive_handle->offset += 7; 91 92 while (get_header_ar(archive_handle) == EXIT_SUCCESS) 93 continue; 239 while (*argv) { 240 llist_add_to_end(&archive_handle->accept, *argv++); 241 } 242 243 #if ENABLE_FEATURE_AR_CREATE 244 if (opt & AR_CMD_INSERT) 245 return write_ar_archive(archive_handle); 246 #endif 247 248 unpack_ar_archive(archive_handle); 94 249 95 250 return EXIT_SUCCESS; -
branches/2.2.9/mindi-busybox/archival/bbunzip.c
r1765 r2725 1 1 /* vi: set sw=4 ts=4: */ 2 2 /* 3 * Common code for gunzip-like applets 4 * 5 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 6 */ 7 3 * Common code for gunzip-like applets 4 * 5 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 */ 8 7 #include "libbb.h" 9 #include " unarchive.h"8 #include "archive.h" 10 9 11 10 enum { 12 OPT_STDOUT = 0x1,13 OPT_FORCE = 0x2,14 /* gunzip only: */15 OPT_VERBOSE = 0x4,16 OPT_DECOMPRESS = 0x8,17 OPT_TEST = 0x10,11 OPT_STDOUT = 1 << 0, 12 OPT_FORCE = 1 << 1, 13 /* only some decompressors: */ 14 OPT_VERBOSE = 1 << 2, 15 OPT_DECOMPRESS = 1 << 3, 16 OPT_TEST = 1 << 4, 18 17 }; 19 18 … … 29 28 } 30 29 31 int bbunpack(char **argv, 32 char* (*make_new_name)(char *filename), 33 USE_DESKTOP(long long) int (*unpacker)(void) 30 char* FAST_FUNC append_ext(char *filename, const char *expected_ext) 31 { 32 return xasprintf("%s.%s", filename, expected_ext); 33 } 34 35 int FAST_FUNC bbunpack(char **argv, 36 IF_DESKTOP(long long) int FAST_FUNC (*unpacker)(unpack_info_t *info), 37 char* FAST_FUNC (*make_new_name)(char *filename, const char *expected_ext), 38 const char *expected_ext 34 39 ) 35 40 { 36 41 struct stat stat_buf; 37 USE_DESKTOP(long long) int status;42 IF_DESKTOP(long long) int status; 38 43 char *filename, *new_name; 39 44 smallint exitcode = 0; 45 unpack_info_t info; 40 46 41 47 do { … … 50 56 if (filename) { 51 57 if (stat(filename, &stat_buf) != 0) { 52 bb_ perror_msg("%s",filename);58 bb_simple_perror_msg(filename); 53 59 err: 54 60 exitcode = 1; … … 69 75 /* Open dst if we are going to unpack to file */ 70 76 if (filename) { 71 new_name = make_new_name(filename );77 new_name = make_new_name(filename, expected_ext); 72 78 if (!new_name) { 73 79 bb_error_msg("%s: unknown suffix - ignored", filename); 74 80 goto err; 75 81 } 82 83 /* -f: overwrite existing output files */ 84 if (option_mask32 & OPT_FORCE) { 85 unlink(new_name); 86 } 87 76 88 /* O_EXCL: "real" bunzip2 doesn't overwrite files */ 77 /* GNU gunzip goes not bail out, but goes to next file */89 /* GNU gunzip does not bail out, but goes to next file */ 78 90 if (open_to_or_warn(STDOUT_FILENO, new_name, O_WRONLY | O_CREAT | O_EXCL, 79 91 stat_buf.st_mode)) … … 87 99 } 88 100 89 status = unpacker(); 101 /* memset(&info, 0, sizeof(info)); */ 102 info.mtime = 0; /* so far it has one member only */ 103 status = unpacker(&info); 90 104 if (status < 0) 91 105 exitcode = 1; 106 xclose(STDOUT_FILENO); /* with error check! */ 92 107 93 108 if (filename) { 94 109 char *del = new_name; 95 110 if (status >= 0) { 96 /* TODO: restore user/group/times here? */ 111 /* TODO: restore other things? */ 112 if (info.mtime) { 113 struct timeval times[2]; 114 115 times[1].tv_sec = times[0].tv_sec = info.mtime; 116 times[1].tv_usec = times[0].tv_usec = 0; 117 /* Note: we closed it first. 118 * On some systems calling utimes 119 * then closing resets the mtime 120 * back to current time. */ 121 utimes(new_name, times); /* ignoring errors */ 122 } 123 97 124 /* Delete _compressed_ file */ 98 125 del = filename; … … 120 147 } 121 148 122 #if ENABLE_BUNZIP2 || ENABLE_UNLZMA || ENABLE_UNCOMPRESS 123 124 static 125 char* make_new_name_generic(char *filename, const char *expected_ext) 149 #if ENABLE_UNCOMPRESS || ENABLE_BUNZIP2 || ENABLE_UNLZMA || ENABLE_UNXZ 150 static 151 char* FAST_FUNC make_new_name_generic(char *filename, const char *expected_ext) 126 152 { 127 153 char *extension = strrchr(filename, '.'); … … 134 160 return filename; 135 161 } 136 137 #endif 138 139 140 /* 141 * Modified for busybox by Glenn McGrath <bug1@iinet.net.au> 142 * Added support output to stdout by Thomas Lundquist <thomasez@zelow.no> 143 * 144 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. 145 */ 146 147 #if ENABLE_BUNZIP2 148 149 static 150 char* make_new_name_bunzip2(char *filename) 151 { 152 return make_new_name_generic(filename, "bz2"); 153 } 154 155 static 156 USE_DESKTOP(long long) int unpack_bunzip2(void) 157 { 158 return unpack_bz2_stream(STDIN_FILENO, STDOUT_FILENO); 159 } 160 161 int bunzip2_main(int argc, char **argv); 162 int bunzip2_main(int argc, char **argv) 162 #endif 163 164 165 /* 166 * Uncompress applet for busybox (c) 2002 Glenn McGrath 167 * 168 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 169 */ 170 #if ENABLE_UNCOMPRESS 171 static 172 IF_DESKTOP(long long) int FAST_FUNC unpack_uncompress(unpack_info_t *info UNUSED_PARAM) 173 { 174 IF_DESKTOP(long long) int status = -1; 175 176 if ((xread_char(STDIN_FILENO) != 0x1f) || (xread_char(STDIN_FILENO) != 0x9d)) { 177 bb_error_msg("invalid magic"); 178 } else { 179 status = unpack_Z_stream(STDIN_FILENO, STDOUT_FILENO); 180 } 181 return status; 182 } 183 int uncompress_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 184 int uncompress_main(int argc UNUSED_PARAM, char **argv) 163 185 { 164 186 getopt32(argv, "cf"); 165 187 argv += optind; 166 if (applet_name[2] == 'c') 167 option_mask32 |= OPT_STDOUT; 168 169 return bbunpack(argv, make_new_name_bunzip2, unpack_bunzip2); 170 } 171 188 189 return bbunpack(argv, unpack_uncompress, make_new_name_generic, "Z"); 190 } 172 191 #endif 173 192 … … 186 205 * 187 206 * General cleanup to better adhere to the style guide and make use of standard 188 * busybox functions by Glenn McGrath <bug1@iinet.net.au>189 * 190 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.207 * busybox functions by Glenn McGrath 208 * 209 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 191 210 * 192 211 * gzip (GNU zip) -- compress files with zip algorithm and 'compress' interface … … 200 219 * See the file algorithm.doc for the compression algorithms and file formats. 201 220 */ 202 203 221 #if ENABLE_GUNZIP 204 205 static 206 char* make_new_name_gunzip(char *filename) 222 static 223 char* FAST_FUNC make_new_name_gunzip(char *filename, const char *expected_ext UNUSED_PARAM) 207 224 { 208 225 char *extension = strrchr(filename, '.'); … … 213 230 extension++; 214 231 if (strcmp(extension, "tgz" + 1) == 0 215 #if ENABLE_FEATURE_ GUNZIP_UNCOMPRESS216 || strcmp(extension, "Z") == 0232 #if ENABLE_FEATURE_SEAMLESS_Z 233 || (extension[0] == 'Z' && extension[1] == '\0') 217 234 #endif 218 235 ) { … … 228 245 return filename; 229 246 } 230 231 static 232 USE_DESKTOP(long long) int unpack_gunzip(void) 233 { 234 USE_DESKTOP(long long) int status = -1; 247 static 248 IF_DESKTOP(long long) int FAST_FUNC unpack_gunzip(unpack_info_t *info) 249 { 250 IF_DESKTOP(long long) int status = -1; 235 251 236 252 /* do the decompression, and cleanup */ … … 239 255 240 256 magic2 = xread_char(STDIN_FILENO); 241 if (ENABLE_FEATURE_ GUNZIP_UNCOMPRESS&& magic2 == 0x9d) {242 status = un compress(STDIN_FILENO, STDOUT_FILENO);257 if (ENABLE_FEATURE_SEAMLESS_Z && magic2 == 0x9d) { 258 status = unpack_Z_stream(STDIN_FILENO, STDOUT_FILENO); 243 259 } else if (magic2 == 0x8b) { 244 check_header_gzip_or_die(STDIN_FILENO); 245 status = unpack_gz_stream(STDIN_FILENO, STDOUT_FILENO); 260 status = unpack_gz_stream_with_info(STDIN_FILENO, STDOUT_FILENO, info); 246 261 } else { 247 262 goto bad_magic; … … 257 272 return status; 258 273 } 259 260 int gunzip_main(int argc, char **argv); 261 int gunzip_main(int argc, char **argv) 262 { 263 getopt32(argv, "cfvdt"); 274 /* 275 * Linux kernel build uses gzip -d -n. We accept and ignore it. 276 * Man page says: 277 * -n --no-name 278 * gzip: do not save the original file name and time stamp. 279 * (The original name is always saved if the name had to be truncated.) 280 * gunzip: do not restore the original file name/time even if present 281 * (remove only the gzip suffix from the compressed file name). 282 * This option is the default when decompressing. 283 * -N --name 284 * gzip: always save the original file name and time stamp (this is the default) 285 * gunzip: restore the original file name and time stamp if present. 286 */ 287 int gunzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 288 int gunzip_main(int argc UNUSED_PARAM, char **argv) 289 { 290 getopt32(argv, "cfvdtn"); 264 291 argv += optind; 265 292 /* if called as zcat */ … … 267 294 option_mask32 |= OPT_STDOUT; 268 295 269 return bbunpack(argv, make_new_name_gunzip, unpack_gunzip); 270 } 271 296 return bbunpack(argv, unpack_gunzip, make_new_name_gunzip, /*unused:*/ NULL); 297 } 298 #endif 299 300 301 /* 302 * Modified for busybox by Glenn McGrath 303 * Added support output to stdout by Thomas Lundquist <thomasez@zelow.no> 304 * 305 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 306 */ 307 //usage:#define bunzip2_trivial_usage 308 //usage: "[-cf] [FILE]..." 309 //usage:#define bunzip2_full_usage "\n\n" 310 //usage: "Decompress FILEs (or stdin)\n" 311 //usage: "\nOptions:" 312 //usage: "\n -c Write to stdout" 313 //usage: "\n -f Force" 314 //usage:#define bzcat_trivial_usage 315 //usage: "FILE" 316 //usage:#define bzcat_full_usage "\n\n" 317 //usage: "Decompress to stdout" 318 //applet:IF_BUNZIP2(APPLET(bunzip2, _BB_DIR_USR_BIN, _BB_SUID_DROP)) 319 //applet:IF_BUNZIP2(APPLET_ODDNAME(bzcat, bunzip2, _BB_DIR_USR_BIN, _BB_SUID_DROP, bzcat)) 320 #if ENABLE_BUNZIP2 321 static 322 IF_DESKTOP(long long) int FAST_FUNC unpack_bunzip2(unpack_info_t *info UNUSED_PARAM) 323 { 324 return unpack_bz2_stream_prime(STDIN_FILENO, STDOUT_FILENO); 325 } 326 int bunzip2_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 327 int bunzip2_main(int argc UNUSED_PARAM, char **argv) 328 { 329 getopt32(argv, "cfvdt"); 330 argv += optind; 331 if (applet_name[2] == 'c') /* bzcat */ 332 option_mask32 |= OPT_STDOUT; 333 334 return bbunpack(argv, unpack_bunzip2, make_new_name_generic, "bz2"); 335 } 272 336 #endif 273 337 … … 279 343 * Based on bunzip.c from busybox 280 344 * 281 * Licensed under GPL v2, see file LICENSE in this tarball for details. 282 */ 283 345 * Licensed under GPLv2, see file LICENSE in this source tree. 346 */ 284 347 #if ENABLE_UNLZMA 285 286 static 287 char* make_new_name_unlzma(char *filename) 288 { 289 return make_new_name_generic(filename, "lzma"); 290 } 291 292 static 293 USE_DESKTOP(long long) int unpack_unlzma(void) 348 static 349 IF_DESKTOP(long long) int FAST_FUNC unpack_unlzma(unpack_info_t *info UNUSED_PARAM) 294 350 { 295 351 return unpack_lzma_stream(STDIN_FILENO, STDOUT_FILENO); 296 352 } 297 298 int unlzma_main(int argc, char **argv); 299 int unlzma_main(int argc, char **argv) 300 { 301 getopt32(argv, "cf"); 353 int unlzma_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 354 int unlzma_main(int argc UNUSED_PARAM, char **argv) 355 { 356 IF_LZMA(int opts =) getopt32(argv, "cfvdt"); 357 # if ENABLE_LZMA 358 /* lzma without -d or -t? */ 359 if (applet_name[2] == 'm' && !(opts & (OPT_DECOMPRESS|OPT_TEST))) 360 bb_show_usage(); 361 # endif 362 /* lzcat? */ 363 if (applet_name[2] == 'c') 364 option_mask32 |= OPT_STDOUT; 365 302 366 argv += optind; 303 /* lzmacat? */ 304 if (applet_name[4] == 'c') 367 return bbunpack(argv, unpack_unlzma, make_new_name_generic, "lzma"); 368 } 369 #endif 370 371 372 #if ENABLE_UNXZ 373 static 374 IF_DESKTOP(long long) int FAST_FUNC unpack_unxz(unpack_info_t *info UNUSED_PARAM) 375 { 376 struct { 377 uint32_t v1; 378 uint16_t v2; 379 } magic; 380 xread(STDIN_FILENO, &magic, 6); 381 if (magic.v1 != XZ_MAGIC1a || magic.v2 != XZ_MAGIC2a) { 382 bb_error_msg("invalid magic"); 383 return -1; 384 } 385 return unpack_xz_stream(STDIN_FILENO, STDOUT_FILENO); 386 } 387 int unxz_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 388 int unxz_main(int argc UNUSED_PARAM, char **argv) 389 { 390 IF_XZ(int opts =) getopt32(argv, "cfvdt"); 391 # if ENABLE_XZ 392 /* xz without -d or -t? */ 393 if (applet_name[2] == '\0' && !(opts & (OPT_DECOMPRESS|OPT_TEST))) 394 bb_show_usage(); 395 # endif 396 /* xzcat? */ 397 if (applet_name[2] == 'c') 305 398 option_mask32 |= OPT_STDOUT; 306 399 307 return bbunpack(argv, make_new_name_unlzma, unpack_unlzma);308 }309 310 #endif311 312 313 /*314 * Uncompress applet for busybox (c) 2002 Glenn McGrath315 *316 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.317 */318 319 #if ENABLE_UNCOMPRESS320 321 static322 char* make_new_name_uncompress(char *filename)323 {324 return make_new_name_generic(filename, "Z");325 }326 327 static328 USE_DESKTOP(long long) int unpack_uncompress(void)329 {330 USE_DESKTOP(long long) int status = -1;331 332 if ((xread_char(STDIN_FILENO) != 0x1f) || (xread_char(STDIN_FILENO) != 0x9d)) {333 bb_error_msg("invalid magic");334 } else {335 status = uncompress(STDIN_FILENO, STDOUT_FILENO);336 }337 return status;338 }339 340 int uncompress_main(int argc, char **argv);341 int uncompress_main(int argc, char **argv)342 {343 getopt32(argv, "cf");344 400 argv += optind; 345 346 return bbunpack(argv, make_new_name_uncompress, unpack_uncompress); 347 } 348 349 #endif 401 return bbunpack(argv, unpack_unxz, make_new_name_generic, "xz"); 402 } 403 #endif -
branches/2.2.9/mindi-busybox/archival/cpio.c
r1765 r2725 5 5 * Copyright (C) 2001 by Glenn McGrath 6 6 * 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 8 * 9 9 * Limitations: 10 * 11 * 10 * Doesn't check CRC's 11 * Only supports new ASCII and CRC formats 12 12 * 13 13 */ 14 14 #include "libbb.h" 15 #include "unarchive.h" 16 17 #define CPIO_OPT_EXTRACT 0x01 18 #define CPIO_OPT_TEST 0x02 19 #define CPIO_OPT_UNCONDITIONAL 0x04 20 #define CPIO_OPT_VERBOSE 0x08 21 #define CPIO_OPT_FILE 0x10 22 #define CPIO_OPT_CREATE_LEADING_DIR 0x20 23 #define CPIO_OPT_PRESERVE_MTIME 0x40 24 25 int cpio_main(int argc, char **argv); 26 int cpio_main(int argc, char **argv) 15 #include "archive.h" 16 17 /* GNU cpio 2.9 --help (abridged): 18 19 Modes: 20 -t, --list List the archive 21 -i, --extract Extract files from an archive 22 -o, --create Create the archive 23 -p, --pass-through Copy-pass mode [was ist das?!] 24 25 Options valid in any mode: 26 --block-size=SIZE I/O block size = SIZE * 512 bytes 27 -B I/O block size = 5120 bytes 28 -c Use the old portable (ASCII) archive format 29 -C, --io-size=NUMBER I/O block size in bytes 30 -f, --nonmatching Only copy files that do not match given pattern 31 -F, --file=FILE Use FILE instead of standard input or output 32 -H, --format=FORMAT Use given archive FORMAT 33 -M, --message=STRING Print STRING when the end of a volume of the 34 backup media is reached 35 -n, --numeric-uid-gid If -v, show numeric UID and GID 36 --quiet Do not print the number of blocks copied 37 --rsh-command=COMMAND Use remote COMMAND instead of rsh 38 -v, --verbose Verbosely list the files processed 39 -V, --dot Print a "." for each file processed 40 -W, --warning=FLAG Control warning display: 'none','truncate','all'; 41 multiple options accumulate 42 43 Options valid only in --extract mode: 44 -b, --swap Swap both halfwords of words and bytes of 45 halfwords in the data (equivalent to -sS) 46 -r, --rename Interactively rename files 47 -s, --swap-bytes Swap the bytes of each halfword in the files 48 -S, --swap-halfwords Swap the halfwords of each word (4 bytes) 49 --to-stdout Extract files to standard output 50 -E, --pattern-file=FILE Read additional patterns specifying filenames to 51 extract or list from FILE 52 --only-verify-crc Verify CRC's, don't actually extract the files 53 54 Options valid only in --create mode: 55 -A, --append Append to an existing archive 56 -O FILE File to use instead of standard output 57 58 Options valid only in --pass-through mode: 59 -l, --link Link files instead of copying them, when possible 60 61 Options valid in --extract and --create modes: 62 --absolute-filenames Do not strip file system prefix components from 63 the file names 64 --no-absolute-filenames Create all files relative to the current dir 65 66 Options valid in --create and --pass-through modes: 67 -0, --null A list of filenames is terminated by a NUL 68 -a, --reset-access-time Reset the access times of files after reading them 69 -I FILE File to use instead of standard input 70 -L, --dereference Dereference symbolic links (copy the files 71 that they point to instead of copying the links) 72 -R, --owner=[USER][:.][GROUP] Set owner of created files 73 74 Options valid in --extract and --pass-through modes: 75 -d, --make-directories Create leading directories where needed 76 -m, --preserve-modification-time Retain mtime when creating files 77 --no-preserve-owner Do not change the ownership of the files 78 --sparse Write files with blocks of zeros as sparse files 79 -u, --unconditional Replace all files unconditionally 80 */ 81 enum { 82 CPIO_OPT_EXTRACT = (1 << 0), 83 CPIO_OPT_TEST = (1 << 1), 84 CPIO_OPT_NUL_TERMINATED = (1 << 2), 85 CPIO_OPT_UNCONDITIONAL = (1 << 3), 86 CPIO_OPT_VERBOSE = (1 << 4), 87 CPIO_OPT_CREATE_LEADING_DIR = (1 << 5), 88 CPIO_OPT_PRESERVE_MTIME = (1 << 6), 89 CPIO_OPT_DEREF = (1 << 7), 90 CPIO_OPT_FILE = (1 << 8), 91 OPTBIT_FILE = 8, 92 IF_FEATURE_CPIO_O(OPTBIT_CREATE ,) 93 IF_FEATURE_CPIO_O(OPTBIT_FORMAT ,) 94 IF_FEATURE_CPIO_P(OPTBIT_PASSTHROUGH,) 95 IF_LONG_OPTS( OPTBIT_QUIET ,) 96 IF_LONG_OPTS( OPTBIT_2STDOUT ,) 97 CPIO_OPT_CREATE = IF_FEATURE_CPIO_O((1 << OPTBIT_CREATE )) + 0, 98 CPIO_OPT_FORMAT = IF_FEATURE_CPIO_O((1 << OPTBIT_FORMAT )) + 0, 99 CPIO_OPT_PASSTHROUGH = IF_FEATURE_CPIO_P((1 << OPTBIT_PASSTHROUGH)) + 0, 100 CPIO_OPT_QUIET = IF_LONG_OPTS( (1 << OPTBIT_QUIET )) + 0, 101 CPIO_OPT_2STDOUT = IF_LONG_OPTS( (1 << OPTBIT_2STDOUT )) + 0, 102 }; 103 104 #define OPTION_STR "it0uvdmLF:" 105 106 #if ENABLE_FEATURE_CPIO_O 107 static off_t cpio_pad4(off_t size) 108 { 109 int i; 110 111 i = (- size) & 3; 112 size += i; 113 while (--i >= 0) 114 bb_putchar('\0'); 115 return size; 116 } 117 118 /* Return value will become exit code. 119 * It's ok to exit instead of return. */ 120 static NOINLINE int cpio_o(void) 121 { 122 static const char trailer[] ALIGN1 = "TRAILER!!!"; 123 struct name_s { 124 struct name_s *next; 125 char name[1]; 126 }; 127 struct inodes_s { 128 struct inodes_s *next; 129 struct name_s *names; 130 struct stat st; 131 }; 132 133 struct inodes_s *links = NULL; 134 off_t bytes = 0; /* output bytes count */ 135 136 while (1) { 137 const char *name; 138 char *line; 139 struct stat st; 140 141 line = (option_mask32 & CPIO_OPT_NUL_TERMINATED) 142 ? bb_get_chunk_from_file(stdin, NULL) 143 : xmalloc_fgetline(stdin); 144 145 if (line) { 146 /* Strip leading "./[./]..." from the filename */ 147 name = line; 148 while (name[0] == '.' && name[1] == '/') { 149 while (*++name == '/') 150 continue; 151 } 152 if (!*name) { /* line is empty */ 153 free(line); 154 continue; 155 } 156 if ((option_mask32 & CPIO_OPT_DEREF) 157 ? stat(name, &st) 158 : lstat(name, &st) 159 ) { 160 abort_cpio_o: 161 bb_simple_perror_msg_and_die(name); 162 } 163 164 if (!(S_ISLNK(st.st_mode) || S_ISREG(st.st_mode))) 165 st.st_size = 0; /* paranoia */ 166 167 /* Store hardlinks for later processing, dont output them */ 168 if (!S_ISDIR(st.st_mode) && st.st_nlink > 1) { 169 struct name_s *n; 170 struct inodes_s *l; 171 172 /* Do we have this hardlink remembered? */ 173 l = links; 174 while (1) { 175 if (l == NULL) { 176 /* Not found: add new item to "links" list */ 177 l = xzalloc(sizeof(*l)); 178 l->st = st; 179 l->next = links; 180 links = l; 181 break; 182 } 183 if (l->st.st_ino == st.st_ino) { 184 /* found */ 185 break; 186 } 187 l = l->next; 188 } 189 /* Add new name to "l->names" list */ 190 n = xmalloc(sizeof(*n) + strlen(name)); 191 strcpy(n->name, name); 192 n->next = l->names; 193 l->names = n; 194 195 free(line); 196 continue; 197 } 198 199 } else { /* line == NULL: EOF */ 200 next_link: 201 if (links) { 202 /* Output hardlink's data */ 203 st = links->st; 204 name = links->names->name; 205 links->names = links->names->next; 206 /* GNU cpio is reported to emit file data 207 * only for the last instance. Mimic that. */ 208 if (links->names == NULL) 209 links = links->next; 210 else 211 st.st_size = 0; 212 /* NB: we leak links->names and/or links, 213 * this is intended (we exit soon anyway) */ 214 } else { 215 /* If no (more) hardlinks to output, 216 * output "trailer" entry */ 217 name = trailer; 218 /* st.st_size == 0 is a must, but for uniformity 219 * in the output, we zero out everything */ 220 memset(&st, 0, sizeof(st)); 221 /* st.st_nlink = 1; - GNU cpio does this */ 222 } 223 } 224 225 bytes += printf("070701" 226 "%08X%08X%08X%08X%08X%08X%08X" 227 "%08X%08X%08X%08X" /* GNU cpio uses uppercase hex */ 228 /* strlen+1: */ "%08X" 229 /* chksum: */ "00000000" /* (only for "070702" files) */ 230 /* name,NUL: */ "%s%c", 231 (unsigned)(uint32_t) st.st_ino, 232 (unsigned)(uint32_t) st.st_mode, 233 (unsigned)(uint32_t) st.st_uid, 234 (unsigned)(uint32_t) st.st_gid, 235 (unsigned)(uint32_t) st.st_nlink, 236 (unsigned)(uint32_t) st.st_mtime, 237 (unsigned)(uint32_t) st.st_size, 238 (unsigned)(uint32_t) major(st.st_dev), 239 (unsigned)(uint32_t) minor(st.st_dev), 240 (unsigned)(uint32_t) major(st.st_rdev), 241 (unsigned)(uint32_t) minor(st.st_rdev), 242 (unsigned)(strlen(name) + 1), 243 name, '\0'); 244 bytes = cpio_pad4(bytes); 245 246 if (st.st_size) { 247 if (S_ISLNK(st.st_mode)) { 248 char *lpath = xmalloc_readlink_or_warn(name); 249 if (!lpath) 250 goto abort_cpio_o; 251 bytes += printf("%s", lpath); 252 free(lpath); 253 } else { /* S_ISREG */ 254 int fd = xopen(name, O_RDONLY); 255 fflush_all(); 256 /* We must abort if file got shorter too! */ 257 bb_copyfd_exact_size(fd, STDOUT_FILENO, st.st_size); 258 bytes += st.st_size; 259 close(fd); 260 } 261 bytes = cpio_pad4(bytes); 262 } 263 264 if (!line) { 265 if (name != trailer) 266 goto next_link; 267 /* TODO: GNU cpio pads trailer to 512 bytes, do we want that? */ 268 return EXIT_SUCCESS; 269 } 270 271 free(line); 272 } /* end of "while (1)" */ 273 } 274 #endif 275 276 int cpio_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 277 int cpio_main(int argc UNUSED_PARAM, char **argv) 27 278 { 28 279 archive_handle_t *archive_handle; 29 char *cpio_filename = NULL; 280 char *cpio_filename; 281 IF_FEATURE_CPIO_O(const char *cpio_fmt = "";) 30 282 unsigned opt; 31 283 32 /* Initialise */ 284 #if ENABLE_LONG_OPTS 285 applet_long_options = 286 "extract\0" No_argument "i" 287 "list\0" No_argument "t" 288 #if ENABLE_FEATURE_CPIO_O 289 "create\0" No_argument "o" 290 "format\0" Required_argument "H" 291 #if ENABLE_FEATURE_CPIO_P 292 "pass-through\0" No_argument "p" 293 #endif 294 #endif 295 "verbose\0" No_argument "v" 296 "quiet\0" No_argument "\xff" 297 "to-stdout\0" No_argument "\xfe" 298 ; 299 #endif 300 33 301 archive_handle = init_handle(); 34 archive_handle->src_fd = STDIN_FILENO; 35 archive_handle->seek = seek_by_read; 36 archive_handle->flags = ARCHIVE_EXTRACT_NEWER | ARCHIVE_PRESERVE_DATE; 37 38 opt = getopt32(argv, "ituvF:dm", &cpio_filename); 302 /* archive_handle->src_fd = STDIN_FILENO; - done by init_handle */ 303 archive_handle->ah_flags = ARCHIVE_EXTRACT_NEWER; 304 305 /* As of now we do not enforce this: */ 306 /* -i,-t,-o,-p are mutually exclusive */ 307 /* -u,-d,-m make sense only with -i or -p */ 308 /* -L makes sense only with -o or -p */ 309 310 #if !ENABLE_FEATURE_CPIO_O 311 opt = getopt32(argv, OPTION_STR, &cpio_filename); 312 argv += optind; 313 if (opt & CPIO_OPT_FILE) { /* -F */ 314 xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); 315 } 316 #else 317 opt = getopt32(argv, OPTION_STR "oH:" IF_FEATURE_CPIO_P("p"), &cpio_filename, &cpio_fmt); 318 argv += optind; 319 if ((opt & (CPIO_OPT_FILE|CPIO_OPT_CREATE)) == CPIO_OPT_FILE) { /* -F without -o */ 320 xmove_fd(xopen(cpio_filename, O_RDONLY), STDIN_FILENO); 321 } 322 if (opt & CPIO_OPT_PASSTHROUGH) { 323 pid_t pid; 324 struct fd_pair pp; 325 326 if (argv[0] == NULL) 327 bb_show_usage(); 328 if (opt & CPIO_OPT_CREATE_LEADING_DIR) 329 mkdir(argv[0], 0777); 330 /* Crude existence check: 331 * close(xopen(argv[0], O_RDONLY | O_DIRECTORY)); 332 * We can also xopen, fstat, IS_DIR, later fchdir. 333 * This would check for existence earlier and cleaner. 334 * As it stands now, if we fail xchdir later, 335 * child dies on EPIPE, unless it caught 336 * a diffrerent problem earlier. 337 * This is good enough for now. 338 */ 339 #if !BB_MMU 340 pp.rd = 3; 341 pp.wr = 4; 342 if (!re_execed) { 343 close(3); 344 close(4); 345 xpiped_pair(pp); 346 } 347 #else 348 xpiped_pair(pp); 349 #endif 350 pid = fork_or_rexec(argv - optind); 351 if (pid == 0) { /* child */ 352 close(pp.rd); 353 xmove_fd(pp.wr, STDOUT_FILENO); 354 goto dump; 355 } 356 /* parent */ 357 xchdir(*argv++); 358 close(pp.wr); 359 xmove_fd(pp.rd, STDIN_FILENO); 360 //opt &= ~CPIO_OPT_PASSTHROUGH; 361 opt |= CPIO_OPT_EXTRACT; 362 goto skip; 363 } 364 /* -o */ 365 if (opt & CPIO_OPT_CREATE) { 366 if (cpio_fmt[0] != 'n') /* we _require_ "-H newc" */ 367 bb_show_usage(); 368 if (opt & CPIO_OPT_FILE) { 369 xmove_fd(xopen(cpio_filename, O_WRONLY | O_CREAT | O_TRUNC), STDOUT_FILENO); 370 } 371 dump: 372 return cpio_o(); 373 } 374 skip: 375 #endif 39 376 40 377 /* One of either extract or test options must be given */ … … 45 382 if (opt & CPIO_OPT_TEST) { 46 383 /* if both extract and test options are given, ignore extract option */ 47 if (opt & CPIO_OPT_EXTRACT) { 48 opt &= ~CPIO_OPT_EXTRACT; 49 } 384 opt &= ~CPIO_OPT_EXTRACT; 50 385 archive_handle->action_header = header_list; 51 386 } 52 387 if (opt & CPIO_OPT_EXTRACT) { 53 388 archive_handle->action_data = data_extract_all; 389 if (opt & CPIO_OPT_2STDOUT) 390 archive_handle->action_data = data_extract_to_stdout; 54 391 } 55 392 if (opt & CPIO_OPT_UNCONDITIONAL) { 56 archive_handle-> flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;57 archive_handle-> flags &= ~ARCHIVE_EXTRACT_NEWER;393 archive_handle->ah_flags |= ARCHIVE_UNLINK_OLD; 394 archive_handle->ah_flags &= ~ARCHIVE_EXTRACT_NEWER; 58 395 } 59 396 if (opt & CPIO_OPT_VERBOSE) { … … 64 401 } 65 402 } 66 if (cpio_filename) { /* CPIO_OPT_FILE */67 archive_handle->src_fd = xopen(cpio_filename, O_RDONLY);68 archive_handle->seek = seek_by_jump;69 }70 403 if (opt & CPIO_OPT_CREATE_LEADING_DIR) { 71 archive_handle->flags |= ARCHIVE_CREATE_LEADING_DIRS; 72 } 73 74 while (optind < argc) { 404 archive_handle->ah_flags |= ARCHIVE_CREATE_LEADING_DIRS; 405 } 406 if (opt & CPIO_OPT_PRESERVE_MTIME) { 407 archive_handle->ah_flags |= ARCHIVE_RESTORE_DATE; 408 } 409 410 while (*argv) { 75 411 archive_handle->filter = filter_accept_list; 76 llist_add_to(&(archive_handle->accept), argv[optind]); 77 optind++; 78 } 79 80 while (get_header_cpio(archive_handle) == EXIT_SUCCESS); 412 llist_add_to(&archive_handle->accept, *argv); 413 argv++; 414 } 415 416 /* see get_header_cpio */ 417 archive_handle->cpio__blocks = (off_t)-1; 418 while (get_header_cpio(archive_handle) == EXIT_SUCCESS) 419 continue; 420 421 if (archive_handle->cpio__blocks != (off_t)-1 422 && !(opt & CPIO_OPT_QUIET) 423 ) { 424 fprintf(stderr, "%"OFF_FMT"u blocks\n", archive_handle->cpio__blocks); 425 } 81 426 82 427 return EXIT_SUCCESS; -
branches/2.2.9/mindi-busybox/archival/dpkg.c
r1765 r2725 7 7 * copyright (c) 2001 by glenn mcgrath 8 8 * 9 * parts of the version comparison code is plucked from the real dpkg 10 * application which is licensed GPLv2 and 11 * copyright (c) 1995 Ian Jackson <ian@chiark.greenend.org.uk> 12 * 9 13 * started life as a busybox implementation of udpkg 10 14 * 11 * licensed under gplv2 or later, see file license in this tarball for details.15 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 12 16 */ 13 17 … … 26 30 27 31 #include "libbb.h" 28 #include "unarchive.h" 32 #include <fnmatch.h> 33 #include "archive.h" 29 34 30 35 /* note: if you vary hash_prime sizes be aware, … … 76 81 } status_node_t; 77 82 78 /* Were statically declared here, but such a big bss is nommu-unfriendly */ 79 static char **name_hashtable; /* [NAME_HASH_PRIME + 1] */ 80 static common_node_t **package_hashtable; /* [PACKAGE_HASH_PRIME + 1] */ 81 static status_node_t **status_hashtable; /* [STATUS_HASH_PRIME + 1] */ 83 84 /* Globals */ 85 struct globals { 86 char *name_hashtable[NAME_HASH_PRIME + 1]; 87 common_node_t *package_hashtable[PACKAGE_HASH_PRIME + 1]; 88 status_node_t *status_hashtable[STATUS_HASH_PRIME + 1]; 89 }; 90 #define G (*ptr_to_globals) 91 #define name_hashtable (G.name_hashtable ) 92 #define package_hashtable (G.package_hashtable) 93 #define status_hashtable (G.status_hashtable ) 94 #define INIT_G() do { \ 95 SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \ 96 } while (0) 97 82 98 83 99 /* Even numbers are for 'extras', like ored dependencies or null */ … … 124 140 * shift amount is mod 24 because long int is 32 bit and data 125 141 * to be shifted is 8, don't want to shift data to where it has 126 * no effect */127 hash_num += ( (key[i] + key[i-1]) << ((key[i] * i) % 24));142 * no effect */ 143 hash_num += (key[i] + key[i-1]) << ((key[i] * i) % 24); 128 144 } 129 145 *start = (unsigned) hash_num % hash_prime; … … 134 150 static int search_name_hashtable(const char *key) 135 151 { 136 unsigned probe_address = 0;137 unsigned probe_decrement = 0;152 unsigned probe_address; 153 unsigned probe_decrement; 138 154 139 155 make_hash(key, &probe_address, &probe_decrement, NAME_HASH_PRIME); … … 156 172 static unsigned search_status_hashtable(const char *key) 157 173 { 158 unsigned probe_address = 0;159 unsigned probe_decrement = 0;174 unsigned probe_address; 175 unsigned probe_decrement; 160 176 161 177 make_hash(key, &probe_address, &probe_decrement, STATUS_HASH_PRIME); … … 172 188 } 173 189 174 /* Need to rethink version comparison, maybe the official dpkg has something i can use ? */ 175 static int version_compare_part(const char *version1, const char *version2) 176 { 177 int upstream_len1 = 0; 178 int upstream_len2 = 0; 179 char *name1_char; 180 char *name2_char; 181 int len1 = 0; 182 int len2 = 0; 183 int tmp_int; 184 int ver_num1; 185 int ver_num2; 186 187 if (version1 == NULL) { 188 version1 = xstrdup(""); 189 } 190 if (version2 == NULL) { 191 version2 = xstrdup(""); 192 } 193 upstream_len1 = strlen(version1); 194 upstream_len2 = strlen(version2); 195 196 while ((len1 < upstream_len1) || (len2 < upstream_len2)) { 197 /* Compare non-digit section */ 198 tmp_int = strcspn(&version1[len1], "0123456789"); 199 name1_char = xstrndup(&version1[len1], tmp_int); 200 len1 += tmp_int; 201 tmp_int = strcspn(&version2[len2], "0123456789"); 202 name2_char = xstrndup(&version2[len2], tmp_int); 203 len2 += tmp_int; 204 tmp_int = strcmp(name1_char, name2_char); 205 free(name1_char); 206 free(name2_char); 207 if (tmp_int != 0) { 208 return tmp_int; 209 } 210 211 /* Compare digits */ 212 tmp_int = strspn(&version1[len1], "0123456789"); 213 name1_char = xstrndup(&version1[len1], tmp_int); 214 len1 += tmp_int; 215 tmp_int = strspn(&version2[len2], "0123456789"); 216 name2_char = xstrndup(&version2[len2], tmp_int); 217 len2 += tmp_int; 218 ver_num1 = atoi(name1_char); 219 ver_num2 = atoi(name2_char); 220 free(name1_char); 221 free(name2_char); 222 if (ver_num1 < ver_num2) { 190 static int order(char x) 191 { 192 return (x == '~' ? -1 193 : x == '\0' ? 0 194 : isdigit(x) ? 0 195 : isalpha(x) ? x 196 : (unsigned char)x + 256 197 ); 198 } 199 200 /* This code is taken from dpkg and modified slightly to work with busybox */ 201 static int version_compare_part(const char *val, const char *ref) 202 { 203 if (!val) val = ""; 204 if (!ref) ref = ""; 205 206 while (*val || *ref) { 207 int first_diff; 208 209 while ((*val && !isdigit(*val)) || (*ref && !isdigit(*ref))) { 210 int vc = order(*val); 211 int rc = order(*ref); 212 if (vc != rc) 213 return vc - rc; 214 val++; 215 ref++; 216 } 217 218 while (*val == '0') 219 val++; 220 while (*ref == '0') 221 ref++; 222 223 first_diff = 0; 224 while (isdigit(*val) && isdigit(*ref)) { 225 if (first_diff == 0) 226 first_diff = *val - *ref; 227 val++; 228 ref++; 229 } 230 if (isdigit(*val)) 231 return 1; 232 if (isdigit(*ref)) 223 233 return -1; 224 } 225 if (ver_num1 > ver_num2) { 226 return 1; 227 } 234 if (first_diff) 235 return first_diff; 228 236 } 229 237 return 0; … … 238 246 char *ch_ver1 = name_hashtable[ver1]; 239 247 char *ch_ver2 = name_hashtable[ver2]; 240 241 char epoch1, epoch2;248 unsigned epoch1 = 0, epoch2 = 0; 249 char *colon; 242 250 char *deb_ver1, *deb_ver2; 243 char *ver1_ptr, *ver2_ptr;244 251 char *upstream_ver1; 245 252 char *upstream_ver2; … … 247 254 248 255 /* Compare epoch */ 249 if (ch_ver1[1] == ':') { 250 epoch1 = ch_ver1[0]; 251 ver1_ptr = strchr(ch_ver1, ':') + 1; 252 } else { 253 epoch1 = '0'; 254 ver1_ptr = ch_ver1; 255 } 256 if (ch_ver2[1] == ':') { 257 epoch2 = ch_ver2[0]; 258 ver2_ptr = strchr(ch_ver2, ':') + 1; 259 } else { 260 epoch2 = '0'; 261 ver2_ptr = ch_ver2; 256 colon = strchr(ch_ver1, ':'); 257 if (colon) { 258 epoch1 = atoi(ch_ver1); 259 ch_ver1 = colon + 1; 260 } 261 colon = strchr(ch_ver2, ':'); 262 if (colon) { 263 epoch2 = atoi(ch_ver2); 264 ch_ver2 = colon + 1; 262 265 } 263 266 if (epoch1 < epoch2) { 264 267 return -1; 265 268 } 266 elseif (epoch1 > epoch2) {269 if (epoch1 > epoch2) { 267 270 return 1; 268 271 } 269 272 270 273 /* Compare upstream version */ 271 upstream_ver1 = xstrdup( ver1_ptr);272 upstream_ver2 = xstrdup( ver2_ptr);274 upstream_ver1 = xstrdup(ch_ver1); 275 upstream_ver2 = xstrdup(ch_ver2); 273 276 274 277 /* Chop off debian version, and store for later use */ … … 276 279 deb_ver2 = strrchr(upstream_ver2, '-'); 277 280 if (deb_ver1) { 278 deb_ver1[0] = '\0'; 279 deb_ver1++; 281 *deb_ver1++ = '\0'; 280 282 } 281 283 if (deb_ver2) { 282 deb_ver2[0] = '\0'; 283 deb_ver2++; 284 *deb_ver2++ = '\0'; 284 285 } 285 286 result = version_compare_part(upstream_ver1, upstream_ver2); 286 if ( !result)287 if (result == 0) { 287 288 /* Compare debian versions */ 288 289 result = version_compare_part(deb_ver1, deb_ver2); 290 } 289 291 290 292 free(upstream_ver1); … … 313 315 } 314 316 315 316 317 static int search_package_hashtable(const unsigned name, const unsigned version, const unsigned operator) 317 318 { 318 unsigned probe_address = 0;319 unsigned probe_decrement = 0;319 unsigned probe_address; 320 unsigned probe_decrement; 320 321 321 322 make_hash(name_hashtable[name], &probe_address, &probe_decrement, PACKAGE_HASH_PRIME); … … 373 374 static void add_edge_to_node(common_node_t *node, edge_t *edge) 374 375 { 375 node->num_of_edges++; 376 node->edge = xrealloc(node->edge, sizeof(edge_t) * (node->num_of_edges + 1)); 377 node->edge[node->num_of_edges - 1] = edge; 376 node->edge = xrealloc_vector(node->edge, 2, node->num_of_edges); 377 node->edge[node->num_of_edges++] = edge; 378 378 } 379 379 … … 411 411 && (strcmp(field, field2) != 0) 412 412 ) { 413 or_edge = x malloc(sizeof(edge_t));413 or_edge = xzalloc(sizeof(edge_t)); 414 414 or_edge->type = edge_type + 1; 415 415 or_edge->name = search_name_hashtable(field); 416 or_edge->version = 0; // tracks the number of alternatives416 //or_edge->version = 0; // tracks the number of alternatives 417 417 add_edge_to_node(parent_node, or_edge); 418 418 } … … 440 440 if (strncmp(version, "=", offset_ch) == 0) { 441 441 edge->operator = VER_EQUAL; 442 } 443 else if (strncmp(version, "<<", offset_ch) == 0) { 442 } else if (strncmp(version, "<<", offset_ch) == 0) { 444 443 edge->operator = VER_LESS; 445 } 446 else if (strncmp(version, "<=", offset_ch) == 0) { 444 } else if (strncmp(version, "<=", offset_ch) == 0) { 447 445 edge->operator = VER_LESS_EQUAL; 448 } 449 else if (strncmp(version, ">>", offset_ch) == 0) { 446 } else if (strncmp(version, ">>", offset_ch) == 0) { 450 447 edge->operator = VER_MORE; 451 } 452 else if (strncmp(version, ">=", offset_ch) == 0) { 448 } else if (strncmp(version, ">=", offset_ch) == 0) { 453 449 edge->operator = VER_MORE_EQUAL; 454 450 } else { … … 497 493 498 494 /* 499 * Gets the next package field from package_buffer, sep erated into the field name495 * Gets the next package field from package_buffer, separated into the field name 500 496 * and field value, it returns the int offset to the first character of the next field 501 497 */ … … 603 599 604 600 if (field_name == NULL) { 605 goto fill_package_struct_cleanup; /* Oh no, the dreaded goto statement! */601 goto fill_package_struct_cleanup; 606 602 } 607 603 … … 736 732 } 737 733 738 739 734 static void index_status_file(const char *filename) 740 735 { … … 745 740 unsigned status_num; 746 741 747 status_file = xfopen (filename, "r");748 while ((control_buffer = xmalloc_fget s_str(status_file, "\n\n")) != NULL) {742 status_file = xfopen_for_read(filename); 743 while ((control_buffer = xmalloc_fgetline_str(status_file, "\n\n")) != NULL) { 749 744 const unsigned package_num = fill_package_struct(control_buffer); 750 745 if (package_num != -1) { … … 787 782 static void write_status_file(deb_file_t **deb_file) 788 783 { 789 FILE *old_status_file = xfopen ("/var/lib/dpkg/status", "r");790 FILE *new_status_file = xfopen ("/var/lib/dpkg/status.udeb", "w");784 FILE *old_status_file = xfopen_for_read("/var/lib/dpkg/status"); 785 FILE *new_status_file = xfopen_for_write("/var/lib/dpkg/status.udeb"); 791 786 char *package_name; 792 787 char *status_from_file; … … 799 794 800 795 /* Update previously known packages */ 801 while ((control_buffer = xmalloc_fget s_str(old_status_file, "\n\n")) != NULL) {796 while ((control_buffer = xmalloc_fgetline_str(old_status_file, "\n\n")) != NULL) { 802 797 tmp_string = strstr(control_buffer, "Package:"); 803 798 if (tmp_string == NULL) { … … 811 806 tmp_string = strstr(control_buffer, "Status:"); 812 807 if (tmp_string != NULL) { 813 /* Sep erate the status value from the control buffer */808 /* Separate the status value from the control buffer */ 814 809 tmp_string += 7; 815 810 tmp_string += strspn(tmp_string, " \n\t"); … … 863 858 break; 864 859 } 865 if ((strcmp(field_name, "Priority") == 0) || 866 (strcmp(field_name, "Section") == 0)) { 860 if ((strcmp(field_name, "Priority") == 0) 861 || (strcmp(field_name, "Section") == 0) 862 ) { 867 863 fprintf(new_status_file, "%s: %s\n", field_name, field_value); 868 864 } … … 871 867 fputs("\n", new_status_file); 872 868 } 873 else if 869 else if (strcmp("config-files", name_hashtable[state_status]) == 0) { 874 870 /* only change the status line */ 875 871 while (1) { … … 914 910 fclose(new_status_file); 915 911 916 917 912 /* Create a separate backfile to dpkg */ 918 913 if (rename("/var/lib/dpkg/status", "/var/lib/dpkg/status.udeb.bak") == -1) { 919 struct stat stat_buf;920 xstat("/var/lib/dpkg/status", &stat_buf);914 if (errno != ENOENT) 915 bb_error_msg_and_die("can't create backup status file"); 921 916 /* Its ok if renaming the status file fails because status 922 917 * file doesnt exist, maybe we are starting from scratch */ … … 924 919 } 925 920 926 if (rename("/var/lib/dpkg/status.udeb", "/var/lib/dpkg/status") == -1) { 927 bb_error_msg_and_die("DANGER: cannot create status file, " 928 "you need to manually repair your status file"); 929 } 921 xrename("/var/lib/dpkg/status.udeb", "/var/lib/dpkg/status"); 930 922 } 931 923 … … 948 940 949 941 switch (depend_type) { 950 case EDGE_PRE_DEPENDS: 951 case EDGE_DEPENDS: 942 case EDGE_PRE_DEPENDS: return get_status(status_num, 3) == search_name_hashtable("installed"); 943 case EDGE_DEPENDS: return get_status(status_num, 1) == search_name_hashtable("install"); 952 944 } 953 945 return 0; 954 946 } 955 947 956 static int check_deps(deb_file_t **deb_file, int deb_start , int dep_max_count)948 static int check_deps(deb_file_t **deb_file, int deb_start /*, int dep_max_count - ?? */) 957 949 { 958 950 int *conflicts = NULL; … … 972 964 while (deb_file[i] != NULL) { 973 965 const unsigned package_num = deb_file[i]->package; 974 conflicts = xrealloc (conflicts, sizeof(int) * (conflicts_num + 1));966 conflicts = xrealloc_vector(conflicts, 2, conflicts_num); 975 967 conflicts[conflicts_num] = package_num; 976 968 conflicts_num++; 977 969 /* add provides to conflicts list */ 978 for (j = 0; j < 970 for (j = 0; j < package_hashtable[package_num]->num_of_edges; j++) { 979 971 if (package_hashtable[package_num]->edge[j]->type == EDGE_PROVIDES) { 980 972 const int conflicts_package_num = search_package_hashtable( … … 989 981 package_hashtable[conflicts_package_num] = new_node; 990 982 } 991 conflicts = xrealloc (conflicts, sizeof(int) * (conflicts_num + 1));983 conflicts = xrealloc_vector(conflicts, 2, conflicts_num); 992 984 conflicts[conflicts_num] = conflicts_package_num; 993 985 conflicts_num++; … … 1076 1068 if (package_edge->type == EDGE_OR_PRE_DEPENDS 1077 1069 || package_edge->type == EDGE_OR_DEPENDS 1078 ) { /* start an EDGE_OR_ list */ 1070 ) { 1071 /* start an EDGE_OR_ list */ 1079 1072 number_of_alternatives = package_edge->version; 1080 1073 root_of_alternatives = package_edge; 1081 1074 continue; 1082 1075 } 1083 if (number_of_alternatives == 0) { 1076 if (number_of_alternatives == 0) { /* not in the middle of an EDGE_OR_ list */ 1084 1077 number_of_alternatives = 1; 1085 1078 root_of_alternatives = NULL; … … 1088 1081 package_num = search_package_hashtable(package_edge->name, package_edge->version, package_edge->operator); 1089 1082 1090 if (package_edge->type == EDGE_PRE_DEPENDS || 1091 package_edge->type == EDGE_DEPENDS) { 1083 if (package_edge->type == EDGE_PRE_DEPENDS 1084 || package_edge->type == EDGE_DEPENDS 1085 ) { 1092 1086 int result=1; 1093 1087 status_num = 0; … … 1157 1151 { 1158 1152 FILE *list_stream; 1159 char **file_list = NULL;1160 char *line = NULL;1161 int count = 0;1153 char **file_list; 1154 char *line; 1155 int count; 1162 1156 1163 1157 /* don't use [xw]fopen here, handle error ourself */ 1164 list_stream = fopen (filename, "r");1158 list_stream = fopen_for_read(filename); 1165 1159 if (list_stream == NULL) { 1166 1160 return NULL; 1167 1161 } 1168 1162 1169 while ((line = xmalloc_getline(list_stream)) != NULL) { 1170 file_list = xrealloc(file_list, sizeof(char *) * (count + 2)); 1171 file_list[count] = line; 1172 count++; 1163 file_list = NULL; 1164 count = 0; 1165 while ((line = xmalloc_fgetline(list_stream)) != NULL) { 1166 file_list = xrealloc_vector(file_list, 2, count); 1167 file_list[count++] = line; 1168 /*file_list[count] = NULL; - xrealloc_vector did it */ 1173 1169 } 1174 1170 fclose(list_stream); 1175 1171 1176 if (count == 0) {1177 return NULL;1178 }1179 file_list[count] = NULL;1180 1172 return file_list; 1181 1173 } … … 1214 1206 } 1215 1207 1216 static int run_package_script(const char *package_name, const char *script_type) 1217 { 1218 struct stat path_stat; 1208 static void run_package_script_or_die(const char *package_name, const char *script_type) 1209 { 1219 1210 char *script_path; 1220 1211 int result; … … 1222 1213 script_path = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, script_type); 1223 1214 1224 /* If the file doesnt exist is isnt afatal */1225 result = lstat(script_path, &path_stat) < 0? EXIT_SUCCESS : system(script_path);1215 /* If the file doesnt exist is isnt fatal */ 1216 result = access(script_path, F_OK) ? EXIT_SUCCESS : system(script_path); 1226 1217 free(script_path); 1227 return result; 1228 } 1229 1218 if (result) 1219 bb_error_msg_and_die("%s failed, exit code %d", script_type, result); 1220 } 1221 1222 /* 1223 The policy manual defines what scripts get called when and with 1224 what arguments. I realize that busybox does not support all of 1225 these scenarios, but it does support some of them; it does not, 1226 however, run them with any parameters in run_package_script_or_die(). 1227 Here are the scripts: 1228 1229 preinst install 1230 preinst install <old_version> 1231 preinst upgrade <old_version> 1232 preinst abort_upgrade <new_version> 1233 postinst configure <most_recent_version> 1234 postinst abort-upgade <new_version> 1235 postinst abort-remove 1236 postinst abort-remove in-favour <package> <version> 1237 postinst abort-deconfigure in-favor <failed_install_package> removing <conflicting_package> <version> 1238 prerm remove 1239 prerm upgrade <new_version> 1240 prerm failed-upgrade <old_version> 1241 prerm remove in-favor <package> <new_version> 1242 prerm deconfigure in-favour <package> <version> removing <package> <version> 1243 postrm remove 1244 postrm purge 1245 postrm upgrade <new_version> 1246 postrm failed-upgrade <old_version> 1247 postrm abort-install 1248 postrm abort-install <old_version> 1249 postrm abort-upgrade <old_version> 1250 postrm disappear <overwriter> <version> 1251 */ 1230 1252 static const char *const all_control_files[] = { 1231 1253 "preinst", "postinst", "prerm", "postrm", 1232 1254 "list", "md5sums", "shlibs", "conffiles", 1233 "config", "templates" , NULL1255 "config", "templates" 1234 1256 }; 1235 1257 … … 1240 1262 1241 1263 /* Create a list of all /var/lib/dpkg/info/<package> files */ 1242 remove_files = xzalloc(sizeof(all_control_files)); 1243 while (all_control_files[i]) { 1244 remove_files[i] = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, all_control_files[i]); 1264 remove_files = xzalloc(sizeof(all_control_files) + sizeof(char*)); 1265 while (i < ARRAY_SIZE(all_control_files)) { 1266 remove_files[i] = xasprintf("/var/lib/dpkg/info/%s.%s", 1267 package_name, all_control_files[i]); 1245 1268 i++; 1246 1269 } … … 1265 1288 * scanning the status file. The resulting list, however, is unsorted. 1266 1289 */ 1267 static void list_packages( void)1290 static void list_packages(const char *pattern) 1268 1291 { 1269 1292 int i; … … 1286 1309 vers_str = name_hashtable[package_hashtable[status_hashtable[i]->package]->version]; 1287 1310 1311 if (pattern && fnmatch(pattern, name_str, 0) != 0) 1312 continue; 1313 1288 1314 /* get abbreviation for status field 1 */ 1289 1315 s1 = stat_str[0] == 'i' ? 'i' : 'r'; … … 1315 1341 printf("Removing %s (%s)...\n", package_name, package_version); 1316 1342 1317 /* run prerm script */ 1318 if (run_package_script(package_name, "prerm") != 0) { 1319 bb_error_msg_and_die("script failed, prerm failure"); 1320 } 1343 /* Run prerm script */ 1344 run_package_script_or_die(package_name, "prerm"); 1321 1345 1322 1346 /* Create a list of files to remove, and a separate list of those to keep */ 1323 sprintf(list_name, "/var/lib/dpkg/info/%s. list", package_name);1347 sprintf(list_name, "/var/lib/dpkg/info/%s.%s", package_name, "list"); 1324 1348 remove_files = create_list(list_name); 1325 1349 1326 sprintf(conffile_name, "/var/lib/dpkg/info/%s. conffiles", package_name);1350 sprintf(conffile_name, "/var/lib/dpkg/info/%s.%s", package_name, "conffiles"); 1327 1351 exclude_files = create_list(conffile_name); 1328 1352 1329 1353 /* Some directories can't be removed straight away, so do multiple passes */ 1330 while (remove_file_array(remove_files, exclude_files)) /*repeat */; 1354 while (remove_file_array(remove_files, exclude_files)) 1355 continue; 1331 1356 free_array(exclude_files); 1332 1357 free_array(remove_files); 1333 1358 1334 /* Create a list of files in /var/lib/dpkg/info/<package>.* to keep 1335 exclude_files = xzalloc(sizeof( char*) * 3);1359 /* Create a list of files in /var/lib/dpkg/info/<package>.* to keep */ 1360 exclude_files = xzalloc(sizeof(exclude_files[0]) * 3); 1336 1361 exclude_files[0] = xstrdup(conffile_name); 1337 exclude_files[1] = xasprintf("/var/lib/dpkg/info/%s. postrm", package_name);1362 exclude_files[1] = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "postrm"); 1338 1363 1339 1364 /* Create a list of all /var/lib/dpkg/info/<package> files */ … … 1344 1369 free_array(exclude_files); 1345 1370 1346 /* rename <package>.conffile to <package>.list */ 1371 /* rename <package>.conffiles to <package>.list 1372 * The conffiles control file isn't required in Debian packages, so don't 1373 * error out if it's missing. */ 1347 1374 rename(conffile_name, list_name); 1348 1375 … … 1362 1389 printf("Purging %s (%s)...\n", package_name, package_version); 1363 1390 1364 /* run prerm script */ 1365 if (run_package_script(package_name, "prerm") != 0) { 1366 bb_error_msg_and_die("script failed, prerm failure"); 1367 } 1391 /* Run prerm script */ 1392 run_package_script_or_die(package_name, "prerm"); 1368 1393 1369 1394 /* Create a list of files to remove */ 1370 sprintf(list_name, "/var/lib/dpkg/info/%s. list", package_name);1395 sprintf(list_name, "/var/lib/dpkg/info/%s.%s", package_name, "list"); 1371 1396 remove_files = create_list(list_name); 1372 1397 1373 exclude_files = xzalloc(sizeof(char*));1374 1375 1398 /* Some directories cant be removed straight away, so do multiple passes */ 1376 while (remove_file_array(remove_files, exclude_files)) /* repeat */; 1399 while (remove_file_array(remove_files, NULL)) 1400 continue; 1377 1401 free_array(remove_files); 1378 1402 1379 1403 /* Create a list of all /var/lib/dpkg/info/<package> files */ 1380 1404 remove_files = all_control_list(package_name); 1405 1406 /* Delete all of them except the postrm script */ 1407 exclude_files = xzalloc(sizeof(exclude_files[0]) * 2); 1408 exclude_files[0] = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "postrm"); 1381 1409 remove_file_array(remove_files, exclude_files); 1410 free_array(exclude_files); 1411 1412 /* Run and remove postrm script */ 1413 run_package_script_or_die(package_name, "postrm"); 1414 remove_file_array(remove_files, NULL); 1415 1382 1416 free_array(remove_files); 1383 free(exclude_files);1384 1385 /* run postrm script */1386 if (run_package_script(package_name, "postrm") != 0) {1387 bb_error_msg_and_die("postrm failure.. set status to what?");1388 }1389 1417 1390 1418 /* Change package status */ … … 1413 1441 1414 1442 /* We don't care about data.tar.* or debian-binary, just control.tar.* */ 1415 #if ENABLE_FEATURE_ DEB_TAR_GZ1443 #if ENABLE_FEATURE_SEAMLESS_GZ 1416 1444 llist_add_to(&(ar_handle->accept), (char*)"control.tar.gz"); 1417 1445 #endif 1418 #if ENABLE_FEATURE_ DEB_TAR_BZ21446 #if ENABLE_FEATURE_SEAMLESS_BZ2 1419 1447 llist_add_to(&(ar_handle->accept), (char*)"control.tar.bz2"); 1420 1448 #endif 1421 1449 1422 1450 /* Assign the tar handle as a subarchive of the ar handle */ 1423 ar_handle-> sub_archive = tar_handle;1451 ar_handle->dpkg__sub_archive = tar_handle; 1424 1452 } 1425 1453 … … 1433 1461 1434 1462 /* We don't care about control.tar.* or debian-binary, just data.tar.* */ 1435 #if ENABLE_FEATURE_ DEB_TAR_GZ1463 #if ENABLE_FEATURE_SEAMLESS_GZ 1436 1464 llist_add_to(&(ar_handle->accept), (char*)"data.tar.gz"); 1437 1465 #endif 1438 #if ENABLE_FEATURE_ DEB_TAR_BZ21466 #if ENABLE_FEATURE_SEAMLESS_BZ2 1439 1467 llist_add_to(&(ar_handle->accept), (char*)"data.tar.bz2"); 1440 1468 #endif 1441 1469 1442 1470 /* Assign the tar handle as a subarchive of the ar handle */ 1443 ar_handle->sub_archive = tar_handle; 1471 ar_handle->dpkg__sub_archive = tar_handle; 1472 } 1473 1474 static void FAST_FUNC data_extract_to_buffer(archive_handle_t *archive_handle) 1475 { 1476 unsigned size = archive_handle->file_header->size; 1477 1478 archive_handle->dpkg__buffer = xzalloc(size + 1); 1479 xread(archive_handle->src_fd, archive_handle->dpkg__buffer, size); 1444 1480 } 1445 1481 1446 1482 static char *deb_extract_control_file_to_buffer(archive_handle_t *ar_handle, llist_t *myaccept) 1447 1483 { 1448 ar_handle-> sub_archive->action_data = data_extract_to_buffer;1449 ar_handle-> sub_archive->accept = myaccept;1450 ar_handle-> sub_archive->filter = filter_accept_list;1484 ar_handle->dpkg__sub_archive->action_data = data_extract_to_buffer; 1485 ar_handle->dpkg__sub_archive->accept = myaccept; 1486 ar_handle->dpkg__sub_archive->filter = filter_accept_list; 1451 1487 1452 1488 unpack_ar_archive(ar_handle); 1453 1489 close(ar_handle->src_fd); 1454 1490 1455 return ar_handle->sub_archive->buffer; 1456 } 1457 1458 static void data_extract_all_prefix(archive_handle_t *archive_handle) 1491 return ar_handle->dpkg__sub_archive->dpkg__buffer; 1492 } 1493 1494 static void append_control_file_to_llist(const char *package_name, const char *control_name, llist_t **ll) 1495 { 1496 FILE *fp; 1497 char *filename, *line; 1498 1499 filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, control_name); 1500 fp = fopen_for_read(filename); 1501 free(filename); 1502 if (fp != NULL) { 1503 while ((line = xmalloc_fgetline(fp)) != NULL) 1504 llist_add_to(ll, line); 1505 fclose(fp); 1506 } 1507 } 1508 1509 static char FAST_FUNC filter_rename_config(archive_handle_t *archive_handle) 1510 { 1511 int fd; 1512 char *name_ptr = archive_handle->file_header->name + 1; 1513 1514 /* Is this file marked as config file? */ 1515 if (!find_list_entry(archive_handle->accept, name_ptr)) 1516 return EXIT_SUCCESS; /* no */ 1517 1518 fd = open(name_ptr, O_RDONLY); 1519 if (fd >= 0) { 1520 md5_ctx_t md5; 1521 char *md5line, *buf; 1522 int count; 1523 1524 /* Calculate MD5 of existing file */ 1525 buf = xmalloc(4096); 1526 md5_begin(&md5); 1527 while ((count = safe_read(fd, buf, 4096)) > 0) 1528 md5_hash(&md5, buf, count); 1529 md5_end(&md5, buf); /* using buf as result storage */ 1530 close(fd); 1531 1532 md5line = xmalloc(16 * 2 + 2 + strlen(name_ptr) + 1); 1533 sprintf(bin2hex(md5line, buf, 16), " %s", name_ptr); 1534 free(buf); 1535 1536 /* Is it changed after install? */ 1537 if (find_list_entry(archive_handle->accept, md5line) == NULL) { 1538 printf("Warning: Creating %s as %s.dpkg-new\n", name_ptr, name_ptr); 1539 archive_handle->file_header->name = xasprintf("%s.dpkg-new", archive_handle->file_header->name); 1540 } 1541 free(md5line); 1542 } 1543 return EXIT_SUCCESS; 1544 } 1545 1546 static void FAST_FUNC data_extract_all_prefix(archive_handle_t *archive_handle) 1459 1547 { 1460 1548 char *name_ptr = archive_handle->file_header->name; 1461 1549 1462 name_ptr += strspn(name_ptr, "./"); 1550 /* Skip all leading "/" */ 1551 while (*name_ptr == '/') 1552 name_ptr++; 1553 /* Skip all leading "./" and "../" */ 1554 while (name_ptr[0] == '.') { 1555 if (name_ptr[1] == '.') 1556 name_ptr++; 1557 if (name_ptr[1] != '/') 1558 break; 1559 name_ptr += 2; 1560 } 1561 1463 1562 if (name_ptr[0] != '\0') { 1464 archive_handle->file_header->name = xasprintf("%s%s", archive_handle-> buffer, name_ptr);1563 archive_handle->file_header->name = xasprintf("%s%s", archive_handle->dpkg__buffer, name_ptr); 1465 1564 data_extract_all(archive_handle); 1466 } 1467 } 1565 if (fnmatch("*.dpkg-new", archive_handle->file_header->name, 0) == 0) { 1566 /* remove .dpkg-new suffix */ 1567 archive_handle->file_header->name[strlen(archive_handle->file_header->name) - 9] = '\0'; 1568 } 1569 } 1570 } 1571 1572 enum { 1573 /* Commands */ 1574 OPT_configure = (1 << 0), 1575 OPT_install = (1 << 1), 1576 OPT_list_installed = (1 << 2), 1577 OPT_purge = (1 << 3), 1578 OPT_remove = (1 << 4), 1579 OPT_unpack = (1 << 5), 1580 OPTMASK_cmd = (1 << 6) - 1, 1581 /* Options */ 1582 OPT_force = (1 << 6), 1583 OPT_force_ignore_depends = (1 << 7), 1584 OPT_force_confnew = (1 << 8), 1585 OPT_force_confold = (1 << 9), 1586 }; 1468 1587 1469 1588 static void unpack_package(deb_file_t *deb_file) … … 1476 1595 archive_handle_t *archive_handle; 1477 1596 FILE *out_stream; 1478 llist_t *accept_list = NULL; 1479 int i = 0; 1597 llist_t *accept_list; 1598 llist_t *conffile_list; 1599 int i; 1480 1600 1481 1601 /* If existing version, remove it first */ 1602 conffile_list = NULL; 1482 1603 if (strcmp(name_hashtable[get_status(status_num, 3)], "installed") == 0) { 1483 1604 /* Package is already installed, remove old version first */ … … 1485 1606 name_hashtable[package_hashtable[status_package_num]->version], 1486 1607 deb_file->filename); 1608 1609 /* Read md5sums from old package */ 1610 if (!(option_mask32 & OPT_force_confold)) 1611 append_control_file_to_llist(package_name, "md5sums", &conffile_list); 1612 1487 1613 remove_package(status_package_num, 0); 1488 1614 } else { … … 1491 1617 1492 1618 /* Extract control.tar.gz to /var/lib/dpkg/info/<package>.filename */ 1493 info_prefix = xasprintf("/var/lib/dpkg/info/%s. ", package_name);1619 info_prefix = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, ""); 1494 1620 archive_handle = init_archive_deb_ar(deb_file->filename); 1495 1621 init_archive_deb_control(archive_handle); 1496 1622 1497 while (all_control_files[i]) { 1623 accept_list = NULL; 1624 i = 0; 1625 while (i < ARRAY_SIZE(all_control_files)) { 1498 1626 char *c = xasprintf("./%s", all_control_files[i]); 1499 1627 llist_add_to(&accept_list, c); 1500 1628 i++; 1501 1629 } 1502 archive_handle-> sub_archive->accept = accept_list;1503 archive_handle-> sub_archive->filter = filter_accept_list;1504 archive_handle-> sub_archive->action_data = data_extract_all_prefix;1505 archive_handle-> sub_archive->buffer = info_prefix;1506 archive_handle-> sub_archive->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL;1630 archive_handle->dpkg__sub_archive->accept = accept_list; 1631 archive_handle->dpkg__sub_archive->filter = filter_accept_list; 1632 archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix; 1633 archive_handle->dpkg__sub_archive->dpkg__buffer = info_prefix; 1634 archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_UNLINK_OLD; 1507 1635 unpack_ar_archive(archive_handle); 1508 1636 1509 1637 /* Run the preinst prior to extracting */ 1510 if (run_package_script(package_name, "preinst") != 0) { 1511 /* when preinst returns exit code != 0 then quit installation process */ 1512 bb_error_msg_and_die("subprocess pre-installation script returned error"); 1513 } 1638 run_package_script_or_die(package_name, "preinst"); 1639 1640 /* Don't overwrite existing config files */ 1641 if (!(option_mask32 & OPT_force_confnew)) 1642 append_control_file_to_llist(package_name, "conffiles", &conffile_list); 1514 1643 1515 1644 /* Extract data.tar.gz to the root directory */ 1516 1645 archive_handle = init_archive_deb_ar(deb_file->filename); 1517 1646 init_archive_deb_data(archive_handle); 1518 archive_handle->sub_archive->action_data = data_extract_all_prefix; 1519 archive_handle->sub_archive->buffer = (char*)"/"; /* huh? */ 1520 archive_handle->sub_archive->flags |= ARCHIVE_EXTRACT_UNCONDITIONAL; 1647 archive_handle->dpkg__sub_archive->accept = conffile_list; 1648 archive_handle->dpkg__sub_archive->filter = filter_rename_config; 1649 archive_handle->dpkg__sub_archive->action_data = data_extract_all_prefix; 1650 archive_handle->dpkg__sub_archive->dpkg__buffer = (char*)"/"; /* huh? */ 1651 archive_handle->dpkg__sub_archive->ah_flags |= ARCHIVE_UNLINK_OLD; 1521 1652 unpack_ar_archive(archive_handle); 1522 1653 1523 1654 /* Create the list file */ 1524 list_filename = xasprintf("/var/lib/dpkg/info/%s. list", package_name);1525 out_stream = xfopen (list_filename, "w");1526 while (archive_handle-> sub_archive->passed) {1655 list_filename = xasprintf("/var/lib/dpkg/info/%s.%s", package_name, "list"); 1656 out_stream = xfopen_for_write(list_filename); 1657 while (archive_handle->dpkg__sub_archive->passed) { 1527 1658 /* the leading . has been stripped by data_extract_all_prefix already */ 1528 fputs(archive_handle-> sub_archive->passed->data, out_stream);1659 fputs(archive_handle->dpkg__sub_archive->passed->data, out_stream); 1529 1660 fputc('\n', out_stream); 1530 archive_handle-> sub_archive->passed = archive_handle->sub_archive->passed->link;1661 archive_handle->dpkg__sub_archive->passed = archive_handle->dpkg__sub_archive->passed->link; 1531 1662 } 1532 1663 fclose(out_stream); … … 1549 1680 1550 1681 /* Run the postinst script */ 1551 if (run_package_script(package_name, "postinst") != 0) { 1552 /* TODO: handle failure gracefully */ 1553 bb_error_msg_and_die("postinst failure.. set status to what?"); 1554 } 1682 /* TODO: handle failure gracefully */ 1683 run_package_script_or_die(package_name, "postinst"); 1684 1555 1685 /* Change status to reflect success */ 1556 1686 set_status(status_num, "install", 1); … … 1558 1688 } 1559 1689 1560 int dpkg_main(int argc, char **argv) ;1561 int dpkg_main(int argc , char **argv)1690 int dpkg_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 1691 int dpkg_main(int argc UNUSED_PARAM, char **argv) 1562 1692 { 1563 1693 deb_file_t **deb_file = NULL; … … 1570 1700 int status_num; 1571 1701 int i; 1572 enum { 1573 OPT_configure = 0x1, 1574 OPT_force_ignore_depends = 0x2, 1575 OPT_install = 0x4, 1576 OPT_list_installed = 0x8, 1577 OPT_purge = 0x10, 1578 OPT_remove = 0x20, 1579 OPT_unpack = 0x40, 1580 }; 1581 1582 opt = getopt32(argv, "CF:ilPru", &str_f); 1702 #if ENABLE_LONG_OPTS 1703 static const char dpkg_longopts[] ALIGN1 = 1704 // FIXME: we use -C non-compatibly, should be: 1705 // "-C|--audit Check for broken package(s)" 1706 "configure\0" No_argument "C" 1707 "force\0" Required_argument "F" 1708 "install\0" No_argument "i" 1709 "list\0" No_argument "l" 1710 "purge\0" No_argument "P" 1711 "remove\0" No_argument "r" 1712 "unpack\0" No_argument "u" 1713 "force-depends\0" No_argument "\xff" 1714 "force-confnew\0" No_argument "\xfe" 1715 "force-confold\0" No_argument "\xfd" 1716 ; 1717 #endif 1718 1719 INIT_G(); 1720 1721 IF_LONG_OPTS(applet_long_options = dpkg_longopts); 1722 opt = getopt32(argv, "CilPruF:", &str_f); 1723 argv += optind; 1583 1724 //if (opt & OPT_configure) ... // -C 1584 if (opt & OPT_force_ignore_depends) { // -F (--force in official dpkg) 1585 if (strcmp(str_f, "depends")) 1586 opt &= ~OPT_force_ignore_depends; 1725 if (opt & OPT_force) { // -F (--force in official dpkg) 1726 if (strcmp(str_f, "depends") == 0) 1727 opt |= OPT_force_ignore_depends; 1728 else if (strcmp(str_f, "confnew") == 0) 1729 opt |= OPT_force_confnew; 1730 else if (strcmp(str_f, "confold") == 0) 1731 opt |= OPT_force_confold; 1732 else 1733 bb_show_usage(); 1734 option_mask32 = opt; 1587 1735 } 1588 1736 //if (opt & OPT_install) ... // -i … … 1591 1739 //if (opt & OPT_remove) ... // -r 1592 1740 //if (opt & OPT_unpack) ... // -u (--unpack in official dpkg) 1593 argc -= optind; 1594 argv += optind; 1595 /* check for non-option argument if expected */ 1596 if (!opt || (!argc && !(opt && OPT_list_installed))) 1741 if (!(opt & OPTMASK_cmd) /* no cmd */ 1742 || ((opt & OPTMASK_cmd) & ((opt & OPTMASK_cmd)-1)) /* more than one cmd */ 1743 ) { 1597 1744 bb_show_usage(); 1598 1599 name_hashtable = xzalloc(sizeof(name_hashtable[0]) * (NAME_HASH_PRIME + 1)); 1600 package_hashtable = xzalloc(sizeof(package_hashtable[0]) * (PACKAGE_HASH_PRIME + 1)); 1601 status_hashtable = xzalloc(sizeof(status_hashtable[0]) * (STATUS_HASH_PRIME + 1)); 1745 } 1602 1746 1603 1747 /* puts("(Reading database ... xxxxx files and directories installed.)"); */ … … 1606 1750 /* if the list action was given print the installed packages and exit */ 1607 1751 if (opt & OPT_list_installed) { 1608 list_packages( );1752 list_packages(argv[0]); /* param can be NULL */ 1609 1753 return EXIT_SUCCESS; 1610 1754 } … … 1613 1757 while (*argv) { 1614 1758 /* deb_count = nb_elem - 1 and we need nb_elem + 1 to allocate terminal node [NULL pointer] */ 1615 deb_file = xrealloc (deb_file, sizeof(deb_file[0]) * (deb_count + 2));1759 deb_file = xrealloc_vector(deb_file, 2, deb_count); 1616 1760 deb_file[deb_count] = xzalloc(sizeof(deb_file[0][0])); 1617 1761 if (opt & (OPT_install | OPT_unpack)) { … … 1626 1770 deb_file[deb_count]->control_file = deb_extract_control_file_to_buffer(archive_handle, control_list); 1627 1771 if (deb_file[deb_count]->control_file == NULL) { 1628 bb_error_msg_and_die("can not extract control file");1772 bb_error_msg_and_die("can't extract control file"); 1629 1773 } 1630 1774 deb_file[deb_count]->filename = xstrdup(argv[0]); … … 1694 1838 /* Check that the deb file arguments are installable */ 1695 1839 if (!(opt & OPT_force_ignore_depends)) { 1696 if (!check_deps(deb_file, 0 , deb_count)) {1840 if (!check_deps(deb_file, 0 /*, deb_count*/)) { 1697 1841 bb_error_msg_and_die("dependency check failed"); 1698 1842 } -
branches/2.2.9/mindi-busybox/archival/dpkg_deb.c
r1765 r2725 3 3 * dpkg-deb packs, unpacks and provides information about Debian archives. 4 4 * 5 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.5 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 6 6 */ 7 7 #include "libbb.h" 8 #include " unarchive.h"8 #include "archive.h" 9 9 10 #define DPKG_DEB_OPT_CONTENTS 11 #define DPKG_DEB_OPT_CONTROL 12 #define DPKG_DEB_OPT_FIELD 13 #define DPKG_DEB_OPT_EXTRACT 14 #define DPKG_DEB_OPT_EXTRACT_VERBOSE 10 #define DPKG_DEB_OPT_CONTENTS 1 11 #define DPKG_DEB_OPT_CONTROL 2 12 #define DPKG_DEB_OPT_FIELD 4 13 #define DPKG_DEB_OPT_EXTRACT 8 14 #define DPKG_DEB_OPT_EXTRACT_VERBOSE 16 15 15 16 int dpkg_deb_main(int argc, char **argv) ;16 int dpkg_deb_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 17 17 int dpkg_deb_main(int argc, char **argv) 18 18 { … … 21 21 llist_t *control_tar_llist = NULL; 22 22 unsigned opt; 23 const char *extract_dir = NULL;24 short argcount = 1;23 const char *extract_dir; 24 int need_args; 25 25 26 26 /* Setup the tar archive handle */ … … 29 29 /* Setup an ar archive handle that refers to the gzip sub archive */ 30 30 ar_archive = init_handle(); 31 ar_archive-> sub_archive = tar_archive;31 ar_archive->dpkg__sub_archive = tar_archive; 32 32 ar_archive->filter = filter_accept_list_reassign; 33 33 34 #if ENABLE_FEATURE_ DEB_TAR_GZ35 llist_add_to(& (ar_archive->accept), (char*)"data.tar.gz");34 #if ENABLE_FEATURE_SEAMLESS_GZ 35 llist_add_to(&ar_archive->accept, (char*)"data.tar.gz"); 36 36 llist_add_to(&control_tar_llist, (char*)"control.tar.gz"); 37 37 #endif 38 39 #if ENABLE_FEATURE_DEB_TAR_BZ2 40 llist_add_to(&(ar_archive->accept), (char*)"data.tar.bz2"); 38 #if ENABLE_FEATURE_SEAMLESS_BZ2 39 llist_add_to(&ar_archive->accept, (char*)"data.tar.bz2"); 41 40 llist_add_to(&control_tar_llist, (char*)"control.tar.bz2"); 42 41 #endif 42 #if ENABLE_FEATURE_SEAMLESS_LZMA 43 llist_add_to(&ar_archive->accept, (char*)"data.tar.lzma"); 44 llist_add_to(&control_tar_llist, (char*)"control.tar.lzma"); 45 #endif 43 46 44 opt_complementary = " ?c--efXx:e--cfXx:f--ceXx:X--cefx:x--cefX";47 opt_complementary = "c--efXx:e--cfXx:f--ceXx:X--cefx:x--cefX"; 45 48 opt = getopt32(argv, "cefXx"); 49 argv += optind; 50 argc -= optind; 46 51 47 52 if (opt & DPKG_DEB_OPT_CONTENTS) { 48 53 tar_archive->action_header = header_verbose_list; 49 54 } 55 extract_dir = NULL; 56 need_args = 1; 50 57 if (opt & DPKG_DEB_OPT_CONTROL) { 51 58 ar_archive->accept = control_tar_llist; 52 59 tar_archive->action_data = data_extract_all; 53 if ( optind +1 == argc) {60 if (1 == argc) { 54 61 extract_dir = "./DEBIAN"; 55 62 } else { 56 argcount++;63 need_args++; 57 64 } 58 65 } … … 71 78 if (opt & (DPKG_DEB_OPT_EXTRACT_VERBOSE | DPKG_DEB_OPT_EXTRACT)) { 72 79 tar_archive->action_data = data_extract_all; 73 argcount= 2;80 need_args = 2; 74 81 } 75 82 76 if ( (optind + argcount)!= argc) {83 if (need_args != argc) { 77 84 bb_show_usage(); 78 85 } 79 86 80 tar_archive->src_fd = ar_archive->src_fd = xopen(argv[ optind++], O_RDONLY);87 tar_archive->src_fd = ar_archive->src_fd = xopen(argv[0], O_RDONLY); 81 88 82 /* Work out where to extract the files */89 /* Work out where to extract the files */ 83 90 /* 2nd argument is a dir name */ 84 if (argv[ optind]) {85 extract_dir = argv[ optind];91 if (argv[1]) { 92 extract_dir = argv[1]; 86 93 } 87 94 if (extract_dir) { … … 89 96 xchdir(extract_dir); 90 97 } 98 99 /* Do it */ 91 100 unpack_ar_archive(ar_archive); 92 101 93 102 /* Cleanup */ 94 close(ar_archive->src_fd); 103 if (ENABLE_FEATURE_CLEAN_UP) 104 close(ar_archive->src_fd); 95 105 96 106 return EXIT_SUCCESS; -
branches/2.2.9/mindi-busybox/archival/gzip.c
r1765 r2725 14 14 * command line handling. 15 15 * 16 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.16 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 17 17 */ 18 18 … … 41 41 42 42 #include "libbb.h" 43 #include "archive.h" 43 44 44 45 … … 68 69 #define SMALL_MEM 69 70 70 #ifndef 71 #ifndef INBUFSIZ 71 72 # ifdef SMALL_MEM 72 73 # define INBUFSIZ 0x2000 /* input buffer size */ … … 76 77 #endif 77 78 78 #ifndef 79 #ifndef OUTBUFSIZ 79 80 # ifdef SMALL_MEM 80 81 # define OUTBUFSIZ 8192 /* output buffer size */ … … 267 268 type * array 268 269 #define ALLOC(type, array, size) \ 269 array = xzalloc((size_t)(((size)+1L)/2) * 2*sizeof(type)) ;270 array = xzalloc((size_t)(((size)+1L)/2) * 2*sizeof(type)) 270 271 #define FREE(array) \ 271 272 do { free(array); array = NULL; } while (0) … … 340 341 #endif 341 342 342 uint32_t *crc_32_tab;343 /*uint32_t *crc_32_tab;*/ 343 344 uint32_t crc; /* shift register contents */ 344 345 }; … … 389 390 390 391 /* =========================================================================== 391 * Clear input and output buffers392 */393 static void clear_bufs(void)394 {395 G1.outcnt = 0;396 #ifdef DEBUG397 G1.insize = 0;398 #endif399 G1.isize = 0;400 }401 402 403 /* ===========================================================================404 392 * Run a set of bytes through the crc shift register. If s is a NULL 405 393 * pointer, then initialize the crc shift register contents instead. 406 394 * Return the current crc in either case. 407 395 */ 408 static uint32_t updcrc(uch * s, unsigned n) 409 { 410 uint32_t c = G1.crc; 411 while (n) { 412 c = G1.crc_32_tab[(uch)(c ^ *s++)] ^ (c >> 8); 413 n--; 414 } 415 G1.crc = c; 416 return c; 396 static void updcrc(uch * s, unsigned n) 397 { 398 G1.crc = crc32_block_endian0(G1.crc, s, n, global_crc32_table /*G1.crc_32_tab*/); 417 399 } 418 400 … … 633 615 * or if the match length is less than 2: 634 616 */ 635 if (match[best_len] != scan_end || 636 match[best_len - 1] != scan_end1 || 637 *match != *scan || *++match != scan[1]) 617 if (match[best_len] != scan_end 618 || match[best_len - 1] != scan_end1 619 || *match != *scan || *++match != scan[1] 620 ) { 638 621 continue; 622 } 639 623 640 624 /* The check at best_len-1 can be removed because it will be made … … 687 671 bb_error_msg("\\[%d,%d]", start - match, length); 688 672 do { 689 putc(G1.window[start++], stderr);673 bb_putchar_stderr(G1.window[start++]); 690 674 } while (--length != 0); 691 675 } … … 975 959 # define SEND_CODE(c, tree) \ 976 960 { \ 977 if (verbose > 1) bb_error_msg("\ncd %3d ", (c)); \961 if (verbose > 1) bb_error_msg("\ncd %3d ", (c)); \ 978 962 send_bits(tree[c].Code, tree[c].Len); \ 979 963 } … … 1186 1170 Tracec(tree != G2.static_ltree, 1187 1171 (stderr, "\nn %3d %c l %2d c %4x (%x) ", n, 1188 ( isgraph(n)? n : ' '), len, tree[n].Code,1172 (n > ' ' ? n : ' '), len, tree[n].Code, 1189 1173 next_code[len] - 1)); 1190 1174 } … … 1554 1538 if ((flag & 1) == 0) { 1555 1539 SEND_CODE(lc, ltree); /* send a literal byte */ 1556 Tracecv( isgraph(lc), (stderr, " '%c' ", lc));1540 Tracecv(lc > ' ', (stderr, " '%c' ", lc)); 1557 1541 } else { 1558 1542 /* Here, lc is the match length - MIN_MATCH */ … … 2009 1993 /* ======================================================================== */ 2010 1994 static 2011 char* make_new_name_gzip(char *filename) 2012 { 2013 return xasprintf("%s.gz", filename); 2014 } 2015 2016 static 2017 USE_DESKTOP(long long) int pack_gzip(void) 1995 IF_DESKTOP(long long) int FAST_FUNC pack_gzip(unpack_info_t *info UNUSED_PARAM) 2018 1996 { 2019 1997 struct stat s; 2020 1998 2021 clear_bufs(); 2022 s.st_ctime = 0; 2023 fstat(STDIN_FILENO, &s); 2024 zip(s.st_ctime); 2025 return 0; 2026 } 2027 2028 int gzip_main(int argc, char **argv); 2029 int gzip_main(int argc, char **argv) 2030 { 2031 unsigned opt; 2032 2033 /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */ 2034 opt = getopt32(argv, "cfv" USE_GUNZIP("d") "q123456789" ); 2035 option_mask32 &= 0x7; /* Clear -d, ignore -q, -0..9 */ 2036 //if (opt & 0x1) // -c 2037 //if (opt & 0x2) // -f 2038 //if (opt & 0x4) // -v 2039 #if ENABLE_GUNZIP /* gunzip_main may not be visible... */ 2040 if (opt & 0x8) { // -d 2041 return gunzip_main(argc, argv); 2042 } 2043 #endif 2044 argv += optind; 2045 2046 PTR_TO_GLOBALS = xzalloc(sizeof(struct globals) + sizeof(struct globals2)) 2047 + sizeof(struct globals); 2048 G2.l_desc.dyn_tree = G2.dyn_ltree; 2049 G2.l_desc.static_tree = G2.static_ltree; 2050 G2.l_desc.extra_bits = extra_lbits; 2051 G2.l_desc.extra_base = LITERALS + 1; 2052 G2.l_desc.elems = L_CODES; 2053 G2.l_desc.max_length = MAX_BITS; 2054 //G2.l_desc.max_code = 0; 2055 2056 G2.d_desc.dyn_tree = G2.dyn_dtree; 2057 G2.d_desc.static_tree = G2.static_dtree; 2058 G2.d_desc.extra_bits = extra_dbits; 2059 //G2.d_desc.extra_base = 0; 2060 G2.d_desc.elems = D_CODES; 2061 G2.d_desc.max_length = MAX_BITS; 2062 //G2.d_desc.max_code = 0; 2063 1999 /* Clear input and output buffers */ 2000 G1.outcnt = 0; 2001 #ifdef DEBUG 2002 G1.insize = 0; 2003 #endif 2004 G1.isize = 0; 2005 2006 /* Reinit G2.xxx */ 2007 memset(&G2, 0, sizeof(G2)); 2008 G2.l_desc.dyn_tree = G2.dyn_ltree; 2009 G2.l_desc.static_tree = G2.static_ltree; 2010 G2.l_desc.extra_bits = extra_lbits; 2011 G2.l_desc.extra_base = LITERALS + 1; 2012 G2.l_desc.elems = L_CODES; 2013 G2.l_desc.max_length = MAX_BITS; 2014 //G2.l_desc.max_code = 0; 2015 G2.d_desc.dyn_tree = G2.dyn_dtree; 2016 G2.d_desc.static_tree = G2.static_dtree; 2017 G2.d_desc.extra_bits = extra_dbits; 2018 //G2.d_desc.extra_base = 0; 2019 G2.d_desc.elems = D_CODES; 2020 G2.d_desc.max_length = MAX_BITS; 2021 //G2.d_desc.max_code = 0; 2064 2022 G2.bl_desc.dyn_tree = G2.bl_tree; 2065 2023 //G2.bl_desc.static_tree = NULL; … … 2070 2028 //G2.bl_desc.max_code = 0; 2071 2029 2030 s.st_ctime = 0; 2031 fstat(STDIN_FILENO, &s); 2032 zip(s.st_ctime); 2033 return 0; 2034 } 2035 2036 #if ENABLE_FEATURE_GZIP_LONG_OPTIONS 2037 static const char gzip_longopts[] ALIGN1 = 2038 "stdout\0" No_argument "c" 2039 "to-stdout\0" No_argument "c" 2040 "force\0" No_argument "f" 2041 "verbose\0" No_argument "v" 2042 #if ENABLE_GUNZIP 2043 "decompress\0" No_argument "d" 2044 "uncompress\0" No_argument "d" 2045 "test\0" No_argument "t" 2046 #endif 2047 "quiet\0" No_argument "q" 2048 "fast\0" No_argument "1" 2049 "best\0" No_argument "9" 2050 ; 2051 #endif 2052 2053 /* 2054 * Linux kernel build uses gzip -d -n. We accept and ignore -n. 2055 * Man page says: 2056 * -n --no-name 2057 * gzip: do not save the original file name and time stamp. 2058 * (The original name is always saved if the name had to be truncated.) 2059 * gunzip: do not restore the original file name/time even if present 2060 * (remove only the gzip suffix from the compressed file name). 2061 * This option is the default when decompressing. 2062 * -N --name 2063 * gzip: always save the original file name and time stamp (this is the default) 2064 * gunzip: restore the original file name and time stamp if present. 2065 */ 2066 2067 int gzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 2068 #if ENABLE_GUNZIP 2069 int gzip_main(int argc, char **argv) 2070 #else 2071 int gzip_main(int argc UNUSED_PARAM, char **argv) 2072 #endif 2073 { 2074 unsigned opt; 2075 2076 #if ENABLE_FEATURE_GZIP_LONG_OPTIONS 2077 applet_long_options = gzip_longopts; 2078 #endif 2079 /* Must match bbunzip's constants OPT_STDOUT, OPT_FORCE! */ 2080 opt = getopt32(argv, "cfv" IF_GUNZIP("dt") "q123456789n"); 2081 #if ENABLE_GUNZIP /* gunzip_main may not be visible... */ 2082 if (opt & 0x18) // -d and/or -t 2083 return gunzip_main(argc, argv); 2084 #endif 2085 option_mask32 &= 0x7; /* ignore -q, -0..9 */ 2086 //if (opt & 0x1) // -c 2087 //if (opt & 0x2) // -f 2088 //if (opt & 0x4) // -v 2089 argv += optind; 2090 2091 SET_PTR_TO_GLOBALS((char *)xzalloc(sizeof(struct globals)+sizeof(struct globals2)) 2092 + sizeof(struct globals)); 2093 2072 2094 /* Allocate all global buffers (for DYN_ALLOC option) */ 2073 2095 ALLOC(uch, G1.l_buf, INBUFSIZ); … … 2077 2099 ALLOC(ush, G1.prev, 1L << BITS); 2078 2100 2079 /* Initiali se the CRC32 table */2080 G1.crc_32_tab= crc32_filltable(NULL, 0);2081 2082 return bbunpack(argv, make_new_name_gzip, pack_gzip);2083 } 2101 /* Initialize the CRC32 table */ 2102 global_crc32_table = crc32_filltable(NULL, 0); 2103 2104 return bbunpack(argv, pack_gzip, append_ext, "gz"); 2105 } -
branches/2.2.9/mindi-busybox/archival/rpm.c
r1765 r2725 5 5 * Copyright (C) 2001,2002 by Laurence Anderson 6 6 * 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 8 */ 9 9 10 10 #include "libbb.h" 11 #include " unarchive.h"12 13 #define RPM_HEADER_MAGIC "\216\255\350" 11 #include "archive.h" 12 #include "rpm.h" 13 14 14 #define RPM_CHAR_TYPE 1 15 15 #define RPM_INT8_TYPE 2 … … 47 47 #define TAG_BASENAMES 1117 48 48 #define TAG_DIRNAMES 1118 49 49 50 #define RPMFILE_CONFIG (1 << 0) 50 51 #define RPMFILE_DOC (1 << 1) … … 71 72 static int tagcount; 72 73 73 static void extract_cpio _gz(int fd);74 static void extract_cpio(int fd, const char *source_rpm); 74 75 static rpm_index **rpm_gettags(int fd, int *num_tags); 75 76 static int bsearch_rpmtag(const void *key, const void *item); … … 81 82 static void loop_through_files(int filetag, void (*fileaction)(char *filename, int fileref)); 82 83 83 int rpm_main(int argc, char **argv) ;84 int rpm_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 84 85 int rpm_main(int argc, char **argv) 85 86 { … … 116 117 } 117 118 argv += optind; 118 argc -= optind; 119 if (!argc) bb_show_usage(); 119 //argc -= optind; 120 if (!argv[0]) { 121 bb_show_usage(); 122 } 120 123 121 124 while (*argv) { 125 const char *source_rpm; 126 122 127 rpm_fd = xopen(*argv++, O_RDONLY); 123 128 mytags = rpm_gettags(rpm_fd, &tagcount); … … 128 133 map = mmap(0, offset > pagesize ? (offset + offset % pagesize) : pagesize, PROT_READ, MAP_PRIVATE, rpm_fd, 0); 129 134 135 source_rpm = rpm_getstr(TAG_SOURCERPM, 0); 136 130 137 if (func & rpm_install) { 131 138 /* Backup any config files */ 132 139 loop_through_files(TAG_BASENAMES, fileaction_dobackup); 133 140 /* Extact the archive */ 134 extract_cpio _gz(rpm_fd);141 extract_cpio(rpm_fd, source_rpm); 135 142 /* Set the correct file uid/gid's */ 136 143 loop_through_files(TAG_BASENAMES, fileaction_setowngrp); … … 144 151 /* Do the nice printout */ 145 152 time_t bdate_time; 146 struct tm *bdate ;153 struct tm *bdate_ptm; 147 154 char bdatestring[50]; 148 printf("Name : %-29sRelocations: %s\n", rpm_getstr(TAG_NAME, 0), rpm_getstr(TAG_PREFIXS, 0) ? rpm_getstr(TAG_PREFIXS, 0) : "(not relocateable)"); 149 printf("Version : %-34sVendor: %s\n", rpm_getstr(TAG_VERSION, 0), rpm_getstr(TAG_VENDOR, 0) ? rpm_getstr(TAG_VENDOR, 0) : "(none)"); 155 const char *p; 156 157 p = rpm_getstr(TAG_PREFIXS, 0); 158 if (!p) p = "(not relocateable)"; 159 printf("Name : %-29sRelocations: %s\n", rpm_getstr(TAG_NAME, 0), p); 160 p = rpm_getstr(TAG_VENDOR, 0); 161 if (!p) p = "(none)"; 162 printf("Version : %-34sVendor: %s\n", rpm_getstr(TAG_VERSION, 0), p); 150 163 bdate_time = rpm_getint(TAG_BUILDTIME, 0); 151 bdate = localtime((time_t *)&bdate_time);152 strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate );164 bdate_ptm = localtime(&bdate_time); 165 strftime(bdatestring, 50, "%a %d %b %Y %T %Z", bdate_ptm); 153 166 printf("Release : %-30sBuild Date: %s\n", rpm_getstr(TAG_RELEASE, 0), bdatestring); 154 167 printf("Install date: %-30sBuild Host: %s\n", "(not installed)", rpm_getstr(TAG_BUILDHOST, 0)); 155 printf("Group : %-30sSource RPM: %s\n", rpm_getstr(TAG_GROUP, 0), rpm_getstr(TAG_SOURCERPM, 0));168 printf("Group : %-30sSource RPM: %s\n", rpm_getstr(TAG_GROUP, 0), source_rpm); 156 169 printf("Size : %-33dLicense: %s\n", rpm_getint(TAG_SIZE, 0), rpm_getstr(TAG_LICENSE, 0)); 157 170 printf("URL : %s\n", rpm_getstr(TAG_URL, 0)); … … 186 199 } 187 200 188 static void extract_cpio _gz(int fd)201 static void extract_cpio(int fd, const char *source_rpm) 189 202 { 190 203 archive_handle_t *archive_handle; 191 unsigned char magic[2]; 192 #if BB_MMU 193 USE_DESKTOP(long long) int (*xformer)(int src_fd, int dst_fd); 194 enum { xformer_prog = 0 }; 195 #else 196 enum { xformer = 0 }; 197 const char *xformer_prog; 198 #endif 204 205 if (source_rpm != NULL) { 206 /* Binary rpm (it was built from some SRPM), install to root */ 207 xchdir("/"); 208 } /* else: SRPM, install to current dir */ 199 209 200 210 /* Initialize */ 201 211 archive_handle = init_handle(); 202 212 archive_handle->seek = seek_by_read; 203 //archive_handle->action_header = header_list;204 213 archive_handle->action_data = data_extract_all; 205 archive_handle->flags |= ARCHIVE_PRESERVE_DATE; 206 archive_handle->flags |= ARCHIVE_CREATE_LEADING_DIRS; 214 #if 0 /* For testing (rpm -i only lists the files in internal cpio): */ 215 archive_handle->action_header = header_list; 216 archive_handle->action_data = data_skip; 217 #endif 218 archive_handle->ah_flags = ARCHIVE_RESTORE_DATE | ARCHIVE_CREATE_LEADING_DIRS 219 /* compat: overwrite existing files. 220 * try "rpm -i foo.src.rpm" few times in a row - 221 * standard rpm will not complain. 222 * (TODO? real rpm creates "file;1234" and then renames it) */ 223 | ARCHIVE_UNLINK_OLD; 207 224 archive_handle->src_fd = fd; 208 archive_handle->offset = 0; 209 210 xread(archive_handle->src_fd, &magic, 2); 211 #if BB_MMU 212 xformer = unpack_gz_stream; 213 #else 214 xformer_prog = "gunzip"; 215 #endif 216 if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) { 217 if (ENABLE_FEATURE_RPM_BZ2 218 && (magic[0] == 0x42) && (magic[1] == 0x5a)) { 219 #if BB_MMU 220 xformer = unpack_bz2_stream; 221 #else 222 xformer_prog = "bunzip2"; 223 #endif 224 /* We can do better, need modifying unpack_bz2_stream to not require 225 * first 2 bytes. Not very hard to do... I mean, TODO :) */ 226 xlseek(archive_handle->src_fd, -2, SEEK_CUR); 227 } else 228 bb_error_msg_and_die("no gzip" 229 USE_FEATURE_RPM_BZ2("/bzip") 230 " magic"); 231 } else { 232 check_header_gzip_or_die(archive_handle->src_fd); 233 #if !BB_MMU 234 /* NOMMU version of open_transformer execs an external unzipper that should 235 * have the file position at the start of the file */ 236 xlseek(archive_handle->src_fd, 0, SEEK_SET); 237 #endif 238 } 239 240 xchdir("/"); /* Install RPM's to root */ 241 archive_handle->src_fd = open_transformer(archive_handle->src_fd, xformer, xformer_prog, xformer_prog, "-cf", "-", NULL); 242 archive_handle->offset = 0; 225 /*archive_handle->offset = 0; - init_handle() did it */ 226 227 setup_unzip_on_fd(archive_handle->src_fd /*, fail_if_not_detected: 1*/); 243 228 while (get_header_cpio(archive_handle) == EXIT_SUCCESS) 244 229 continue; 245 230 } 246 231 247 248 232 static rpm_index **rpm_gettags(int fd, int *num_tags) 249 233 { 250 /* We should never need mo de than 200, and realloc later*/251 rpm_index **tags = xzalloc(200 * sizeof( struct rpmtag *));234 /* We should never need more than 200 (shrink via realloc later) */ 235 rpm_index **tags = xzalloc(200 * sizeof(tags[0])); 252 236 int pass, tagindex = 0; 253 237 … … 256 240 /* 1st pass is the signature headers, 2nd is the main stuff */ 257 241 for (pass = 0; pass < 2; pass++) { 258 struct { 259 char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */ 260 uint8_t version; /* 1 byte version number */ 261 uint32_t reserved; /* 4 bytes reserved */ 262 uint32_t entries; /* Number of entries in header (4 bytes) */ 263 uint32_t size; /* Size of store (4 bytes) */ 264 } header; 242 struct rpm_header header; 265 243 rpm_index *tmpindex; 266 244 int storepos; 267 245 268 246 xread(fd, &header, sizeof(header)); 269 if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) 270 return NULL; /* Invalid magic */ 271 if (header.version != 1) 272 return NULL; /* This program only supports v1 headers */ 247 if (header.magic_and_ver != htonl(RPM_HEADER_MAGICnVER)) 248 return NULL; /* Invalid magic, or not version 1 */ 273 249 header.size = ntohl(header.size); 274 250 header.entries = ntohl(header.entries); 275 storepos = xlseek(fd, 0,SEEK_CUR) + header.entries * 16;251 storepos = xlseek(fd, 0, SEEK_CUR) + header.entries * 16; 276 252 277 253 while (header.entries--) { 278 tmpindex = tags[tagindex++] = xmalloc(sizeof( rpm_index));279 xread(fd, tmpindex, sizeof( rpm_index));254 tmpindex = tags[tagindex++] = xmalloc(sizeof(*tmpindex)); 255 xread(fd, tmpindex, sizeof(*tmpindex)); 280 256 tmpindex->tag = ntohl(tmpindex->tag); 281 257 tmpindex->type = ntohl(tmpindex->type); 282 258 tmpindex->count = ntohl(tmpindex->count); 283 259 tmpindex->offset = storepos + ntohl(tmpindex->offset); 284 if (pass ==0)260 if (pass == 0) 285 261 tmpindex->tag -= 743; 286 262 } 287 xlseek(fd, header.size, SEEK_CUR); /* Seek past store */263 storepos = xlseek(fd, header.size, SEEK_CUR); /* Seek past store */ 288 264 /* Skip padding to 8 byte boundary after reading signature headers */ 289 if (pass==0) 290 xlseek(fd, (8 - (xlseek(fd,0,SEEK_CUR) % 8)) % 8, SEEK_CUR); 291 } 292 tags = xrealloc(tags, tagindex * sizeof(struct rpmtag *)); /* realloc tags to save space */ 265 if (pass == 0) 266 xlseek(fd, (-storepos) & 0x7, SEEK_CUR); 267 } 268 /* realloc tags to save space */ 269 tags = xrealloc(tags, tagindex * sizeof(tags[0])); 293 270 *num_tags = tagindex; 294 return tags; /* All done, leave the file at the start of the gzipped cpio archive */ 271 /* All done, leave the file at the start of the gzipped cpio archive */ 272 return tags; 295 273 } 296 274 … … 317 295 if (!found || itemindex >= found[0]->count) 318 296 return NULL; 319 if (found[0]->type == RPM_STRING_TYPE || found[0]->type == RPM_I18NSTRING_TYPE || found[0]->type == RPM_STRING_ARRAY_TYPE) { 297 if (found[0]->type == RPM_STRING_TYPE 298 || found[0]->type == RPM_I18NSTRING_TYPE 299 || found[0]->type == RPM_STRING_ARRAY_TYPE 300 ) { 320 301 int n; 321 char *tmpstr = (char *) (map + found[0]->offset);322 for (n =0; n < itemindex; n++)302 char *tmpstr = (char *) map + found[0]->offset; 303 for (n = 0; n < itemindex; n++) 323 304 tmpstr = tmpstr + strlen(tmpstr) + 1; 324 305 return tmpstr; … … 338 319 return -1; 339 320 340 tmpint = (int *) ( map + found[0]->offset);321 tmpint = (int *) ((char *) map + found[0]->offset); 341 322 342 323 if (found[0]->type == RPM_INT32_TYPE) { … … 381 362 static void fileaction_setowngrp(char *filename, int fileref) 382 363 { 383 int uid, gid; 384 uid = xuname2uid(rpm_getstr(TAG_FILEUSERNAME, fileref)); 385 gid = xgroup2gid(rpm_getstr(TAG_FILEGROUPNAME, fileref)); 364 /* real rpm warns: "user foo does not exist - using <you>" */ 365 struct passwd *pw = getpwnam(rpm_getstr(TAG_FILEUSERNAME, fileref)); 366 int uid = pw ? pw->pw_uid : getuid(); /* or euid? */ 367 struct group *gr = getgrnam(rpm_getstr(TAG_FILEGROUPNAME, fileref)); 368 int gid = gr ? gr->gr_gid : getgid(); 386 369 chown(filename, uid, gid); 387 370 } -
branches/2.2.9/mindi-busybox/archival/rpm2cpio.c
r1765 r2725 5 5 * Copyright (C) 2001 by Laurence Anderson 6 6 * 7 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 8 8 */ 9 9 #include "libbb.h" 10 #include "unarchive.h" 10 #include "archive.h" 11 #include "rpm.h" 11 12 12 #define RPM_MAGIC "\355\253\356\333" 13 #define RPM_HEADER_MAGIC "\216\255\350" 13 enum { rpm_fd = STDIN_FILENO }; 14 14 15 struct rpm_lead { 16 unsigned char magic[4]; 17 uint8_t major, minor; 18 uint16_t type; 19 uint16_t archnum; 20 char name[66]; 21 uint16_t osnum; 22 uint16_t signature_type; 23 char reserved[16]; 24 }; 25 26 struct rpm_header { 27 char magic[3]; /* 3 byte magic: 0x8e 0xad 0xe8 */ 28 uint8_t version; /* 1 byte version number */ 29 uint32_t reserved; /* 4 bytes reserved */ 30 uint32_t entries; /* Number of entries in header (4 bytes) */ 31 uint32_t size; /* Size of store (4 bytes) */ 32 }; 33 34 static void skip_header(int rpm_fd) 15 static unsigned skip_header(void) 35 16 { 36 17 struct rpm_header header; 18 unsigned len; 37 19 38 xread(rpm_fd, &header, sizeof(struct rpm_header)); 39 if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC, 3) != 0) { 40 bb_error_msg_and_die("invalid RPM header magic"); /* Invalid magic */ 20 xread(rpm_fd, &header, sizeof(header)); 21 // if (strncmp((char *) &header.magic, RPM_HEADER_MAGIC_STR, 3) != 0) { 22 // bb_error_msg_and_die("invalid RPM header magic"); 23 // } 24 // if (header.version != 1) { 25 // bb_error_msg_and_die("unsupported RPM header version"); 26 // } 27 if (header.magic_and_ver != htonl(RPM_HEADER_MAGICnVER)) { 28 bb_error_msg_and_die("invalid RPM header magic or unsupported version"); 29 // ": %x != %x", header.magic_and_ver, htonl(RPM_HEADER_MAGICnVER)); 41 30 } 42 if (header.version != 1) { 43 bb_error_msg_and_die("unsupported RPM header version"); /* This program only supports v1 headers */ 44 } 45 header.entries = ntohl(header.entries); 46 header.size = ntohl(header.size); 47 lseek (rpm_fd, 16 * header.entries, SEEK_CUR); /* Seek past index entries */ 48 lseek (rpm_fd, header.size, SEEK_CUR); /* Seek past store */ 31 32 /* Seek past index entries, and past store */ 33 len = 16 * ntohl(header.entries) + ntohl(header.size); 34 seek_by_jump(rpm_fd, len); 35 36 return sizeof(header) + len; 49 37 } 50 38 51 39 /* No getopt required */ 52 int rpm2cpio_main(int argc, char **argv) ;53 int rpm2cpio_main(int argc , char **argv)40 int rpm2cpio_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 41 int rpm2cpio_main(int argc UNUSED_PARAM, char **argv) 54 42 { 55 43 struct rpm_lead lead; 56 int rpm_fd; 57 unsigned char magic[2]; 44 unsigned pos; 58 45 59 if (argc == 1) { 60 rpm_fd = STDIN_FILENO; 61 } else { 62 rpm_fd = xopen(argv[1], O_RDONLY); 46 if (argv[1]) { 47 xmove_fd(xopen(argv[1], O_RDONLY), rpm_fd); 48 } 49 xread(rpm_fd, &lead, sizeof(lead)); 50 51 /* Just check the magic, the rest is irrelevant */ 52 if (lead.magic != htonl(RPM_LEAD_MAGIC)) { 53 bb_error_msg_and_die("invalid RPM magic"); 63 54 } 64 55 65 xread(rpm_fd, &lead, sizeof(struct rpm_lead)); 66 if (strncmp((char *) &lead.magic, RPM_MAGIC, 4) != 0) { 67 bb_error_msg_and_die("invalid RPM magic"); /* Just check the magic, the rest is irrelevant */ 68 } 69 70 /* Skip the signature header */ 71 skip_header(rpm_fd); 72 lseek(rpm_fd, (8 - (lseek(rpm_fd, 0, SEEK_CUR) % 8)) % 8, SEEK_CUR); 56 /* Skip the signature header, align to 8 bytes */ 57 pos = skip_header(); 58 seek_by_jump(rpm_fd, (-(int)pos) & 7); 73 59 74 60 /* Skip the main header */ 75 skip_header( rpm_fd);61 skip_header(); 76 62 77 xread(rpm_fd, &magic, 2); 78 if ((magic[0] != 0x1f) || (magic[1] != 0x8b)) { 79 bb_error_msg_and_die("invalid gzip magic"); 63 #if 0 64 /* This works, but doesn't report uncompress errors (they happen in child) */ 65 setup_unzip_on_fd(rpm_fd /*fail_if_not_detected: 1*/); 66 if (bb_copyfd_eof(rpm_fd, STDOUT_FILENO) < 0) 67 bb_error_msg_and_die("error unpacking"); 68 #else 69 /* BLOAT */ 70 { 71 union { 72 uint8_t b[4]; 73 uint16_t b16[2]; 74 uint32_t b32[1]; 75 } magic; 76 IF_DESKTOP(long long) int FAST_FUNC (*unpack)(int src_fd, int dst_fd); 77 78 xread(rpm_fd, magic.b16, sizeof(magic.b16[0])); 79 if (magic.b16[0] == GZIP_MAGIC) { 80 unpack = unpack_gz_stream; 81 } else 82 if (ENABLE_FEATURE_SEAMLESS_BZ2 83 && magic.b16[0] == BZIP2_MAGIC 84 ) { 85 unpack = unpack_bz2_stream; 86 } else 87 if (ENABLE_FEATURE_SEAMLESS_XZ 88 && magic.b16[0] == XZ_MAGIC1 89 ) { 90 xread(rpm_fd, magic.b32, sizeof(magic.b32[0])); 91 if (magic.b32[0] != XZ_MAGIC2) 92 goto no_magic; 93 /* unpack_xz_stream wants fd at position 6, no need to seek */ 94 //xlseek(rpm_fd, -6, SEEK_CUR); 95 unpack = unpack_xz_stream; 96 } else { 97 no_magic: 98 bb_error_msg_and_die("no gzip" 99 IF_FEATURE_SEAMLESS_BZ2("/bzip2") 100 IF_FEATURE_SEAMLESS_XZ("/xz") 101 " magic"); 102 } 103 if (unpack(rpm_fd, STDOUT_FILENO) < 0) 104 bb_error_msg_and_die("error unpacking"); 80 105 } 106 #endif 81 107 82 check_header_gzip_or_die(rpm_fd); 83 if (unpack_gz_stream(rpm_fd, STDOUT_FILENO) < 0) { 84 bb_error_msg("error inflating"); 108 if (ENABLE_FEATURE_CLEAN_UP) { 109 close(rpm_fd); 85 110 } 86 87 close(rpm_fd);88 111 89 112 return 0; -
branches/2.2.9/mindi-busybox/archival/tar.c
r1765 r2725 4 4 * 5 5 * Modified to use common extraction code used by ar, cpio, dpkg-deb, dpkg 6 * Glenn McGrath <bug1@iinet.net.au>6 * by Glenn McGrath 7 7 * 8 8 * Note, that as of BusyBox-0.43, tar has been completely rewritten from the … … 16 16 * Permission is granted to use, distribute, or modify this source, 17 17 * provided that this copyright notice remains intact. 18 * Permission to distribute sash derived code under theGPL has been granted.18 * Permission to distribute sash derived code under GPL has been granted. 19 19 * 20 20 * Based in part on the tar implementation from busybox-0.28 21 21 * Copyright (C) 1995 Bruce Perens 22 22 * 23 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.23 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 24 24 */ 25 25 26 26 #include <fnmatch.h> 27 #include <getopt.h>28 27 #include "libbb.h" 29 #include "unarchive.h" 28 #include "archive.h" 29 /* FIXME: Stop using this non-standard feature */ 30 #ifndef FNM_LEADING_DIR 31 # define FNM_LEADING_DIR 0 32 #endif 33 34 35 //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__) 36 #define DBG(...) ((void)0) 37 30 38 31 39 #define block_buf bb_common_bufsiz1 32 40 41 42 #if !ENABLE_FEATURE_SEAMLESS_GZ && !ENABLE_FEATURE_SEAMLESS_BZ2 43 /* Do not pass gzip flag to writeTarFile() */ 44 #define writeTarFile(tar_fd, verboseFlag, dereferenceFlag, include, exclude, gzip) \ 45 writeTarFile(tar_fd, verboseFlag, dereferenceFlag, include, exclude) 46 #endif 47 48 33 49 #if ENABLE_FEATURE_TAR_CREATE 34 35 /* Tar file constants */36 37 #define TAR_BLOCK_SIZE 51238 39 /* POSIX tar Header Block, from POSIX 1003.1-1990 */40 #define NAME_SIZE 10041 #define NAME_SIZE_STR "100"42 typedef struct TarHeader TarHeader;43 struct TarHeader { /* byte offset */44 char name[NAME_SIZE]; /* 0-99 */45 char mode[8]; /* 100-107 */46 char uid[8]; /* 108-115 */47 char gid[8]; /* 116-123 */48 char size[12]; /* 124-135 */49 char mtime[12]; /* 136-147 */50 char chksum[8]; /* 148-155 */51 char typeflag; /* 156-156 */52 char linkname[NAME_SIZE]; /* 157-256 */53 char magic[6]; /* 257-262 */54 char version[2]; /* 263-264 */55 char uname[32]; /* 265-296 */56 char gname[32]; /* 297-328 */57 char devmajor[8]; /* 329-336 */58 char devminor[8]; /* 337-344 */59 char prefix[155]; /* 345-499 */60 char padding[12]; /* 500-512 (pad to exactly the TAR_BLOCK_SIZE) */61 };62 50 63 51 /* … … 66 54 ** Even these functions use the xxxHardLinkInfo() functions. 67 55 */ 68 typedef struct HardLinkInfo HardLinkInfo; 69 struct HardLinkInfo { 70 HardLinkInfo *next; /* Next entry in list */ 71 dev_t dev; /* Device number */ 72 ino_t ino; /* Inode number */ 73 short linkCount; /* (Hard) Link Count */ 74 char name[1]; /* Start of filename (must be last) */ 75 }; 56 typedef struct HardLinkInfo { 57 struct HardLinkInfo *next; /* Next entry in list */ 58 dev_t dev; /* Device number */ 59 ino_t ino; /* Inode number */ 60 // short linkCount; /* (Hard) Link Count */ 61 char name[1]; /* Start of filename (must be last) */ 62 } HardLinkInfo; 76 63 77 64 /* Some info to be carried along when creating a new tarball */ 78 typedef struct TarBallInfo TarBallInfo;79 struct TarBallInfo { 80 int tarFd; /* Open-for-write file descriptor81 for the tarball*/82 struct stat statBuf; /* Stat info for the tarball, letting83 us know the inode and device that the84 tarball lives, so we can avoid trying85 to include the tarball into itself */ 86 int verboseFlag; /* Whether to print extra stuff or not */87 const llist_t *excludeList; /* List of files to not include */88 HardLinkInfo *hlInfoHead; /* Hard Link Tracking Information */89 HardLinkInfo *hlInfo; /* Hard Link Info for the current file*/90 } ;65 typedef struct TarBallInfo { 66 int tarFd; /* Open-for-write file descriptor 67 * for the tarball */ 68 int verboseFlag; /* Whether to print extra stuff or not */ 69 const llist_t *excludeList; /* List of files to not include */ 70 HardLinkInfo *hlInfoHead; /* Hard Link Tracking Information */ 71 HardLinkInfo *hlInfo; /* Hard Link Info for the current file */ 72 //TODO: save only st_dev + st_ino 73 struct stat tarFileStatBuf; /* Stat info for the tarball, letting 74 * us know the inode and device that the 75 * tarball lives, so we can avoid trying 76 * to include the tarball into itself */ 77 } TarBallInfo; 91 78 92 79 /* A nice enum with all the possible tar file content types */ 93 enum TarFileType{80 enum { 94 81 REGTYPE = '0', /* regular file */ 95 82 REGTYPE0 = '\0', /* regular file (ancient bug compat) */ … … 104 91 GNULONGNAME = 'L', /* GNU long (>100 chars) file name */ 105 92 }; 106 typedef enum TarFileType TarFileType;107 93 108 94 /* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */ 109 static void addHardLinkInfo(HardLinkInfo ** 95 static void addHardLinkInfo(HardLinkInfo **hlInfoHeadPtr, 110 96 struct stat *statbuf, 111 97 const char *fileName) … … 119 105 hlInfo->dev = statbuf->st_dev; 120 106 hlInfo->ino = statbuf->st_ino; 121 hlInfo->linkCount = statbuf->st_nlink;107 // hlInfo->linkCount = statbuf->st_nlink; 122 108 strcpy(hlInfo->name, fileName); 123 109 } 124 110 125 static void freeHardLinkInfo(HardLinkInfo ** 111 static void freeHardLinkInfo(HardLinkInfo **hlInfoHeadPtr) 126 112 { 127 113 HardLinkInfo *hlInfo; … … 139 125 } 140 126 141 /* Might be faster (and bigger) if the dev/ino were stored in numeric order ;) */142 static HardLinkInfo *findHardLinkInfo(HardLinkInfo * 127 /* Might be faster (and bigger) if the dev/ino were stored in numeric order ;) */ 128 static HardLinkInfo *findHardLinkInfo(HardLinkInfo *hlInfo, struct stat *statbuf) 143 129 { 144 130 while (hlInfo) { 145 if ((statbuf->st_ino == hlInfo->ino) && (statbuf->st_dev == hlInfo->dev)) 131 if (statbuf->st_ino == hlInfo->ino 132 && statbuf->st_dev == hlInfo->dev 133 ) { 134 DBG("found hardlink:'%s'", hlInfo->name); 146 135 break; 136 } 147 137 hlInfo = hlInfo->next; 148 138 } … … 155 145 static void putOctal(char *cp, int len, off_t value) 156 146 { 157 char tempBuffer[sizeof(off_t)*3 +1];147 char tempBuffer[sizeof(off_t)*3 + 1]; 158 148 char *tempString = tempBuffer; 159 149 int width; … … 173 163 #define PUT_OCTAL(a, b) putOctal((a), sizeof(a), (b)) 174 164 175 static void chksum_and_xwrite(int fd, struct TarHeader* hp)165 static void chksum_and_xwrite(int fd, struct tar_header_t* hp) 176 166 { 177 167 /* POSIX says that checksum is done on unsigned bytes … … 215 205 "00000000000", 216 206 }; 217 struct TarHeaderheader;207 struct tar_header_t header; 218 208 int size; 219 209 … … 242 232 243 233 /* Write out a tar header for the specified file/directory/whatever */ 244 void BUG_tar_header_size(void);245 234 static int writeTarHeader(struct TarBallInfo *tbInfo, 246 235 const char *header_name, const char *fileName, struct stat *statbuf) 247 236 { 248 struct TarHeader header; 249 250 if (sizeof(header) != 512) 251 BUG_tar_header_size(); 252 253 memset(&header, 0, sizeof(struct TarHeader)); 237 struct tar_header_t header; 238 239 memset(&header, 0, sizeof(header)); 254 240 255 241 strncpy(header.name, header_name, sizeof(header.name)); … … 315 301 && statbuf->st_size > (off_t)0777777777777LL 316 302 ) { 317 bb_error_msg_and_die("can not store file '%s' "318 "of size %"OFF_FMT" d, aborting",303 bb_error_msg_and_die("can't store file '%s' " 304 "of size %"OFF_FMT"u, aborting", 319 305 fileName, statbuf->st_size); 320 306 } … … 341 327 FILE *vbFd = stdout; 342 328 343 if (tbInfo->tarFd == STDOUT_FILENO) /* If the archive goes to stdout, verbose to stderr */ 329 /* If archive goes to stdout, verbose goes to stderr */ 330 if (tbInfo->tarFd == STDOUT_FILENO) 344 331 vbFd = stderr; 345 332 /* GNU "tar cvvf" prints "extended" listing a-la "ls -l" */ … … 359 346 if (excluded_files->data[0] == '/') { 360 347 if (fnmatch(excluded_files->data, file, 361 348 FNM_PATHNAME | FNM_LEADING_DIR) == 0) 362 349 return 1; 363 350 } else { … … 365 352 366 353 for (p = file; p[0] != '\0'; p++) { 367 if ((p == file || p[-1] == '/') && p[0] != '/' && 368 fnmatch(excluded_files->data, p, 369 FNM_PATHNAME | FNM_LEADING_DIR) == 0) 354 if ((p == file || p[-1] == '/') 355 && p[0] != '/' 356 && fnmatch(excluded_files->data, p, 357 FNM_PATHNAME | FNM_LEADING_DIR) == 0 358 ) { 370 359 return 1; 360 } 371 361 } 372 362 } … … 377 367 } 378 368 #else 379 # define exclude_file(excluded_files, file) 0380 #endif 381 382 static int writeFileToTarball(const char *fileName, struct stat *statbuf,383 void *userData, int depth ATTRIBUTE_UNUSED)369 # define exclude_file(excluded_files, file) 0 370 #endif 371 372 static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statbuf, 373 void *userData, int depth UNUSED_PARAM) 384 374 { 385 375 struct TarBallInfo *tbInfo = (struct TarBallInfo *) userData; 386 376 const char *header_name; 387 377 int inputFileFd = -1; 378 379 DBG("writeFileToTarball('%s')", fileName); 380 381 /* Strip leading '/' (must be before memorizing hardlink's name) */ 382 header_name = fileName; 383 while (header_name[0] == '/') { 384 static smallint warned; 385 386 if (!warned) { 387 bb_error_msg("removing leading '/' from member names"); 388 warned = 1; 389 } 390 header_name++; 391 } 392 393 if (header_name[0] == '\0') 394 return TRUE; 395 396 /* It is against the rules to archive a socket */ 397 if (S_ISSOCK(statbuf->st_mode)) { 398 bb_error_msg("%s: socket ignored", fileName); 399 return TRUE; 400 } 388 401 389 402 /* … … 395 408 */ 396 409 tbInfo->hlInfo = NULL; 397 if (statbuf->st_nlink > 1) { 410 if (!S_ISDIR(statbuf->st_mode) && statbuf->st_nlink > 1) { 411 DBG("'%s': st_nlink > 1", header_name); 398 412 tbInfo->hlInfo = findHardLinkInfo(tbInfo->hlInfoHead, statbuf); 399 if (tbInfo->hlInfo == NULL) 400 addHardLinkInfo(&tbInfo->hlInfoHead, statbuf, fileName); 401 } 402 403 /* It is against the rules to archive a socket */ 404 if (S_ISSOCK(statbuf->st_mode)) { 405 bb_error_msg("%s: socket ignored", fileName); 406 return TRUE; 413 if (tbInfo->hlInfo == NULL) { 414 DBG("'%s': addHardLinkInfo", header_name); 415 addHardLinkInfo(&tbInfo->hlInfoHead, statbuf, header_name); 416 } 407 417 } 408 418 … … 410 420 * so check the device and inode to be sure that this particular file isn't 411 421 * the new tarball */ 412 if (tbInfo->statBuf.st_dev == statbuf->st_dev && 413 tbInfo->statBuf.st_ino == statbuf->st_ino) { 422 if (tbInfo->tarFileStatBuf.st_dev == statbuf->st_dev 423 && tbInfo->tarFileStatBuf.st_ino == statbuf->st_ino 424 ) { 414 425 bb_error_msg("%s: file is the archive; skipping", fileName); 415 426 return TRUE; 416 427 } 417 428 418 header_name = fileName; 419 while (header_name[0] == '/') { 420 static smallint warned; 421 422 if (!warned) { 423 bb_error_msg("removing leading '/' from member names"); 424 warned = 1; 425 } 426 header_name++; 427 } 429 if (exclude_file(tbInfo->excludeList, header_name)) 430 return SKIP; 428 431 429 432 #if !ENABLE_FEATURE_TAR_GNU_EXTENSIONS 430 if (strlen( fileName) >= NAME_SIZE) {433 if (strlen(header_name) >= NAME_SIZE) { 431 434 bb_error_msg("names longer than "NAME_SIZE_STR" chars not supported"); 432 435 return TRUE; 433 436 } 434 437 #endif 435 436 if (header_name[0] == '\0')437 return TRUE;438 439 if (exclude_file(tbInfo->excludeList, header_name))440 return SKIP;441 438 442 439 /* Is this a regular file? */ … … 485 482 } 486 483 487 static int writeTarFile(const int tar_fd, const int verboseFlag, 488 const unsigned long dereferenceFlag, const llist_t *include, 489 const llist_t *exclude, const int gzip) 490 { 491 pid_t gzipPid = 0; 484 #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 485 # if !(ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2) 486 # define vfork_compressor(tar_fd, gzip) vfork_compressor(tar_fd) 487 # endif 488 /* Don't inline: vfork scares gcc and pessimizes code */ 489 static void NOINLINE vfork_compressor(int tar_fd, int gzip) 490 { 491 pid_t gzipPid; 492 # if ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2 493 const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2"; 494 # elif ENABLE_FEATURE_SEAMLESS_GZ 495 const char *zip_exec = "gzip"; 496 # else /* only ENABLE_FEATURE_SEAMLESS_BZ2 */ 497 const char *zip_exec = "bzip2"; 498 # endif 499 // On Linux, vfork never unpauses parent early, although standard 500 // allows for that. Do we want to waste bytes checking for it? 501 # define WAIT_FOR_CHILD 0 502 volatile int vfork_exec_errno = 0; 503 struct fd_pair gzipDataPipe; 504 # if WAIT_FOR_CHILD 505 struct fd_pair gzipStatusPipe; 506 xpiped_pair(gzipStatusPipe); 507 # endif 508 xpiped_pair(gzipDataPipe); 509 510 signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */ 511 512 # if defined(__GNUC__) && __GNUC__ 513 /* Avoid vfork clobbering */ 514 (void) &zip_exec; 515 # endif 516 517 gzipPid = xvfork(); 518 519 if (gzipPid == 0) { 520 /* child */ 521 /* NB: close _first_, then move fds! */ 522 close(gzipDataPipe.wr); 523 # if WAIT_FOR_CHILD 524 close(gzipStatusPipe.rd); 525 /* gzipStatusPipe.wr will close only on exec - 526 * parent waits for this close to happen */ 527 fcntl(gzipStatusPipe.wr, F_SETFD, FD_CLOEXEC); 528 # endif 529 xmove_fd(gzipDataPipe.rd, 0); 530 xmove_fd(tar_fd, 1); 531 /* exec gzip/bzip2 program/applet */ 532 BB_EXECLP(zip_exec, zip_exec, "-f", NULL); 533 vfork_exec_errno = errno; 534 _exit(EXIT_FAILURE); 535 } 536 537 /* parent */ 538 xmove_fd(gzipDataPipe.wr, tar_fd); 539 close(gzipDataPipe.rd); 540 # if WAIT_FOR_CHILD 541 close(gzipStatusPipe.wr); 542 while (1) { 543 char buf; 544 int n; 545 546 /* Wait until child execs (or fails to) */ 547 n = full_read(gzipStatusPipe.rd, &buf, 1); 548 if (n < 0 /* && errno == EAGAIN */) 549 continue; /* try it again */ 550 } 551 close(gzipStatusPipe.rd); 552 # endif 553 if (vfork_exec_errno) { 554 errno = vfork_exec_errno; 555 bb_perror_msg_and_die("can't execute '%s'", zip_exec); 556 } 557 } 558 #endif /* ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 */ 559 560 561 /* gcc 4.2.1 inlines it, making code bigger */ 562 static NOINLINE int writeTarFile(int tar_fd, int verboseFlag, 563 int dereferenceFlag, const llist_t *include, 564 const llist_t *exclude, int gzip) 565 { 492 566 int errorFlag = FALSE; 493 567 struct TarBallInfo tbInfo; 494 568 495 569 tbInfo.hlInfoHead = NULL; 496 497 fchmod(tar_fd, 0644);498 570 tbInfo.tarFd = tar_fd; 499 571 tbInfo.verboseFlag = verboseFlag; … … 501 573 /* Store the stat info for the tarball's file, so 502 574 * can avoid including the tarball into itself.... */ 503 if (fstat(tbInfo.tarFd, &tbInfo.statBuf) < 0) 504 bb_perror_msg_and_die("cannot stat tar file"); 505 506 if ((ENABLE_FEATURE_TAR_GZIP || ENABLE_FEATURE_TAR_BZIP2) && gzip) { 507 int gzipDataPipe[2] = { -1, -1 }; 508 int gzipStatusPipe[2] = { -1, -1 }; 509 volatile int vfork_exec_errno = 0; 510 const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2"; 511 512 xpipe(gzipDataPipe); 513 xpipe(gzipStatusPipe); 514 515 signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */ 516 517 #if defined(__GNUC__) && __GNUC__ 518 /* Avoid vfork clobbering */ 519 (void) &include; 520 (void) &errorFlag; 521 (void) &zip_exec; 522 #endif 523 524 gzipPid = vfork(); 525 526 if (gzipPid == 0) { 527 dup2(gzipDataPipe[0], 0); 528 close(gzipDataPipe[1]); 529 530 dup2(tbInfo.tarFd, 1); 531 532 close(gzipStatusPipe[0]); 533 fcntl(gzipStatusPipe[1], F_SETFD, FD_CLOEXEC); /* close on exec shows success */ 534 535 BB_EXECLP(zip_exec, zip_exec, "-f", NULL); 536 vfork_exec_errno = errno; 537 538 close(gzipStatusPipe[1]); 539 exit(-1); 540 } else if (gzipPid > 0) { 541 close(gzipDataPipe[0]); 542 close(gzipStatusPipe[1]); 543 544 while (1) { 545 char buf; 546 547 int n = full_read(gzipStatusPipe[0], &buf, 1); 548 549 if (n == 0 && vfork_exec_errno != 0) { 550 errno = vfork_exec_errno; 551 bb_perror_msg_and_die("cannot exec %s", zip_exec); 552 } else if ((n < 0) && (errno == EAGAIN || errno == EINTR)) 553 continue; /* try it again */ 554 break; 555 } 556 close(gzipStatusPipe[0]); 557 558 tbInfo.tarFd = gzipDataPipe[1]; 559 } else bb_perror_msg_and_die("vfork gzip"); 560 } 575 xfstat(tbInfo.tarFd, &tbInfo.tarFileStatBuf, "can't stat tar file"); 576 577 #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 578 if (gzip) 579 vfork_compressor(tbInfo.tarFd, gzip); 580 #endif 561 581 562 582 tbInfo.excludeList = exclude; … … 566 586 if (!recursive_action(include->data, ACTION_RECURSE | 567 587 (dereferenceFlag ? ACTION_FOLLOWLINKS : 0), 568 writeFileToTarball, writeFileToTarball, &tbInfo, 0) )569 {588 writeFileToTarball, writeFileToTarball, &tbInfo, 0) 589 ) { 570 590 errorFlag = TRUE; 571 591 } … … 591 611 bb_error_msg("error exit delayed from previous errors"); 592 612 593 if (gzipPid) { 613 #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 614 if (gzip) { 594 615 int status; 595 if ( waitpid(gzipPid, &status, 0) == -1)616 if (safe_waitpid(-1, &status, 0) == -1) 596 617 bb_perror_msg("waitpid"); 597 618 else if (!WIFEXITED(status) || WEXITSTATUS(status)) … … 599 620 errorFlag = TRUE; 600 621 } 622 #endif 601 623 return errorFlag; 602 624 } 603 625 #else 604 int writeTarFile( const int tar_fd, constint verboseFlag,605 const unsigned longdereferenceFlag, const llist_t *include,606 const llist_t *exclude, constint gzip);626 int writeTarFile(int tar_fd, int verboseFlag, 627 int dereferenceFlag, const llist_t *include, 628 const llist_t *exclude, int gzip); 607 629 #endif /* FEATURE_TAR_CREATE */ 608 630 … … 611 633 { 612 634 FILE *src_stream; 613 llist_t *cur = list;614 llist_t *tmp;615 635 char *line; 616 636 llist_t *newlist = NULL; 617 637 618 while (cur) { 619 src_stream = xfopen(cur->data, "r"); 620 tmp = cur; 621 cur = cur->link; 622 free(tmp); 623 while ((line = xmalloc_getline(src_stream)) != NULL) { 638 while (list) { 639 src_stream = xfopen_for_read(llist_pop(&list)); 640 while ((line = xmalloc_fgetline(src_stream)) != NULL) { 624 641 /* kill trailing '/' unless the string is just "/" */ 625 642 char *cp = last_char_is(line, '/'); … … 633 650 } 634 651 #else 635 # define append_file_list_to_list(x) 0636 #endif 637 638 #if ENABLE_FEATURE_ TAR_COMPRESS639 static char get_header_tar_Z(archive_handle_t *archive_handle)652 # define append_file_list_to_list(x) 0 653 #endif 654 655 #if ENABLE_FEATURE_SEAMLESS_Z 656 static char FAST_FUNC get_header_tar_Z(archive_handle_t *archive_handle) 640 657 { 641 658 /* Can't lseek over pipes */ … … 649 666 } 650 667 651 archive_handle->src_fd = open_transformer(archive_handle->src_fd, uncompress, "uncompress", "uncompress", "-cf", "-", NULL);668 open_transformer(archive_handle->src_fd, unpack_Z_stream, "uncompress"); 652 669 archive_handle->offset = 0; 653 670 while (get_header_tar(archive_handle) == EXIT_SUCCESS) 654 /* nothing */;671 continue; 655 672 656 673 /* Can only do one file at a time */ … … 658 675 } 659 676 #else 660 # define get_header_tar_Z NULL677 # define get_header_tar_Z NULL 661 678 #endif 662 679 … … 671 688 672 689 /* Wait for any child without blocking */ 673 if (wait pid(-1, &status, WNOHANG) < 0)690 if (wait_any_nohang(&status) < 0) 674 691 /* wait failed?! I'm confused... */ 675 692 return; 676 693 677 if (WIFEXITED(status) && WEXITSTATUS(status) ==0)694 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) 678 695 /* child exited with 0 */ 679 696 return; … … 684 701 #endif 685 702 703 //usage:#define tar_trivial_usage 704 //usage: "-[" IF_FEATURE_TAR_CREATE("c") "xt" IF_FEATURE_SEAMLESS_GZ("z") 705 //usage: IF_FEATURE_SEAMLESS_BZ2("j") IF_FEATURE_SEAMLESS_LZMA("a") 706 //usage: IF_FEATURE_SEAMLESS_Z("Z") IF_FEATURE_TAR_NOPRESERVE_TIME("m") "vO] " 707 //usage: IF_FEATURE_TAR_FROM("[-X FILE] ") 708 //usage: "[-f TARFILE] [-C DIR] [FILE]..." 709 //usage:#define tar_full_usage "\n\n" 710 //usage: IF_FEATURE_TAR_CREATE("Create, extract, ") 711 //usage: IF_NOT_FEATURE_TAR_CREATE("Extract ") 712 //usage: "or list files from a tar file\n" 713 //usage: "\nOperation:" 714 //usage: IF_FEATURE_TAR_CREATE( 715 //usage: "\n c Create" 716 //usage: ) 717 //usage: "\n x Extract" 718 //usage: "\n t List" 719 //usage: "\nOptions:" 720 //usage: "\n f Name of TARFILE ('-' for stdin/out)" 721 //usage: "\n C Change to DIR before operation" 722 //usage: "\n v Verbose" 723 //usage: IF_FEATURE_SEAMLESS_GZ( 724 //usage: "\n z (De)compress using gzip" 725 //usage: ) 726 //usage: IF_FEATURE_SEAMLESS_BZ2( 727 //usage: "\n j (De)compress using bzip2" 728 //usage: ) 729 //usage: IF_FEATURE_SEAMLESS_LZMA( 730 //usage: "\n a (De)compress using lzma" 731 //usage: ) 732 //usage: IF_FEATURE_SEAMLESS_Z( 733 //usage: "\n Z (De)compress using compress" 734 //usage: ) 735 //usage: "\n O Extract to stdout" 736 //usage: IF_FEATURE_TAR_CREATE( 737 //usage: "\n h Follow symlinks" 738 //usage: ) 739 //usage: IF_FEATURE_TAR_NOPRESERVE_TIME( 740 //usage: "\n m Don't restore mtime" 741 //usage: ) 742 //usage: IF_FEATURE_TAR_FROM( 743 //usage: IF_FEATURE_TAR_LONG_OPTIONS( 744 //usage: "\n exclude File to exclude" 745 //usage: ) 746 //usage: "\n X File with names to exclude" 747 //usage: "\n T File with names to include" 748 //usage: ) 749 //usage: 750 //usage:#define tar_example_usage 751 //usage: "$ zcat /tmp/tarball.tar.gz | tar -xf -\n" 752 //usage: "$ tar -cf /tmp/tarball.tar /usr/local\n" 753 754 // Supported but aren't in --help: 755 // o no-same-owner 756 // p same-permissions 757 // k keep-old 758 // numeric-owner 759 // no-same-permissions 760 // overwrite 761 //IF_FEATURE_TAR_TO_COMMAND( 762 // to-command 763 //) 764 686 765 enum { 687 OPTBIT_KEEP_OLD = 7, 688 USE_FEATURE_TAR_CREATE( OPTBIT_CREATE ,) 689 USE_FEATURE_TAR_CREATE( OPTBIT_DEREFERENCE ,) 690 USE_FEATURE_TAR_BZIP2( OPTBIT_BZIP2 ,) 691 USE_FEATURE_TAR_LZMA( OPTBIT_LZMA ,) 692 USE_FEATURE_TAR_FROM( OPTBIT_INCLUDE_FROM,) 693 USE_FEATURE_TAR_FROM( OPTBIT_EXCLUDE_FROM,) 694 USE_FEATURE_TAR_GZIP( OPTBIT_GZIP ,) 695 USE_FEATURE_TAR_COMPRESS(OPTBIT_COMPRESS ,) 696 OPTBIT_NOPRESERVE_OWN, 766 OPTBIT_KEEP_OLD = 8, 767 IF_FEATURE_TAR_CREATE( OPTBIT_CREATE ,) 768 IF_FEATURE_TAR_CREATE( OPTBIT_DEREFERENCE ,) 769 IF_FEATURE_SEAMLESS_BZ2( OPTBIT_BZIP2 ,) 770 IF_FEATURE_SEAMLESS_LZMA(OPTBIT_LZMA ,) 771 IF_FEATURE_TAR_FROM( OPTBIT_INCLUDE_FROM,) 772 IF_FEATURE_TAR_FROM( OPTBIT_EXCLUDE_FROM,) 773 IF_FEATURE_SEAMLESS_GZ( OPTBIT_GZIP ,) 774 IF_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,) // 16th bit 775 IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,) 776 #if ENABLE_FEATURE_TAR_LONG_OPTIONS 777 IF_FEATURE_TAR_TO_COMMAND(OPTBIT_2COMMAND ,) 778 OPTBIT_NUMERIC_OWNER, 697 779 OPTBIT_NOPRESERVE_PERM, 780 OPTBIT_OVERWRITE, 781 #endif 698 782 OPT_TEST = 1 << 0, // t 699 783 OPT_EXTRACT = 1 << 1, // x … … 701 785 OPT_TARNAME = 1 << 3, // f 702 786 OPT_2STDOUT = 1 << 4, // O 703 OPT_P = 1 << 5, // p 704 OPT_VERBOSE = 1 << 6, // v 705 OPT_KEEP_OLD = 1 << 7, // k 706 OPT_CREATE = USE_FEATURE_TAR_CREATE( (1<<OPTBIT_CREATE )) + 0, // c 707 OPT_DEREFERENCE = USE_FEATURE_TAR_CREATE( (1<<OPTBIT_DEREFERENCE )) + 0, // h 708 OPT_BZIP2 = USE_FEATURE_TAR_BZIP2( (1<<OPTBIT_BZIP2 )) + 0, // j 709 OPT_LZMA = USE_FEATURE_TAR_LZMA( (1<<OPTBIT_LZMA )) + 0, // a 710 OPT_INCLUDE_FROM = USE_FEATURE_TAR_FROM( (1<<OPTBIT_INCLUDE_FROM)) + 0, // T 711 OPT_EXCLUDE_FROM = USE_FEATURE_TAR_FROM( (1<<OPTBIT_EXCLUDE_FROM)) + 0, // X 712 OPT_GZIP = USE_FEATURE_TAR_GZIP( (1<<OPTBIT_GZIP )) + 0, // z 713 OPT_COMPRESS = USE_FEATURE_TAR_COMPRESS((1<<OPTBIT_COMPRESS )) + 0, // Z 714 OPT_NOPRESERVE_OWN = 1 << OPTBIT_NOPRESERVE_OWN , // no-same-owner 715 OPT_NOPRESERVE_PERM = 1 << OPTBIT_NOPRESERVE_PERM, // no-same-permissions 787 OPT_NOPRESERVE_OWNER = 1 << 5, // o == no-same-owner 788 OPT_P = 1 << 6, // p 789 OPT_VERBOSE = 1 << 7, // v 790 OPT_KEEP_OLD = 1 << 8, // k 791 OPT_CREATE = IF_FEATURE_TAR_CREATE( (1 << OPTBIT_CREATE )) + 0, // c 792 OPT_DEREFERENCE = IF_FEATURE_TAR_CREATE( (1 << OPTBIT_DEREFERENCE )) + 0, // h 793 OPT_BZIP2 = IF_FEATURE_SEAMLESS_BZ2( (1 << OPTBIT_BZIP2 )) + 0, // j 794 OPT_LZMA = IF_FEATURE_SEAMLESS_LZMA((1 << OPTBIT_LZMA )) + 0, // a 795 OPT_INCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_INCLUDE_FROM)) + 0, // T 796 OPT_EXCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_EXCLUDE_FROM)) + 0, // X 797 OPT_GZIP = IF_FEATURE_SEAMLESS_GZ( (1 << OPTBIT_GZIP )) + 0, // z 798 OPT_COMPRESS = IF_FEATURE_SEAMLESS_Z( (1 << OPTBIT_COMPRESS )) + 0, // Z 799 OPT_NOPRESERVE_TIME = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m 800 OPT_2COMMAND = IF_FEATURE_TAR_TO_COMMAND( (1 << OPTBIT_2COMMAND )) + 0, // to-command 801 OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner 802 OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions 803 OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite 716 804 }; 717 805 #if ENABLE_FEATURE_TAR_LONG_OPTIONS … … 722 810 "file\0" Required_argument "f" 723 811 "to-stdout\0" No_argument "O" 812 /* do not restore owner */ 813 /* Note: GNU tar handles 'o' as no-same-owner only on extract, 814 * on create, 'o' is --old-archive. We do not support --old-archive. */ 815 "no-same-owner\0" No_argument "o" 724 816 "same-permissions\0" No_argument "p" 725 817 "verbose\0" No_argument "v" … … 729 821 "dereference\0" No_argument "h" 730 822 # endif 731 # if ENABLE_FEATURE_ TAR_BZIP2823 # if ENABLE_FEATURE_SEAMLESS_BZ2 732 824 "bzip2\0" No_argument "j" 733 825 # endif 734 # if ENABLE_FEATURE_ TAR_LZMA826 # if ENABLE_FEATURE_SEAMLESS_LZMA 735 827 "lzma\0" No_argument "a" 736 828 # endif … … 739 831 "exclude-from\0" Required_argument "X" 740 832 # endif 741 # if ENABLE_FEATURE_ TAR_GZIP833 # if ENABLE_FEATURE_SEAMLESS_GZ 742 834 "gzip\0" No_argument "z" 743 835 # endif 744 # if ENABLE_FEATURE_ TAR_COMPRESS836 # if ENABLE_FEATURE_SEAMLESS_Z 745 837 "compress\0" No_argument "Z" 746 838 # endif 747 "no-same-owner\0" No_argument "\xfd" 748 "no-same-permissions\0" No_argument "\xfe" 839 # if ENABLE_FEATURE_TAR_NOPRESERVE_TIME 840 "touch\0" No_argument "m" 841 # endif 842 # if ENABLE_FEATURE_TAR_TO_COMMAND 843 "to-command\0" Required_argument "\xfb" 844 # endif 845 /* use numeric uid/gid from tar header, not textual */ 846 "numeric-owner\0" No_argument "\xfc" 847 /* do not restore mode */ 848 "no-same-permissions\0" No_argument "\xfd" 849 /* on unpack, open with O_TRUNC and !O_EXCL */ 850 "overwrite\0" No_argument "\xfe" 749 851 /* --exclude takes next bit position in option mask, */ 750 /* therefore we have to either put it _after_ --no-same-perm */ 751 /* or add OPT[BIT]_EXCLUDE before OPT[BIT]_NOPRESERVE_OWN */ 852 /* therefore we have to put it _after_ --no-same-permissions */ 752 853 # if ENABLE_FEATURE_TAR_FROM 753 854 "exclude\0" Required_argument "\xff" … … 756 857 #endif 757 858 758 int tar_main(int argc, char **argv) ;759 int tar_main(int argc , char **argv)760 { 761 char (*get_header_ptr)(archive_handle_t *) = get_header_tar;859 int tar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 860 int tar_main(int argc UNUSED_PARAM, char **argv) 861 { 862 char FAST_FUNC (*get_header_ptr)(archive_handle_t *) = get_header_tar; 762 863 archive_handle_t *tar_handle; 763 864 char *base_dir = NULL; … … 771 872 /* Initialise default values */ 772 873 tar_handle = init_handle(); 773 tar_handle->flags = ARCHIVE_CREATE_LEADING_DIRS 774 | ARCHIVE_PRESERVE_DATE 775 | ARCHIVE_EXTRACT_UNCONDITIONAL; 874 tar_handle->ah_flags = ARCHIVE_CREATE_LEADING_DIRS 875 | ARCHIVE_RESTORE_DATE 876 | ARCHIVE_UNLINK_OLD; 877 878 /* Apparently only root's tar preserves perms (see bug 3844) */ 879 if (getuid() != 0) 880 tar_handle->ah_flags |= ARCHIVE_DONT_RESTORE_PERM; 776 881 777 882 /* Prepend '-' to the first argument if required */ … … 783 888 "\xff::" // cumulative lists for --exclude 784 889 #endif 785 USE_FEATURE_TAR_CREATE("c:") "t:x:" // at least one of these is reqd786 USE_FEATURE_TAR_CREATE("c--tx:t--cx:x--ct") // mutually exclusive787 SKIP_FEATURE_TAR_CREATE("t--x:x--t"); // mutually exclusive890 IF_FEATURE_TAR_CREATE("c:") "t:x:" // at least one of these is reqd 891 IF_FEATURE_TAR_CREATE("c--tx:t--cx:x--ct") // mutually exclusive 892 IF_NOT_FEATURE_TAR_CREATE("t--x:x--t"); // mutually exclusive 788 893 #if ENABLE_FEATURE_TAR_LONG_OPTIONS 789 894 applet_long_options = tar_longopts; 790 895 #endif 896 #if ENABLE_DESKTOP 897 if (argv[1] && argv[1][0] != '-') { 898 /* Compat: 899 * 1st argument without dash handles options with parameters 900 * differently from dashed one: it takes *next argv[i]* 901 * as paramenter even if there are more chars in 1st argument: 902 * "tar fx TARFILE" - "x" is not taken as f's param 903 * but is interpreted as -x option 904 * "tar -xf TARFILE" - dashed equivalent of the above 905 * "tar -fx ..." - "x" is taken as f's param 906 * getopt32 wouldn't handle 1st command correctly. 907 * Unfortunately, people do use such commands. 908 * We massage argv[1] to work around it by moving 'f' 909 * to the end of the string. 910 * More contrived "tar fCx TARFILE DIR" still fails, 911 * but such commands are much less likely to be used. 912 */ 913 char *f = strchr(argv[1], 'f'); 914 if (f) { 915 while (f[1] != '\0') { 916 *f = f[1]; 917 f++; 918 } 919 *f = 'f'; 920 } 921 } 922 #endif 791 923 opt = getopt32(argv, 792 "txC:f:Opvk" 793 USE_FEATURE_TAR_CREATE( "ch" ) 794 USE_FEATURE_TAR_BZIP2( "j" ) 795 USE_FEATURE_TAR_LZMA( "a" ) 796 USE_FEATURE_TAR_FROM( "T:X:") 797 USE_FEATURE_TAR_GZIP( "z" ) 798 USE_FEATURE_TAR_COMPRESS("Z" ) 924 "txC:f:Oopvk" 925 IF_FEATURE_TAR_CREATE( "ch" ) 926 IF_FEATURE_SEAMLESS_BZ2( "j" ) 927 IF_FEATURE_SEAMLESS_LZMA("a" ) 928 IF_FEATURE_TAR_FROM( "T:X:") 929 IF_FEATURE_SEAMLESS_GZ( "z" ) 930 IF_FEATURE_SEAMLESS_Z( "Z" ) 931 IF_FEATURE_TAR_NOPRESERVE_TIME("m") 799 932 , &base_dir // -C dir 800 933 , &tar_filename // -f filename 801 USE_FEATURE_TAR_FROM(, &(tar_handle->accept)) // T 802 USE_FEATURE_TAR_FROM(, &(tar_handle->reject)) // X 934 IF_FEATURE_TAR_FROM(, &(tar_handle->accept)) // T 935 IF_FEATURE_TAR_FROM(, &(tar_handle->reject)) // X 936 IF_FEATURE_TAR_TO_COMMAND(, &(tar_handle->tar__to_command)) // --to-command 803 937 #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM 804 938 , &excludes // --exclude … … 807 941 , &verboseFlag // combined count for -t and -v 808 942 ); 943 //bb_error_msg("opt:%08x", opt); 944 argv += optind; 809 945 810 946 if (verboseFlag) tar_handle->action_header = header_verbose_list; … … 817 953 tar_handle->action_data = data_extract_to_stdout; 818 954 955 if (opt & OPT_2COMMAND) { 956 putenv((char*)"TAR_FILETYPE=f"); 957 signal(SIGPIPE, SIG_IGN); 958 tar_handle->action_data = data_extract_to_command; 959 } 960 819 961 if (opt & OPT_KEEP_OLD) 820 tar_handle->flags &= ~ARCHIVE_EXTRACT_UNCONDITIONAL; 821 822 if (opt & OPT_NOPRESERVE_OWN) 823 tar_handle->flags |= ARCHIVE_NOPRESERVE_OWN; 962 tar_handle->ah_flags &= ~ARCHIVE_UNLINK_OLD; 963 964 if (opt & OPT_NUMERIC_OWNER) 965 tar_handle->ah_flags |= ARCHIVE_NUMERIC_OWNER; 966 967 if (opt & OPT_NOPRESERVE_OWNER) 968 tar_handle->ah_flags |= ARCHIVE_DONT_RESTORE_OWNER; 824 969 825 970 if (opt & OPT_NOPRESERVE_PERM) 826 tar_handle->flags |= ARCHIVE_NOPRESERVE_PERM; 971 tar_handle->ah_flags |= ARCHIVE_DONT_RESTORE_PERM; 972 973 if (opt & OPT_OVERWRITE) { 974 tar_handle->ah_flags &= ~ARCHIVE_UNLINK_OLD; 975 tar_handle->ah_flags |= ARCHIVE_O_TRUNC; 976 } 827 977 828 978 if (opt & OPT_GZIP) … … 838 988 get_header_ptr = get_header_tar_Z; 839 989 990 if (opt & OPT_NOPRESERVE_TIME) 991 tar_handle->ah_flags &= ~ARCHIVE_RESTORE_DATE; 992 840 993 #if ENABLE_FEATURE_TAR_FROM 841 994 tar_handle->reject = append_file_list_to_list(tar_handle->reject); 842 # if ENABLE_FEATURE_TAR_LONG_OPTIONS995 # if ENABLE_FEATURE_TAR_LONG_OPTIONS 843 996 /* Append excludes to reject */ 844 997 while (excludes) { … … 848 1001 excludes = next; 849 1002 } 850 # endif1003 # endif 851 1004 tar_handle->accept = append_file_list_to_list(tar_handle->accept); 852 1005 #endif 853 1006 854 /* Check if we are reading from stdin */855 if (argv[optind] && *argv[optind] == '-') {856 /* Default is to read from stdin, so just skip to next arg */857 optind++;858 }859 860 1007 /* Setup an array of filenames to work with */ 861 /* TODO: This is the same as in ar, separate function? */862 while ( optind < argc) {1008 /* TODO: This is the same as in ar, make a separate function? */ 1009 while (*argv) { 863 1010 /* kill trailing '/' unless the string is just "/" */ 864 char *cp = last_char_is( argv[optind], '/');865 if (cp > argv[optind])1011 char *cp = last_char_is(*argv, '/'); 1012 if (cp > *argv) 866 1013 *cp = '\0'; 867 llist_add_to_end(&tar_handle->accept, argv[optind]);868 optind++;1014 llist_add_to_end(&tar_handle->accept, *argv); 1015 argv++; 869 1016 } 870 1017 … … 874 1021 /* Open the tar file */ 875 1022 { 876 FILE *tar_stream;877 int flags ;1023 int tar_fd = STDIN_FILENO; 1024 int flags = O_RDONLY; 878 1025 879 1026 if (opt & OPT_CREATE) { 880 /* Make sure there is at least one file to tar up .*/1027 /* Make sure there is at least one file to tar up */ 881 1028 if (tar_handle->accept == NULL) 882 1029 bb_error_msg_and_die("empty archive"); 883 1030 884 tar_ stream = stdout;1031 tar_fd = STDOUT_FILENO; 885 1032 /* Mimicking GNU tar 1.15.1: */ 886 flags = O_WRONLY|O_CREAT|O_TRUNC; 887 /* was doing unlink; open(O_WRONLY|O_CREAT|O_EXCL); why? */ 888 } else { 889 tar_stream = stdin; 890 flags = O_RDONLY; 1033 flags = O_WRONLY | O_CREAT | O_TRUNC; 891 1034 } 892 1035 893 1036 if (LONE_DASH(tar_filename)) { 894 tar_handle->src_fd = fileno(tar_stream);1037 tar_handle->src_fd = tar_fd; 895 1038 tar_handle->seek = seek_by_read; 896 1039 } else { 897 tar_handle->src_fd = xopen(tar_filename, flags); 1040 if (ENABLE_FEATURE_TAR_AUTODETECT 1041 && flags == O_RDONLY 1042 && get_header_ptr == get_header_tar 1043 ) { 1044 tar_handle->src_fd = open_zipped(tar_filename); 1045 if (tar_handle->src_fd < 0) 1046 bb_perror_msg_and_die("can't open '%s'", tar_filename); 1047 } else { 1048 tar_handle->src_fd = xopen(tar_filename, flags); 1049 } 898 1050 } 899 1051 } … … 907 1059 #endif 908 1060 909 /* create an archive */1061 /* Create an archive */ 910 1062 if (opt & OPT_CREATE) { 1063 #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 911 1064 int zipMode = 0; 912 if (ENABLE_FEATURE_ TAR_GZIP && get_header_ptr == get_header_tar_gz)1065 if (ENABLE_FEATURE_SEAMLESS_GZ && (opt & OPT_GZIP)) 913 1066 zipMode = 1; 914 if (ENABLE_FEATURE_ TAR_BZIP2 && get_header_ptr == get_header_tar_bz2)1067 if (ENABLE_FEATURE_SEAMLESS_BZ2 && (opt & OPT_BZIP2)) 915 1068 zipMode = 2; 1069 #endif 916 1070 /* NB: writeTarFile() closes tar_handle->src_fd */ 917 1071 return writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE, … … 921 1075 922 1076 while (get_header_ptr(tar_handle) == EXIT_SUCCESS) 923 /* nothing */;1077 continue; 924 1078 925 1079 /* Check that every file that should have been extracted was */ -
branches/2.2.9/mindi-busybox/archival/unzip.c
r1765 r2725 8 8 * All options and features should work in this version. 9 9 * 10 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.10 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 11 11 */ 12 12 … … 17 17 18 18 /* TODO 19 * Endian issues20 19 * Zip64 + other methods 21 * Improve handling of zip format, ie.22 * - deferred CRC, comp. & uncomp. lengths (zip header flags bit 3)23 * - unix file permissions, etc.24 * - central directory25 20 */ 26 21 27 22 #include "libbb.h" 28 #include "unarchive.h" 29 30 #define ZIP_FILEHEADER_MAGIC SWAP_LE32(0x04034b50) 31 #define ZIP_CDS_MAGIC SWAP_LE32(0x02014b50) 32 #define ZIP_CDS_END_MAGIC SWAP_LE32(0x06054b50) 33 #define ZIP_DD_MAGIC SWAP_LE32(0x08074b50) 23 #include "archive.h" 24 25 enum { 26 #if BB_BIG_ENDIAN 27 ZIP_FILEHEADER_MAGIC = 0x504b0304, 28 ZIP_CDF_MAGIC = 0x504b0102, /* central directory's file header */ 29 ZIP_CDE_MAGIC = 0x504b0506, /* "end of central directory" record */ 30 ZIP_DD_MAGIC = 0x504b0708, 31 #else 32 ZIP_FILEHEADER_MAGIC = 0x04034b50, 33 ZIP_CDF_MAGIC = 0x02014b50, 34 ZIP_CDE_MAGIC = 0x06054b50, 35 ZIP_DD_MAGIC = 0x08074b50, 36 #endif 37 }; 38 39 #define ZIP_HEADER_LEN 26 34 40 35 41 typedef union { 36 u nsigned char raw[26];42 uint8_t raw[ZIP_HEADER_LEN]; 37 43 struct { 38 unsigned short version; /* 0-1 */ 39 unsigned short flags; /* 2-3 */ 40 unsigned short method; /* 4-5 */ 41 unsigned short modtime; /* 6-7 */ 42 unsigned short moddate; /* 8-9 */ 43 unsigned int crc32 ATTRIBUTE_PACKED; /* 10-13 */ 44 unsigned int cmpsize ATTRIBUTE_PACKED; /* 14-17 */ 45 unsigned int ucmpsize ATTRIBUTE_PACKED; /* 18-21 */ 46 unsigned short filename_len; /* 22-23 */ 47 unsigned short extra_len; /* 24-25 */ 48 } formatted ATTRIBUTE_PACKED; 49 } zip_header_t; 50 51 static void unzip_skip(int fd, off_t skip) 44 uint16_t version; /* 0-1 */ 45 uint16_t zip_flags; /* 2-3 */ 46 uint16_t method; /* 4-5 */ 47 uint16_t modtime; /* 6-7 */ 48 uint16_t moddate; /* 8-9 */ 49 uint32_t crc32 PACKED; /* 10-13 */ 50 uint32_t cmpsize PACKED; /* 14-17 */ 51 uint32_t ucmpsize PACKED; /* 18-21 */ 52 uint16_t filename_len; /* 22-23 */ 53 uint16_t extra_len; /* 24-25 */ 54 } formatted PACKED; 55 } zip_header_t; /* PACKED - gcc 4.2.1 doesn't like it (spews warning) */ 56 57 /* Check the offset of the last element, not the length. This leniency 58 * allows for poor packing, whereby the overall struct may be too long, 59 * even though the elements are all in the right place. 60 */ 61 struct BUG_zip_header_must_be_26_bytes { 62 char BUG_zip_header_must_be_26_bytes[ 63 offsetof(zip_header_t, formatted.extra_len) + 2 64 == ZIP_HEADER_LEN ? 1 : -1]; 65 }; 66 67 #define FIX_ENDIANNESS_ZIP(zip_header) do { \ 68 (zip_header).formatted.version = SWAP_LE16((zip_header).formatted.version ); \ 69 (zip_header).formatted.method = SWAP_LE16((zip_header).formatted.method ); \ 70 (zip_header).formatted.modtime = SWAP_LE16((zip_header).formatted.modtime ); \ 71 (zip_header).formatted.moddate = SWAP_LE16((zip_header).formatted.moddate ); \ 72 (zip_header).formatted.crc32 = SWAP_LE32((zip_header).formatted.crc32 ); \ 73 (zip_header).formatted.cmpsize = SWAP_LE32((zip_header).formatted.cmpsize ); \ 74 (zip_header).formatted.ucmpsize = SWAP_LE32((zip_header).formatted.ucmpsize ); \ 75 (zip_header).formatted.filename_len = SWAP_LE16((zip_header).formatted.filename_len); \ 76 (zip_header).formatted.extra_len = SWAP_LE16((zip_header).formatted.extra_len ); \ 77 } while (0) 78 79 #define CDF_HEADER_LEN 42 80 81 typedef union { 82 uint8_t raw[CDF_HEADER_LEN]; 83 struct { 84 /* uint32_t signature; 50 4b 01 02 */ 85 uint16_t version_made_by; /* 0-1 */ 86 uint16_t version_needed; /* 2-3 */ 87 uint16_t cdf_flags; /* 4-5 */ 88 uint16_t method; /* 6-7 */ 89 uint16_t mtime; /* 8-9 */ 90 uint16_t mdate; /* 10-11 */ 91 uint32_t crc32; /* 12-15 */ 92 uint32_t cmpsize; /* 16-19 */ 93 uint32_t ucmpsize; /* 20-23 */ 94 uint16_t file_name_length; /* 24-25 */ 95 uint16_t extra_field_length; /* 26-27 */ 96 uint16_t file_comment_length; /* 28-29 */ 97 uint16_t disk_number_start; /* 30-31 */ 98 uint16_t internal_file_attributes; /* 32-33 */ 99 uint32_t external_file_attributes PACKED; /* 34-37 */ 100 uint32_t relative_offset_of_local_header PACKED; /* 38-41 */ 101 } formatted PACKED; 102 } cdf_header_t; 103 104 struct BUG_cdf_header_must_be_42_bytes { 105 char BUG_cdf_header_must_be_42_bytes[ 106 offsetof(cdf_header_t, formatted.relative_offset_of_local_header) + 4 107 == CDF_HEADER_LEN ? 1 : -1]; 108 }; 109 110 #define FIX_ENDIANNESS_CDF(cdf_header) do { \ 111 (cdf_header).formatted.crc32 = SWAP_LE32((cdf_header).formatted.crc32 ); \ 112 (cdf_header).formatted.cmpsize = SWAP_LE32((cdf_header).formatted.cmpsize ); \ 113 (cdf_header).formatted.ucmpsize = SWAP_LE32((cdf_header).formatted.ucmpsize ); \ 114 (cdf_header).formatted.file_name_length = SWAP_LE16((cdf_header).formatted.file_name_length); \ 115 (cdf_header).formatted.extra_field_length = SWAP_LE16((cdf_header).formatted.extra_field_length); \ 116 (cdf_header).formatted.file_comment_length = SWAP_LE16((cdf_header).formatted.file_comment_length); \ 117 IF_DESKTOP( \ 118 (cdf_header).formatted.version_made_by = SWAP_LE16((cdf_header).formatted.version_made_by); \ 119 (cdf_header).formatted.external_file_attributes = SWAP_LE32((cdf_header).formatted.external_file_attributes); \ 120 ) \ 121 } while (0) 122 123 #define CDE_HEADER_LEN 16 124 125 typedef union { 126 uint8_t raw[CDE_HEADER_LEN]; 127 struct { 128 /* uint32_t signature; 50 4b 05 06 */ 129 uint16_t this_disk_no; 130 uint16_t disk_with_cdf_no; 131 uint16_t cdf_entries_on_this_disk; 132 uint16_t cdf_entries_total; 133 uint32_t cdf_size; 134 uint32_t cdf_offset; 135 /* uint16_t file_comment_length; */ 136 /* .ZIP file comment (variable size) */ 137 } formatted PACKED; 138 } cde_header_t; 139 140 struct BUG_cde_header_must_be_16_bytes { 141 char BUG_cde_header_must_be_16_bytes[ 142 sizeof(cde_header_t) == CDE_HEADER_LEN ? 1 : -1]; 143 }; 144 145 #define FIX_ENDIANNESS_CDE(cde_header) do { \ 146 (cde_header).formatted.cdf_offset = SWAP_LE32((cde_header).formatted.cdf_offset); \ 147 } while (0) 148 149 enum { zip_fd = 3 }; 150 151 152 #if ENABLE_DESKTOP 153 154 #define PEEK_FROM_END 16384 155 156 /* NB: does not preserve file position! */ 157 static uint32_t find_cdf_offset(void) 52 158 { 53 if (lseek(fd, skip, SEEK_CUR) == (off_t)-1) { 54 if (errno != ESPIPE) 55 bb_error_msg_and_die("seek failure"); 56 bb_copyfd_exact_size(fd, -1, skip); 57 } 159 cde_header_t cde_header; 160 unsigned char *p; 161 off_t end; 162 unsigned char *buf = xzalloc(PEEK_FROM_END); 163 164 end = xlseek(zip_fd, 0, SEEK_END); 165 end -= PEEK_FROM_END; 166 if (end < 0) 167 end = 0; 168 xlseek(zip_fd, end, SEEK_SET); 169 full_read(zip_fd, buf, PEEK_FROM_END); 170 171 p = buf; 172 while (p <= buf + PEEK_FROM_END - CDE_HEADER_LEN - 4) { 173 if (*p != 'P') { 174 p++; 175 continue; 176 } 177 if (*++p != 'K') 178 continue; 179 if (*++p != 5) 180 continue; 181 if (*++p != 6) 182 continue; 183 /* we found CDE! */ 184 memcpy(cde_header.raw, p + 1, CDE_HEADER_LEN); 185 FIX_ENDIANNESS_CDE(cde_header); 186 free(buf); 187 return cde_header.formatted.cdf_offset; 188 } 189 //free(buf); 190 bb_error_msg_and_die("can't find file table"); 191 }; 192 193 static uint32_t read_next_cdf(uint32_t cdf_offset, cdf_header_t *cdf_ptr) 194 { 195 off_t org; 196 197 org = xlseek(zip_fd, 0, SEEK_CUR); 198 199 if (!cdf_offset) 200 cdf_offset = find_cdf_offset(); 201 202 xlseek(zip_fd, cdf_offset + 4, SEEK_SET); 203 xread(zip_fd, cdf_ptr->raw, CDF_HEADER_LEN); 204 FIX_ENDIANNESS_CDF(*cdf_ptr); 205 cdf_offset += 4 + CDF_HEADER_LEN 206 + cdf_ptr->formatted.file_name_length 207 + cdf_ptr->formatted.extra_field_length 208 + cdf_ptr->formatted.file_comment_length; 209 210 xlseek(zip_fd, org, SEEK_SET); 211 return cdf_offset; 212 }; 213 #endif 214 215 static void unzip_skip(off_t skip) 216 { 217 if (lseek(zip_fd, skip, SEEK_CUR) == (off_t)-1) 218 bb_copyfd_exact_size(zip_fd, -1, skip); 58 219 } 59 220 60 static void unzip_create_leading_dirs(c har *fn)221 static void unzip_create_leading_dirs(const char *fn) 61 222 { 62 223 /* Create all leading directories */ … … 68 229 } 69 230 70 static int unzip_extract(zip_header_t *zip_header, int src_fd, int dst_fd)231 static void unzip_extract(zip_header_t *zip_header, int dst_fd) 71 232 { 72 233 if (zip_header->formatted.method == 0) { … … 74 235 off_t size = zip_header->formatted.ucmpsize; 75 236 if (size) 76 bb_copyfd_exact_size( src_fd, dst_fd, size);237 bb_copyfd_exact_size(zip_fd, dst_fd, size); 77 238 } else { 78 239 /* Method 8 - inflate */ 79 240 inflate_unzip_result res; 80 /* err = */ inflate_unzip(&res, zip_header->formatted.cmpsize, src_fd, dst_fd);81 // we should check for -1 error return 241 if (inflate_unzip(&res, zip_header->formatted.cmpsize, zip_fd, dst_fd) < 0) 242 bb_error_msg_and_die("inflate error"); 82 243 /* Validate decompression - crc */ 83 244 if (zip_header->formatted.crc32 != (res.crc ^ 0xffffffffL)) { 84 bb_error_msg("invalid compressed data--%s error", "crc"); 85 return 1; 245 bb_error_msg_and_die("crc error"); 86 246 } 87 247 /* Validate decompression - size */ 88 248 if (zip_header->formatted.ucmpsize != res.bytes_out) { 89 bb_error_msg("invalid compressed data--%s error", "length");90 return 1;91 }92 }93 return 0;249 /* Don't die. Who knows, maybe len calculation 250 * was botched somewhere. After all, crc matched! */ 251 bb_error_msg("bad length"); 252 } 253 } 94 254 } 95 255 96 int unzip_main(int argc, char **argv) ;256 int unzip_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 97 257 int unzip_main(int argc, char **argv) 98 258 { 259 enum { O_PROMPT, O_NEVER, O_ALWAYS }; 260 99 261 zip_header_t zip_header; 100 enum {v_silent, v_normal, v_list} verbosity = v_normal; 101 enum {o_prompt, o_never, o_always} overwrite = o_prompt; 102 unsigned int total_size = 0; 103 unsigned int total_entries = 0; 104 int src_fd = -1, dst_fd = -1; 105 char *src_fn = NULL, *dst_fn = NULL; 262 smallint quiet = 0; 263 IF_NOT_DESKTOP(const) smallint verbose = 0; 264 smallint listing = 0; 265 smallint overwrite = O_PROMPT; 266 #if ENABLE_DESKTOP 267 uint32_t cdf_offset; 268 #endif 269 unsigned long total_usize; 270 unsigned long total_size; 271 unsigned total_entries; 272 int dst_fd = -1; 273 char *src_fn = NULL; 274 char *dst_fn = NULL; 106 275 llist_t *zaccept = NULL; 107 276 llist_t *zreject = NULL; 108 277 char *base_dir = NULL; 109 int failed, i, opt, opt_range = 0, list_header_done = 0; 110 char key_buf[512]; 278 int i, opt; 279 int opt_range = 0; 280 char key_buf[80]; 111 281 struct stat stat_buf; 112 282 113 while ((opt = getopt(argc, argv, "-d:lnopqx")) != -1) { 283 /* -q, -l and -v: UnZip 5.52 of 28 February 2005, by Info-ZIP: 284 * 285 * # /usr/bin/unzip -qq -v decompress_unlzma.i.zip 286 * 204372 Defl:N 35278 83% 09-06-09 14:23 0d056252 decompress_unlzma.i 287 * # /usr/bin/unzip -q -v decompress_unlzma.i.zip 288 * Length Method Size Ratio Date Time CRC-32 Name 289 * -------- ------ ------- ----- ---- ---- ------ ---- 290 * 204372 Defl:N 35278 83% 09-06-09 14:23 0d056252 decompress_unlzma.i 291 * -------- ------- --- ------- 292 * 204372 35278 83% 1 file 293 * # /usr/bin/unzip -v decompress_unlzma.i.zip 294 * Archive: decompress_unlzma.i.zip 295 * Length Method Size Ratio Date Time CRC-32 Name 296 * -------- ------ ------- ----- ---- ---- ------ ---- 297 * 204372 Defl:N 35278 83% 09-06-09 14:23 0d056252 decompress_unlzma.i 298 * -------- ------- --- ------- 299 * 204372 35278 83% 1 file 300 * # unzip -v decompress_unlzma.i.zip 301 * Archive: decompress_unlzma.i.zip 302 * Length Date Time Name 303 * -------- ---- ---- ---- 304 * 204372 09-06-09 14:23 decompress_unlzma.i 305 * -------- ------- 306 * 204372 1 files 307 * # /usr/bin/unzip -l -qq decompress_unlzma.i.zip 308 * 204372 09-06-09 14:23 decompress_unlzma.i 309 * # /usr/bin/unzip -l -q decompress_unlzma.i.zip 310 * Length Date Time Name 311 * -------- ---- ---- ---- 312 * 204372 09-06-09 14:23 decompress_unlzma.i 313 * -------- ------- 314 * 204372 1 file 315 * # /usr/bin/unzip -l decompress_unlzma.i.zip 316 * Archive: decompress_unlzma.i.zip 317 * Length Date Time Name 318 * -------- ---- ---- ---- 319 * 204372 09-06-09 14:23 decompress_unlzma.i 320 * -------- ------- 321 * 204372 1 file 322 */ 323 324 /* '-' makes getopt return 1 for non-options */ 325 while ((opt = getopt(argc, argv, "-d:lnopqxv")) != -1) { 114 326 switch (opt_range) { 115 327 case 0: /* Options */ 116 328 switch (opt) { 117 329 case 'l': /* List */ 118 verbosity = v_list;330 listing = 1; 119 331 break; 120 332 121 333 case 'n': /* Never overwrite existing files */ 122 overwrite = o_never;334 overwrite = O_NEVER; 123 335 break; 124 336 125 337 case 'o': /* Always overwrite existing files */ 126 overwrite = o_always;338 overwrite = O_ALWAYS; 127 339 break; 128 340 … … 131 343 132 344 case 'q': /* Be quiet */ 133 verbosity = (verbosity == v_normal) ? v_silent : verbosity; 134 break; 135 136 case 1 : /* The zip file */ 137 src_fn = xmalloc(strlen(optarg)+4); 345 quiet++; 346 break; 347 348 case 'v': /* Verbose list */ 349 IF_DESKTOP(verbose++;) 350 listing = 1; 351 break; 352 353 case 1: /* The zip file */ 354 /* +5: space for ".zip" and NUL */ 355 src_fn = xmalloc(strlen(optarg) + 5); 138 356 strcpy(src_fn, optarg); 139 357 opt_range++; … … 142 360 default: 143 361 bb_show_usage(); 144 145 362 } 146 363 break; … … 149 366 if (opt == 1) { 150 367 llist_add_to(&zaccept, optarg); 151 152 } else if (opt == 'd') { 368 break; 369 } 370 if (opt == 'd') { 153 371 base_dir = optarg; 154 372 opt_range += 2; 155 156 } else if (opt == 'x') { 373 break; 374 } 375 if (opt == 'x') { 157 376 opt_range++; 158 159 } else { 160 bb_show_usage(); 161 } 162 break; 377 break; 378 } 379 bb_show_usage(); 163 380 164 381 case 2 : /* Exclude files */ 165 382 if (opt == 1) { 166 383 llist_add_to(&zreject, optarg); 167 168 } else if (opt == 'd') { /* Extract to base directory */ 384 break; 385 } 386 if (opt == 'd') { /* Extract to base directory */ 169 387 base_dir = optarg; 170 388 opt_range++; 171 172 } else { 173 bb_show_usage(); 174 } 175 break; 389 break; 390 } 391 /* fall through */ 176 392 177 393 default: … … 186 402 /* Open input file */ 187 403 if (LONE_DASH(src_fn)) { 188 src_fd = STDIN_FILENO;404 xdup2(STDIN_FILENO, zip_fd); 189 405 /* Cannot use prompt mode since zip data is arriving on STDIN */ 190 overwrite = (overwrite == o_prompt) ? o_never : overwrite; 406 if (overwrite == O_PROMPT) 407 overwrite = O_NEVER; 191 408 } else { 192 static const char *const extn[] = {"", ".zip", ".ZIP"};409 static const char extn[][5] = {"", ".zip", ".ZIP"}; 193 410 int orig_src_fn_len = strlen(src_fn); 411 int src_fd = -1; 412 194 413 for (i = 0; (i < 3) && (src_fd == -1); i++) { 195 414 strcpy(src_fn + orig_src_fn_len, extn[i]); … … 198 417 if (src_fd == -1) { 199 418 src_fn[orig_src_fn_len] = '\0'; 200 bb_error_msg_and_die("cannot open %s, %s.zip, %s.ZIP", src_fn, src_fn, src_fn); 201 } 419 bb_error_msg_and_die("can't open %s, %s.zip, %s.ZIP", src_fn, src_fn, src_fn); 420 } 421 xmove_fd(src_fd, zip_fd); 202 422 } 203 423 … … 206 426 xchdir(base_dir); 207 427 208 if (verbosity != v_silent) 209 printf("Archive: %s\n", src_fn); 210 211 failed = 0; 212 428 if (quiet <= 1) { /* not -qq */ 429 if (quiet == 0) 430 printf("Archive: %s\n", src_fn); 431 if (listing) { 432 puts(verbose ? 433 " Length Method Size Ratio Date Time CRC-32 Name\n" 434 "-------- ------ ------- ----- ---- ---- ------ ----" 435 : 436 " Length Date Time Name\n" 437 " -------- ---- ---- ----" 438 ); 439 } 440 } 441 442 /* Example of an archive with one 0-byte long file named 'z' 443 * created by Zip 2.31 on Unix: 444 * 0000 [50 4b]03 04 0a 00 00 00 00 00 42 1a b8 3c 00 00 |PK........B..<..| 445 * sig........ vneed flags compr mtime mdate crc32> 446 * 0010 00 00 00 00 00 00 00 00 00 00 01 00 15 00 7a 55 |..............zU| 447 * >..... csize...... usize...... fnlen exlen fn ex> 448 * 0020 54 09 00 03 cc d3 f9 4b cc d3 f9 4b 55 78 04 00 |T......K...KUx..| 449 * >tra_field...................................... 450 * 0030 00 00 00 00[50 4b]01 02 17 03 0a 00 00 00 00 00 |....PK..........| 451 * ........... sig........ vmade vneed flags compr 452 * 0040 42 1a b8 3c 00 00 00 00 00 00 00 00 00 00 00 00 |B..<............| 453 * mtime mdate crc32...... csize...... usize...... 454 * 0050 01 00 0d 00 00 00 00 00 00 00 00 00 a4 81 00 00 |................| 455 * fnlen exlen clen. dnum. iattr eattr...... relofs> (eattr = rw-r--r--) 456 * 0060 00 00 7a 55 54 05 00 03 cc d3 f9 4b 55 78 00 00 |..zUT......KUx..| 457 * >..... fn extra_field........................... 458 * 0070 [50 4b]05 06 00 00 00 00 01 00 01 00 3c 00 00 00 |PK..........<...| 459 * 0080 34 00 00 00 00 00 |4.....| 460 */ 461 total_usize = 0; 462 total_size = 0; 463 total_entries = 0; 464 #if ENABLE_DESKTOP 465 cdf_offset = 0; 466 #endif 213 467 while (1) { 214 unsigned int magic; 468 uint32_t magic; 469 mode_t dir_mode = 0777; 470 #if ENABLE_DESKTOP 471 mode_t file_mode = 0666; 472 #endif 215 473 216 474 /* Check magic number */ 217 xread(src_fd, &magic, 4); 218 if (magic == ZIP_CDS_MAGIC) { 475 xread(zip_fd, &magic, 4); 476 /* Central directory? It's at the end, so exit */ 477 if (magic == ZIP_CDF_MAGIC) 219 478 break; 220 } else if (magic != ZIP_FILEHEADER_MAGIC) { 221 bb_error_msg_and_die("invalid zip magic %08X", magic); 222 } 479 #if ENABLE_DESKTOP 480 /* Data descriptor? It was a streaming file, go on */ 481 if (magic == ZIP_DD_MAGIC) { 482 /* skip over duplicate crc32, cmpsize and ucmpsize */ 483 unzip_skip(3 * 4); 484 continue; 485 } 486 #endif 487 if (magic != ZIP_FILEHEADER_MAGIC) 488 bb_error_msg_and_die("invalid zip magic %08X", (int)magic); 223 489 224 490 /* Read the file header */ 225 xread(src_fd, zip_header.raw, 26); 226 zip_header.formatted.version = SWAP_LE32(zip_header.formatted.version); 227 zip_header.formatted.flags = SWAP_LE32(zip_header.formatted.flags); 228 zip_header.formatted.method = SWAP_LE32(zip_header.formatted.method); 229 zip_header.formatted.modtime = SWAP_LE32(zip_header.formatted.modtime); 230 zip_header.formatted.moddate = SWAP_LE32(zip_header.formatted.moddate); 231 zip_header.formatted.crc32 = SWAP_LE32(zip_header.formatted.crc32); 232 zip_header.formatted.cmpsize = SWAP_LE32(zip_header.formatted.cmpsize); 233 zip_header.formatted.ucmpsize = SWAP_LE32(zip_header.formatted.ucmpsize); 234 zip_header.formatted.filename_len = SWAP_LE32(zip_header.formatted.filename_len); 235 zip_header.formatted.extra_len = SWAP_LE32(zip_header.formatted.extra_len); 491 xread(zip_fd, zip_header.raw, ZIP_HEADER_LEN); 492 FIX_ENDIANNESS_ZIP(zip_header); 236 493 if ((zip_header.formatted.method != 0) && (zip_header.formatted.method != 8)) { 237 bb_error_msg_and_die("unsupported compression method %d", zip_header.formatted.method); 238 } 494 bb_error_msg_and_die("unsupported method %d", zip_header.formatted.method); 495 } 496 #if !ENABLE_DESKTOP 497 if (zip_header.formatted.zip_flags & SWAP_LE16(0x0009)) { 498 bb_error_msg_and_die("zip flags 1 and 8 are not supported"); 499 } 500 #else 501 if (zip_header.formatted.zip_flags & SWAP_LE16(0x0001)) { 502 /* 0x0001 - encrypted */ 503 bb_error_msg_and_die("zip flag 1 (encryption) is not supported"); 504 } 505 506 { 507 cdf_header_t cdf_header; 508 cdf_offset = read_next_cdf(cdf_offset, &cdf_header); 509 if (zip_header.formatted.zip_flags & SWAP_LE16(0x0008)) { 510 /* 0x0008 - streaming. [u]cmpsize can be reliably gotten 511 * only from Central Directory. See unzip_doc.txt */ 512 zip_header.formatted.crc32 = cdf_header.formatted.crc32; 513 zip_header.formatted.cmpsize = cdf_header.formatted.cmpsize; 514 zip_header.formatted.ucmpsize = cdf_header.formatted.ucmpsize; 515 } 516 if ((cdf_header.formatted.version_made_by >> 8) == 3) { 517 /* this archive is created on Unix */ 518 dir_mode = file_mode = (cdf_header.formatted.external_file_attributes >> 16); 519 } 520 } 521 #endif 239 522 240 523 /* Read filename */ 241 524 free(dst_fn); 242 525 dst_fn = xzalloc(zip_header.formatted.filename_len + 1); 243 xread( src_fd, dst_fn, zip_header.formatted.filename_len);526 xread(zip_fd, dst_fn, zip_header.formatted.filename_len); 244 527 245 528 /* Skip extra header bytes */ 246 unzip_skip(src_fd, zip_header.formatted.extra_len); 247 248 if ((verbosity == v_list) && !list_header_done){ 249 puts(" Length Date Time Name\n" 250 " -------- ---- ---- ----"); 251 list_header_done = 1; 252 } 529 unzip_skip(zip_header.formatted.extra_len); 253 530 254 531 /* Filter zip entries */ 255 if (find_list_entry(zreject, dst_fn) || 256 (zaccept && !find_list_entry(zaccept, dst_fn))) { /* Skip entry */ 532 if (find_list_entry(zreject, dst_fn) 533 || (zaccept && !find_list_entry(zaccept, dst_fn)) 534 ) { /* Skip entry */ 257 535 i = 'n'; 258 536 259 537 } else { /* Extract entry */ 260 total_size += zip_header.formatted.ucmpsize; 261 262 if (verbosity == v_list) { /* List entry */ 263 unsigned int dostime = zip_header.formatted.modtime | (zip_header.formatted.moddate << 16); 264 printf("%9u %02u-%02u-%02u %02u:%02u %s\n", 265 zip_header.formatted.ucmpsize, 266 (dostime & 0x01e00000) >> 21, 267 (dostime & 0x001f0000) >> 16, 268 (((dostime & 0xfe000000) >> 25) + 1980) % 100, 269 (dostime & 0x0000f800) >> 11, 270 (dostime & 0x000007e0) >> 5, 271 dst_fn); 272 total_entries++; 538 if (listing) { /* List entry */ 539 unsigned dostime = zip_header.formatted.modtime | (zip_header.formatted.moddate << 16); 540 if (!verbose) { 541 // " Length Date Time Name\n" 542 // " -------- ---- ---- ----" 543 printf( "%9u %02u-%02u-%02u %02u:%02u %s\n", 544 (unsigned)zip_header.formatted.ucmpsize, 545 (dostime & 0x01e00000) >> 21, 546 (dostime & 0x001f0000) >> 16, 547 (((dostime & 0xfe000000) >> 25) + 1980) % 100, 548 (dostime & 0x0000f800) >> 11, 549 (dostime & 0x000007e0) >> 5, 550 dst_fn); 551 total_usize += zip_header.formatted.ucmpsize; 552 } else { 553 unsigned long percents = zip_header.formatted.ucmpsize - zip_header.formatted.cmpsize; 554 percents = percents * 100; 555 if (zip_header.formatted.ucmpsize) 556 percents /= zip_header.formatted.ucmpsize; 557 // " Length Method Size Ratio Date Time CRC-32 Name\n" 558 // "-------- ------ ------- ----- ---- ---- ------ ----" 559 printf( "%8u Defl:N" "%9u%4u%% %02u-%02u-%02u %02u:%02u %08x %s\n", 560 (unsigned)zip_header.formatted.ucmpsize, 561 (unsigned)zip_header.formatted.cmpsize, 562 (unsigned)percents, 563 (dostime & 0x01e00000) >> 21, 564 (dostime & 0x001f0000) >> 16, 565 (((dostime & 0xfe000000) >> 25) + 1980) % 100, 566 (dostime & 0x0000f800) >> 11, 567 (dostime & 0x000007e0) >> 5, 568 zip_header.formatted.crc32, 569 dst_fn); 570 total_usize += zip_header.formatted.ucmpsize; 571 total_size += zip_header.formatted.cmpsize; 572 } 273 573 i = 'n'; 274 574 } else if (dst_fd == STDOUT_FILENO) { /* Extracting to STDOUT */ … … 277 577 if (stat(dst_fn, &stat_buf) == -1) { 278 578 if (errno != ENOENT) { 279 bb_perror_msg_and_die("can not stat '%s'",dst_fn);579 bb_perror_msg_and_die("can't stat '%s'", dst_fn); 280 580 } 281 if ( verbosity == v_normal) {581 if (!quiet) { 282 582 printf(" creating: %s\n", dst_fn); 283 583 } 284 584 unzip_create_leading_dirs(dst_fn); 285 if (bb_make_directory(dst_fn, 0777, 0)) {585 if (bb_make_directory(dst_fn, dir_mode, 0)) { 286 586 bb_error_msg_and_die("exiting"); 287 587 } … … 294 594 295 595 } else { /* Extract file */ 296 _check_file:596 check_file: 297 597 if (stat(dst_fn, &stat_buf) == -1) { /* File does not exist */ 298 598 if (errno != ENOENT) { 299 bb_perror_msg_and_die("can not stat '%s'",dst_fn);599 bb_perror_msg_and_die("can't stat '%s'", dst_fn); 300 600 } 301 601 i = 'y'; 302 602 } else { /* File already exists */ 303 if (overwrite == o_never) {603 if (overwrite == O_NEVER) { 304 604 i = 'n'; 305 605 } else if (S_ISREG(stat_buf.st_mode)) { /* File is regular file */ 306 if (overwrite == o_always) {606 if (overwrite == O_ALWAYS) { 307 607 i = 'y'; 308 608 } else { 309 609 printf("replace %s? [y]es, [n]o, [A]ll, [N]one, [r]ename: ", dst_fn); 310 if (!fgets(key_buf, 512, stdin)) {311 bb_perror_msg_and_die("can not read input");610 if (!fgets(key_buf, sizeof(key_buf), stdin)) { 611 bb_perror_msg_and_die("can't read input"); 312 612 } 313 613 i = key_buf[0]; 314 614 } 315 615 } else { /* File is not regular file */ 316 bb_error_msg_and_die("'%s' exists but is not regular file", dst_fn);616 bb_error_msg_and_die("'%s' exists but is not regular file", dst_fn); 317 617 } 318 618 } … … 322 622 switch (i) { 323 623 case 'A': 324 overwrite = o_always;624 overwrite = O_ALWAYS; 325 625 case 'y': /* Open file and fall into unzip */ 326 626 unzip_create_leading_dirs(dst_fn); 627 #if ENABLE_DESKTOP 628 dst_fd = xopen3(dst_fn, O_WRONLY | O_CREAT | O_TRUNC, file_mode); 629 #else 327 630 dst_fd = xopen(dst_fn, O_WRONLY | O_CREAT | O_TRUNC); 631 #endif 328 632 case -1: /* Unzip */ 329 if ( verbosity == v_normal) {633 if (!quiet) { 330 634 printf(" inflating: %s\n", dst_fn); 331 635 } 332 if (unzip_extract(&zip_header, src_fd, dst_fd)) { 333 failed = 1; 334 } 636 unzip_extract(&zip_header, dst_fd); 335 637 if (dst_fd != STDOUT_FILENO) { 336 638 /* closing STDOUT is potentially bad for future business */ … … 340 642 341 643 case 'N': 342 overwrite = o_never;644 overwrite = O_NEVER; 343 645 case 'n': 344 646 /* Skip entry data */ 345 unzip_skip( src_fd,zip_header.formatted.cmpsize);647 unzip_skip(zip_header.formatted.cmpsize); 346 648 break; 347 649 … … 349 651 /* Prompt for new name */ 350 652 printf("new name: "); 351 if (!fgets(key_buf, 512, stdin)) {352 bb_perror_msg_and_die("can not read input");653 if (!fgets(key_buf, sizeof(key_buf), stdin)) { 654 bb_perror_msg_and_die("can't read input"); 353 655 } 354 656 free(dst_fn); 355 657 dst_fn = xstrdup(key_buf); 356 658 chomp(dst_fn); 357 goto _check_file;659 goto check_file; 358 660 359 661 default: 360 printf("error: invalid response [%c]\n",(char)i); 361 goto _check_file; 362 } 363 364 /* Data descriptor section */ 365 if (zip_header.formatted.flags & 4) { 366 /* skip over duplicate crc, compressed size and uncompressed size */ 367 unzip_skip(src_fd, 12); 368 } 369 } 370 371 if (verbosity == v_list) { 372 printf(" -------- -------\n" 373 "%9d %d files\n", total_size, total_entries); 374 } 375 376 return failed; 662 printf("error: invalid response [%c]\n", (char)i); 663 goto check_file; 664 } 665 666 total_entries++; 667 } 668 669 if (listing && quiet <= 1) { 670 if (!verbose) { 671 // " Length Date Time Name\n" 672 // " -------- ---- ---- ----" 673 printf( " -------- -------\n" 674 "%9lu" " %u files\n", 675 total_usize, total_entries); 676 } else { 677 unsigned long percents = total_usize - total_size; 678 percents = percents * 100; 679 if (total_usize) 680 percents /= total_usize; 681 // " Length Method Size Ratio Date Time CRC-32 Name\n" 682 // "-------- ------ ------- ----- ---- ---- ------ ----" 683 printf( "-------- ------- --- -------\n" 684 "%8lu" "%17lu%4u%% %u files\n", 685 total_usize, total_size, (unsigned)percents, 686 total_entries); 687 } 688 } 689 690 return 0; 377 691 }
Note:
See TracChangeset
for help on using the changeset viewer.