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