create.c 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380
  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. while (name_next(name, &sb) != -1) {
  83. if ((fd = openin(name, &sb)) < 0) {
  84. /* FIXME: pax wants to exit here??? */
  85. continue;
  86. }
  87. if (rplhead != (Replstr *)NULL) {
  88. rpl_name(name);
  89. if (strlen(name) == 0) {
  90. continue;
  91. }
  92. }
  93. if (get_disposition("add", name) || get_newname(name, sizeof(name))) {
  94. /* skip file... */
  95. if (fd) {
  96. close(fd);
  97. }
  98. continue;
  99. }
  100. if (!f_link && sb.sb_nlink > 1) {
  101. if (islink(name, &sb)) {
  102. sb.sb_size = 0;
  103. }
  104. linkto(name, &sb);
  105. }
  106. if (ar_format == TAR) {
  107. writetar(name, &sb);
  108. } else {
  109. writecpio(name, &sb);
  110. }
  111. if (fd) {
  112. outdata(fd, name, sb.sb_size);
  113. }
  114. if (f_verbose) {
  115. print_entry(name, &sb);
  116. }
  117. }
  118. write_eot();
  119. close_archive();
  120. return (0);
  121. }
  122. /* writetar - write a header block for a tar file
  123. *
  124. * DESCRIPTION
  125. *
  126. * Make a header block for the file name whose stat info is in st.
  127. * Return header pointer for success, NULL if the name is too long.
  128. *
  129. * The tar header block is structured as follows:
  130. *
  131. * FIELD NAME OFFSET SIZE
  132. * -------------|---------------|------
  133. * name 0 100
  134. * mode 100 8
  135. * uid 108 8
  136. * gid 116 8
  137. * size 124 12
  138. * mtime 136 12
  139. * chksum 148 8
  140. * typeflag 156 1
  141. * linkname 157 100
  142. * magic 257 6
  143. * version 263 2
  144. * uname 265 32
  145. * gname 297 32
  146. * devmajor 329 8
  147. * devminor 337 8
  148. * prefix 345 155
  149. *
  150. * PARAMETERS
  151. *
  152. * char *name - name of file to create a header block for
  153. * Stat *asb - pointer to the stat structure for the named file
  154. *
  155. */
  156. #ifdef __STDC__
  157. static void writetar(char *name, Stat *asb)
  158. #else
  159. static void writetar(name, asb)
  160. char *name;
  161. Stat *asb;
  162. #endif
  163. {
  164. char *p;
  165. char *prefix = (char *)NULL;
  166. int i;
  167. int sum;
  168. char hdr[BLOCKSIZE];
  169. Link *from;
  170. memset(hdr, 0, BLOCKSIZE);
  171. if (strlen(name) > 255) {
  172. warn(name, "name too long");
  173. return;
  174. }
  175. /*
  176. * If the pathname is longer than TNAMLEN, but less than 255, then
  177. * we can split it up into the prefix and the filename.
  178. */
  179. if (strlen(name) > 100) {
  180. prefix = name;
  181. name += 155;
  182. while (name > prefix && *name != '/') {
  183. name--;
  184. }
  185. /* no slash found....hmmm.... */
  186. if (name == prefix) {
  187. warn(prefix, "Name too long");
  188. return;
  189. }
  190. *name++ = '\0';
  191. }
  192. #ifdef S_IFLNK
  193. if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
  194. strcpy(&hdr[157], asb->sb_link);
  195. asb->sb_size = 0;
  196. }
  197. #endif
  198. strcpy(hdr, name);
  199. sprintf(&hdr[100], "%06o \0", asb->sb_mode & ~S_IFMT);
  200. sprintf(&hdr[108], "%06o \0", asb->sb_uid);
  201. sprintf(&hdr[116], "%06o \0", asb->sb_gid);
  202. sprintf(&hdr[124], "%011lo ", (long) asb->sb_size);
  203. sprintf(&hdr[136], "%011lo ", (long) asb->sb_mtime);
  204. strncpy(&hdr[148], " ", 8);
  205. hdr[156] = tartype(asb->sb_mode);
  206. if (asb->sb_nlink > 1 && (from = linkfrom(name, asb)) != (Link *)NULL) {
  207. strcpy(&hdr[157], from->l_name);
  208. hdr[156] = LNKTYPE;
  209. }
  210. strcpy(&hdr[257], TMAGIC);
  211. strncpy(&hdr[263], TVERSION, 2);
  212. strcpy(&hdr[265], finduname((int) asb->sb_uid));
  213. strcpy(&hdr[297], findgname((int) asb->sb_gid));
  214. sprintf(&hdr[329], "%06o \0", major(asb->sb_rdev));
  215. sprintf(&hdr[337], "%06o \0", minor(asb->sb_rdev));
  216. if (prefix != (char *)NULL) {
  217. strncpy(&hdr[345], prefix, 155);
  218. }
  219. /* Calculate the checksum */
  220. sum = 0;
  221. p = hdr;
  222. for (i = 0; i < 500; i++) {
  223. sum += 0xFF & *p++;
  224. }
  225. /* Fill in the checksum field. */
  226. sprintf(&hdr[148], "%06o \0", sum);
  227. outwrite(hdr, BLOCKSIZE);
  228. }
  229. /* tartype - return tar file type from file mode
  230. *
  231. * DESCRIPTION
  232. *
  233. * tartype returns the character which represents the type of file
  234. * indicated by "mode".
  235. *
  236. * PARAMETERS
  237. *
  238. * int mode - file mode from a stat block
  239. *
  240. * RETURNS
  241. *
  242. * The character which represents the particular file type in the
  243. * ustar standard headers.
  244. */
  245. #ifdef __STDC__
  246. static char tartype(int mode)
  247. #else
  248. static char tartype(mode)
  249. int mode;
  250. #endif
  251. {
  252. switch (mode & S_IFMT) {
  253. #ifdef S_IFCTG
  254. case S_IFCTG:
  255. return(CONTTYPE);
  256. #endif
  257. case S_IFDIR:
  258. return (DIRTYPE);
  259. #ifdef S_IFLNK
  260. case S_IFLNK:
  261. return (SYMTYPE);
  262. #endif
  263. #ifdef S_IFFIFO
  264. case S_IFIFO:
  265. return (FIFOTYPE);
  266. #endif
  267. #ifdef S_IFCHR
  268. case S_IFCHR:
  269. return (CHRTYPE);
  270. #endif
  271. #ifdef S_IFBLK
  272. case S_IFBLK:
  273. return (BLKTYPE);
  274. #endif
  275. default:
  276. return (REGTYPE);
  277. }
  278. }
  279. /* writecpio - write a cpio archive header
  280. *
  281. * DESCRIPTION
  282. *
  283. * Writes a new CPIO style archive header for the file specified.
  284. *
  285. * PARAMETERS
  286. *
  287. * char *name - name of file to create a header block for
  288. * Stat *asb - pointer to the stat structure for the named file
  289. */
  290. #ifdef __STDC__
  291. static void writecpio(char *name, Stat *asb)
  292. #else
  293. static void writecpio(name, asb)
  294. char *name;
  295. Stat *asb;
  296. #endif
  297. {
  298. uint namelen;
  299. char header[M_STRLEN + H_STRLEN + 1];
  300. namelen = (uint) strlen(name) + 1;
  301. strcpy(header, M_ASCII);
  302. sprintf(header + M_STRLEN, "%06o%06o%06o%06o%06o",
  303. USH(asb->sb_dev), USH(asb->sb_ino), USH(asb->sb_mode),
  304. USH(asb->sb_uid), USH(asb->sb_gid));
  305. sprintf(header + M_STRLEN + 30, "%06o%06o%011lo%06o%011lo",
  306. #ifdef _POSIX_SOURCE
  307. USH(asb->sb_nlink), USH(0),
  308. #else
  309. USH(asb->sb_nlink), USH(asb->sb_rdev),
  310. #endif
  311. f_mtime ? asb->sb_mtime : time((time_t *) 0),
  312. namelen, asb->sb_size);
  313. outwrite(header, M_STRLEN + H_STRLEN);
  314. outwrite(name, namelen);
  315. #ifdef S_IFLNK
  316. if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
  317. outwrite(asb->sb_link, (uint) asb->sb_size);
  318. }
  319. #endif /* S_IFLNK */
  320. }