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/create.c,v $
2
 *
3
 * $Revision: 1.3 $
4
 *
5
 * create.c - Create a tape archive. 
6
 *
7
 * DESCRIPTION
8
 *
9
 *	These functions are used to create/write and archive from an set of
10
 *	named files.
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:	create.c,v $
33
 * Revision 1.3  89/02/12  10:29:37  mark
34
 * Fixed misspelling of Replstr
35
 * 
36
 * Revision 1.2  89/02/12  10:04:17  mark
37
 * 1.2 release fixes
38
 * 
39
 * Revision 1.1  88/12/23  18:02:06  mark
40
 * Initial revision
41
 * 
42
 */
43
 
44
#ifndef lint
45
static char *ident = "$Id: create.c,v 1.3 89/02/12 10:29:37 mark Exp Locker: mark $";
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
 
55
/* Function Prototypes */
56
 
57
#ifdef __STDC__
58
 
59
static void writetar(char *, Stat *);
60
static void writecpio(char *, Stat *);
61
static char tartype(int);
62
 
63
#else /* !__STDC__ */
64
 
65
static void writetar();
66
static void writecpio();
67
static char tartype();
68
 
69
#endif /* __STDC__ */
70
 
71
 
72
/* create_archive - create a tar archive.
73
 *
74
 * DESCRIPTION
75
 *
76
 *	Create_archive is used as an entry point to both create and append
77
 *	archives.  Create archive goes through the files specified by the
78
 *	user and writes each one to the archive if it can.  Create_archive
79
 *	knows how to write both cpio and tar headers and the padding which
80
 *	is needed for each type of archive.
81
 *
82
 * RETURNS
83
 *
84
 *	Always returns 0
85
 */
86
 
87
#ifdef __STDC__
88
 
89
int create_archive(void)
90
 
91
#else
92
 
93
int create_archive()
94
 
95
#endif
96
{
97
    char            name[PATH_MAX + 1];
98
    Stat            sb;
99
    int             fd;
100
 
101
    while (name_next(name, &sb) != -1) {
102
	if ((fd = openin(name, &sb)) < 0) {
103
	    /* FIXME: pax wants to exit here??? */
104
	    continue;
105
	}
106
 
107
	if (rplhead != (Replstr *)NULL) {
108
	    rpl_name(name);
109
	    if (strlen(name) == 0) {
110
		continue;
111
	    }
112
	}
113
	if (get_disposition("add", name) || get_newname(name, sizeof(name))) {
114
	    /* skip file... */
115
	    if (fd) {
116
		close(fd);
117
	    }
118
	    continue;
119
	} 
120
 
121
	if (!f_link && sb.sb_nlink > 1) {
122
	    if (islink(name, &sb)) {
123
		sb.sb_size = 0;
124
	    }
125
	    linkto(name, &sb);
126
	}
127
	if (ar_format == TAR) {
128
	    writetar(name, &sb);
129
	} else {
130
	    writecpio(name, &sb);
131
	}
132
	if (fd) {
133
	    outdata(fd, name, sb.sb_size);
134
	}
135
	if (f_verbose) {
136
	    print_entry(name, &sb);
137
	}
138
    }
139
 
140
    write_eot();
141
    close_archive();
142
    return (0);
143
}
144
 
145
 
146
/* writetar - write a header block for a tar file
147
 *
148
 * DESCRIPTION
149
 *
150
 * 	Make a header block for the file name whose stat info is in st.  
151
 *	Return header pointer for success, NULL if the name is too long.
152
 *
153
 * 	The tar header block is structured as follows:
154
 *
155
 *		FIELD NAME	OFFSET		SIZE
156
 *      	-------------|---------------|------
157
 *		name		  0		100
158
 *		mode		100		  8
159
 *		uid		108		  8
160
 *		gid		116		  8
161
 *		size		124		 12
162
 *		mtime		136		 12
163
 *		chksum		148		  8
164
 *		typeflag	156		  1
165
 *		linkname	157		100
166
 *		magic		257		  6
167
 *		version		263		  2
168
 *		uname		265		 32
169
 *		gname		297		 32
170
 *		devmajor	329		  8
171
 *		devminor	337		  8
172
 *		prefix		345		155
173
 *
174
 * PARAMETERS
175
 *
176
 *	char	*name	- name of file to create a header block for
177
 *	Stat	*asb	- pointer to the stat structure for the named file
178
 *
179
 */
180
 
181
#ifdef __STDC__
182
 
183
static void writetar(char *name, Stat *asb)
184
 
185
#else
186
 
187
static void writetar(name, asb)
188
char           *name;
189
Stat           *asb;
190
 
191
#endif
192
{
193
    char	   *p;
194
    char           *prefix = (char *)NULL;
195
    int             i;
196
    int             sum;
197
    char            hdr[BLOCKSIZE];
198
    Link           *from;
199
 
200
    memset(hdr, 0, BLOCKSIZE);
201
    if (strlen(name) > 255) {
202
	warn(name, "name too long");
203
	return;
204
    }
205
 
206
    /* 
207
     * If the pathname is longer than TNAMLEN, but less than 255, then
208
     * we can split it up into the prefix and the filename.
209
     */
210
    if (strlen(name) > 100) {
211
	prefix = name;
212
	name += 155;
213
	while (name > prefix && *name != '/') {
214
	    name--;
215
	}
216
 
217
	/* no slash found....hmmm.... */
218
	if (name == prefix) {
219
	    warn(prefix, "Name too long");
220
	    return;
221
	}
222
	*name++ = '\0';
223
    }
224
 
225
#ifdef S_IFLNK
226
    if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
227
	strcpy(&hdr[157], asb->sb_link);
228
	asb->sb_size = 0;
229
    }
