Changeset 2725 in MondoRescue for branches/2.2.9/mindi-busybox/archival/ar.c
- Timestamp:
- Feb 25, 2011, 9:26:54 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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;
Note:
See TracChangeset
for help on using the changeset viewer.