Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 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
 
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
 
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
 
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
 
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
}