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.

419 lines
13 KiB

  1. /* $Source: /u/mark/src/pax/RCS/fileio.c,v $
  2. *
  3. * $Revision: 1.2 $
  4. *
  5. * fileio.c - file I/O functions for all archive interfaces
  6. *
  7. * DESCRIPTION
  8. *
  9. * These function all do I/O of some form or another. They are
  10. * grouped here mainly for convienence.
  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: fileio.c,v $
  33. * Revision 1.2 89/02/12 10:04:31 mark
  34. * 1.2 release fixes
  35. *
  36. * Revision 1.1 88/12/23 18:02:09 mark
  37. * Initial revision
  38. *
  39. */
  40. #ifndef lint
  41. static char *ident = "$Id: fileio.c,v 1.2 89/02/12 10:04:31 mark Exp $";
  42. static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
  43. #endif /* ! lint */
  44. /* Headers */
  45. #include "pax.h"
  46. int mknod (const char *path, mode_t mode, int dev);
  47. /* open_archive - open an archive file.
  48. *
  49. * DESCRIPTION
  50. *
  51. * Open_archive will open an archive file for reading or writing,
  52. * setting the proper file mode, depending on the "mode" passed to
  53. * it. All buffer pointers are reset according to the mode
  54. * specified.
  55. *
  56. * PARAMETERS
  57. *
  58. * int mode - specifies whether we are reading or writing.
  59. *
  60. * RETURNS
  61. *
  62. * Returns a zero if successfull, or -1 if an error occured during
  63. * the open.
  64. */
  65. int open_archive(int mode)
  66. {
  67. #ifdef DF_TRACE_DEBUG
  68. printf("DF_TRACE_DEBUG: int open_archive() in fileio.c\n");
  69. #endif
  70. if (ar_file[0] == '-' && ar_file[1] == '\0') {
  71. if (mode == AR_READ) {
  72. archivefd = STDIN;
  73. bufend = bufidx = bufstart;
  74. } else {
  75. archivefd = STDOUT;
  76. }
  77. } else if (mode == AR_READ) {
  78. archivefd = open(ar_file, O_RDONLY | O_BINARY);
  79. bufend = bufidx = bufstart; /* set up for initial read */
  80. } else if (mode == AR_WRITE) {
  81. archivefd = open(ar_file, O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, /* Xn */
  82. S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); /* Xn */
  83. } else if (mode == AR_APPEND) {
  84. archivefd = open(ar_file, O_RDWR | O_BINARY, /* Xn */
  85. S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH|S_IWOTH); /* Xn */
  86. bufend = bufidx = bufstart; /* set up for initial read */
  87. }
  88. if (archivefd < 0) {
  89. warnarch(strerror(errno), (OFFSET) 0); /* Xn */
  90. return (-1);
  91. }
  92. ++arvolume;
  93. return (0);
  94. }
  95. /* close_archive - close the archive file
  96. *
  97. * DESCRIPTION
  98. *
  99. * Closes the current archive and resets the archive end of file
  100. * marker.
  101. */
  102. void close_archive(void)
  103. {
  104. #ifdef DF_TRACE_DEBUG
  105. printf("DF_TRACE_DEBUG: void close_archive() in fileio.c\n");
  106. #endif
  107. if (archivefd != STDIN && archivefd != STDOUT) {
  108. close(archivefd);
  109. }
  110. areof = 0;
  111. }
  112. /* openout - open an output file
  113. *
  114. * DESCRIPTION
  115. *
  116. * Openo opens the named file for output. The file mode and type are
  117. * set based on the values stored in the stat structure for the file.
  118. * If the file is a special file, then no data will be written, the
  119. * file/directory/Fifo, etc., will just be created. Appropriate
  120. * permission may be required to create special files.
  121. *
  122. * PARAMETERS
  123. *
  124. * char *name - The name of the file to create
  125. * Stat *asb - Stat structure for the file
  126. * Link *linkp; - pointer to link chain for this file
  127. * int ispass - true if we are operating in "pass" mode
  128. *
  129. * RETURNS
  130. *
  131. * Returns the output file descriptor, 0 if no data is required or -1
  132. * if unsuccessful. Note that UNIX open() will never return 0 because
  133. * the standard input is in use.
  134. */
  135. int openout(char *name, Stat *asb, Link *linkp, int ispass)
  136. {
  137. int exists;
  138. int fd;
  139. ushort perm;
  140. ushort operm = 0;
  141. Stat osb;
  142. #ifdef S_IFLNK
  143. int ssize;
  144. char sname[PATH_MAX + 1];
  145. #endif /* S_IFLNK */
  146. #ifdef DF_TRACE_DEBUG
  147. printf("DF_TRACE_DEBUG: int openout() in fileio.c\n");
  148. #endif
  149. if (exists = (LSTAT(name, &osb) == 0)) {
  150. if (ispass && osb.sb_ino == asb->sb_ino && osb.sb_dev == asb->sb_dev) {
  151. warn(name, "Same file");
  152. return (-1);
  153. } else if ((osb.sb_mode & S_IFMT) == (asb->sb_mode & S_IFMT)) {
  154. operm = (ushort)(osb.sb_mode & S_IPERM);
  155. } else if (REMOVE(name, &osb) < 0) {
  156. warn(name, strerror(errno)); /* Xn */
  157. return (-1);
  158. } else {
  159. exists = 0;
  160. }
  161. }
  162. if (linkp) {
  163. if (exists) {
  164. if (asb->sb_ino == osb.sb_ino && asb->sb_dev == osb.sb_dev) {
  165. return (0);
  166. } else if (unlink(name) < 0) {
  167. warn(name, strerror(errno)); /* Xn */
  168. return (-1);
  169. } else {
  170. exists = 0;
  171. }
  172. }
  173. if (link(linkp->l_name, name) != 0) {
  174. if (errno == ENOENT) {
  175. if (f_dir_create) {
  176. if (dirneed(name) != 0 ||
  177. link(linkp->l_name, name) != 0) {
  178. warn(name, strerror(errno)); /* Xn */
  179. return (-1);
  180. }
  181. } else {
  182. warn(name,
  183. "Directories are not being created (-d option)");
  184. }
  185. return (0);
  186. } else if (errno != EXDEV) {
  187. warn(name, strerror(errno)); /* Xn */
  188. return (-1);
  189. }
  190. } else {
  191. return (0);
  192. }
  193. }
  194. perm = (ushort)(asb->sb_mode & S_IPERM);
  195. switch (asb->sb_mode & S_IFMT) {
  196. case S_IFBLK:
  197. case S_IFCHR:
  198. fd = 0;
  199. if (exists) {
  200. if (REMOVE(name, &osb) < 0) {
  201. warn(name, strerror(errno)); /* Xn */
  202. return (-1);
  203. } else {
  204. exists = 0;
  205. }
  206. }
  207. if (mknod(name, (int) asb->sb_mode, 0)) {
  208. if (errno == ENOENT) {
  209. if (f_dir_create) {
  210. if (dirneed(name) < 0 || mknod(name, (int) asb->sb_mode,
  211. 0)) {
  212. warn(name, strerror(errno)); /* Xn */
  213. return (-1);
  214. }
  215. } else {
  216. warn(name, "Directories are not being created (-d option)");
  217. }
  218. } else {
  219. warn(name, strerror(errno)); /* Xn */
  220. return (-1);
  221. }
  222. }
  223. return (0);
  224. break;
  225. case S_IFDIR:
  226. if (exists) {
  227. if (perm != operm && chmod(name, (int) perm) < 0) {
  228. warn(name, strerror(errno)); /* Xn */
  229. return (-1);
  230. }
  231. } else if (f_dir_create) {
  232. if (dirmake(name, asb) < 0 || dirneed(name) < 0) {
  233. warn(name, strerror(errno)); /* Xn */
  234. return (-1);
  235. }
  236. } else {
  237. warn(name, "Directories are not being created (-d option)");
  238. }
  239. return (0);
  240. #ifdef S_IFIFO
  241. case S_IFIFO:
  242. fd = 0;
  243. if (exists) {
  244. if (perm != operm && chmod(name, (int) perm) < 0) {
  245. warn(name, strerror(errno)); /* Xn */
  246. return (-1);
  247. }
  248. } else if (mkfifo(name, asb->sb_mode) < 0) { /* Xn */
  249. if (errno == ENOENT) {
  250. if (f_dir_create) {
  251. if (dirneed(name) < 0
  252. || mkfifo(name, asb->sb_mode) < 0) { /* Xn */
  253. warn(name, strerror(errno)); /* Xn */
  254. return (-1);
  255. }
  256. } else {
  257. warn(name, "Directories are not being created (-d option)");
  258. }
  259. } else {
  260. warn(name, strerror(errno)); /* Xn */
  261. return (-1);
  262. }
  263. }
  264. return (0);
  265. break;
  266. #endif /* S_IFIFO */
  267. #ifdef S_IFLNK
  268. case S_IFLNK:
  269. if (exists) {
  270. if ((ssize = readlink(name, sname, sizeof(sname))) < 0) {
  271. warn(name, strerror(errno)); /* Xn */
  272. return (-1);
  273. } else if (strncmp(sname, asb->sb_link, ssize) == 0) {
  274. return (0);
  275. } else if (REMOVE(name, &osb) < 0) {
  276. warn(name, strerror(errno)); /* Xn */
  277. return (-1);
  278. } else {
  279. exists = 0;
  280. }
  281. }
  282. if (symlink(asb->sb_link, name) < 0) {
  283. if (errno == ENOENT) {
  284. if (f_dir_create) {
  285. if (dirneed(name) < 0 || symlink(asb->sb_link, name) < 0) {
  286. warn(name, strerror(errno)); /* Xn */
  287. return (-1);
  288. }
  289. } else {
  290. warn(name, "Directories are not being created (-d option)");
  291. }
  292. } else {
  293. warn(name, strerror(errno)); /* Xn */
  294. return (-1);
  295. }
  296. }
  297. return (0); /* Can't chown()/chmod() a symbolic link */
  298. #endif /* S_IFLNK */
  299. case S_IFREG:
  300. if (exists) {
  301. if (!f_unconditional && osb.sb_mtime > asb->sb_mtime) {
  302. warn(name, "Newer file exists");
  303. return (-1);
  304. } else if (unlink(name) < 0) {
  305. warn(name, strerror(errno)); /* Xn */
  306. return (-1);
  307. } else {
  308. exists = 0;
  309. }
  310. }
  311. if ((fd = creat(name, (int) perm)) < 0) {
  312. if (errno == ENOENT) {
  313. if (f_dir_create) {
  314. if (dirneed(name) < 0 ||
  315. (fd = creat(name, (int) perm)) < 0) {
  316. warn(name, strerror(errno)); /* Xn */
  317. return (-1);
  318. }
  319. } else {
  320. /*
  321. * the file requires a directory which does not exist
  322. * and which the user does not want created, so skip
  323. * the file...
  324. */
  325. warn(name, "Directories are not being created (-d option)");
  326. return (0);
  327. }
  328. } else {
  329. warn(name, strerror(errno)); /* Xn */
  330. return (-1);
  331. }
  332. }
  333. break;
  334. default:
  335. warn(name, "Unknown filetype");
  336. return (-1);
  337. }
  338. if (f_owner) {
  339. if (!exists || asb->sb_uid != osb.sb_uid || asb->sb_gid != osb.sb_gid) {
  340. chown(name, (int) asb->sb_uid, (int) asb->sb_gid);
  341. }
  342. }
  343. return (fd);
  344. }
  345. /* openin - open the next input file
  346. *
  347. * DESCRIPTION
  348. *
  349. * Openi will attempt to open the next file for input. If the file is
  350. * a special file, such as a directory, FIFO, link, character- or
  351. * block-special file, then the file size field of the stat structure
  352. * is zeroed to make sure that no data is written out for the file.
  353. * If the file is a special file, then a file descriptor of 0 is
  354. * returned to the caller, which is handled specially. If the file
  355. * is a regular file, then the file is opened and a file descriptor
  356. * to the open file is returned to the caller.
  357. *
  358. * PARAMETERS
  359. *
  360. * char *name - pointer to the name of the file to open
  361. * Stat *asb - pointer to the stat block for the file to open
  362. *
  363. * RETURNS
  364. *
  365. * Returns a file descriptor, 0 if no data exists, or -1 at EOF. This
  366. * kludge works because standard input is in use, preventing open() from
  367. * returning zero.
  368. */
  369. int openin(char *name, Stat *asb)
  370. {
  371. int fd;
  372. #ifdef DF_TRACE_DEBUG
  373. printf("DF_TRACE_DEBUG: int openin() in fileio.c\n");
  374. #endif
  375. switch (asb->sb_mode & S_IFMT) {
  376. case S_IFDIR:
  377. asb->sb_size = 0;
  378. return (0);
  379. #ifdef S_IFLNK
  380. case S_IFLNK:
  381. if ((asb->sb_size = readlink(name,
  382. asb->sb_link, sizeof(asb->sb_link) - 1)) < 0) {
  383. warn(name, strerror(errno)); /* Xn */
  384. return (0);
  385. }
  386. asb->sb_link[asb->sb_size] = '\0';
  387. return (0);
  388. #endif /* S_IFLNK */
  389. case S_IFREG:
  390. if (asb->sb_size == 0) {
  391. return (0);
  392. }
  393. if ((fd = open(name, O_RDONLY | O_BINARY)) < 0) {
  394. warn(name, strerror(errno)); /* Xn */}
  395. return (fd);
  396. default:
  397. asb->sb_size = 0;
  398. return (0);
  399. }
  400. }