Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

355 lines
8.4 KiB

  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. int __cdecl atoi(const char *);
  47. /* Defines */
  48. #define DEF_BLOCKING 20 /* default blocking factor for extract */
  49. /* Function Prototypes */
  50. #ifdef __STDC__
  51. static int taropt(int , char **, char *);
  52. static void usage(void);
  53. #else /* !__STDC__ */
  54. static int taropt();
  55. static void usage();
  56. #endif /* __STDC__ */
  57. /* do_tar - main routine for tar.
  58. *
  59. * DESCRIPTION
  60. *
  61. * Provides a tar interface to the PAX program. All tar standard
  62. * command line options are supported.
  63. *
  64. * PARAMETERS
  65. *
  66. * int argc - argument count (argc from main)
  67. * char **argv - argument list (argv from main)
  68. *
  69. * RETURNS
  70. *
  71. * zero
  72. */
  73. #ifdef __STDC__
  74. void do_tar(int argc, char **argv) /* Xn */
  75. #else
  76. void do_tar(argc, argv) /* Xn */
  77. int argc; /* argument count (argc from main) */
  78. char **argv; /* argument list (argv from main) */
  79. #endif
  80. {
  81. int c; /* Option letter */
  82. /* Set default option values */
  83. names_from_stdin = 0;
  84. #ifdef DF_TRACE_DEBUG
  85. printf("DF_TRACE_DEBUG: void do_tar() in tar.c\n");
  86. #endif
  87. ar_file = getenv("TAPE"); /* From environment, or */
  88. if (ar_file == 0) {
  89. ar_file = DEF_AR_FILE; /* From Makefile */
  90. }
  91. /*
  92. * set up the flags to reflect the default pax inteface. Unfortunately
  93. * the pax interface has several options which are completely opposite
  94. * of the tar and/or cpio interfaces...
  95. */
  96. f_unconditional = 1;
  97. f_mtime = 1;
  98. f_dir_create = 1;
  99. blocking = 0;
  100. ar_interface = TAR;
  101. ar_format = TAR;
  102. msgfile=stderr;
  103. /* Parse options */
  104. while ((c = taropt(argc, argv, "b:cf:hlmortuvwx")) != EOF) {
  105. switch (c) {
  106. case 'b': /* specify blocking factor */
  107. /*
  108. * FIXME - we should use a conversion routine that does
  109. * some kind of reasonable error checking, but...
  110. */
  111. if (optarg) {
  112. // optarg should never be null, but paranoia is a good
  113. // attribute in a programmer.
  114. blocking = atoi(optarg);
  115. }
  116. break;
  117. case 'c': /* create a new archive */
  118. f_create = 1;
  119. break;
  120. case 'f': /* specify input/output file */
  121. ar_file = optarg;
  122. break;
  123. case 'h':
  124. f_follow_links = 1; /* follow symbolic links */
  125. break;
  126. case 'l': /* report unresolved links */
  127. f_linksleft = 1;
  128. break;
  129. case 'm': /* don't restore modification times */
  130. f_modified = 1;
  131. break;
  132. case 'o': /* take on user's group rather than
  133. * archives */
  134. break;
  135. case 'r': /* named files are appended to archive */
  136. f_append = 1;
  137. break;
  138. case 't':
  139. f_list = 1; /* list files in archive */
  140. break;
  141. case 'u': /* named files are added to archive */
  142. f_newer = 1;
  143. break;
  144. case 'v': /* verbose mode */
  145. f_verbose = 1;
  146. break;
  147. case 'w': /* user interactive mode */
  148. f_disposition = 1;
  149. break;
  150. case 'x': /* named files are extracted from archive */
  151. f_extract = 1;
  152. break;
  153. case '?':
  154. usage();
  155. exit(EX_ARGSBAD);
  156. }
  157. }
  158. /* check command line argument sanity */
  159. if (f_create + f_extract + f_list + f_append + f_newer != 1) {
  160. (void) fprintf(stderr,
  161. "%s: you must specify exactly one of the c, t, r, u or x options\n",
  162. myname);
  163. usage();
  164. exit(EX_ARGSBAD);
  165. }
  166. /* set the blocking factor, if not set by the user */
  167. if (blocking == 0) {
  168. #ifdef USG
  169. if (f_extract || f_list) {
  170. blocking = DEF_BLOCKING;
  171. fprintf(stderr, "Tar: blocksize = %d\n", blocking);
  172. } else {
  173. blocking = 1;
  174. }
  175. #else /* !USG */
  176. blocking = 20;
  177. #endif /* USG */
  178. }
  179. blocksize = blocking * BLOCKSIZE;
  180. buf_allocate((OFFSET) blocksize);
  181. if (f_create) {
  182. open_archive(AR_WRITE);
  183. create_archive(); /* create the archive */
  184. } else if (f_extract) {
  185. open_archive(AR_READ);
  186. read_archive(); /* extract files from archive */
  187. } else if (f_list) {
  188. open_archive(AR_READ);
  189. read_archive(); /* read and list contents of archive */
  190. } else if (f_append) {
  191. open_archive(AR_APPEND);
  192. append_archive(); /* append files to archive */
  193. }
  194. if (f_linksleft) {
  195. linkleft(); /* report any unresolved links */
  196. }
  197. #if 0 /* Xn */
  198. return (0);
  199. #endif /* Xn */
  200. }
  201. /* taropt - tar specific getopt
  202. *
  203. * DESCRIPTION
  204. *
  205. * Plug-compatible replacement for getopt() for parsing tar-like
  206. * arguments. If the first argument begins with "-", it uses getopt;
  207. * otherwise, it uses the old rules used by tar, dump, and ps.
  208. *
  209. * PARAMETERS
  210. *
  211. * int argc - argument count (argc from main)
  212. * char **argv - argument list (argv from main)
  213. * char *optstring - sring which describes allowable options
  214. *
  215. * RETURNS
  216. *
  217. * Returns the next option character in the option string(s). If the
  218. * option requires an argument and an argument was given, the argument
  219. * is pointed to by "optarg". If no option character was found,
  220. * returns an EOF.
  221. *
  222. */
  223. #ifdef __STDC__
  224. static int taropt(int argc, char **argv, char *optstring)
  225. #else
  226. static int taropt(argc, argv, optstring)
  227. int argc;
  228. char **argv;
  229. char *optstring;
  230. #endif
  231. {
  232. extern char *optarg; /* Points to next arg */
  233. extern int optind; /* Global argv index */
  234. static char *key = NULL; /* Points to next keyletter */ /* Xn */
  235. static char use_getopt = 0; /* !=0 if argv[1][0] was '-' */ /* Xn */
  236. char c;
  237. char *place;
  238. #ifdef DF_TRACE_DEBUG
  239. printf("DF_TRACE_DEBUG: static int taropt() in tar.c\n");
  240. #endif
  241. optarg = (char *)NULL;
  242. if (key == (char *)NULL) { /* First time */
  243. if (argc < 2)
  244. return EOF;
  245. key = argv[1];
  246. if (*key == '-')
  247. use_getopt++;
  248. else
  249. optind = 2;
  250. }
  251. if (use_getopt) {
  252. #ifdef _POSIX2_SOURCE /* Xn */
  253. return getopt(argc, (const char * const *) argv, optstring); /* Xn */
  254. #else /* Xn */
  255. return getopt(argc, argv, optstring);
  256. #endif /* Xn */
  257. }
  258. c = *key++;
  259. if (c == '\0') {
  260. key--;
  261. return EOF;
  262. }
  263. place = strchr(optstring, c);
  264. if (place == (char *)NULL || c == ':') {
  265. fprintf(stderr, "%s: unknown option %c\n", argv[0], c);
  266. return ('?');
  267. }
  268. place++;
  269. if (*place == ':') {
  270. if (optind < argc) {
  271. optarg = argv[optind];
  272. optind++;
  273. } else {
  274. fprintf(stderr, "%s: %c argument missing\n",
  275. argv[0], c);
  276. return ('?');
  277. }
  278. }
  279. return (c);
  280. }
  281. /* usage - print a helpful message and exit
  282. *
  283. * DESCRIPTION
  284. *
  285. * Usage prints out the usage message for the TAR interface and then
  286. * exits with a non-zero termination status. This is used when a user
  287. * has provided non-existant or incompatible command line arguments.
  288. *
  289. * RETURNS
  290. *
  291. * Returns an exit status of 1 to the parent process.
  292. *
  293. */
  294. #ifdef __STDC__
  295. static void usage(void)
  296. #else
  297. static void usage()
  298. #endif
  299. {
  300. #ifdef DF_TRACE_DEBUG
  301. printf("DF_TRACE_DEBUG: static void usage() in tar.c\n");
  302. #endif
  303. fprintf(stderr, "Usage: %s -c[bfvw] device block filename..\n", myname);
  304. fprintf(stderr, " %s -r[bvw] device block [filename...]\n", myname);
  305. fprintf(stderr, " %s -t[vf] device\n", myname);
  306. fprintf(stderr, " %s -u[bvw] device block [filename...]\n", myname);
  307. fprintf(stderr, " %s -x[flmovw] device [filename...]\n", myname);
  308. exit(1);
  309. }