tar.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  1. /* $Source: /u/mark/src/pax/RCS/tar.c,v $
  2. *
  3. * $Revision: 1.2 $
  4. *
  5. * tar.c - tar specific functions for archive handling
  6. *
  7. * DESCRIPTION
  8. *
  9. * These routines provide a tar conforming interface to the pax
  10. * program.
  11. *
  12. * AUTHOR
  13. *
  14. * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  15. *
  16. * Sponsored by The USENIX Association for public distribution.
  17. *
  18. * Copyright (c) 1989 Mark H. Colburn.
  19. * All rights reserved.
  20. *
  21. * Redistribution and use in source and binary forms are permitted
  22. * provided that the above copyright notice is duplicated in all such
  23. * forms and that any documentation, advertising materials, and other
  24. * materials related to such distribution and use acknowledge that the
  25. * software was developed by Mark H. Colburn and sponsored by The
  26. * USENIX Association.
  27. *
  28. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  29. * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  30. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  31. *
  32. * $Log: tar.c,v $
  33. * Revision 1.2 89/02/12 10:06:05 mark
  34. * 1.2 release fixes
  35. *
  36. * Revision 1.1 88/12/23 18:02:38 mark
  37. * Initial revision
  38. *
  39. */
  40. #ifndef lint
  41. static char *ident = "$Id: tar.c,v 1.2 89/02/12 10:06:05 mark Exp $";
  42. static char *copyright ="Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.";
  43. #endif /* not lint */
  44. /* Headers */
  45. #include "pax.h"
  46. /* Defines */
  47. #define DEF_BLOCKING 20 /* default blocking factor for extract */
  48. /* Function Prototypes */
  49. #ifdef __STDC__
  50. static int taropt(int , char **, char *);
  51. static void usage(void);
  52. #else /* !__STDC__ */
  53. static int taropt();
  54. static void usage();
  55. #endif /* __STDC__ */
  56. /* do_tar - main routine for tar.
  57. *
  58. * DESCRIPTION
  59. *
  60. * Provides a tar interface to the PAX program. All tar standard
  61. * command line options are supported.
  62. *
  63. * PARAMETERS
  64. *
  65. * int argc - argument count (argc from main)
  66. * char **argv - argument list (argv from main)
  67. *
  68. * RETURNS
  69. *
  70. * zero
  71. */
  72. #ifdef __STDC__
  73. int do_tar(int argc, char **argv)
  74. #else
  75. int do_tar(argc, argv)
  76. int argc; /* argument count (argc from main) */
  77. char **argv; /* argument list (argv from main) */
  78. #endif
  79. {
  80. int c; /* Option letter */
  81. /* Set default option values */
  82. names_from_stdin = 0;
  83. ar_file = getenv("TAPE"); /* From environment, or */
  84. if (ar_file == 0) {
  85. ar_file = DEF_AR_FILE; /* From Makefile */
  86. }
  87. /*
  88. * set up the flags to reflect the default pax inteface. Unfortunately
  89. * the pax interface has several options which are completely opposite
  90. * of the tar and/or cpio interfaces...
  91. */
  92. f_unconditional = 1;
  93. f_mtime = 1;
  94. f_dir_create = 1;
  95. blocking = 0;
  96. ar_interface = TAR;
  97. ar_format = TAR;
  98. msgfile=stderr;
  99. /* Parse options */
  100. while ((c = taropt(argc, argv, "b:cf:hlmortuvwx")) != EOF) {
  101. switch (c) {
  102. case 'b': /* specify blocking factor */
  103. /*
  104. * FIXME - we should use a conversion routine that does
  105. * some kind of reasonable error checking, but...
  106. */
  107. blocking = atoi(optarg);
  108. break;
  109. case 'c': /* create a new archive */
  110. f_create = 1;
  111. break;
  112. case 'f': /* specify input/output file */
  113. ar_file = optarg;
  114. break;
  115. case 'h':
  116. f_follow_links = 1; /* follow symbolic links */
  117. break;
  118. case 'l': /* report unresolved links */
  119. f_linksleft = 1;
  120. break;
  121. case 'm': /* don't restore modification times */
  122. f_modified = 1;
  123. break;
  124. case 'o': /* take on user's group rather than
  125. * archives */
  126. break;
  127. case 'r': /* named files are appended to archive */
  128. f_append = 1;
  129. break;
  130. case 't':
  131. f_list = 1; /* list files in archive */
  132. break;
  133. case 'u': /* named files are added to archive */
  134. f_newer = 1;
  135. break;
  136. case 'v': /* verbose mode */
  137. f_verbose = 1;
  138. break;
  139. case 'w': /* user interactive mode */
  140. f_disposition = 1;
  141. break;
  142. case 'x': /* named files are extracted from archive */
  143. f_extract = 1;
  144. break;
  145. case '?':
  146. usage();
  147. exit(EX_ARGSBAD);
  148. }
  149. }
  150. /* check command line argument sanity */
  151. if (f_create + f_extract + f_list + f_append + f_newer != 1) {
  152. (void) fprintf(stderr,
  153. "%s: you must specify exactly one of the c, t, r, u or x options\n",
  154. myname);
  155. usage();
  156. exit(EX_ARGSBAD);
  157. }
  158. /* set the blocking factor, if not set by the user */
  159. if (blocking == 0) {
  160. #ifdef USG
  161. if (f_extract || f_list) {
  162. blocking = DEF_BLOCKING;
  163. fprintf(stderr, "Tar: blocksize = %d\n", blocking);
  164. } else {
  165. blocking = 1;
  166. }
  167. #else /* !USG */
  168. blocking = 20;
  169. #endif /* USG */
  170. }
  171. blocksize = blocking * BLOCKSIZE;
  172. buf_allocate((OFFSET) blocksize);
  173. if (f_create) {
  174. open_archive(AR_WRITE);
  175. create_archive(); /* create the archive */
  176. } else if (f_extract) {
  177. open_archive(AR_READ);
  178. read_archive(); /* extract files from archive */
  179. } else if (f_list) {
  180. open_archive(AR_READ);
  181. read_archive(); /* read and list contents of archive */
  182. } else if (f_append) {
  183. open_archive(AR_APPEND);
  184. append_archive(); /* append files to archive */
  185. }
  186. if (f_linksleft) {
  187. linkleft(); /* report any unresolved links */
  188. }
  189. return (0);
  190. }
  191. /* taropt - tar specific getopt
  192. *
  193. * DESCRIPTION
  194. *
  195. * Plug-compatible replacement for getopt() for parsing tar-like
  196. * arguments. If the first argument begins with "-", it uses getopt;
  197. * otherwise, it uses the old rules used by tar, dump, and ps.
  198. *
  199. * PARAMETERS
  200. *
  201. * int argc - argument count (argc from main)
  202. * char **argv - argument list (argv from main)
  203. * char *optstring - sring which describes allowable options
  204. *
  205. * RETURNS
  206. *
  207. * Returns the next option character in the option string(s). If the
  208. * option requires an argument and an argument was given, the argument
  209. * is pointed to by "optarg". If no option character was found,
  210. * returns an EOF.
  211. *
  212. */
  213. #ifdef __STDC__
  214. static int taropt(int argc, char **argv, char *optstring)
  215. #else
  216. static int taropt(argc, argv, optstring)
  217. int argc;
  218. char **argv;
  219. char *optstring;
  220. #endif
  221. {
  222. extern char *optarg; /* Points to next arg */
  223. extern int optind; /* Global argv index */
  224. static char *key; /* Points to next keyletter */
  225. static char use_getopt; /* !=0 if argv[1][0] was '-' */
  226. char c;
  227. char *place;
  228. optarg = (char *)NULL;
  229. if (key == (char *)NULL) { /* First time */
  230. if (argc < 2)
  231. return EOF;
  232. key = argv[1];
  233. if (*key == '-')
  234. use_getopt++;
  235. else
  236. optind = 2;
  237. }
  238. if (use_getopt) {
  239. return getopt(argc, argv, optstring);
  240. }
  241. c = *key++;
  242. if (c == '\0') {
  243. key--;
  244. return EOF;
  245. }
  246. place = strchr(optstring, c);
  247. if (place == (char *)NULL || c == ':') {
  248. fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
  249. return ('?');
  250. }
  251. place++;
  252. if (*place == ':') {
  253. if (optind < argc) {
  254. optarg = argv[optind];
  255. optind++;
  256. } else {
  257. fprintf(stderr, "%s: %c argument missing\n",
  258. argv[0], c);
  259. return ('?');
  260. }
  261. }
  262. return (c);
  263. }
  264. /* usage - print a helpful message and exit
  265. *
  266. * DESCRIPTION
  267. *
  268. * Usage prints out the usage message for the TAR interface and then
  269. * exits with a non-zero termination status. This is used when a user
  270. * has provided non-existant or incompatible command line arguments.
  271. *
  272. * RETURNS
  273. *
  274. * Returns an exit status of 1 to the parent process.
  275. *
  276. */
  277. #ifdef __STDC__
  278. static void usage(void)
  279. #else
  280. static void usage()
  281. #endif
  282. {
  283. fprintf(stderr, "Usage: %s -c[bfvw] device block filename..\n", myname);
  284. fprintf(stderr, " %s -r[bvw] device block [filename...]\n", myname);
  285. fprintf(stderr, " %s -t[vf] device\n", myname);
  286. fprintf(stderr, " %s -u[bvw] device block [filename...]\n", myname);
  287. fprintf(stderr, " %s -x[flmovw] device [filename...]\n", myname);
  288. exit(1);
  289. }