230
#endif
231
    strcpy(hdr, name);
232
    sprintf(&hdr[100], "%06o \0", asb->sb_mode & ~S_IFMT);
233
    sprintf(&hdr[108], "%06o \0", asb->sb_uid);
234
    sprintf(&hdr[116], "%06o \0", asb->sb_gid);
235
    sprintf(&hdr[124], "%011lo ", (long) asb->sb_size);
236
    sprintf(&hdr[136], "%011lo ", (long) asb->sb_mtime);
237
    strncpy(&hdr[148], "        ", 8);
238
    hdr[156] = tartype(asb->sb_mode);
239
    if (asb->sb_nlink > 1 && (from = linkfrom(name, asb)) != (Link *)NULL) {
240
	strcpy(&hdr[157], from->l_name);
241
	hdr[156] = LNKTYPE;
242
    }
243
    strcpy(&hdr[257], TMAGIC);
244
    strncpy(&hdr[263], TVERSION, 2);
245
    strcpy(&hdr[265], finduname((int) asb->sb_uid));
246
    strcpy(&hdr[297], findgname((int) asb->sb_gid));
247
    sprintf(&hdr[329], "%06o \0", major(asb->sb_rdev));
248
    sprintf(&hdr[337], "%06o \0", minor(asb->sb_rdev));
249
    if (prefix != (char *)NULL) {
250
	strncpy(&hdr[345], prefix, 155);
251
    }
252
 
253
    /* Calculate the checksum */
254
 
255
    sum = 0;
256
    p = hdr;
257
    for (i = 0; i < 500; i++) {
258
	sum += 0xFF & *p++;
259
    }
260
 
261
    /* Fill in the checksum field. */
262
 
263
    sprintf(&hdr[148], "%06o \0", sum);
264
 
265
    outwrite(hdr, BLOCKSIZE);
266
}
267
 
268
 
269
/* tartype - return tar file type from file mode
270
 *
271
 * DESCRIPTION
272
 *
273
 *	tartype returns the character which represents the type of file
274
 *	indicated by "mode". 
275
 *
276
 * PARAMETERS
277
 *
278
 *	int	mode	- file mode from a stat block
279
 *
280
 * RETURNS
281
 *
282
 *	The character which represents the particular file type in the 
283
 *	ustar standard headers.
284
 */
285
 
286
#ifdef __STDC__
287
 
288
static char tartype(int mode)
289
 
290
#else
291
 
292
static char tartype(mode)
293
int	    mode;
294
 
295
#endif
296
{
297
    switch (mode & S_IFMT) {
298
 
299
#ifdef S_IFCTG
300
    case S_IFCTG:
301
	return(CONTTYPE);
302
#endif
303
 
304
    case S_IFDIR:
305
	return (DIRTYPE);
306
 
307
#ifdef S_IFLNK
308
    case S_IFLNK:
309
	return (SYMTYPE);
310
#endif
311
 
312
#ifdef S_IFFIFO
313
    case S_IFIFO:
314
	return (FIFOTYPE);
315
#endif
316
 
317
#ifdef S_IFCHR
318
    case S_IFCHR:
319
	return (CHRTYPE);
320
#endif
321
 
322
#ifdef S_IFBLK
323
    case S_IFBLK:
324
	return (BLKTYPE);
325
#endif
326
 
327
    default:
328
	return (REGTYPE);
329
    }
330
}
331
 
332
 
333
/* writecpio - write a cpio archive header
334
 *
335
 * DESCRIPTION
336
 *
337
 *	Writes a new CPIO style archive header for the file specified.
338
 *
339
 * PARAMETERS
340
 *
341
 *	char	*name	- name of file to create a header block for
342
 *	Stat	*asb	- pointer to the stat structure for the named file
343
 */
344
 
345
#ifdef __STDC__
346
 
347
static void writecpio(char *name, Stat *asb)
348
 
349
#else
350
 
351
static void writecpio(name, asb)
352
char           *name;
353
Stat           *asb;
354
 
355
#endif
356
{
357
    uint            namelen;
358
    char            header[M_STRLEN + H_STRLEN + 1];
359
 
360
    namelen = (uint) strlen(name) + 1;
361
    strcpy(header, M_ASCII);
362
    sprintf(header + M_STRLEN, "%06o%06o%06o%06o%06o",
363
	    USH(asb->sb_dev), USH(asb->sb_ino), USH(asb->sb_mode), 
364
	    USH(asb->sb_uid), USH(asb->sb_gid));
365
    sprintf(header + M_STRLEN + 30, "%06o%06o%011lo%06o%011lo",
366
#ifdef _POSIX_SOURCE
367
	    USH(asb->sb_nlink), USH(0),
368
#else
369
	    USH(asb->sb_nlink), USH(asb->sb_rdev),
370
#endif
371
	    f_mtime ? asb->sb_mtime : time((time_t *) 0),
372
	    namelen, asb->sb_size);
373
    outwrite(header, M_STRLEN + H_STRLEN);
374
    outwrite(name, namelen);
375
#ifdef	S_IFLNK
376
    if ((asb->sb_mode & S_IFMT) == S_IFLNK) {
377
	outwrite(asb->sb_link, (uint) asb->sb_size);
378
    }
379
#endif	/* S_IFLNK */
380
}