tar.c 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Mini tar implementation for busybox
  4. *
  5. * Modified to use common extraction code used by ar, cpio, dpkg-deb, dpkg
  6. * by Glenn McGrath
  7. *
  8. * Note, that as of BusyBox-0.43, tar has been completely rewritten from the
  9. * ground up. It still has remnants of the old code lying about, but it is
  10. * very different now (i.e., cleaner, less global variables, etc.)
  11. *
  12. * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
  13. *
  14. * Based in part in the tar implementation in sash
  15. * Copyright (c) 1999 by David I. Bell
  16. * Permission is granted to use, distribute, or modify this source,
  17. * provided that this copyright notice remains intact.
  18. * Permission to distribute sash derived code under GPL has been granted.
  19. *
  20. * Based in part on the tar implementation from busybox-0.28
  21. * Copyright (C) 1995 Bruce Perens
  22. *
  23. * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  24. */
  25. #include <fnmatch.h>
  26. #include "libbb.h"
  27. #include "unarchive.h"
  28. /* FIXME: Stop using this non-standard feature */
  29. #ifndef FNM_LEADING_DIR
  30. # define FNM_LEADING_DIR 0
  31. #endif
  32. //#define DBG(fmt, ...) bb_error_msg("%s: " fmt, __func__, ## __VA_ARGS__)
  33. #define DBG(...) ((void)0)
  34. #define block_buf bb_common_bufsiz1
  35. #if !ENABLE_FEATURE_SEAMLESS_GZ && !ENABLE_FEATURE_SEAMLESS_BZ2
  36. /* Do not pass gzip flag to writeTarFile() */
  37. #define writeTarFile(tar_fd, verboseFlag, dereferenceFlag, include, exclude, gzip) \
  38. writeTarFile(tar_fd, verboseFlag, dereferenceFlag, include, exclude)
  39. #endif
  40. #if ENABLE_FEATURE_TAR_CREATE
  41. /*
  42. ** writeTarFile(), writeFileToTarball(), and writeTarHeader() are
  43. ** the only functions that deal with the HardLinkInfo structure.
  44. ** Even these functions use the xxxHardLinkInfo() functions.
  45. */
  46. typedef struct HardLinkInfo {
  47. struct HardLinkInfo *next; /* Next entry in list */
  48. dev_t dev; /* Device number */
  49. ino_t ino; /* Inode number */
  50. // short linkCount; /* (Hard) Link Count */
  51. char name[1]; /* Start of filename (must be last) */
  52. } HardLinkInfo;
  53. /* Some info to be carried along when creating a new tarball */
  54. typedef struct TarBallInfo {
  55. int tarFd; /* Open-for-write file descriptor
  56. * for the tarball */
  57. int verboseFlag; /* Whether to print extra stuff or not */
  58. const llist_t *excludeList; /* List of files to not include */
  59. HardLinkInfo *hlInfoHead; /* Hard Link Tracking Information */
  60. HardLinkInfo *hlInfo; /* Hard Link Info for the current file */
  61. //TODO: save only st_dev + st_ino
  62. struct stat tarFileStatBuf; /* Stat info for the tarball, letting
  63. * us know the inode and device that the
  64. * tarball lives, so we can avoid trying
  65. * to include the tarball into itself */
  66. } TarBallInfo;
  67. /* A nice enum with all the possible tar file content types */
  68. enum {
  69. REGTYPE = '0', /* regular file */
  70. REGTYPE0 = '\0', /* regular file (ancient bug compat) */
  71. LNKTYPE = '1', /* hard link */
  72. SYMTYPE = '2', /* symbolic link */
  73. CHRTYPE = '3', /* character special */
  74. BLKTYPE = '4', /* block special */
  75. DIRTYPE = '5', /* directory */
  76. FIFOTYPE = '6', /* FIFO special */
  77. CONTTYPE = '7', /* reserved */
  78. GNULONGLINK = 'K', /* GNU long (>100 chars) link name */
  79. GNULONGNAME = 'L', /* GNU long (>100 chars) file name */
  80. };
  81. /* Might be faster (and bigger) if the dev/ino were stored in numeric order;) */
  82. static void addHardLinkInfo(HardLinkInfo **hlInfoHeadPtr,
  83. struct stat *statbuf,
  84. const char *fileName)
  85. {
  86. /* Note: hlInfoHeadPtr can never be NULL! */
  87. HardLinkInfo *hlInfo;
  88. hlInfo = xmalloc(sizeof(HardLinkInfo) + strlen(fileName));
  89. hlInfo->next = *hlInfoHeadPtr;
  90. *hlInfoHeadPtr = hlInfo;
  91. hlInfo->dev = statbuf->st_dev;
  92. hlInfo->ino = statbuf->st_ino;
  93. // hlInfo->linkCount = statbuf->st_nlink;
  94. strcpy(hlInfo->name, fileName);
  95. }
  96. static void freeHardLinkInfo(HardLinkInfo **hlInfoHeadPtr)
  97. {
  98. HardLinkInfo *hlInfo;
  99. HardLinkInfo *hlInfoNext;
  100. if (hlInfoHeadPtr) {
  101. hlInfo = *hlInfoHeadPtr;
  102. while (hlInfo) {
  103. hlInfoNext = hlInfo->next;
  104. free(hlInfo);
  105. hlInfo = hlInfoNext;
  106. }
  107. *hlInfoHeadPtr = NULL;
  108. }
  109. }
  110. /* Might be faster (and bigger) if the dev/ino were stored in numeric order ;) */
  111. static HardLinkInfo *findHardLinkInfo(HardLinkInfo *hlInfo, struct stat *statbuf)
  112. {
  113. while (hlInfo) {
  114. if (statbuf->st_ino == hlInfo->ino
  115. && statbuf->st_dev == hlInfo->dev
  116. ) {
  117. DBG("found hardlink:'%s'", hlInfo->name);
  118. break;
  119. }
  120. hlInfo = hlInfo->next;
  121. }
  122. return hlInfo;
  123. }
  124. /* Put an octal string into the specified buffer.
  125. * The number is zero padded and possibly null terminated.
  126. * Stores low-order bits only if whole value does not fit. */
  127. static void putOctal(char *cp, int len, off_t value)
  128. {
  129. char tempBuffer[sizeof(off_t)*3 + 1];
  130. char *tempString = tempBuffer;
  131. int width;
  132. width = sprintf(tempBuffer, "%0*"OFF_FMT"o", len, value);
  133. tempString += (width - len);
  134. /* If string has leading zeroes, we can drop one */
  135. /* and field will have trailing '\0' */
  136. /* (increases chances of compat with other tars) */
  137. if (tempString[0] == '0')
  138. tempString++;
  139. /* Copy the string to the field */
  140. memcpy(cp, tempString, len);
  141. }
  142. #define PUT_OCTAL(a, b) putOctal((a), sizeof(a), (b))
  143. static void chksum_and_xwrite(int fd, struct tar_header_t* hp)
  144. {
  145. /* POSIX says that checksum is done on unsigned bytes
  146. * (Sun and HP-UX gets it wrong... more details in
  147. * GNU tar source) */
  148. const unsigned char *cp;
  149. int chksum, size;
  150. strcpy(hp->magic, "ustar ");
  151. /* Calculate and store the checksum (i.e., the sum of all of the bytes of
  152. * the header). The checksum field must be filled with blanks for the
  153. * calculation. The checksum field is formatted differently from the
  154. * other fields: it has 6 digits, a null, then a space -- rather than
  155. * digits, followed by a null like the other fields... */
  156. memset(hp->chksum, ' ', sizeof(hp->chksum));
  157. cp = (const unsigned char *) hp;
  158. chksum = 0;
  159. size = sizeof(*hp);
  160. do { chksum += *cp++; } while (--size);
  161. putOctal(hp->chksum, sizeof(hp->chksum)-1, chksum);
  162. /* Now write the header out to disk */
  163. xwrite(fd, hp, sizeof(*hp));
  164. }
  165. #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
  166. static void writeLongname(int fd, int type, const char *name, int dir)
  167. {
  168. static const struct {
  169. char mode[8]; /* 100-107 */
  170. char uid[8]; /* 108-115 */
  171. char gid[8]; /* 116-123 */
  172. char size[12]; /* 124-135 */
  173. char mtime[12]; /* 136-147 */
  174. } prefilled = {
  175. "0000000",
  176. "0000000",
  177. "0000000",
  178. "00000000000",
  179. "00000000000",
  180. };
  181. struct tar_header_t header;
  182. int size;
  183. dir = !!dir; /* normalize: 0/1 */
  184. size = strlen(name) + 1 + dir; /* GNU tar uses strlen+1 */
  185. /* + dir: account for possible '/' */
  186. memset(&header, 0, sizeof(header));
  187. strcpy(header.name, "././@LongLink");
  188. memcpy(header.mode, prefilled.mode, sizeof(prefilled));
  189. PUT_OCTAL(header.size, size);
  190. header.typeflag = type;
  191. chksum_and_xwrite(fd, &header);
  192. /* Write filename[/] and pad the block. */
  193. /* dir=0: writes 'name<NUL>', pads */
  194. /* dir=1: writes 'name', writes '/<NUL>', pads */
  195. dir *= 2;
  196. xwrite(fd, name, size - dir);
  197. xwrite(fd, "/", dir);
  198. size = (-size) & (TAR_BLOCK_SIZE-1);
  199. memset(&header, 0, size);
  200. xwrite(fd, &header, size);
  201. }
  202. #endif
  203. /* Write out a tar header for the specified file/directory/whatever */
  204. static int writeTarHeader(struct TarBallInfo *tbInfo,
  205. const char *header_name, const char *fileName, struct stat *statbuf)
  206. {
  207. struct tar_header_t header;
  208. memset(&header, 0, sizeof(header));
  209. strncpy(header.name, header_name, sizeof(header.name));
  210. /* POSIX says to mask mode with 07777. */
  211. PUT_OCTAL(header.mode, statbuf->st_mode & 07777);
  212. PUT_OCTAL(header.uid, statbuf->st_uid);
  213. PUT_OCTAL(header.gid, statbuf->st_gid);
  214. memset(header.size, '0', sizeof(header.size)-1); /* Regular file size is handled later */
  215. PUT_OCTAL(header.mtime, statbuf->st_mtime);
  216. /* Enter the user and group names */
  217. safe_strncpy(header.uname, get_cached_username(statbuf->st_uid), sizeof(header.uname));
  218. safe_strncpy(header.gname, get_cached_groupname(statbuf->st_gid), sizeof(header.gname));
  219. if (tbInfo->hlInfo) {
  220. /* This is a hard link */
  221. header.typeflag = LNKTYPE;
  222. strncpy(header.linkname, tbInfo->hlInfo->name,
  223. sizeof(header.linkname));
  224. #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
  225. /* Write out long linkname if needed */
  226. if (header.linkname[sizeof(header.linkname)-1])
  227. writeLongname(tbInfo->tarFd, GNULONGLINK,
  228. tbInfo->hlInfo->name, 0);
  229. #endif
  230. } else if (S_ISLNK(statbuf->st_mode)) {
  231. char *lpath = xmalloc_readlink_or_warn(fileName);
  232. if (!lpath)
  233. return FALSE;
  234. header.typeflag = SYMTYPE;
  235. strncpy(header.linkname, lpath, sizeof(header.linkname));
  236. #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
  237. /* Write out long linkname if needed */
  238. if (header.linkname[sizeof(header.linkname)-1])
  239. writeLongname(tbInfo->tarFd, GNULONGLINK, lpath, 0);
  240. #else
  241. /* If it is larger than 100 bytes, bail out */
  242. if (header.linkname[sizeof(header.linkname)-1]) {
  243. free(lpath);
  244. bb_error_msg("names longer than "NAME_SIZE_STR" chars not supported");
  245. return FALSE;
  246. }
  247. #endif
  248. free(lpath);
  249. } else if (S_ISDIR(statbuf->st_mode)) {
  250. header.typeflag = DIRTYPE;
  251. /* Append '/' only if there is a space for it */
  252. if (!header.name[sizeof(header.name)-1])
  253. header.name[strlen(header.name)] = '/';
  254. } else if (S_ISCHR(statbuf->st_mode)) {
  255. header.typeflag = CHRTYPE;
  256. PUT_OCTAL(header.devmajor, major(statbuf->st_rdev));
  257. PUT_OCTAL(header.devminor, minor(statbuf->st_rdev));
  258. } else if (S_ISBLK(statbuf->st_mode)) {
  259. header.typeflag = BLKTYPE;
  260. PUT_OCTAL(header.devmajor, major(statbuf->st_rdev));
  261. PUT_OCTAL(header.devminor, minor(statbuf->st_rdev));
  262. } else if (S_ISFIFO(statbuf->st_mode)) {
  263. header.typeflag = FIFOTYPE;
  264. } else if (S_ISREG(statbuf->st_mode)) {
  265. if (sizeof(statbuf->st_size) > 4
  266. && statbuf->st_size > (off_t)0777777777777LL
  267. ) {
  268. bb_error_msg_and_die("can't store file '%s' "
  269. "of size %"OFF_FMT"u, aborting",
  270. fileName, statbuf->st_size);
  271. }
  272. header.typeflag = REGTYPE;
  273. PUT_OCTAL(header.size, statbuf->st_size);
  274. } else {
  275. bb_error_msg("%s: unknown file type", fileName);
  276. return FALSE;
  277. }
  278. #if ENABLE_FEATURE_TAR_GNU_EXTENSIONS
  279. /* Write out long name if needed */
  280. /* (we, like GNU tar, output long linkname *before* long name) */
  281. if (header.name[sizeof(header.name)-1])
  282. writeLongname(tbInfo->tarFd, GNULONGNAME,
  283. header_name, S_ISDIR(statbuf->st_mode));
  284. #endif
  285. /* Now write the header out to disk */
  286. chksum_and_xwrite(tbInfo->tarFd, &header);
  287. /* Now do the verbose thing (or not) */
  288. if (tbInfo->verboseFlag) {
  289. FILE *vbFd = stdout;
  290. /* If archive goes to stdout, verbose goes to stderr */
  291. if (tbInfo->tarFd == STDOUT_FILENO)
  292. vbFd = stderr;
  293. /* GNU "tar cvvf" prints "extended" listing a-la "ls -l" */
  294. /* We don't have such excesses here: for us "v" == "vv" */
  295. /* '/' is probably a GNUism */
  296. fprintf(vbFd, "%s%s\n", header_name,
  297. S_ISDIR(statbuf->st_mode) ? "/" : "");
  298. }
  299. return TRUE;
  300. }
  301. #if ENABLE_FEATURE_TAR_FROM
  302. static int exclude_file(const llist_t *excluded_files, const char *file)
  303. {
  304. while (excluded_files) {
  305. if (excluded_files->data[0] == '/') {
  306. if (fnmatch(excluded_files->data, file,
  307. FNM_PATHNAME | FNM_LEADING_DIR) == 0)
  308. return 1;
  309. } else {
  310. const char *p;
  311. for (p = file; p[0] != '\0'; p++) {
  312. if ((p == file || p[-1] == '/')
  313. && p[0] != '/'
  314. && fnmatch(excluded_files->data, p,
  315. FNM_PATHNAME | FNM_LEADING_DIR) == 0
  316. ) {
  317. return 1;
  318. }
  319. }
  320. }
  321. excluded_files = excluded_files->link;
  322. }
  323. return 0;
  324. }
  325. #else
  326. # define exclude_file(excluded_files, file) 0
  327. #endif
  328. static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statbuf,
  329. void *userData, int depth UNUSED_PARAM)
  330. {
  331. struct TarBallInfo *tbInfo = (struct TarBallInfo *) userData;
  332. const char *header_name;
  333. int inputFileFd = -1;
  334. DBG("writeFileToTarball('%s')", fileName);
  335. /* Strip leading '/' (must be before memorizing hardlink's name) */
  336. header_name = fileName;
  337. while (header_name[0] == '/') {
  338. static smallint warned;
  339. if (!warned) {
  340. bb_error_msg("removing leading '/' from member names");
  341. warned = 1;
  342. }
  343. header_name++;
  344. }
  345. if (header_name[0] == '\0')
  346. return TRUE;
  347. /* It is against the rules to archive a socket */
  348. if (S_ISSOCK(statbuf->st_mode)) {
  349. bb_error_msg("%s: socket ignored", fileName);
  350. return TRUE;
  351. }
  352. /*
  353. * Check to see if we are dealing with a hard link.
  354. * If so -
  355. * Treat the first occurance of a given dev/inode as a file while
  356. * treating any additional occurances as hard links. This is done
  357. * by adding the file information to the HardLinkInfo linked list.
  358. */
  359. tbInfo->hlInfo = NULL;
  360. if (!S_ISDIR(statbuf->st_mode) && statbuf->st_nlink > 1) {
  361. DBG("'%s': st_nlink > 1", header_name);
  362. tbInfo->hlInfo = findHardLinkInfo(tbInfo->hlInfoHead, statbuf);
  363. if (tbInfo->hlInfo == NULL) {
  364. DBG("'%s': addHardLinkInfo", header_name);
  365. addHardLinkInfo(&tbInfo->hlInfoHead, statbuf, header_name);
  366. }
  367. }
  368. /* It is a bad idea to store the archive we are in the process of creating,
  369. * so check the device and inode to be sure that this particular file isn't
  370. * the new tarball */
  371. if (tbInfo->tarFileStatBuf.st_dev == statbuf->st_dev
  372. && tbInfo->tarFileStatBuf.st_ino == statbuf->st_ino
  373. ) {
  374. bb_error_msg("%s: file is the archive; skipping", fileName);
  375. return TRUE;
  376. }
  377. if (exclude_file(tbInfo->excludeList, header_name))
  378. return SKIP;
  379. #if !ENABLE_FEATURE_TAR_GNU_EXTENSIONS
  380. if (strlen(header_name) >= NAME_SIZE) {
  381. bb_error_msg("names longer than "NAME_SIZE_STR" chars not supported");
  382. return TRUE;
  383. }
  384. #endif
  385. /* Is this a regular file? */
  386. if (tbInfo->hlInfo == NULL && S_ISREG(statbuf->st_mode)) {
  387. /* open the file we want to archive, and make sure all is well */
  388. inputFileFd = open_or_warn(fileName, O_RDONLY);
  389. if (inputFileFd < 0) {
  390. return FALSE;
  391. }
  392. }
  393. /* Add an entry to the tarball */
  394. if (writeTarHeader(tbInfo, header_name, fileName, statbuf) == FALSE) {
  395. return FALSE;
  396. }
  397. /* If it was a regular file, write out the body */
  398. if (inputFileFd >= 0) {
  399. size_t readSize;
  400. /* Write the file to the archive. */
  401. /* We record size into header first, */
  402. /* and then write out file. If file shrinks in between, */
  403. /* tar will be corrupted. So we don't allow for that. */
  404. /* NB: GNU tar 1.16 warns and pads with zeroes */
  405. /* or even seeks back and updates header */
  406. bb_copyfd_exact_size(inputFileFd, tbInfo->tarFd, statbuf->st_size);
  407. ////off_t readSize;
  408. ////readSize = bb_copyfd_size(inputFileFd, tbInfo->tarFd, statbuf->st_size);
  409. ////if (readSize != statbuf->st_size && readSize >= 0) {
  410. //// bb_error_msg_and_die("short read from %s, aborting", fileName);
  411. ////}
  412. /* Check that file did not grow in between? */
  413. /* if (safe_read(inputFileFd, 1) == 1) warn but continue? */
  414. close(inputFileFd);
  415. /* Pad the file up to the tar block size */
  416. /* (a few tricks here in the name of code size) */
  417. readSize = (-(int)statbuf->st_size) & (TAR_BLOCK_SIZE-1);
  418. memset(block_buf, 0, readSize);
  419. xwrite(tbInfo->tarFd, block_buf, readSize);
  420. }
  421. return TRUE;
  422. }
  423. #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
  424. # if !(ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2)
  425. # define vfork_compressor(tar_fd, gzip) vfork_compressor(tar_fd)
  426. # endif
  427. /* Don't inline: vfork scares gcc and pessimizes code */
  428. static void NOINLINE vfork_compressor(int tar_fd, int gzip)
  429. {
  430. pid_t gzipPid;
  431. # if ENABLE_FEATURE_SEAMLESS_GZ && ENABLE_FEATURE_SEAMLESS_BZ2
  432. const char *zip_exec = (gzip == 1) ? "gzip" : "bzip2";
  433. # elif ENABLE_FEATURE_SEAMLESS_GZ
  434. const char *zip_exec = "gzip";
  435. # else /* only ENABLE_FEATURE_SEAMLESS_BZ2 */
  436. const char *zip_exec = "bzip2";
  437. # endif
  438. // On Linux, vfork never unpauses parent early, although standard
  439. // allows for that. Do we want to waste bytes checking for it?
  440. # define WAIT_FOR_CHILD 0
  441. volatile int vfork_exec_errno = 0;
  442. struct fd_pair gzipDataPipe;
  443. # if WAIT_FOR_CHILD
  444. struct fd_pair gzipStatusPipe;
  445. xpiped_pair(gzipStatusPipe);
  446. # endif
  447. xpiped_pair(gzipDataPipe);
  448. signal(SIGPIPE, SIG_IGN); /* we only want EPIPE on errors */
  449. # if defined(__GNUC__) && __GNUC__
  450. /* Avoid vfork clobbering */
  451. (void) &zip_exec;
  452. # endif
  453. gzipPid = xvfork();
  454. if (gzipPid == 0) {
  455. /* child */
  456. /* NB: close _first_, then move fds! */
  457. close(gzipDataPipe.wr);
  458. # if WAIT_FOR_CHILD
  459. close(gzipStatusPipe.rd);
  460. /* gzipStatusPipe.wr will close only on exec -
  461. * parent waits for this close to happen */
  462. fcntl(gzipStatusPipe.wr, F_SETFD, FD_CLOEXEC);
  463. # endif
  464. xmove_fd(gzipDataPipe.rd, 0);
  465. xmove_fd(tar_fd, 1);
  466. /* exec gzip/bzip2 program/applet */
  467. BB_EXECLP(zip_exec, zip_exec, "-f", NULL);
  468. vfork_exec_errno = errno;
  469. _exit(EXIT_FAILURE);
  470. }
  471. /* parent */
  472. xmove_fd(gzipDataPipe.wr, tar_fd);
  473. close(gzipDataPipe.rd);
  474. # if WAIT_FOR_CHILD
  475. close(gzipStatusPipe.wr);
  476. while (1) {
  477. char buf;
  478. int n;
  479. /* Wait until child execs (or fails to) */
  480. n = full_read(gzipStatusPipe.rd, &buf, 1);
  481. if (n < 0 /* && errno == EAGAIN */)
  482. continue; /* try it again */
  483. }
  484. close(gzipStatusPipe.rd);
  485. # endif
  486. if (vfork_exec_errno) {
  487. errno = vfork_exec_errno;
  488. bb_perror_msg_and_die("can't execute '%s'", zip_exec);
  489. }
  490. }
  491. #endif /* ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2 */
  492. /* gcc 4.2.1 inlines it, making code bigger */
  493. static NOINLINE int writeTarFile(int tar_fd, int verboseFlag,
  494. int dereferenceFlag, const llist_t *include,
  495. const llist_t *exclude, int gzip)
  496. {
  497. int errorFlag = FALSE;
  498. struct TarBallInfo tbInfo;
  499. tbInfo.hlInfoHead = NULL;
  500. tbInfo.tarFd = tar_fd;
  501. tbInfo.verboseFlag = verboseFlag;
  502. /* Store the stat info for the tarball's file, so
  503. * can avoid including the tarball into itself.... */
  504. if (fstat(tbInfo.tarFd, &tbInfo.tarFileStatBuf) < 0)
  505. bb_perror_msg_and_die("can't stat tar file");
  506. #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
  507. if (gzip)
  508. vfork_compressor(tbInfo.tarFd, gzip);
  509. #endif
  510. tbInfo.excludeList = exclude;
  511. /* Read the directory/files and iterate over them one at a time */
  512. while (include) {
  513. if (!recursive_action(include->data, ACTION_RECURSE |
  514. (dereferenceFlag ? ACTION_FOLLOWLINKS : 0),
  515. writeFileToTarball, writeFileToTarball, &tbInfo, 0)
  516. ) {
  517. errorFlag = TRUE;
  518. }
  519. include = include->link;
  520. }
  521. /* Write two empty blocks to the end of the archive */
  522. memset(block_buf, 0, 2*TAR_BLOCK_SIZE);
  523. xwrite(tbInfo.tarFd, block_buf, 2*TAR_BLOCK_SIZE);
  524. /* To be pedantically correct, we would check if the tarball
  525. * is smaller than 20 tar blocks, and pad it if it was smaller,
  526. * but that isn't necessary for GNU tar interoperability, and
  527. * so is considered a waste of space */
  528. /* Close so the child process (if any) will exit */
  529. close(tbInfo.tarFd);
  530. /* Hang up the tools, close up shop, head home */
  531. if (ENABLE_FEATURE_CLEAN_UP)
  532. freeHardLinkInfo(&tbInfo.hlInfoHead);
  533. if (errorFlag)
  534. bb_error_msg("error exit delayed from previous errors");
  535. #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
  536. if (gzip) {
  537. int status;
  538. if (safe_waitpid(-1, &status, 0) == -1)
  539. bb_perror_msg("waitpid");
  540. else if (!WIFEXITED(status) || WEXITSTATUS(status))
  541. /* gzip was killed or has exited with nonzero! */
  542. errorFlag = TRUE;
  543. }
  544. #endif
  545. return errorFlag;
  546. }
  547. #else
  548. int writeTarFile(int tar_fd, int verboseFlag,
  549. int dereferenceFlag, const llist_t *include,
  550. const llist_t *exclude, int gzip);
  551. #endif /* FEATURE_TAR_CREATE */
  552. #if ENABLE_FEATURE_TAR_FROM
  553. static llist_t *append_file_list_to_list(llist_t *list)
  554. {
  555. FILE *src_stream;
  556. char *line;
  557. llist_t *newlist = NULL;
  558. while (list) {
  559. src_stream = xfopen_for_read(llist_pop(&list));
  560. while ((line = xmalloc_fgetline(src_stream)) != NULL) {
  561. /* kill trailing '/' unless the string is just "/" */
  562. char *cp = last_char_is(line, '/');
  563. if (cp > line)
  564. *cp = '\0';
  565. llist_add_to(&newlist, line);
  566. }
  567. fclose(src_stream);
  568. }
  569. return newlist;
  570. }
  571. #else
  572. # define append_file_list_to_list(x) 0
  573. #endif
  574. #if ENABLE_FEATURE_SEAMLESS_Z
  575. static char FAST_FUNC get_header_tar_Z(archive_handle_t *archive_handle)
  576. {
  577. /* Can't lseek over pipes */
  578. archive_handle->seek = seek_by_read;
  579. /* do the decompression, and cleanup */
  580. if (xread_char(archive_handle->src_fd) != 0x1f
  581. || xread_char(archive_handle->src_fd) != 0x9d
  582. ) {
  583. bb_error_msg_and_die("invalid magic");
  584. }
  585. open_transformer(archive_handle->src_fd, unpack_Z_stream, "uncompress");
  586. archive_handle->offset = 0;
  587. while (get_header_tar(archive_handle) == EXIT_SUCCESS)
  588. continue;
  589. /* Can only do one file at a time */
  590. return EXIT_FAILURE;
  591. }
  592. #else
  593. # define get_header_tar_Z NULL
  594. #endif
  595. #ifdef CHECK_FOR_CHILD_EXITCODE
  596. /* Looks like it isn't needed - tar detects malformed (truncated)
  597. * archive if e.g. bunzip2 fails */
  598. static int child_error;
  599. static void handle_SIGCHLD(int status)
  600. {
  601. /* Actually, 'status' is a signo. We reuse it for other needs */
  602. /* Wait for any child without blocking */
  603. if (wait_any_nohang(&status) < 0)
  604. /* wait failed?! I'm confused... */
  605. return;
  606. if (WIFEXITED(status) && WEXITSTATUS(status) == 0)
  607. /* child exited with 0 */
  608. return;
  609. /* Cannot happen?
  610. if (!WIFSIGNALED(status) && !WIFEXITED(status)) return; */
  611. child_error = 1;
  612. }
  613. #endif
  614. //usage:#define tar_trivial_usage
  615. //usage: "-[" IF_FEATURE_TAR_CREATE("c") "xt" IF_FEATURE_SEAMLESS_GZ("z")
  616. //usage: IF_FEATURE_SEAMLESS_BZ2("j") IF_FEATURE_SEAMLESS_LZMA("a")
  617. //usage: IF_FEATURE_SEAMLESS_Z("Z") IF_FEATURE_TAR_NOPRESERVE_TIME("m") "vO] "
  618. //usage: IF_FEATURE_TAR_FROM("[-X FILE] ")
  619. //usage: "[-f TARFILE] [-C DIR] [FILE]..."
  620. //usage:#define tar_full_usage "\n\n"
  621. //usage: IF_FEATURE_TAR_CREATE("Create, extract, ")
  622. //usage: IF_NOT_FEATURE_TAR_CREATE("Extract ")
  623. //usage: "or list files from a tar file\n"
  624. //usage: "\nOperation:"
  625. //usage: IF_FEATURE_TAR_CREATE(
  626. //usage: "\n c Create"
  627. //usage: )
  628. //usage: "\n x Extract"
  629. //usage: "\n t List"
  630. //usage: "\nOptions:"
  631. //usage: "\n f Name of TARFILE ('-' for stdin/out)"
  632. //usage: "\n C Change to DIR before operation"
  633. //usage: "\n v Verbose"
  634. //usage: IF_FEATURE_SEAMLESS_GZ(
  635. //usage: "\n z (De)compress using gzip"
  636. //usage: )
  637. //usage: IF_FEATURE_SEAMLESS_BZ2(
  638. //usage: "\n j (De)compress using bzip2"
  639. //usage: )
  640. //usage: IF_FEATURE_SEAMLESS_LZMA(
  641. //usage: "\n a (De)compress using lzma"
  642. //usage: )
  643. //usage: IF_FEATURE_SEAMLESS_Z(
  644. //usage: "\n Z (De)compress using compress"
  645. //usage: )
  646. //usage: "\n O Extract to stdout"
  647. //usage: IF_FEATURE_TAR_CREATE(
  648. //usage: "\n h Follow symlinks"
  649. //usage: )
  650. //usage: IF_FEATURE_TAR_NOPRESERVE_TIME(
  651. //usage: "\n m Don't restore mtime"
  652. //usage: )
  653. //usage: IF_FEATURE_TAR_FROM(
  654. //usage: IF_FEATURE_TAR_LONG_OPTIONS(
  655. //usage: "\n exclude File to exclude"
  656. //usage: )
  657. //usage: "\n X File with names to exclude"
  658. //usage: "\n T File with names to include"
  659. //usage: )
  660. //usage:
  661. //usage:#define tar_example_usage
  662. //usage: "$ zcat /tmp/tarball.tar.gz | tar -xf -\n"
  663. //usage: "$ tar -cf /tmp/tarball.tar /usr/local\n"
  664. // Supported but aren't in --help:
  665. // o no-same-owner
  666. // p same-permissions
  667. // k keep-old
  668. // numeric-owner
  669. // no-same-permissions
  670. // overwrite
  671. //IF_FEATURE_TAR_TO_COMMAND(
  672. // to-command
  673. //)
  674. enum {
  675. OPTBIT_KEEP_OLD = 8,
  676. IF_FEATURE_TAR_CREATE( OPTBIT_CREATE ,)
  677. IF_FEATURE_TAR_CREATE( OPTBIT_DEREFERENCE ,)
  678. IF_FEATURE_SEAMLESS_BZ2( OPTBIT_BZIP2 ,)
  679. IF_FEATURE_SEAMLESS_LZMA(OPTBIT_LZMA ,)
  680. IF_FEATURE_TAR_FROM( OPTBIT_INCLUDE_FROM,)
  681. IF_FEATURE_TAR_FROM( OPTBIT_EXCLUDE_FROM,)
  682. IF_FEATURE_SEAMLESS_GZ( OPTBIT_GZIP ,)
  683. IF_FEATURE_SEAMLESS_Z( OPTBIT_COMPRESS ,) // 16th bit
  684. IF_FEATURE_TAR_NOPRESERVE_TIME(OPTBIT_NOPRESERVE_TIME,)
  685. #if ENABLE_FEATURE_TAR_LONG_OPTIONS
  686. IF_FEATURE_TAR_TO_COMMAND(OPTBIT_2COMMAND ,)
  687. OPTBIT_NUMERIC_OWNER,
  688. OPTBIT_NOPRESERVE_PERM,
  689. OPTBIT_OVERWRITE,
  690. #endif
  691. OPT_TEST = 1 << 0, // t
  692. OPT_EXTRACT = 1 << 1, // x
  693. OPT_BASEDIR = 1 << 2, // C
  694. OPT_TARNAME = 1 << 3, // f
  695. OPT_2STDOUT = 1 << 4, // O
  696. OPT_NOPRESERVE_OWNER = 1 << 5, // o == no-same-owner
  697. OPT_P = 1 << 6, // p
  698. OPT_VERBOSE = 1 << 7, // v
  699. OPT_KEEP_OLD = 1 << 8, // k
  700. OPT_CREATE = IF_FEATURE_TAR_CREATE( (1 << OPTBIT_CREATE )) + 0, // c
  701. OPT_DEREFERENCE = IF_FEATURE_TAR_CREATE( (1 << OPTBIT_DEREFERENCE )) + 0, // h
  702. OPT_BZIP2 = IF_FEATURE_SEAMLESS_BZ2( (1 << OPTBIT_BZIP2 )) + 0, // j
  703. OPT_LZMA = IF_FEATURE_SEAMLESS_LZMA((1 << OPTBIT_LZMA )) + 0, // a
  704. OPT_INCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_INCLUDE_FROM)) + 0, // T
  705. OPT_EXCLUDE_FROM = IF_FEATURE_TAR_FROM( (1 << OPTBIT_EXCLUDE_FROM)) + 0, // X
  706. OPT_GZIP = IF_FEATURE_SEAMLESS_GZ( (1 << OPTBIT_GZIP )) + 0, // z
  707. OPT_COMPRESS = IF_FEATURE_SEAMLESS_Z( (1 << OPTBIT_COMPRESS )) + 0, // Z
  708. OPT_NOPRESERVE_TIME = IF_FEATURE_TAR_NOPRESERVE_TIME((1 << OPTBIT_NOPRESERVE_TIME)) + 0, // m
  709. OPT_2COMMAND = IF_FEATURE_TAR_TO_COMMAND( (1 << OPTBIT_2COMMAND )) + 0, // to-command
  710. OPT_NUMERIC_OWNER = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NUMERIC_OWNER )) + 0, // numeric-owner
  711. OPT_NOPRESERVE_PERM = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_NOPRESERVE_PERM)) + 0, // no-same-permissions
  712. OPT_OVERWRITE = IF_FEATURE_TAR_LONG_OPTIONS((1 << OPTBIT_OVERWRITE )) + 0, // overwrite
  713. };
  714. #if ENABLE_FEATURE_TAR_LONG_OPTIONS
  715. static const char tar_longopts[] ALIGN1 =
  716. "list\0" No_argument "t"
  717. "extract\0" No_argument "x"
  718. "directory\0" Required_argument "C"
  719. "file\0" Required_argument "f"
  720. "to-stdout\0" No_argument "O"
  721. /* do not restore owner */
  722. /* Note: GNU tar handles 'o' as no-same-owner only on extract,
  723. * on create, 'o' is --old-archive. We do not support --old-archive. */
  724. "no-same-owner\0" No_argument "o"
  725. "same-permissions\0" No_argument "p"
  726. "verbose\0" No_argument "v"
  727. "keep-old\0" No_argument "k"
  728. # if ENABLE_FEATURE_TAR_CREATE
  729. "create\0" No_argument "c"
  730. "dereference\0" No_argument "h"
  731. # endif
  732. # if ENABLE_FEATURE_SEAMLESS_BZ2
  733. "bzip2\0" No_argument "j"
  734. # endif
  735. # if ENABLE_FEATURE_SEAMLESS_LZMA
  736. "lzma\0" No_argument "a"
  737. # endif
  738. # if ENABLE_FEATURE_TAR_FROM
  739. "files-from\0" Required_argument "T"
  740. "exclude-from\0" Required_argument "X"
  741. # endif
  742. # if ENABLE_FEATURE_SEAMLESS_GZ
  743. "gzip\0" No_argument "z"
  744. # endif
  745. # if ENABLE_FEATURE_SEAMLESS_Z
  746. "compress\0" No_argument "Z"
  747. # endif
  748. # if ENABLE_FEATURE_TAR_NOPRESERVE_TIME
  749. "touch\0" No_argument "m"
  750. # endif
  751. # if ENABLE_FEATURE_TAR_TO_COMMAND
  752. "to-command\0" Required_argument "\xfb"
  753. # endif
  754. /* use numeric uid/gid from tar header, not textual */
  755. "numeric-owner\0" No_argument "\xfc"
  756. /* do not restore mode */
  757. "no-same-permissions\0" No_argument "\xfd"
  758. /* on unpack, open with O_TRUNC and !O_EXCL */
  759. "overwrite\0" No_argument "\xfe"
  760. /* --exclude takes next bit position in option mask, */
  761. /* therefore we have to put it _after_ --no-same-permissions */
  762. # if ENABLE_FEATURE_TAR_FROM
  763. "exclude\0" Required_argument "\xff"
  764. # endif
  765. ;
  766. #endif
  767. int tar_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  768. int tar_main(int argc UNUSED_PARAM, char **argv)
  769. {
  770. char FAST_FUNC (*get_header_ptr)(archive_handle_t *) = get_header_tar;
  771. archive_handle_t *tar_handle;
  772. char *base_dir = NULL;
  773. const char *tar_filename = "-";
  774. unsigned opt;
  775. int verboseFlag = 0;
  776. #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
  777. llist_t *excludes = NULL;
  778. #endif
  779. /* Initialise default values */
  780. tar_handle = init_handle();
  781. tar_handle->ah_flags = ARCHIVE_CREATE_LEADING_DIRS
  782. | ARCHIVE_RESTORE_DATE
  783. | ARCHIVE_UNLINK_OLD;
  784. /* Apparently only root's tar preserves perms (see bug 3844) */
  785. if (getuid() != 0)
  786. tar_handle->ah_flags |= ARCHIVE_DONT_RESTORE_PERM;
  787. /* Prepend '-' to the first argument if required */
  788. opt_complementary = "--:" // first arg is options
  789. "tt:vv:" // count -t,-v
  790. "?:" // bail out with usage instead of error return
  791. "X::T::" // cumulative lists
  792. #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
  793. "\xff::" // cumulative lists for --exclude
  794. #endif
  795. IF_FEATURE_TAR_CREATE("c:") "t:x:" // at least one of these is reqd
  796. IF_FEATURE_TAR_CREATE("c--tx:t--cx:x--ct") // mutually exclusive
  797. IF_NOT_FEATURE_TAR_CREATE("t--x:x--t"); // mutually exclusive
  798. #if ENABLE_FEATURE_TAR_LONG_OPTIONS
  799. applet_long_options = tar_longopts;
  800. #endif
  801. #if ENABLE_DESKTOP
  802. if (argv[1] && argv[1][0] != '-') {
  803. /* Compat:
  804. * 1st argument without dash handles options with parameters
  805. * differently from dashed one: it takes *next argv[i]*
  806. * as paramenter even if there are more chars in 1st argument:
  807. * "tar fx TARFILE" - "x" is not taken as f's param
  808. * but is interpreted as -x option
  809. * "tar -xf TARFILE" - dashed equivalent of the above
  810. * "tar -fx ..." - "x" is taken as f's param
  811. * getopt32 wouldn't handle 1st command correctly.
  812. * Unfortunately, people do use such commands.
  813. * We massage argv[1] to work around it by moving 'f'
  814. * to the end of the string.
  815. * More contrived "tar fCx TARFILE DIR" still fails,
  816. * but such commands are much less likely to be used.
  817. */
  818. char *f = strchr(argv[1], 'f');
  819. if (f) {
  820. while (f[1] != '\0') {
  821. *f = f[1];
  822. f++;
  823. }
  824. *f = 'f';
  825. }
  826. }
  827. #endif
  828. opt = getopt32(argv,
  829. "txC:f:Oopvk"
  830. IF_FEATURE_TAR_CREATE( "ch" )
  831. IF_FEATURE_SEAMLESS_BZ2( "j" )
  832. IF_FEATURE_SEAMLESS_LZMA("a" )
  833. IF_FEATURE_TAR_FROM( "T:X:")
  834. IF_FEATURE_SEAMLESS_GZ( "z" )
  835. IF_FEATURE_SEAMLESS_Z( "Z" )
  836. IF_FEATURE_TAR_NOPRESERVE_TIME("m")
  837. , &base_dir // -C dir
  838. , &tar_filename // -f filename
  839. IF_FEATURE_TAR_FROM(, &(tar_handle->accept)) // T
  840. IF_FEATURE_TAR_FROM(, &(tar_handle->reject)) // X
  841. IF_FEATURE_TAR_TO_COMMAND(, &(tar_handle->tar__to_command)) // --to-command
  842. #if ENABLE_FEATURE_TAR_LONG_OPTIONS && ENABLE_FEATURE_TAR_FROM
  843. , &excludes // --exclude
  844. #endif
  845. , &verboseFlag // combined count for -t and -v
  846. , &verboseFlag // combined count for -t and -v
  847. );
  848. //bb_error_msg("opt:%08x", opt);
  849. argv += optind;
  850. if (verboseFlag) tar_handle->action_header = header_verbose_list;
  851. if (verboseFlag == 1) tar_handle->action_header = header_list;
  852. if (opt & OPT_EXTRACT)
  853. tar_handle->action_data = data_extract_all;
  854. if (opt & OPT_2STDOUT)
  855. tar_handle->action_data = data_extract_to_stdout;
  856. if (opt & OPT_2COMMAND) {
  857. putenv((char*)"TAR_FILETYPE=f");
  858. signal(SIGPIPE, SIG_IGN);
  859. tar_handle->action_data = data_extract_to_command;
  860. }
  861. if (opt & OPT_KEEP_OLD)
  862. tar_handle->ah_flags &= ~ARCHIVE_UNLINK_OLD;
  863. if (opt & OPT_NUMERIC_OWNER)
  864. tar_handle->ah_flags |= ARCHIVE_NUMERIC_OWNER;
  865. if (opt & OPT_NOPRESERVE_OWNER)
  866. tar_handle->ah_flags |= ARCHIVE_DONT_RESTORE_OWNER;
  867. if (opt & OPT_NOPRESERVE_PERM)
  868. tar_handle->ah_flags |= ARCHIVE_DONT_RESTORE_PERM;
  869. if (opt & OPT_OVERWRITE) {
  870. tar_handle->ah_flags &= ~ARCHIVE_UNLINK_OLD;
  871. tar_handle->ah_flags |= ARCHIVE_O_TRUNC;
  872. }
  873. if (opt & OPT_GZIP)
  874. get_header_ptr = get_header_tar_gz;
  875. if (opt & OPT_BZIP2)
  876. get_header_ptr = get_header_tar_bz2;
  877. if (opt & OPT_LZMA)
  878. get_header_ptr = get_header_tar_lzma;
  879. if (opt & OPT_COMPRESS)
  880. get_header_ptr = get_header_tar_Z;
  881. if (opt & OPT_NOPRESERVE_TIME)
  882. tar_handle->ah_flags &= ~ARCHIVE_RESTORE_DATE;
  883. #if ENABLE_FEATURE_TAR_FROM
  884. tar_handle->reject = append_file_list_to_list(tar_handle->reject);
  885. # if ENABLE_FEATURE_TAR_LONG_OPTIONS
  886. /* Append excludes to reject */
  887. while (excludes) {
  888. llist_t *next = excludes->link;
  889. excludes->link = tar_handle->reject;
  890. tar_handle->reject = excludes;
  891. excludes = next;
  892. }
  893. # endif
  894. tar_handle->accept = append_file_list_to_list(tar_handle->accept);
  895. #endif
  896. /* Setup an array of filenames to work with */
  897. /* TODO: This is the same as in ar, make a separate function? */
  898. while (*argv) {
  899. /* kill trailing '/' unless the string is just "/" */
  900. char *cp = last_char_is(*argv, '/');
  901. if (cp > *argv)
  902. *cp = '\0';
  903. llist_add_to_end(&tar_handle->accept, *argv);
  904. argv++;
  905. }
  906. if (tar_handle->accept || tar_handle->reject)
  907. tar_handle->filter = filter_accept_reject_list;
  908. /* Open the tar file */
  909. {
  910. int tar_fd = STDIN_FILENO;
  911. int flags = O_RDONLY;
  912. if (opt & OPT_CREATE) {
  913. /* Make sure there is at least one file to tar up */
  914. if (tar_handle->accept == NULL)
  915. bb_error_msg_and_die("empty archive");
  916. tar_fd = STDOUT_FILENO;
  917. /* Mimicking GNU tar 1.15.1: */
  918. flags = O_WRONLY | O_CREAT | O_TRUNC;
  919. }
  920. if (LONE_DASH(tar_filename)) {
  921. tar_handle->src_fd = tar_fd;
  922. tar_handle->seek = seek_by_read;
  923. } else {
  924. if (ENABLE_FEATURE_TAR_AUTODETECT && flags == O_RDONLY) {
  925. get_header_ptr = get_header_tar;
  926. tar_handle->src_fd = open_zipped(tar_filename);
  927. if (tar_handle->src_fd < 0)
  928. bb_perror_msg_and_die("can't open '%s'", tar_filename);
  929. } else {
  930. tar_handle->src_fd = xopen(tar_filename, flags);
  931. }
  932. }
  933. }
  934. if (base_dir)
  935. xchdir(base_dir);
  936. #ifdef CHECK_FOR_CHILD_EXITCODE
  937. /* We need to know whether child (gzip/bzip/etc) exits abnormally */
  938. signal(SIGCHLD, handle_SIGCHLD);
  939. #endif
  940. /* Create an archive */
  941. if (opt & OPT_CREATE) {
  942. #if ENABLE_FEATURE_SEAMLESS_GZ || ENABLE_FEATURE_SEAMLESS_BZ2
  943. int zipMode = 0;
  944. if (ENABLE_FEATURE_SEAMLESS_GZ && (opt & OPT_GZIP))
  945. zipMode = 1;
  946. if (ENABLE_FEATURE_SEAMLESS_BZ2 && (opt & OPT_BZIP2))
  947. zipMode = 2;
  948. #endif
  949. /* NB: writeTarFile() closes tar_handle->src_fd */
  950. return writeTarFile(tar_handle->src_fd, verboseFlag, opt & OPT_DEREFERENCE,
  951. tar_handle->accept,
  952. tar_handle->reject, zipMode);
  953. }
  954. while (get_header_ptr(tar_handle) == EXIT_SUCCESS)
  955. continue;
  956. /* Check that every file that should have been extracted was */
  957. while (tar_handle->accept) {
  958. if (!find_list_entry(tar_handle->reject, tar_handle->accept->data)
  959. && !find_list_entry(tar_handle->passed, tar_handle->accept->data)
  960. ) {
  961. bb_error_msg_and_die("%s: not found in archive",
  962. tar_handle->accept->data);
  963. }
  964. tar_handle->accept = tar_handle->accept->link;
  965. }
  966. if (ENABLE_FEATURE_CLEAN_UP /* && tar_handle->src_fd != STDIN_FILENO */)
  967. close(tar_handle->src_fd);
  968. return EXIT_SUCCESS;
  969. }