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.

426 lines
9.0 KiB

  1. /* $Source: /u/mark/src/pax/RCS/create.c,v $
  2. *
  3. * $Revision: 1.3 $
  4. *
  5. * create.c - Create a tape archive.
  6. *
  7. * DESCRIPTION
  8. *
  9. * These functions are used to create/write and archive from an set of
  10. * named files.
  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: create.c,v $
  33. * Revision 1.3 89/02/12 10:29:37 mark
  34. * Fixed misspelling of Replstr
  35. *
  36. * Revision 1.2 89/02/12 10:04:17 mark
  37. * 1.2 release fixes
  38. *
  39. * Revision 1.1 88/12/23 18:02:06 mark
  40. * Initial revision
  41. *
  42. */
  43. #ifndef lint
  44. static char *ident = "$Id: create.c,v 1.3 89/02/12 10:29:37 mark Exp Locker: mark $";
  45. static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  46. #endif /* ! lint */
  47. /* Headers */
  48. #include "pax.h"
  49. /* Function Prototypes */
  50. #ifdef __STDC__
  51. static void writetar(char *, Stat *);
  52. static void writecpio(char *, Stat *);
  53. static char tartype(int);
  54. #else /* !__STDC__ */
  55. static void writetar();
  56. static void writecpio();
  57. static char tartype();
  58. #endif /* __STDC__ */
  59. /* create_archive - create a tar archive.
  60. *
  61. * DESCRIPTION
  62. *
  63. * Create_archive is used as an entry point to both create and append
  64. * archives. Create archive goes through the files specified by the
  65. * user and writes each one to the archive if it can. Create_archive
  66. * knows how to write both cpio and tar headers and the padding which
  67. * is needed for each type of archive.
  68. *
  69. * RETURNS
  70. *
  71. * Always returns 0
  72. */
  73. #ifdef __STDC__
  74. int create_archive(void)
  75. #else
  76. int create_archive()
  77. #endif
  78. {
  79. char name[PATH_MAX + 1];
  80. Stat sb;
  81. int fd;
  82. #ifdef DF_TRACE_DEBUG
  83. printf("DF_TRACE_DEBUG: int create_archive() in create.c\n");
  84. #endif
  85. if (f_append) { /* Xn */
  86. if (ar_format == TAR) { /* Xn */
  87. (void) lseek(archivefd, -(OFFSET) (2*blocksize), SEEK_END); /* Xn */
  88. } else { /* Xn */
  89. OFFSET eoa; /* Xn */
  90. /* Xn */
  91. eoa = lseek(archivefd, (OFFSET) 0, SEEK_CUR); /* Xn */
  92. (void) lseek(archivefd, -(eoa - total + 87), SEEK_END); /* Xn */
  93. } /* Xn */
  94. } /* Xn */
  95. /* Xn */
  96. while (name_next(name, &sb) != -1) {
  97. if ((fd = openin(name, &sb)) < 0) {
  98. /* FIXME: pax wants to exit here??? */
  99. continue;
  100. }
  101. if (rplhead != (Replstr *)NULL) {
  102. rpl_name(name);
  103. if (strlen(name) == 0) {
  104. continue;
  105. }
  106. }
  107. if (get_disposition("add", name) || get_newname(name, sizeof(name))) {
  108. /* skip file... */
  109. if (fd) {
  110. close(fd);
  111. }
  112. continue;
  113. }
  114. if (!f_link && sb.sb_nlink > 1) {
  115. #if 0 /* NIST-PCTS */
  116. if (islink(name, &sb)) {
  117. #else /* NIST-PCTS */
  118. if (ar_format == TAR && islink(name, &sb)) { /* NIST-PCTS */
  119. #endif /* NIST-PCTS */
  120. sb.sb_size = 0;
  121. }
  122. linkto(name, &sb);
  123. }
  124. if (ar_format == TAR) {
  125. writetar(name, &sb);
  126. } else {
  127. writecpio(name, &sb);
  128. }
  129. if (fd) {
  130. outdata(fd, name, sb.sb_size);
  131. }
  132. if (f_verbose) {
  133. print_entry(name, &sb);
  134. }
  135. }
  136. write_eot();
  137. close_archive();
  138. return (0);
  139. }
  140. /* writetar - write a header block for a tar file
  141. *
  142. * DESCRIPTION
  143. *
  144. * Make a header block for the file name whose stat info is in st.
  145. * Return header pointer for success, NULL if the name is too long.
  146. *
  147. * The tar header block is structured as follows:
  148. *
  149. * FIELD NAME OFFSET SIZE
  150. * -------------|---------------|------
  151. * name 0 100
  152. * mode 100 8
  153. * uid 108 8
  154. * gid 116 8
  155. * size 124 12
  156. * mtime 136 12
  157. * chksum 148 8
  158. * typeflag 156 1
  159. * linkname 157 100
  160. * magic 257 6
  161. * version 263 2
  162. * uname 265 32
  163. * gname 297 32
  164. * devmajor 329 8
  165. * devminor 337 8
  166. * prefix 345 155
  167. *
  168. * PARAMETERS
  169. *
  170. * char *name - name of file to create a header block for
  171. * Stat *asb - pointer to the stat structure for the named file
  172. *
  173. */
  174. #ifdef __STDC__
  175. static void writetar(char *name, Stat *asb)
  176. #else
  177. static void writetar(name, asb)
  178. char *name;
  179. Stat *asb;
  180. #endif
  181. {
  182. char *p;
  183. char *prefix = (char *)NULL;
  184. int i;
  185. int sum;
  186. char hdr[BLOCKSIZE];
  187. Link *from;
  188. #ifdef DF_TRACE_DEBUG
  189. printf("DF_TRACE_DEBUG: static void writetar() in create.c\n");
  190. #endif
  191. memset(hdr, 0, BLOCKSIZE);
  192. if (strlen(name) > 256) {
  193. warn(name, "name too long");
  194. return;
  195. }
  196. /*
  197. * If the pathname is longer than TNAMLEN, but less than 256, then
  198. * we can split it up into the prefix and the filename.
  199. */
  200. if (strlen(name) > 100) {
  201. prefix = name;
  202. for (;;) {
  203. name = strchr(name + 1, '/');
  204. if (NULL == name) {
  205. warn(prefix, "Name too long");
  206. return;
  207. }
  208. if (strlen(name + 1) <= 100) {
  209. // fits
  210. *name++ = '\0';
  211. break;
  212. }
  213. }
  214. }
  215. #ifdef S_IFLNK
  216. if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
  217. strcpy(&hdr[157], asb->sb_link);
  218. asb->sb_size = 0;
  219. }
  220. #endif
  221. strcpy(hdr, name);
  222. sprintf(&hdr[100], "%06o \0", asb->sb_mode & ~S_IFMT);
  223. sprintf(&hdr[108], "%06o \0", asb->sb_uid);
  224. sprintf(&hdr[116], "%06o \0", asb->sb_gid);
  225. sprintf(&hdr[124], "%011lo ", (long) asb->sb_size);
  226. sprintf(&hdr[136], "%011lo ", (long) asb->sb_mtime);
  227. strncpy(&hdr[148], " ", 8);
  228. hdr[156] = tartype(asb->sb_mode);
  229. if (asb->sb_nlink > 1 && (from = linkfrom(name, asb)) != (Link *)NULL) {
  230. if (strlen(from->l_name) > 100) {
  231. warn(name, "link name too long");
  232. return;
  233. }
  234. strcpy(&hdr[157], from->l_name);
  235. hdr[156] = LNKTYPE;
  236. }
  237. strcpy(&hdr[257], TMAGIC);
  238. strncpy(&hdr[263], TVERSION, 2);
  239. strcpy(&hdr[265], finduname((int) asb->sb_uid));
  240. strcpy(&hdr[297], findgname((int) asb->sb_gid));
  241. #ifndef _POSIX_SOURCE
  242. sprintf(&hdr[329], "%06o \0", major(asb->sb_rdev));
  243. sprintf(&hdr[337], "%06o \0", minor(asb->sb_rdev));
  244. #endif
  245. if (prefix != (char *)NULL) {
  246. strncpy(&hdr[345], prefix, 155);
  247. }
  248. /* Calculate the checksum */
  249. sum = 0;
  250. p = hdr;
  251. for (i = 0; i < 500; i++) {
  252. sum += 0xFF & *p++;
  253. }
  254. /* Fill in the checksum field. */
  255. sprintf(&hdr[148], "%06o \0", sum);
  256. outwrite(hdr, BLOCKSIZE);
  257. }
  258. /* tartype - return tar file type from file mode
  259. *
  260. * DESCRIPTION
  261. *
  262. * tartype returns the character which represents the type of file
  263. * indicated by "mode".
  264. *
  265. * PARAMETERS
  266. *
  267. * int mode - file mode from a stat block
  268. *
  269. * RETURNS
  270. *
  271. * The character which represents the particular file type in the
  272. * ustar standard headers.
  273. */
  274. #ifdef __STDC__
  275. static char tartype(int mode)
  276. #else
  277. static char tartype(mode)
  278. int mode;
  279. #endif
  280. {
  281. #ifdef DF_TRACE_DEBUG
  282. printf("DF_TRACE_DEBUG: static char tartype() in create.c\n");
  283. #endif
  284. switch (mode & S_IFMT) {
  285. #ifdef S_IFCTG
  286. case S_IFCTG:
  287. return(CONTTYPE);
  288. #endif
  289. case S_IFDIR:
  290. return (DIRTYPE);
  291. #ifdef S_IFLNK
  292. case S_IFLNK:
  293. return (SYMTYPE);
  294. #endif
  295. #ifdef S_IFIFO /* Xn */
  296. case S_IFIFO:
  297. return (FIFOTYPE);
  298. #endif
  299. #ifdef S_IFCHR
  300. case S_IFCHR:
  301. return (CHRTYPE);
  302. #endif
  303. #ifdef S_IFBLK
  304. case S_IFBLK:
  305. return (BLKTYPE);
  306. #endif
  307. /* Xn */
  308. #ifdef S_IFSOCK /* Xn */
  309. case S_IFSOCK: /* Xn */
  310. return (SOCKTYPE); /* Xn */
  311. #endif /* Xn */
  312. default:
  313. return (REGTYPE);
  314. }
  315. }
  316. /* writecpio - write a cpio archive header
  317. *
  318. * DESCRIPTION
  319. *
  320. * Writes a new CPIO style archive header for the file specified.
  321. *
  322. * PARAMETERS
  323. *
  324. * char *name - name of file to create a header block for
  325. * Stat *asb - pointer to the stat structure for the named file
  326. */
  327. #ifdef __STDC__
  328. static void writecpio(char *name, Stat *asb)
  329. #else
  330. static void writecpio(name, asb)
  331. char *name;
  332. Stat *asb;
  333. #endif
  334. {
  335. uint namelen;
  336. char header[M_STRLEN + H_STRLEN + 1];
  337. #ifdef DF_TRACE_DEBUG
  338. printf("DF_TRACE_DEBUG: static void writecpio() in create.c\n");
  339. #endif
  340. namelen = (uint) strlen(name) + 1;
  341. strcpy(header, M_ASCII);
  342. sprintf(header + M_STRLEN, "%06o%06o%06o%06o%06o",
  343. USH(asb->sb_dev), USH(asb->sb_ino), USH(asb->sb_mode),
  344. USH(asb->sb_uid), USH(asb->sb_gid));
  345. sprintf(header + M_STRLEN + 30, "%06o%06o%011lo%06o%011lo",
  346. USH(asb->sb_nlink),
  347. #ifndef _POSIX_SOURCE
  348. USH(asb->sb_rdev),
  349. #else
  350. USH(0),
  351. #endif
  352. f_mtime ? asb->sb_mtime : time((time_t *) 0),
  353. namelen, asb->sb_size);
  354. outwrite(header, M_STRLEN + H_STRLEN);
  355. outwrite(name, namelen);
  356. #ifdef S_IFLNK
  357. if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
  358. outwrite(asb->sb_link, (uint) asb->sb_size);
  359. }
  360. #endif /* S_IFLNK */
  361. }