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
41 #ifndef lint
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";
44 #endif /* ! lint */
45
46
47 /* Headers */
48
49 #include "pax.h"
50
51
52 /* open_archive - open an archive file.
53 *
54 * DESCRIPTION
55 *
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
59 * specified.
60 *
61 * PARAMETERS
62 *
63 * int mode - specifies whether we are reading or writing.
64 *
65 * RETURNS
66 *
67 * Returns a zero if successfull, or -1 if an error occured during
68 * the open.
69 */
70
71 #ifdef __STDC__
72
open_archive(int mode)73 int open_archive(int mode)
74
75 #else
76
77 int open_archive(mode)
78 int mode;
79
80 #endif
81 {
82 if (ar_file[0] == '-' && ar_file[1] == '\0') {
83 if (mode == AR_READ) {
84 archivefd = STDIN;
85 bufend = bufidx = bufstart;
86 } else {
87 archivefd = STDOUT;
88 }
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 */
97 }
98
99 if (archivefd < 0) {
100 warnarch(strerror(), (OFFSET) 0);
101 return (-1);
102 }
103 ++arvolume;
104 return (0);
105 }
106
107
108 /* close_archive - close the archive file
109 *
110 * DESCRIPTION
111 *
112 * Closes the current archive and resets the archive end of file
113 * marker.
114 */
115
116 #ifdef __STDC__
117
close_archive(void)118 void close_archive(void)
119
120 #else
121
122 void close_archive()
123
124 #endif
125 {
126 if (archivefd != STDIN && archivefd != STDOUT) {
127 close(archivefd);
128 }
129 areof = 0;
130 }
131
132
133 /* openout - open an output file
134 *
135 * DESCRIPTION
136 *
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.
142 *
143 * PARAMETERS
144 *
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
149 *
150 * RETURNS
151 *
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.
155 */
156
157 #ifdef __STDC__
158
openout(char * name,Stat * asb,Link * linkp,int ispass)159 int openout(char *name, Stat *asb, Link *linkp, int ispass)
160
161 #else
162
163 int openout(name, asb, linkp, ispass)
164 char *name;
165 Stat *asb;
166 Link *linkp;
167 int ispass;
168
169 #endif
170 {
171 int exists;
172 int fd;
173 ushort perm;
174 ushort operm = 0;
175 Stat osb;
176 #ifdef S_IFLNK
177 int ssize;
178 char sname[PATH_MAX + 1];
179 #endif /* S_IFLNK */
180
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");
184 return (-1);
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());
189 return (-1);
190 } else {
191 exists = 0;
192 }
193 }
194 if (linkp) {
195 if (exists) {
196 if (asb->sb_ino == osb.sb_ino && asb->sb_dev == osb.sb_dev) {
197 return (0);
198 } else if (unlink(name) < 0) {
199 warn(name, strerror());
200 return (-1);
201 } else {
202 exists = 0;
203 }
204 }
205 if (link(linkp->l_name, name) != 0) {
206 if (errno == ENOENT) {
207 if (f_dir_create) {
208 if (dirneed(name) != 0 ||
209 link(linkp->l_name, name) != 0) {
210 warn(name, strerror());
211 return (-1);
212 }
213 } else {
214 warn(name,
215 "Directories are not being created (-d option)");
216 }
217 return(0);
218 } else if (errno != EXDEV) {
219 warn(name, strerror());
220 return (-1);
221 }
222 } else {
223 return(0);
224 }
225 }
226 perm = asb->sb_mode & S_IPERM;
227 switch (asb->sb_mode & S_IFMT) {
228 case S_IFBLK:
229 case S_IFCHR:
230 #ifdef _POSIX_SOURCE
231 warn(name, "Can't create special files");
232 return (-1);
233 #else
234 fd = 0;
235 if (exists) {
236 if (asb->sb_rdev == osb.sb_rdev) {
237 if (perm != operm && chmod(name, (int) perm) < 0) {
238 warn(name, strerror());
239 return (-1);
240 } else {
241 break;
242 }
243 } else if (REMOVE(name, &osb) < 0) {
244 warn(name, strerror());
245 return (-1);
246 } else {
247 exists = 0;
248 }
249 }
250 if (mknod(name, (int) asb->sb_mode, (int) asb->sb_rdev) < 0) {
251 if (errno == ENOENT) {
252 if (f_dir_create) {
253 if (dirneed(name) < 0 || mknod(name, (int) asb->sb_mode,
254 (int) asb->sb_rdev) < 0) {
255 warn(name, strerror());
256 return (-1);
257 }
258 } else {
259 warn(name, "Directories are not being created (-d option)");
260 }
261 } else {
262 warn(name, strerror());
263 return (-1);
264 }
265 }
266 return(0);
267 #endif /* _POSIX_SOURCE */
268 break;
269 case S_IFDIR:
270 if (exists) {
271 if (perm != operm && chmod(name, (int) perm) < 0) {
272 warn(name, strerror());
273 return (-1);
274 }
275 } else if (f_dir_create) {
276 if (dirmake(name, asb) < 0 || dirneed(name) < 0) {
277 warn(name, strerror());
278 return (-1);
279 }
280 } else {
281 warn(name, "Directories are not being created (-d option)");
282 }
283 return (0);
284 #ifndef _POSIX_SOURCE
285 #ifdef S_IFIFO
286 case S_IFIFO:
287 fd = 0;
288 if (exists) {
289 if (perm != operm && chmod(name, (int) perm) < 0) {
290 warn(name, strerror());
291 return (-1);
292 }
293 } else if (mknod(name, (int) asb->sb_mode, 0) < 0) {
294 if (errno == ENOENT) {
295 if (f_dir_create) {
296 if (dirneed(name) < 0
297 || mknod(name, (int) asb->sb_mode, 0) < 0) {
298 warn(name, strerror());
299 return (-1);
300 }
301 } else {
302 warn(name, "Directories are not being created (-d option)");
303 }
304 } else {
305 warn(name, strerror());
306 return (-1);
307 }
308 }
309 return(0);
310 break;
311 #endif /* S_IFIFO */
312 #endif /* _POSIX_SOURCE */
313 #ifdef S_IFLNK
314 case S_IFLNK:
315 if (exists) {
316 if ((ssize = readlink(name, sname, sizeof(sname))) < 0) {
317 warn(name, strerror());
318 return (-1);
319 } else if (strncmp(sname, asb->sb_link, ssize) == 0) {
320 return (0);
321 } else if (REMOVE(name, &osb) < 0) {
322 warn(name, strerror());
323 return (-1);
324 } else {
325 exists = 0;
326 }
327 }
328 if (symlink(asb->sb_link, name) < 0) {
329 if (errno == ENOENT) {
330 if (f_dir_create) {
331 if (dirneed(name) < 0 || symlink(asb->sb_link, name) < 0) {
332 warn(name, strerror());
333 return (-1);
334 }
335 } else {
336 warn(name, "Directories are not being created (-d option)");
337 }
338 } else {
339 warn(name, strerror());
340 return (-1);
341 }
342 }
343 return (0); /* Can't chown()/chmod() a symbolic link */
344 #endif /* S_IFLNK */
345 case S_IFREG:
346 if (exists) {
347 if (!f_unconditional && osb.sb_mtime > asb->sb_mtime) {
348 warn(name, "Newer file exists");
349 return (-1);
350 } else if (unlink(name) < 0) {
351 warn(name, strerror());
352 return (-1);
353 } else {
354 exists = 0;
355 }
356 }
357 if ((fd = creat(name, (int) perm)) < 0) {
358 if (errno == ENOENT) {
359 if (f_dir_create) {
360 if (dirneed(name) < 0 ||
361 (fd = creat(name, (int) perm)) < 0) {
362 warn(name, strerror());
363 return (-1);
364 }
365 } else {
366 /*
367 * the file requires a directory which does not exist
368 * and which the user does not want created, so skip
369 * the file...
370 */
371 warn(name, "Directories are not being created (-d option)");
372 return(0);
373 }
374 } else {
375 warn(name, strerror());
376 return (-1);
377 }
378 }
379 break;
380 default:
381 warn(name, "Unknown filetype");
382 return (-1);
383 }
384 if (f_owner) {
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);
387 }
388 }
389 return (fd);
390 }
391
392
393 /* openin - open the next input file
394 *
395 * DESCRIPTION
396 *
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.
405 *
406 * PARAMETERS
407 *
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
410 *
411 * RETURNS
412 *
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
415 * returning zero.
416 */
417
418 #ifdef __STDC__
419
openin(char * name,Stat * asb)420 int openin(char *name, Stat *asb)
421
422 #else
423
424 int openin(name, asb)
425 char *name; /* name of file to open */
426 Stat *asb; /* pointer to stat structure for file */
427
428 #endif
429 {
430 int fd;
431
432 switch (asb->sb_mode & S_IFMT) {
433 case S_IFDIR:
434 asb->sb_nlink = 1;
435 asb->sb_size = 0;
436 return (0);
437 #ifdef S_IFLNK
438 case S_IFLNK:
439 if ((asb->sb_size = readlink(name,
440 asb->sb_link, sizeof(asb->sb_link) - 1)) < 0) {
441 warn(name, strerror());
442 return(0);
443 }
444 asb->sb_link[asb->sb_size] = '\0';
445 return (0);
446 #endif /* S_IFLNK */
447 case S_IFREG:
448 if (asb->sb_size == 0) {
449 return (0);
450 }
451 if ((fd = open(name, O_RDONLY | O_BINARY)) < 0) {
452 warn(name, strerror());
453 }
454 return (fd);
455 default:
456 asb->sb_size = 0;
457 return (0);
458 }
459 }
460