libtar.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424
  1. /*
  2. ** Copyright 1998-2003 University of Illinois Board of Trustees
  3. ** Copyright 1998-2003 Mark D. Roth
  4. ** All rights reserved.
  5. **
  6. ** libtar.c - demo driver program for libtar
  7. **
  8. ** Mark D. Roth <[email protected]>
  9. ** Campus Information Technologies and Educational Services
  10. ** University of Illinois at Urbana-Champaign
  11. */
  12. #include <libtar/config.h>
  13. #include <libtar/libtar.h>
  14. #include <stdio.h>
  15. #include <fcntl.h>
  16. #include <errno.h>
  17. #if defined(_WIN32) && !defined(__CYGWIN__)
  18. #include <libtar/compat.h>
  19. #include <io.h>
  20. #else
  21. # ifdef HAVE_SYS_PARAM_H
  22. # include <sys/param.h>
  23. # endif
  24. #endif
  25. #ifdef STDC_HEADERS
  26. # include <string.h>
  27. #endif
  28. #ifdef HAVE_UNISTD_H
  29. # include <unistd.h>
  30. # include <stdlib.h>
  31. #endif
  32. #ifdef DEBUG
  33. # include <signal.h>
  34. #endif
  35. #include CMTAR_ZLIB_HEADER
  36. #include <libtar/compat.h>
  37. char *progname;
  38. int verbose = 0;
  39. int use_gnu = 0;
  40. #ifdef DEBUG
  41. void
  42. segv_handler(int sig)
  43. {
  44. puts("OOPS! Caught SIGSEGV, bailing out...");
  45. fflush(stdout);
  46. fflush(stderr);
  47. }
  48. #endif
  49. #ifdef HAVE_LIBZ
  50. int use_zlib = 0;
  51. struct gzStruct
  52. {
  53. gzFile* GZFile;
  54. };
  55. struct gzStruct GZStruct;
  56. #if defined ( _MSC_VER) || defined(__WATCOMC__)
  57. #include <io.h>
  58. //Yogi: hack. this should work on windows where there is no O_ACCMODE defined
  59. #ifndef O_ACCMODE
  60. # define O_ACCMODE 0x0003
  61. #endif
  62. #endif
  63. static int libtar_gzopen(void* call_data, const char *pathname,
  64. int oflags, mode_t mode)
  65. {
  66. char *gzoflags;
  67. int fd;
  68. struct gzStruct* gzf = (struct gzStruct*)call_data;
  69. switch (oflags & O_ACCMODE)
  70. {
  71. case O_WRONLY:
  72. gzoflags = "wb";
  73. break;
  74. case O_RDONLY:
  75. gzoflags = "rb";
  76. break;
  77. default:
  78. case O_RDWR:
  79. errno = EINVAL;
  80. return -1;
  81. }
  82. fd = open(pathname, oflags, mode);
  83. if (fd == -1)
  84. {
  85. return -1;
  86. }
  87. #if defined(__BEOS__) && !defined(__ZETA__) /* no fchmod on BeOS...do pathname instead. */
  88. if ((oflags & O_CREAT) && chmod(pathname, mode & 07777))
  89. {
  90. return -1;
  91. }
  92. #elif !defined(_WIN32) || defined(__CYGWIN__)
  93. if ((oflags & O_CREAT) && fchmod(fd, mode & 07777))
  94. {
  95. return -1;
  96. }
  97. #endif
  98. gzf->GZFile = gzdopen(fd, gzoflags);
  99. if (!gzf->GZFile)
  100. {
  101. errno = ENOMEM;
  102. return -1;
  103. }
  104. return fd;
  105. }
  106. static int libtar_gzclose(void* call_data)
  107. {
  108. struct gzStruct* gzf = (struct gzStruct*)call_data;
  109. return gzclose(gzf->GZFile);
  110. }
  111. static ssize_t libtar_gzread(void* call_data, void* buf, size_t count)
  112. {
  113. struct gzStruct* gzf = (struct gzStruct*)call_data;
  114. return gzread(gzf->GZFile, buf, (unsigned int)count);
  115. }
  116. static ssize_t libtar_gzwrite(void* call_data, const void* buf, size_t count)
  117. {
  118. struct gzStruct* gzf = (struct gzStruct*)call_data;
  119. return gzwrite(gzf->GZFile, (void*)buf, (unsigned int)count);
  120. }
  121. tartype_t gztype = {
  122. libtar_gzopen,
  123. libtar_gzclose,
  124. libtar_gzread,
  125. libtar_gzwrite,
  126. &GZStruct
  127. };
  128. #endif /* HAVE_LIBZ */
  129. static int
  130. create(char *tarfile, char *rootdir, libtar_list_t *l)
  131. {
  132. TAR *t;
  133. char *pathname;
  134. char buf[TAR_MAXPATHLEN];
  135. libtar_listptr_t lp;
  136. if (tar_open(&t, tarfile,
  137. #ifdef HAVE_LIBZ
  138. (use_zlib ? &gztype : NULL),
  139. #else
  140. NULL,
  141. #endif
  142. O_WRONLY | O_CREAT, 0644,
  143. (verbose ? TAR_VERBOSE : 0)
  144. | (use_gnu ? TAR_GNU : 0)) == -1)
  145. {
  146. fprintf(stderr, "tar_open(): %s\n", strerror(errno));
  147. return -1;
  148. }
  149. libtar_listptr_reset(&lp);
  150. while (libtar_list_next(l, &lp) != 0)
  151. {
  152. pathname = (char *)libtar_listptr_data(&lp);
  153. if (pathname[0] != '/' && rootdir != NULL)
  154. snprintf(buf, sizeof(buf), "%s/%s", rootdir, pathname);
  155. else
  156. strlcpy(buf, pathname, sizeof(buf));
  157. if (tar_append_tree(t, buf, pathname) != 0)
  158. {
  159. fprintf(stderr,
  160. "tar_append_tree(\"%s\", \"%s\"): %s\n", buf,
  161. pathname, strerror(errno));
  162. tar_close(t);
  163. return -1;
  164. }
  165. }
  166. if (tar_append_eof(t) != 0)
  167. {
  168. fprintf(stderr, "tar_append_eof(): %s\n", strerror(errno));
  169. tar_close(t);
  170. return -1;
  171. }
  172. if (tar_close(t) != 0)
  173. {
  174. fprintf(stderr, "tar_close(): %s\n", strerror(errno));
  175. return -1;
  176. }
  177. return 0;
  178. }
  179. static int
  180. list(char *tarfile)
  181. {
  182. TAR *t;
  183. int i;
  184. if (tar_open(&t, tarfile,
  185. #ifdef HAVE_LIBZ
  186. (use_zlib ? &gztype : NULL),
  187. #else
  188. NULL,
  189. #endif
  190. O_RDONLY, 0,
  191. (verbose ? TAR_VERBOSE : 0)
  192. | (use_gnu ? TAR_GNU : 0)) == -1)
  193. {
  194. fprintf(stderr, "tar_open(): %s\n", strerror(errno));
  195. return -1;
  196. }
  197. while ((i = th_read(t)) == 0)
  198. {
  199. th_print_long_ls(t);
  200. #ifdef DEBUG
  201. th_print(t);
  202. #endif
  203. if (TH_ISREG(t) && tar_skip_regfile(t) != 0)
  204. {
  205. fprintf(stderr, "tar_skip_regfile(): %s\n",
  206. strerror(errno));
  207. return -1;
  208. }
  209. }
  210. #ifdef DEBUG
  211. printf("th_read() returned %d\n", i);
  212. printf("EOF mark encountered after %ld bytes\n",
  213. # ifdef HAVE_LIBZ
  214. (use_zlib
  215. ? gzseek((gzFile) t->fd, 0, SEEK_CUR)
  216. :
  217. # endif
  218. lseek(t->fd, 0, SEEK_CUR)
  219. # ifdef HAVE_LIBZ
  220. )
  221. # endif
  222. );
  223. #endif
  224. if (tar_close(t) != 0)
  225. {
  226. fprintf(stderr, "tar_close(): %s\n", strerror(errno));
  227. return -1;
  228. }
  229. (void)i;
  230. return 0;
  231. }
  232. static int
  233. extract(char *tarfile, char *rootdir)
  234. {
  235. TAR *t;
  236. #ifdef DEBUG
  237. puts("opening tarfile...");
  238. #endif
  239. if (tar_open(&t, tarfile,
  240. #ifdef HAVE_LIBZ
  241. (use_zlib ? &gztype : NULL),
  242. #else
  243. NULL,
  244. #endif
  245. O_RDONLY, 0,
  246. (verbose ? TAR_VERBOSE : 0)
  247. | (use_gnu ? TAR_GNU : 0)) == -1)
  248. {
  249. fprintf(stderr, "tar_open(): %s\n", strerror(errno));
  250. return -1;
  251. }
  252. #ifdef DEBUG
  253. puts("extracting tarfile...");
  254. #endif
  255. if (tar_extract_all(t, rootdir) != 0)
  256. {
  257. fprintf(stderr, "tar_extract_all(): %s\n", strerror(errno));
  258. return -1;
  259. }
  260. #ifdef DEBUG
  261. puts("closing tarfile...");
  262. #endif
  263. if (tar_close(t) != 0)
  264. {
  265. fprintf(stderr, "tar_close(): %s\n", strerror(errno));
  266. return -1;
  267. }
  268. return 0;
  269. }
  270. static void
  271. usage()
  272. {
  273. printf("Usage: %s [-C rootdir] [-g] [-z] -x|-t filename.tar\n",
  274. progname);
  275. printf(" %s [-C rootdir] [-g] [-z] -c filename.tar ...\n",
  276. progname);
  277. exit(-1);
  278. }
  279. #define MODE_LIST 1
  280. #define MODE_CREATE 2
  281. #define MODE_EXTRACT 3
  282. int
  283. main(int argc, char *argv[])
  284. {
  285. char* tarfile;
  286. char *rootdir = NULL;
  287. int c;
  288. int mode;
  289. libtar_list_t *l;
  290. #if defined(_WIN32) && !defined(__CYGWIN__)
  291. int optind;
  292. #endif
  293. progname = basename(argv[0]);
  294. #if !defined(_WIN32) || defined(__CYGWIN__)
  295. mode = 0;
  296. while ((c = getopt(argc, argv, "cC:gtvVxz")) != -1)
  297. switch (c)
  298. {
  299. case 'V':
  300. printf("libtar %s by Mark D. Roth <[email protected]>\n",
  301. libtar_version);
  302. break;
  303. case 'C':
  304. rootdir = strdup(optarg);
  305. break;
  306. case 'v':
  307. verbose = 1;
  308. break;
  309. case 'g':
  310. use_gnu = 1;
  311. break;
  312. case 'c':
  313. if (mode)
  314. usage();
  315. mode = MODE_CREATE;
  316. break;
  317. case 'x':
  318. if (mode)
  319. usage();
  320. mode = MODE_EXTRACT;
  321. break;
  322. case 't':
  323. if (mode)
  324. usage();
  325. mode = MODE_LIST;
  326. break;
  327. #ifdef HAVE_LIBZ
  328. case 'z':
  329. use_zlib = 1;
  330. break;
  331. #endif /* HAVE_LIBZ */
  332. default:
  333. usage();
  334. }
  335. if (!mode || ((argc - optind) < (mode == MODE_CREATE ? 2 : 1)))
  336. {
  337. #ifdef DEBUG
  338. printf("argc - optind == %d\tmode == %d\n", argc - optind,
  339. mode);
  340. #endif
  341. usage();
  342. }
  343. #else
  344. mode = MODE_EXTRACT;
  345. use_zlib=1;
  346. optind = 1;
  347. #endif
  348. #ifdef DEBUG
  349. signal(SIGSEGV, segv_handler);
  350. #endif
  351. switch (mode)
  352. {
  353. case MODE_EXTRACT:
  354. return extract(argv[optind], rootdir);
  355. case MODE_CREATE:
  356. tarfile = argv[optind];
  357. l = libtar_list_new(LIST_QUEUE, NULL);
  358. for (c = optind + 1; c < argc; c++)
  359. libtar_list_add(l, argv[c]);
  360. return create(tarfile, rootdir, l);
  361. case MODE_LIST:
  362. return list(argv[optind]);
  363. default:
  364. break;
  365. }
  366. /* NOTREACHED */
  367. return -2;
  368. }