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