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