fileio.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  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. /* open_archive - open an archive file.
  47. *
  48. * DESCRIPTION
  49. *
  50. * Open_archive will open an archive file for reading or writing,
  51. * setting the proper file mode, depending on the "mode" passed to
  52. * it. All buffer pointers are reset according to the mode
  53. * specified.
  54. *
  55. * PARAMETERS
  56. *
  57. * int mode - specifies whether we are reading or writing.
  58. *
  59. * RETURNS
  60. *
  61. * Returns a zero if successfull, or -1 if an error occured during
  62. * the open.
  63. */
  64. #ifdef __STDC__
  65. int open_archive(int mode)
  66. #else
  67. int open_archive(mode)
  68. int mode;
  69. #endif
  70. {
  71. if (ar_file[0] == '-' && ar_file[1] == '\0') {
  72. if (mode == AR_READ) {
  73. archivefd = STDIN;
  74. bufend = bufidx = bufstart;
  75. } else {
  76. archivefd = STDOUT;
  77. }
  78. } else if (mode == AR_READ) {
  79. archivefd = open(ar_file, O_RDONLY | O_BINARY);
  80. bufend = bufidx = bufstart; /* set up for initial read */
  81. } else if (mode == AR_WRITE) {
  82. archivefd = open(ar_file, O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, 0666);
  83. } else if (mode == AR_APPEND) {
  84. archivefd = open(ar_file, O_RDWR | O_BINARY, 0666);
  85. bufend = bufidx = bufstart; /* set up for initial read */
  86. }
  87. if (archivefd < 0) {
  88. warnarch(strerror(), (OFFSET) 0);
  89. return (-1);
  90. }
  91. ++arvolume;
  92. return (0);
  93. }
  94. /* close_archive - close the archive file
  95. *
  96. * DESCRIPTION
  97. *
  98. * Closes the current archive and resets the archive end of file
  99. * marker.
  100. */
  101. #ifdef __STDC__
  102. void close_archive(void)
  103. #else
  104. void close_archive()
  105. #endif
  106. {
  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. #ifdef __STDC__
  136. int openout(char *name, Stat *asb, Link *linkp, int ispass)
  137. #else
  138. int openout(name, asb, linkp, ispass)
  139. char *name;
  140. Stat *asb;
  141. Link *linkp;
  142. int ispass;
  143. #endif
  144. {
  145. int exists;
  146. int fd;
  147. ushort perm;
  148. ushort operm = 0;
  149. Stat osb;
  150. #ifdef S_IFLNK
  151. int ssize;
  152. char sname[PATH_MAX + 1];
  153. #endif /* S_IFLNK */
  154. if (exists = (LSTAT(name, &osb) == 0)) {
  155. if (ispass && osb.sb_ino == asb->sb_ino && osb.sb_dev == asb->sb_dev) {
  156. warn(name, "Same file");
  157. return (-1);
  158. } else if ((osb.sb_mode & S_IFMT) == (asb->sb_mode & S_IFMT)) {
  159. operm = osb.sb_mode & S_IPERM;
  160. } else if (REMOVE(name, &osb) < 0) {
  161. warn(name, strerror());
  162. return (-1);
  163. } else {
  164. exists = 0;
  165. }
  166. }
  167. if (linkp) {
  168. if (exists) {
  169. if (asb->sb_ino == osb.sb_ino && asb->sb_dev == osb.sb_dev) {
  170. return (0);
  171. } else if (unlink(name) < 0) {
  172. warn(name, strerror());
  173. return (-1);
  174. } else {
  175. exists = 0;
  176. }
  177. }
  178. if (link(linkp->l_name, name) != 0) {
  179. if (errno == ENOENT) {
  180. if (f_dir_create) {
  181. if (dirneed(name) != 0 ||
  182. link(linkp->l_name, name) != 0) {
  183. warn(name, strerror());
  184. return (-1);
  185. }
  186. } else {
  187. warn(name,
  188. "Directories are not being created (-d option)");
  189. }
  190. return(0);
  191. } else if (errno != EXDEV) {
  192. warn(name, strerror());
  193. return (-1);
  194. }
  195. } else {
  196. return(0);
  197. }
  198. }
  199. perm = asb->sb_mode & S_IPERM;
  200. switch (asb->sb_mode & S_IFMT) {
  201. case S_IFBLK:
  202. case S_IFCHR:
  203. #ifdef _POSIX_SOURCE
  204. warn(name, "Can't create special files");
  205. return (-1);
  206. #else
  207. fd = 0;
  208. if (exists) {
  209. if (asb->sb_rdev == osb.sb_rdev) {
  210. if (perm != operm && chmod(name, (int) perm) < 0) {
  211. warn(name, strerror());
  212. return (-1);
  213. } else {
  214. break;
  215. }
  216. } else if (REMOVE(name, &osb) < 0) {
  217. warn(name, strerror());
  218. return (-1);
  219. } else {
  220. exists = 0;
  221. }
  222. }
  223. if (mknod(name, (int) asb->sb_mode, (int) asb->sb_rdev) < 0) {
  224. if (errno == ENOENT) {
  225. if (f_dir_create) {
  226. if (dirneed(name) < 0 || mknod(name, (int) asb->sb_mode,
  227. (int) asb->sb_rdev) < 0) {
  228. warn(name, strerror());
  229. return (-1);
  230. }
  231. } else {
  232. warn(name, "Directories are not being created (-d option)");
  233. }
  234. } else {
  235. warn(name, strerror());
  236. return (-1);
  237. }
  238. }
  239. return(0);
  240. #endif /* _POSIX_SOURCE */
  241. break;
  242. case S_IFDIR:
  243. if (exists) {
  244. if (perm != operm && chmod(name, (int) perm) < 0) {
  245. warn(name, strerror());
  246. return (-1);
  247. }
  248. } else if (f_dir_create) {
  249. if (dirmake(name, asb) < 0 || dirneed(name) < 0) {
  250. warn(name, strerror());
  251. return (-1);
  252. }
  253. } else {
  254. warn(name, "Directories are not being created (-d option)");
  255. }
  256. return (0);
  257. #ifndef _POSIX_SOURCE
  258. #ifdef S_IFIFO
  259. case S_IFIFO:
  260. fd = 0;
  261. if (exists) {
  262. if (perm != operm && chmod(name, (int) perm) < 0) {
  263. warn(name, strerror());
  264. return (-1);
  265. }
  266. } else if (mknod(name, (int) asb->sb_mode, 0) < 0) {
  267. if (errno == ENOENT) {
  268. if (f_dir_create) {
  269. if (dirneed(name) < 0
  270. || mknod(name, (int) asb->sb_mode, 0) < 0) {
  271. warn(name, strerror());
  272. return (-1);
  273. }
  274. } else {
  275. warn(name, "Directories are not being created (-d option)");
  276. }
  277. } else {
  278. warn(name, strerror());
  279. return (-1);
  280. }
  281. }
  282. return(0);
  283. break;
  284. #endif /* S_IFIFO */
  285. #endif /* _POSIX_SOURCE */
  286. #ifdef S_IFLNK
  287. case S_IFLNK:
  288. if (exists) {
  289. if ((ssize = readlink(name, sname, sizeof(sname))) < 0) {
  290. warn(name, strerror());
  291. return (-1);
  292. } else if (strncmp(sname, asb->sb_link, ssize) == 0) {
  293. return (0);
  294. } else if (REMOVE(name, &osb) < 0) {
  295. warn(name, strerror());
  296. return (-1);
  297. } else {
  298. exists = 0;
  299. }
  300. }
  301. if (symlink(asb->sb_link, name) < 0) {
  302. if (errno == ENOENT) {
  303. if (f_dir_create) {
  304. if (dirneed(name) < 0 || symlink(asb->sb_link, name) < 0) {
  305. warn(name, strerror());
  306. return (-1);
  307. }
  308. } else {
  309. warn(name, "Directories are not being created (-d option)");
  310. }
  311. } else {
  312. warn(name, strerror());
  313. return (-1);
  314. }
  315. }
  316. return (0); /* Can't chown()/chmod() a symbolic link */
  317. #endif /* S_IFLNK */
  318. case S_IFREG:
  319. if (exists) {
  320. if (!f_unconditional && osb.sb_mtime > asb->sb_mtime) {
  321. warn(name, "Newer file exists");
  322. return (-1);
  323. } else if (unlink(name) < 0) {
  324. warn(name, strerror());
  325. return (-1);
  326. } else {
  327. exists = 0;
  328. }
  329. }
  330. if ((fd = creat(name, (int) perm)) < 0) {
  331. if (errno == ENOENT) {
  332. if (f_dir_create) {
  333. if (dirneed(name) < 0 ||
  334. (fd = creat(name, (int) perm)) < 0) {
  335. warn(name, strerror());
  336. return (-1);
  337. }
  338. } else {
  339. /*
  340. * the file requires a directory which does not exist
  341. * and which the user does not want created, so skip
  342. * the file...
  343. */
  344. warn(name, "Directories are not being created (-d option)");
  345. return(0);
  346. }
  347. } else {
  348. warn(name, strerror());
  349. return (-1);
  350. }
  351. }
  352. break;
  353. default:
  354. warn(name, "Unknown filetype");
  355. return (-1);
  356. }
  357. if (f_owner) {
  358. if (!exists || asb->sb_uid != osb.sb_uid || asb->sb_gid != osb.sb_gid) {
  359. chown(name, (int) asb->sb_uid, (int) asb->sb_gid);
  360. }
  361. }
  362. return (fd);
  363. }
  364. /* openin - open the next input file
  365. *
  366. * DESCRIPTION
  367. *
  368. * Openi will attempt to open the next file for input. If the file is
  369. * a special file, such as a directory, FIFO, link, character- or
  370. * block-special file, then the file size field of the stat structure
  371. * is zeroed to make sure that no data is written out for the file.
  372. * If the file is a special file, then a file descriptor of 0 is
  373. * returned to the caller, which is handled specially. If the file
  374. * is a regular file, then the file is opened and a file descriptor
  375. * to the open file is returned to the caller.
  376. *
  377. * PARAMETERS
  378. *
  379. * char *name - pointer to the name of the file to open
  380. * Stat *asb - pointer to the stat block for the file to open
  381. *
  382. * RETURNS
  383. *
  384. * Returns a file descriptor, 0 if no data exists, or -1 at EOF. This
  385. * kludge works because standard input is in use, preventing open() from
  386. * returning zero.
  387. */
  388. #ifdef __STDC__
  389. int openin(char *name, Stat *asb)
  390. #else
  391. int openin(name, asb)
  392. char *name; /* name of file to open */
  393. Stat *asb; /* pointer to stat structure for file */
  394. #endif
  395. {
  396. int fd;
  397. switch (asb->sb_mode & S_IFMT) {
  398. case S_IFDIR:
  399. asb->sb_nlink = 1;
  400. asb->sb_size = 0;
  401. return (0);
  402. #ifdef S_IFLNK
  403. case S_IFLNK:
  404. if ((asb->sb_size = readlink(name,
  405. asb->sb_link, sizeof(asb->sb_link) - 1)) < 0) {
  406. warn(name, strerror());
  407. return(0);
  408. }
  409. asb->sb_link[asb->sb_size] = '\0';
  410. return (0);
  411. #endif /* S_IFLNK */
  412. case S_IFREG:
  413. if (asb->sb_size == 0) {
  414. return (0);
  415. }
  416. if ((fd = open(name, O_RDONLY | O_BINARY)) < 0) {
  417. warn(name, strerror());
  418. }
  419. return (fd);
  420. default:
  421. asb->sb_size = 0;
  422. return (0);
  423. }
  424. }