1 /* $Source: /u/mark/src/pax/RCS/fileio.c,v $
5 * fileio.c - file I/O functions for all archive interfaces
9 * These function all do I/O of some form or another. They are
10 * grouped here mainly for convienence.
14 * Mark H. Colburn, NAPS International (mark@jhereg.mn.org)
16 * Sponsored by The USENIX Association for public distribution.
18 * Copyright (c) 1989 Mark H. Colburn.
19 * All rights reserved.
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
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.
33 * Revision 1.2 89/02/12 10:04:31 mark
36 * Revision 1.1 88/12/23 18:02:09 mark
42 static char *ident = "$Id: fileio.c,v 1.2 89/02/12 10:04:31 mark Exp $";
43 static char *copyright = "Copyright (c) 1989 Mark H. Colburn.\nAll rights reserved.\n";
52 /* open_archive - open an archive file.
56 * Open_archive will open an archive file for reading or writing,
57 * setting the proper file mode, depending on the "mode" passed to
58 * it. All buffer pointers are reset according to the mode
63 * int mode - specifies whether we are reading or writing.
67 * Returns a zero if successfull, or -1 if an error occured during
73 int open_archive(int mode)
77 int open_archive(mode)
82 if (ar_file[0] == '-' && ar_file[1] == '\0') {
83 if (mode == AR_READ) {
85 bufend = bufidx = bufstart;
89 } else if (mode == AR_READ) {
90 archivefd = open(ar_file, O_RDONLY | O_BINARY);
91 bufend = bufidx = bufstart; /* set up for initial read */
92 } else if (mode == AR_WRITE) {
93 archivefd = open(ar_file, O_WRONLY|O_TRUNC|O_CREAT|O_BINARY, 0666);
94 } else if (mode == AR_APPEND) {
95 archivefd = open(ar_file, O_RDWR | O_BINARY, 0666);
96 bufend = bufidx = bufstart; /* set up for initial read */
100 warnarch(strerror(), (OFFSET) 0);
108 /* close_archive - close the archive file
112 * Closes the current archive and resets the archive end of file
118 void close_archive(void)
126 if (archivefd != STDIN && archivefd != STDOUT) {
133 /* openout - open an output file
137 * Openo opens the named file for output. The file mode and type are
138 * set based on the values stored in the stat structure for the file.
139 * If the file is a special file, then no data will be written, the
140 * file/directory/Fifo, etc., will just be created. Appropriate
141 * permission may be required to create special files.
145 * char *name - The name of the file to create
146 * Stat *asb - Stat structure for the file
147 * Link *linkp; - pointer to link chain for this file
148 * int ispass - true if we are operating in "pass" mode
152 * Returns the output file descriptor, 0 if no data is required or -1
153 * if unsuccessful. Note that UNIX open() will never return 0 because
154 * the standard input is in use.
159 int openout(char *name, Stat *asb, Link *linkp, int ispass)
163 int openout(name, asb, linkp, ispass)
178 char sname[PATH_MAX + 1];
181 if (exists = (LSTAT(name, &osb) == 0)) {
182 if (ispass && osb.sb_ino == asb->sb_ino && osb.sb_dev == asb->sb_dev) {
183 warn(name, "Same file");
185 } else if ((osb.sb_mode & S_IFMT) == (asb->sb_mode & S_IFMT)) {
186 operm = osb.sb_mode & S_IPERM;
187 } else if (REMOVE(name, &osb) < 0) {
188 warn(name, strerror());
196 if (asb->sb_ino == osb.sb_ino && asb->sb_dev == osb.sb_dev) {
198 } else if (unlink(name) < 0) {
199 warn(name, strerror());
205 if (link(linkp->l_name, name) != 0) {
206 if (errno == ENOENT) {
208 if (dirneed(name) != 0 ||
209 link(linkp->l_name, name) != 0) {
210 warn(name, strerror());
215 "Directories are not being created (-d option)");
218 } else if (errno != EXDEV) {
219 warn(name, strerror());
226 perm = asb->sb_mode & S_IPERM;
227 switch (asb->sb_mode & S_IFMT) {
231 warn(name, "Can't create special files");
236 if (asb->sb_rdev == osb.sb_rdev) {
237 if (perm != operm && chmod(name, (int) perm) < 0) {
238 warn(name, strerror());
243 } else if (REMOVE(name, &osb) < 0) {
244 warn(name, strerror());
250 if (mknod(name, (int) asb->sb_mode, (int) asb->sb_rdev) < 0) {
251 if (errno == ENOENT) {
253 if (dirneed(name) < 0 || mknod(name, (int) asb->sb_mode,
254 (int) asb->sb_rdev) < 0) {
255 warn(name, strerror());
259 warn(name, "Directories are not being created (-d option)");
262 warn(name, strerror());
267 #endif /* _POSIX_SOURCE */
271 if (perm != operm && chmod(name, (int) perm) < 0) {
272 warn(name, strerror());
275 } else if (f_dir_create) {
276 if (dirmake(name, asb) < 0 || dirneed(name) < 0) {
277 warn(name, strerror());
281 warn(name, "Directories are not being created (-d option)");
284 #ifndef _POSIX_SOURCE
289 if (perm != operm && chmod(name, (int) perm) < 0) {
290 warn(name, strerror());
293 } else if (mknod(name, (int) asb->sb_mode, 0) < 0) {
294 if (errno == ENOENT) {
296 if (dirneed(name) < 0
297 || mknod(name, (int) asb->sb_mode, 0) < 0) {
298 warn(name, strerror());
302 warn(name, "Directories are not being created (-d option)");
305 warn(name, strerror());
312 #endif /* _POSIX_SOURCE */
316 if ((ssize = readlink(name, sname, sizeof(sname))) < 0) {
317 warn(name, strerror());
319 } else if (strncmp(sname, asb->sb_link, ssize) == 0) {
321 } else if (REMOVE(name, &osb) < 0) {
322 warn(name, strerror());
328 if (symlink(asb->sb_link, name) < 0) {
329 if (errno == ENOENT) {
331 if (dirneed(name) < 0 || symlink(asb->sb_link, name) < 0) {
332 warn(name, strerror());
336 warn(name, "Directories are not being created (-d option)");
339 warn(name, strerror());
343 return (0); /* Can't chown()/chmod() a symbolic link */
347 if (!f_unconditional && osb.sb_mtime > asb->sb_mtime) {
348 warn(name, "Newer file exists");
350 } else if (unlink(name) < 0) {
351 warn(name, strerror());
357 if ((fd = creat(name, (int) perm)) < 0) {
358 if (errno == ENOENT) {
360 if (dirneed(name) < 0 ||
361 (fd = creat(name, (int) perm)) < 0) {
362 warn(name, strerror());
367 * the file requires a directory which does not exist
368 * and which the user does not want created, so skip
371 warn(name, "Directories are not being created (-d option)");
375 warn(name, strerror());
381 warn(name, "Unknown filetype");
385 if (!exists || asb->sb_uid != osb.sb_uid || asb->sb_gid != osb.sb_gid) {
386 chown(name, (int) asb->sb_uid, (int) asb->sb_gid);
393 /* openin - open the next input file
397 * Openi will attempt to open the next file for input. If the file is
398 * a special file, such as a directory, FIFO, link, character- or
399 * block-special file, then the file size field of the stat structure
400 * is zeroed to make sure that no data is written out for the file.
401 * If the file is a special file, then a file descriptor of 0 is
402 * returned to the caller, which is handled specially. If the file
403 * is a regular file, then the file is opened and a file descriptor
404 * to the open file is returned to the caller.
408 * char *name - pointer to the name of the file to open
409 * Stat *asb - pointer to the stat block for the file to open
413 * Returns a file descriptor, 0 if no data exists, or -1 at EOF. This
414 * kludge works because standard input is in use, preventing open() from
420 int openin(char *name, Stat *asb)
424 int openin(name, asb)
425 char *name; /* name of file to open */
426 Stat *asb; /* pointer to stat structure for file */
432 switch (asb->sb_mode & S_IFMT) {
439 if ((asb->sb_size = readlink(name,
440 asb->sb_link, sizeof(asb->sb_link) - 1)) < 0) {
441 warn(name, strerror());
444 asb->sb_link[asb->sb_size] = '\0';
448 if (asb->sb_size == 0) {
451 if ((fd = open(name, O_RDONLY | O_BINARY)) < 0) {
452 warn(name, strerror());