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.

559 lines
14 KiB

  1. /* $Source: /u/mark/src/pax/RCS/pax.c,v $
  2. *
  3. * $Revision: 1.2 $
  4. *
  5. * DESCRIPTION
  6. *
  7. * Pax is the archiver described in IEEE P1003.2. It is an archiver
  8. * which understands both tar and cpio archives and has a new interface.
  9. *
  10. * SYNOPSIS
  11. *
  12. * pax -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]
  13. * pax -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]
  14. * pax -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]...]
  15. * [-t device][-x format][pathname...]
  16. * pax -r -w [-ilmopuvy][-s replstr][pathname...] directory
  17. *
  18. * DESCRIPTION
  19. *
  20. * PAX - POSIX conforming tar and cpio archive handler. This
  21. * program implements POSIX conformant versions of tar, cpio and pax
  22. * archive handlers for UNIX. These handlers have defined befined
  23. * by the IEEE P1003.2 commitee.
  24. *
  25. * COMPILATION
  26. *
  27. * A number of different compile time configuration options are
  28. * available, please see the Makefile and config.h for more details.
  29. *
  30. * AUTHOR
  31. *
  32. * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
  33. *
  34. *
  35. * Sponsored by The USENIX Association for public distribution.
  36. *
  37. * Copyright (c) 1989 Mark H. Colburn.
  38. * All rights reserved.
  39. *
  40. * Redistribution and use in source and binary forms are permitted
  41. * provided that the above copyright notice is duplicated in all such
  42. * forms and that any documentation, advertising materials, and other
  43. * materials related to such distribution and use acknowledge that the
  44. * software was developed * by Mark H. Colburn and sponsored by The
  45. * USENIX Association.
  46. *
  47. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
  48. * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
  49. * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  50. *
  51. * $Log: pax.c,v $
  52. * Revision 1.2 89/02/12 10:05:17 mark
  53. * 1.2 release fixes
  54. *
  55. * Revision 1.1 88/12/23 18:02:23 mark
  56. * Initial revision
  57. *
  58. */
  59. #ifndef lint
  60. static char *ident = "$Id: pax.c,v 1.2 89/02/12 10:05:17 mark Exp $";
  61. static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  62. #endif /* ! lint */
  63. /* Headers */
  64. #define NO_EXTERN
  65. #include "pax.h"
  66. /* Globally Available Identifiers */
  67. char *ar_file; /* File containing name of archive */
  68. char *bufend; /* End of data within archive buffer */
  69. char *bufstart; /* Archive buffer */
  70. char *bufidx; /* Archive buffer index */
  71. char *myname; /* name of executable (argv[0]) */
  72. char **n_argv; /* Argv used by name routines */
  73. int n_argc; /* Argc used by name routines */
  74. int archivefd; /* Archive file descriptor */
  75. int blocking; /* Size of each block, in records */
  76. int gid; /* Group ID */
  77. int head_standard; /* true if archive is POSIX format */
  78. int ar_interface; /* defines interface we are using */
  79. int ar_format; /* defines current archve format */
  80. int mask; /* File creation mask */
  81. int ttyf; /* For interactive queries */
  82. int uid; /* User ID */
  83. int names_from_stdin; /* names for files are from stdin */
  84. OFFSET total; /* Total number of bytes transferred */
  85. short f_access_time; /* Reset access times of input files */
  86. short areof; /* End of input volume reached */
  87. short f_dir_create; /* Create missing directories */
  88. short f_append; /* Add named files to end of archive */
  89. short f_create; /* create a new archive */
  90. short f_extract; /* Extract named files from archive */
  91. short f_follow_links; /* follow symbolic links */
  92. short f_interactive; /* Interactivly extract files */
  93. short f_linksleft; /* Report on unresolved links */
  94. short f_list; /* List files on the archive */
  95. short f_modified; /* Don't restore modification times */
  96. short f_verbose; /* Turn on verbose mode */
  97. short f_link; /* link files where possible */
  98. short f_owner; /* extract files as the user */
  99. short f_pass; /* pass files between directories */
  100. short f_newer; /* append files to archive if newer */
  101. short f_disposition; /* ask for file disposition */
  102. short f_reverse_match; /* Reverse sense of pattern match */
  103. short f_mtime; /* Retain file modification time */
  104. short f_unconditional; /* Copy unconditionally */
  105. short f_quiet; /* Don't beep for volume change */ /* Xn */
  106. time_t now = 0; /* Current time */
  107. uint arvolume; /* Volume number */
  108. uint blocksize = BLOCKSIZE; /* Archive block size */
  109. FILE *msgfile; /* message outpu file stdout/stderr */
  110. Replstr *rplhead = (Replstr *)NULL; /* head of replstr list */
  111. Replstr *rpltail; /* pointer to tail of replstr list */
  112. /* Function Prototypes */
  113. #ifdef __STDC__
  114. static void usage(void);
  115. static OFFSET pax_optsize(char *);
  116. #else /* !__STDC__ */
  117. static void usage();
  118. static OFFSET pax_optsize();
  119. #endif /* __STDC__ */
  120. int do_pax(int ac, char **av);
  121. /* main - main routine for handling all archive formats.
  122. *
  123. * DESCRIPTION
  124. *
  125. * Set up globals and call the proper interface as specified by the user.
  126. *
  127. * PARAMETERS
  128. *
  129. * int argc - count of user supplied arguments
  130. * char **argv - user supplied arguments
  131. *
  132. * RETURNS
  133. *
  134. * Returns an exit code of 0 to the parent process.
  135. */
  136. #ifdef __STDC__
  137. int main(int argc, char **argv)
  138. #else
  139. int main(argc, argv)
  140. int argc;
  141. char **argv;
  142. #endif
  143. {
  144. /* strip the pathname off of the name of the executable */
  145. #ifdef DF_TRACE_DEBUG
  146. printf("DF_TRACE_DEBUG: int main() in pax.c\n");
  147. #endif
  148. if ((myname = strrchr(argv[0], '/')) != (char *)NULL) {
  149. myname++;
  150. } else {
  151. myname = argv[0];
  152. }
  153. /* set upt for collecting other command line arguments */
  154. name_init(argc, argv);
  155. /* get all our necessary information */
  156. mask = umask(0);
  157. uid = getuid();
  158. gid = getgid();
  159. now = time((time_t *) 0);
  160. /* open terminal for interactive queries */
  161. ttyf = open_tty();
  162. if (strcmp(myname, "tar")==0) {
  163. do_tar(argc, argv);
  164. } else if (strcmp(myname, "cpio")==0) {
  165. do_cpio(argc, argv);
  166. } else {
  167. do_pax(argc, argv);
  168. }
  169. return 0; /* Xn */
  170. /* NOTREACHED */
  171. }
  172. /* do_pax - provide a PAX conformant user interface for archive handling
  173. *
  174. * DESCRIPTION
  175. *
  176. * Process the command line parameters given, doing some minimal sanity
  177. * checking, and then launch the specified archiving functions.
  178. *
  179. * PARAMETERS
  180. *
  181. * int ac - A count of arguments in av. Should be passed argc
  182. * from main
  183. * char **av - A pointer to an argument list. Should be passed
  184. * argv from main
  185. *
  186. * RETURNS
  187. *
  188. * Normally returns 0. If an error occurs, -1 is returned
  189. * and state is set to reflect the error.
  190. *
  191. */
  192. #ifdef __STDC__
  193. int do_pax(int ac, char **av)
  194. #else
  195. int do_pax(ac, av)
  196. int ac; /* argument counter */
  197. char **av; /* arguments */
  198. #endif
  199. {
  200. int c;
  201. char *dirname;
  202. Stat st;
  203. /* default input/output file for PAX is STDIN/STDOUT */
  204. ar_file = "-";
  205. /*
  206. * set up the flags to reflect the default pax inteface. Unfortunately
  207. * the pax interface has several options which are completely opposite
  208. * of the tar and/or cpio interfaces...
  209. */
  210. f_unconditional = 1;
  211. f_mtime = 1;
  212. f_dir_create = 1;
  213. f_list = 1;
  214. blocksize = 0;
  215. blocking = 0;
  216. ar_interface = PAX;
  217. ar_format = TAR; /* default interface if none given for -w */
  218. msgfile=stdout;
  219. #ifdef _POSIX2_SOURCE /* Xn */
  220. #ifdef DF_TRACE_DEBUG
  221. printf("DF_TRACE_DEBUG: int do_pax() in pax.c\n");
  222. #endif
  223. while ((c = getopt(ac, (const char * const *) av, "ab:cdf:ilmopqrs:t:uvwx:y")) != EOF) { /* Xn */
  224. #else /* Xn */
  225. while ((c = getopt(ac, av, "ab:cdf:ilmopqrs:t:uvwx:y")) != EOF) { /* Xn */
  226. #endif /* Xn */
  227. switch (c) {
  228. case 'a':
  229. f_append = 1;
  230. f_list = 0;
  231. break;
  232. case 'b':
  233. if ((blocksize = pax_optsize(optarg)) == 0) {
  234. fatal("Bad block size");
  235. }
  236. break;
  237. case 'c':
  238. f_reverse_match = 1;
  239. break;
  240. case 'd':
  241. f_dir_create = 0;
  242. break;
  243. case 'f':
  244. if (blocksize == 0) {
  245. blocking = 1;
  246. blocksize = 1 * BLOCKSIZE;
  247. }
  248. ar_file = optarg;
  249. break;
  250. case 'i':
  251. f_interactive = 1;
  252. break;
  253. case 'l':
  254. f_link = 1;
  255. break;
  256. case 'm':
  257. f_mtime = 0;
  258. break;
  259. case 'o':
  260. f_owner = 1;
  261. break;
  262. case 'p':
  263. f_access_time = 1;
  264. break;
  265. case 'q': /* Xn */
  266. f_quiet = 1; /* Xn */
  267. break; /* Xn */
  268. case 'r':
  269. if (f_create) {
  270. f_create = 0;
  271. f_pass = 1;
  272. } else {
  273. f_list = 0;
  274. f_extract = 1;
  275. }
  276. msgfile=stderr;
  277. break;
  278. case 's':
  279. add_replstr(optarg);
  280. break;
  281. case 't':
  282. if (blocksize == 0) {
  283. blocking = 1;
  284. blocksize = 10 * BLOCKSIZE;
  285. }
  286. ar_file = optarg;
  287. break;
  288. case 'u':
  289. f_unconditional = 1;
  290. break;
  291. case 'v':
  292. f_verbose = 1;
  293. break;
  294. case 'w':
  295. if (f_extract) {
  296. f_extract = 0;
  297. f_pass = 1;
  298. } else {
  299. f_list = 0;
  300. f_create = 1;
  301. }
  302. msgfile=stderr;
  303. break;
  304. case 'x':
  305. if (strcmp(optarg, "ustar") == 0) {
  306. ar_format = TAR;
  307. } else if (strcmp(optarg, "cpio") == 0) {
  308. ar_format = CPIO;
  309. } else {
  310. usage();
  311. }
  312. break;
  313. case 'y':
  314. f_disposition = 1;
  315. break;
  316. default:
  317. usage();
  318. }
  319. }
  320. if (blocksize == 0) {
  321. blocking = 1;
  322. blocksize = blocking * BLOCKSIZE;
  323. }
  324. buf_allocate((OFFSET) blocksize);
  325. if (f_extract || f_list) {
  326. open_archive(AR_READ);
  327. get_archive_type();
  328. read_archive();
  329. //DF_MSS
  330. exit(1);
  331. } else if (f_append) { /* this block used to be after the f_create--Xn */
  332. open_archive(AR_APPEND);
  333. get_archive_type();
  334. append_archive();
  335. } else if (f_create) {
  336. if (optind >= n_argc) {
  337. names_from_stdin++; /* args from stdin */
  338. }
  339. open_archive(AR_WRITE);
  340. create_archive();
  341. } else if (f_pass && optind < n_argc) {
  342. dirname = n_argv[--n_argc];
  343. if (LSTAT(dirname, &st) < 0) {
  344. fatal(strerror(errno)); /* Xn */
  345. }
  346. if ((st.sb_mode & S_IFMT) != S_IFDIR) {
  347. fatal("Not a directory");
  348. }
  349. if (optind >= n_argc) {
  350. names_from_stdin++; /* args from stdin */
  351. }
  352. pass(dirname);
  353. } else {
  354. usage();
  355. }
  356. return (0);
  357. }
  358. /* get_archive_type - determine input archive type from archive header
  359. *
  360. * DESCRIPTION
  361. *
  362. * reads the first block of the archive and determines the archive
  363. * type from the data. If the archive type cannot be determined,
  364. * processing stops, and a 1 is returned to the caller. If verbose
  365. * mode is on, then the archive type will be printed on the standard
  366. * error device as it is determined.
  367. *
  368. * FIXME
  369. *
  370. * be able to understand TAR and CPIO magic numbers
  371. */
  372. #ifdef __STDC__
  373. void get_archive_type(void)
  374. #else
  375. void get_archive_type()
  376. #endif
  377. {
  378. #ifdef DF_TRACE_DEBUG
  379. printf("DF_TRACE_DEBUG: void get_archive_type() in pax.c\n");
  380. #endif
  381. if (ar_read() != 0) {
  382. fatal("Unable to determine archive type.");
  383. }
  384. if (strncmp(bufstart, "070707", 6) == 0) {
  385. ar_format = CPIO;
  386. if (f_verbose) {
  387. fputs("CPIO format archive\n", stderr);
  388. }
  389. } else if (strncmp(&bufstart[257], "ustar", 5) == 0) {
  390. ar_format = TAR;
  391. if (f_verbose) {
  392. fputs("USTAR format archive\n", stderr);
  393. }
  394. } else {
  395. ar_format = TAR;
  396. }
  397. }
  398. /* pax_optsize - interpret a size argument
  399. *
  400. * DESCRIPTION
  401. *
  402. * Recognizes suffixes for blocks (512-bytes), k-bytes and megabytes.
  403. * Also handles simple expressions containing '+' for addition.
  404. *
  405. * PARAMETERS
  406. *
  407. * char *str - A pointer to the string to interpret
  408. *
  409. * RETURNS
  410. *
  411. * Normally returns the value represented by the expression in the
  412. * the string.
  413. *
  414. * ERRORS
  415. *
  416. * If the string cannot be interpretted, the program will fail, since
  417. * the buffering will be incorrect.
  418. *
  419. */
  420. #ifdef __STDC__
  421. static OFFSET pax_optsize(char *str)
  422. #else
  423. static OFFSET pax_optsize(str)
  424. char *str; /* pointer to string to interpret */
  425. #endif
  426. {
  427. char *idx;
  428. OFFSET number; /* temporary storage for current number */
  429. OFFSET result; /* cumulative total to be returned to caller */
  430. result = 0;
  431. idx = str;
  432. #ifdef DF_TRACE_DEBUG
  433. printf("DF_TRACE_DEBUG: static OFFSET pax_optsize() in pax.c\n");
  434. #endif
  435. for (;;) {
  436. number = 0;
  437. while (*idx >= '0' && *idx <= '9')
  438. number = number * 10 + *idx++ - '0';
  439. switch (*idx++) {
  440. case 'b':
  441. result += number * 512L;
  442. continue;
  443. case 'k':
  444. result += number * 1024L;
  445. continue;
  446. case 'm':
  447. result += number * 1024L * 1024L;
  448. continue;
  449. case '+':
  450. result += number;
  451. continue;
  452. case '\0':
  453. result += number;
  454. break;
  455. default:
  456. break;
  457. }
  458. break;
  459. }
  460. if (*--idx) {
  461. fatal("Unrecognizable value");
  462. }
  463. return (result);
  464. }
  465. /* usage - print a helpful message and exit
  466. *
  467. * DESCRIPTION
  468. *
  469. * Usage prints out the usage message for the PAX interface and then
  470. * exits with a non-zero termination status. This is used when a user
  471. * has provided non-existant or incompatible command line arguments.
  472. *
  473. * RETURNS
  474. *
  475. * Returns an exit status of 1 to the parent process.
  476. *
  477. */
  478. #ifdef __STDC__
  479. static void usage(void)
  480. #else
  481. static void usage()
  482. #endif
  483. {
  484. #ifdef DF_TRACE_DEBUG
  485. printf("DF_TRACE_DEBUG: static void usage() in pax.c\n");
  486. #endif
  487. fprintf(stderr, "Usage: %s -[cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n",
  488. myname);
  489. fprintf(stderr, " %s -r [-cimopuvy] [-f archive] [-s replstr] [-t device] [pattern...]\n",
  490. myname);
  491. fprintf(stderr, " %s -w [-adimuvy] [-b blocking] [-f archive] [-s replstr]\n [-t device] [-x format] [pathname...]\n",
  492. myname);
  493. fprintf(stderr, " %s -r -w [-ilmopuvy] [-s replstr] [pathname...] directory\n",
  494. myname);
  495. fprintf(stderr, "\nFor more information on %s syntax, see Command Reference\n", myname);
  496. fprintf(stderr, "Help in the Windows Help file.");
  497. exit(1);
  498. }