Warning: Undefined variable $n in /usr/local/www/websvn.planix.org/include/diff_util.php on line 243

Warning: Undefined variable $n in /usr/local/www/websvn.planix.org/include/diff_util.php on line 247

Warning: Undefined variable $m in /usr/local/www/websvn.planix.org/include/diff_util.php on line 251
WebSVN – tendra.SVN – Diff – /branches/tendra5/src/tools/tcc/archive.c – Rev 5 and 6

Subversion Repositories tendra.SVN

Rev

Rev 5 | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 5 Rev 6
Line -... Line 1...
-
 
1
/*
-
 
2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
-
 
3
 * All rights reserved.
-
 
4
 *
-
 
5
 * Redistribution and use in source and binary forms, with or without
-
 
6
 * modification, are permitted provided that the following conditions are met:
-
 
7
 *
-
 
8
 * 1. Redistributions of source code must retain the above copyright notice,
-
 
9
 *    this list of conditions and the following disclaimer.
-
 
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
-
 
11
 *    this list of conditions and the following disclaimer in the documentation
-
 
12
 *    and/or other materials provided with the distribution.
-
 
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
-
 
14
 *    may be used to endorse or promote products derived from this software
-
 
15
 *    without specific, prior written permission.
-
 
16
 *
-
 
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
-
 
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
-
 
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-
 
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
-
 
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-
 
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-
 
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-
 
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-
 
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-
 
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-
 
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
 
28
 *
-
 
29
 * $Id$
-
 
30
 */
1
/*
31
/*
2
    		 Crown Copyright (c) 1997
32
    		 Crown Copyright (c) 1997
3
    
33
 
4
    This TenDRA(r) Computer Program is subject to Copyright
34
    This TenDRA(r) Computer Program is subject to Copyright
5
    owned by the United Kingdom Secretary of State for Defence
35
    owned by the United Kingdom Secretary of State for Defence
6
    acting through the Defence Evaluation and Research Agency
36
    acting through the Defence Evaluation and Research Agency
7
    (DERA).  It is made available to Recipients with a
37
    (DERA).  It is made available to Recipients with a
8
    royalty-free licence for its use, reproduction, transfer
38
    royalty-free licence for its use, reproduction, transfer
9
    to other parties and amendment for any purpose not excluding
39
    to other parties and amendment for any purpose not excluding
10
    product development provided that any such use et cetera
40
    product development provided that any such use et cetera
11
    shall be deemed to be acceptance of the following conditions:-
41
    shall be deemed to be acceptance of the following conditions:-
12
    
42
 
13
        (1) Its Recipients shall ensure that this Notice is
43
        (1) Its Recipients shall ensure that this Notice is
14
        reproduced upon any copies or amended versions of it;
44
        reproduced upon any copies or amended versions of it;
15
    
45
 
16
        (2) Any amended version of it shall be clearly marked to
46
        (2) Any amended version of it shall be clearly marked to
17
        show both the nature of and the organisation responsible
47
        show both the nature of and the organisation responsible
18
        for the relevant amendment or amendments;
48
        for the relevant amendment or amendments;
19
    
49
 
20
        (3) Its onward transfer from a recipient to another
50
        (3) Its onward transfer from a recipient to another
21
        party shall be deemed to be that party's acceptance of
51
        party shall be deemed to be that party's acceptance of
22
        these conditions;
52
        these conditions;
23
    
53
 
24
        (4) DERA gives no warranty or assurance as to its
54
        (4) DERA gives no warranty or assurance as to its
25
        quality or suitability for any purpose and DERA accepts
55
        quality or suitability for any purpose and DERA accepts
26
        no liability whatsoever in relation to any use to which
56
        no liability whatsoever in relation to any use to which
27
        it may be put.
57
        it may be put.
28
*/
58
*/
Line 34... Line 64...
34
#include "list.h"
64
#include "list.h"
35
#include "archive.h"
65
#include "archive.h"
36
#include "flags.h"
66
#include "flags.h"
37
#include "options.h"
67
#include "options.h"
38
#include "utility.h"
68
#include "utility.h"
124
	}
272
	}
125
    }
-
 
126
    IGNORE fclose ( g ) ;
-
 
127
    return ( 0 ) ;
-
 
128
}
-
 
129
 
-
 
130
 
-
 
131
/*
-
 
132
    CAT A FILE
-
 
133
 
-
 
134
    This routine copies the file named nm to the standard output.  It
-
 
135
    returns a nonzero value if an error occurs.
-
 
136
*/
-
 
137
 
-
 
138
int cat_file
-
 
139
    PROTO_N ( ( nm ) )
-
 
140
    PROTO_T ( char *nm )
-
 
141
{
-
 
142
    return ( write_file ( nm, "r", stdout ) ) ;
-
 
143
}
-
 
144
 
-
 
145
 
-
 
146
/*
-
 
147
    CREATE A DIRECTORY
-
 
148
 
-
 
149
    This routine creates a directory called nm, returning zero if it
-
 
150
    is successful.  Two alternative versions of the routine are provided.
-
 
151
    The first is POSIX compliant and uses mkdir and various mode
-
 
152
    constants from sys/stat.h.  The second raises an error - in this
-
 
153
    case the mkdir function should be implemented by an external call.
-
 
154
*/
-
 
155
 
-
 
156
int make_dir
-
 
157
    PROTO_N ( ( nm ) )
-
 
158
    PROTO_T ( char *nm )
-
 
159
{
-
 
160
    if ( dry_run ) return ( 0 ) ;
-
 
161
#if FS_STAT
-
 
162
    {
-
 
163
	mode_t m = ( mode_t ) ( S_IRWXU | S_IRWXG | S_IRWXO ) ;
-
 
164
	int e = mkdir ( nm, m ) ;
-
 
165
	return ( e ) ;
-
 
166
    }
-
 
167
#else
-
 
168
    {
-
 
169
	error ( INTERNAL, "Built-in mkdir function not implemented" ) ;
-
 
170
	return ( 1 ) ;
-
 
171
    }
-
 
172
#endif
-
 
173
}
-
 
174
 
-
 
175
 
-
 
176
/*
-
 
177
    MOVE A FILE
-
 
178
 
-
 
179
    This routine moves the file named from to the file named to,
-
 
180
    returning zero if it is successful.  Normally the files will be
-
 
181
    on different filesystems, so we can't always use rename.
-
 
182
*/
-
 
183
 
-
 
184
int move_file
-
 
185
    PROTO_N ( ( from, to ) )
-
 
186
    PROTO_T ( char *from X char *to )
-
 
187
{
-
 
188
    int e ;
-
 
189
    FILE *f ;
-
 
190
    if ( dry_run ) return ( 0 ) ;
-
 
191
    if ( streq ( from, to ) ) return ( 0 ) ;
-
 
192
#if FS_STAT
-
 
193
    if ( rename ( from, to ) == 0 ) return ( 0 ) ;
-
 
194
    if ( errno != EXDEV ) {
-
 
195
	error ( SERIOUS, "Can't rename '%s' to '%s'", from, to ) ;
-
 
196
	return ( 1 ) ;
-
 
197
    }
-
 
198
#endif
-
 
199
    f = fopen ( to, "wb" ) ;
-
 
200
    if ( f == null ) {
-
 
201
	error ( SERIOUS, "Can't open copy destination file, '%s'", to ) ;
-
 
202
	return ( 1 ) ;
-
 
203
    }
-
 
204
    e = write_file ( from, "rb", f ) ;
-
 
205
    IGNORE fclose ( f ) ;
-
 
206
    if ( e ) return ( e ) ;
-
 
207
    if ( remove ( from ) ) {
-
 
208
	error ( SERIOUS, "Can't remove source file, '%s'", from ) ;
-
 
209
	return ( 1 ) ;
-
 
210
    }
-
 
211
    return ( 0 ) ;
-
 
212
}
-
 
213
 
-
 
214
 
-
 
215
/*
-
 
216
    REMOVE A FILE
-
 
217
 
-
 
218
    This routine removes the file or directory named nm, returning zero
-
 
219
    if it is successful.  Two alternative versions of the routine are
-
 
220
    provided.  The first is POSIX compliant and uses stuff from
-
 
221
    sys/stat.h and dirent.h.  The second raises an error - in this case
-
 
222
    the remove function should be implemented by an external call.
-
 
223
*/
-
 
224
 
-
 
225
int remove_file
-
 
226
    PROTO_N ( ( nm ) )
-
 
227
    PROTO_T ( char *nm )
-
 
228
{
-
 
229
    if ( dry_run ) return ( 0 ) ;
-
 
230
#if FS_DIRENT
273
#if FS_DIRENT
231
    {
274
	{
232
	struct stat st ;
275
		struct stat st;
233
	int e = stat ( nm, &st ) ;
276
		int e = stat(nm, &st);
234
	if ( e != -1 ) {
277
		if (e != -1) {
235
	    mode_t m = ( mode_t ) st.st_mode ;
278
			mode_t m = (mode_t)st.st_mode;
236
	    if ( S_ISDIR ( m ) ) {
279
			if (S_ISDIR(m)) {
237
		DIR *d = opendir ( nm ) ;
280
				DIR *d = opendir(nm);
238
		if ( d == null ) {
281
				if (d == null) {
-
 
282
					e = 1;
-
 
283
				} else {
-
 
284
					char *p;
-
 
285
					struct dirent *t;
-
 
286
					char buff [1000];
-
 
287
					IGNORE sprintf(buff, "%s/", nm);
-
 
288
					p = buff + strlen(buff);
-
 
289
					while (t = readdir(d), t != null) {
-
 
290
						char *dnm = t->d_name;
-
 
291
						if (!streq(dnm, ".") &&
-
 
292
						    !streq(dnm, "..")) {
-
 
293
							IGNORE strcpy(p, dnm);
-
 
294
							if (remove_file(buff)) {
-
 
295
								e = 1;
-
 
296
							}
-
 
297
						}
-
 
298
					}
-
 
299
					IGNORE closedir(d);
-
 
300
					if (rmdir(nm)) {
239
		    e = 1 ;
301
						e = 1;
-
 
302
					}
-
 
303
				}
-
 
304
			} else {
-
 
305
				e = remove(nm);
-
 
306
			}
240
		} else {
307
		} else {
241
		    char *p ;
-
 
242
		    struct dirent *t ;
-
 
243
		    char buff [1000] ;
-
 
244
		    IGNORE sprintf ( buff, "%s/", nm ) ;
-
 
245
		    p = buff + strlen ( buff ) ;
-
 
246
		    while ( t = readdir ( d ), t != null ) {
308
			/* If the file didn't exist, don't worry */
247
			char *dnm = t->d_name ;
309
			if (errno == ENOENT) {
248
			if ( !streq ( dnm, "." ) && !streq ( dnm, ".." ) ) {
-
 
249
			    IGNORE strcpy ( p, dnm ) ;
310
				return (0);
250
			    if ( remove_file ( buff ) ) e = 1 ;
-
 
251
			}
311
			}
252
		    }
-
 
253
		    IGNORE closedir ( d ) ;
-
 
254
		    if ( rmdir ( nm ) ) e = 1 ;
-
 
255
		}
312
		}
256
	    } else {
313
		if (e) {
-
 
314
			error(SERIOUS, "Can't remove '%s'", nm);
257
		e = remove ( nm ) ;
315
			return (1);
258
	    }
316
		}
259
	} else {
317
		return (0);
260
	    /* If the file didn't exist, don't worry */
-
 
261
	    if ( errno == ENOENT ) return ( 0 ) ;
-
 
262
	}
318
	}
263
	if ( e ) {
319
#else
-
 
320
	{
264
	    error ( SERIOUS, "Can't remove '%s'", nm ) ;
321
		error(INTERNAL, "Built-in remove function not implemented");
265
	    return ( 1 ) ;
322
		return (1);
266
	}
323
	}
267
	return ( 0 ) ;
-
 
268
    }
-
 
269
#else
-
 
270
    {
-
 
271
	error ( INTERNAL, "Built-in remove function not implemented" ) ;
-
 
272
	return ( 1 ) ;
-
 
273
    }
-
 
274
#endif
324
#endif
275
}
325
}
276
 
326
 
277
 
327
 
278
/*
328
/*
279
    TOUCH A FILE
329
 * TOUCH A FILE
280
 
330
 *
281
    This routine touches the file called nm.  It returns 0 if it is
331
 * This routine touches the file called nm. It returns 0 if it is successful.
282
    successful.
-
 
283
*/
332
 */
284
 
333
 
285
int touch_file
334
int
286
    PROTO_N ( ( nm, opt ) )
-
 
287
    PROTO_T ( char *nm X char *opt )
335
touch_file(char *nm, char *opt)
288
{
336
{
289
    if ( !dry_run ) {
337
	if (!dry_run) {
290
	FILE *f = fopen ( nm, "w" ) ;
338
		FILE *f = fopen(nm, "w");
-
 
339
		if (f == null) {
291
	if ( f == null ) error ( SERIOUS, "Can't touch file, '%s'", nm ) ;
340
			error(SERIOUS, "Can't touch file, '%s'", nm);
-
 
341
		}
292
	if ( opt && streq ( opt, "-k" ) ) {
342
		if (opt && streq(opt, "-k")) {
293
	    /* This is an empty C spec file */
343
			/* This is an empty C spec file */
294
	    static unsigned char cs [] = {
344
			static unsigned char cs [] = {
295
		0x80
345
				0x80
296
	    } ;
346
			};
297
	    size_t s1 = sizeof ( cs [0] ) ;
347
			size_t s1 = sizeof(cs [0]);
298
	    size_t sn = ( size_t ) ( sizeof ( cs ) / s1 ) ;
348
			size_t sn = (size_t)(sizeof(cs) / s1);
299
	    IGNORE fwrite ( ( pointer ) cs, s1, sn, f ) ;
349
			IGNORE fwrite((pointer)cs, s1, sn, f);
300
	} else {
350
		} else {
301
	    IGNORE fputs ( "EMPTY\n", f ) ;
351
			IGNORE fputs("EMPTY\n", f);
-
 
352
		}
-
 
353
		IGNORE fclose(f);
302
	}
354
	}
303
	IGNORE fclose ( f ) ;
-
 
304
    }
-
 
305
    return ( 0 ) ;
355
	return (0);
306
}
356
}
307
 
357
 
308
 
358
 
309
/*
359
/*
310
    POOR MAN'S TEMPNAM FUNCTION
360
 * POOR MAN'S TEMPNAM FUNCTION
311
 
361
 *
312
    The token temporary_name can be defined to be either tempnam (which
362
 * The token temporary_name can be defined to be either tempnam (which is in
313
    is in XPG3 but not POSIX) or this routine, which is designed to serve
363
 * XPG3 but not POSIX) or this routine, which is designed to serve a similar
314
    a similar purpose.  The routine uses tmpnam (which is in ANSI) to
364
 * purpose. The routine uses tmpnam (which is in ANSI) to create a temporary
315
    create a temporary file name, and appends the suffix pfx to this name.
365
 * file name, and appends the suffix pfx to this name. The dir argument is not
316
    The dir argument is not used.
366
 * used.
317
*/
367
 */
318
 
368
 
319
#if !FS_TEMPNAM
369
#if !FS_TEMPNAM
320
 
370
 
321
char *like_tempnam
371
char *
322
    PROTO_N ( ( dir, pfx ) )
-
 
323
    PROTO_T ( char *dir X char *pfx ) /* ARGSUSED */
372
like_tempnam(char *dir, char *pfx) /* ARGSUSED */
324
{
373
{
325
    static char letter = 'a' ;
374
	static char letter = 'a';
326
    char *p = buffer ;
375
	char *p = buffer;
327
    UNUSED ( dir ) ;
376
	UNUSED(dir);
328
    IGNORE tmpnam ( p ) ;
377
	IGNORE tmpnam(p);
329
    p += strlen ( p ) ;
378
	p += strlen(p);
330
    p [0] = letter ;
379
	p [0] = letter;
331
    p [1] = '.' ;
380
	p [1] = '.';
332
    IGNORE strcpy ( p + 2, pfx ) ;
381
	IGNORE strcpy(p + 2, pfx);
333
    letter = ( char ) ( letter + 1 ) ;
382
	letter = (char)(letter + 1);
334
    return ( string_copy ( buffer ) ) ;
383
	return (string_copy(buffer));
335
}
384
}
336
 
-
 
337
#endif
-
 
338
 
-
 
339
 
-
 
340
 
-
 
341
/*
-
 
342
    FIND THE SIZE OF A FILE
-
 
343
 
-
 
344
    This routine calculates the length of a file, returning zero for
-
 
345
    non-existant files.  Two versions of the routine are provided.
-
 
346
    The first is POSIX compliant and uses stat from sys/stat.h to
-
 
347
    access the length directly.  The second just reads the file and
-
 
348
    counts the number of characters.
-
 
349
*/
-
 
350
 
385
 
351
long file_size
-
 
352
    PROTO_N ( ( nm ) )
-
 
353
    PROTO_T ( char *nm )
-
 
354
{
-
 
355
#if FS_STAT
-
 
356
    {
-
 
357
	struct stat st ;
-
 
358
	int e = stat ( nm, &st ) ;
-
 
359
	if ( e == -1 ) return ( 0 ) ;
-
 
360
	return ( ( long ) st.st_size ) ;
-
 
361
    }
-
 
362
#else
-
 
363
    {
-
 
364
	size_t n = 0, m ;
-
 
365
	pointer p = ( pointer ) buffer ;
-
 
366
	FILE *f = fopen ( nm, "rb" ) ;
-
 
367
	if ( f == null ) return ( 0 ) ;
-
 
368
	while ( m = fread ( p, sizeof ( char ), block_size, f ), m != 0 ) {
-
 
369
	    n = ( size_t ) ( n + m ) ;
-
 
370
	}
-
 
371
	IGNORE fclose ( f ) ;
-
 
372
	return ( ( long ) n ) ;
-
 
373
    }
-
 
374
#endif
386
#endif
375
}
-
 
376
 
387
 
377
 
388
 
378
 
389
 
379
/*
390
/*
380
    FIND THE DATE STAMP OF A FILE
391
 * FIND THE SIZE OF A FILE
381
 
392
 *
382
    This routine calculates the date stamp of a file.  If the target
393
 * This routine calculates the length of a file, returning zero for
383
    machine does not support stat, or this is a dry run, zero is always
394
 * non-existant files. Two versions of the routine are provided. The first is
-
 
395
 * POSIX compliant and uses stat from sys/stat.h to access the length directly.
384
    returned.
396
 * The second just reads the file and counts the number of characters.
385
*/
397
 */
386
 
398
 
387
static long file_time
399
long
388
    PROTO_N ( ( nm ) )
-
 
389
    PROTO_T ( char *nm )
400
file_size(char *nm)
390
{
401
{
391
#if FS_STAT
402
#if FS_STAT
392
    {
403
	{
393
	int e ;
-
 
394
	struct stat st ;
404
		struct stat st;
395
	if ( dry_run ) return ( 0 ) ;
-
 
396
	e = stat ( nm, &st ) ;
405
		int e = stat(nm, &st);
397
	if ( e == -1 ) {
406
		if (e == -1) {
398
	    error ( SERIOUS, "Can't access file '%s'", nm ) ;
-
 
399
	    return ( 0 ) ;
407
			return (0);
-
 
408
		}
-
 
409
		return ((long)st.st_size);
400
	}
410
	}
401
	return ( ( long ) st.st_mtime ) ;
-
 
402
    }
-
 
403
#else
411
#else
404
    {
412
	{
-
 
413
		size_t n = 0, m;
-
 
414
		pointer p = (pointer)buffer;
-
 
415
		FILE *f = fopen(nm, "rb");
405
	UNUSED ( nm ) ;
416
		if (f == null) {
406
	return ( 0 ) ;
417
			return (0);
407
    }
418
		}
-
 
419
		while (m = fread(p, sizeof(char), block_size, f), m != 0) {
-
 
420
			n = (size_t)(n + m);
-
 
421
		}
-
 
422
		IGNORE fclose(f);
-
 
423
		return ((long)n);
-
 
424
	}
408
#endif
425
#endif
409
}
426
}
-
 
427
 
410
 
428
 
411
 
429
 
412
/*
430
/*
-
 
431
 * FIND THE DATE STAMP OF A FILE
-
 
432
 *
-
 
433
 * This routine calculates the date stamp of a file. If the target machine
-
 
434
 * does not support stat, or this is a dry run, zero is always returned.
-
 
435
 */
-
 
436
 
-
 
437
static long
-
 
438
file_time(char *nm)
-
 
439
{
-
 
440
#if FS_STAT
-
 
441
	{
-
 
442
		int e;
-
 
443
		struct stat st;
-
 
444
		if (dry_run) {
-
 
445
			return (0);
-
 
446
		}
413
    ARCHIVE HEADER
447
		e = stat(nm, &st);
-
 
448
		if (e == -1) {
-
 
449
			error(SERIOUS, "Can't access file '%s'", nm);
-
 
450
			return (0);
-
 
451
		}
-
 
452
		return ((long)st.st_mtime);
-
 
453
	}
-
 
454
#else
-
 
455
	{
-
 
456
		UNUSED(nm);
-
 
457
		return (0);
-
 
458
	}
-
 
459
#endif
-
 
460
}
414
 
461
 
-
 
462
 
-
 
463
/*
-
 
464
 * ARCHIVE HEADER
-
 
465
 *
415
    A TDF archive always starts with ARCHIVE_HEADER, and the main part
466
 * A TDF archive always starts with ARCHIVE_HEADER, and the main part of the
416
    of the archive ends with ARCHIVE_TRAILER.
467
 * archive ends with ARCHIVE_TRAILER.
417
*/
468
 */
418
 
469
 
419
#define ARCHIVE_HEADER		"!TDF\n"
470
#define ARCHIVE_HEADER		"!TDF\n"
420
#define ARCHIVE_TRAILER		"-\n"
471
#define ARCHIVE_TRAILER		"-\n"
421
 
472
 
422
 
473
 
423
/*
474
/*
424
    IS A FILE AN ARCHIVE?
475
 * IS A FILE AN ARCHIVE?
-
 
476
 *
-
 
477
 * This routine returns 1 if the file named nm starts with ARCHIVE_HEADER (and
-
 
478
 * so is probably an archive), and 0 otherwise.
-
 
479
 */
425
 
480
 
426
    This routine returns 1 if the file named nm starts with ARCHIVE_HEADER
-
 
427
    (and so is probably an archive), and 0 otherwise.
-
 
428
*/
-
 
429
 
-
 
430
boolean is_archive
481
boolean
431
    PROTO_N ( ( nm ) )
-
 
432
    PROTO_T ( char *nm )
482
is_archive(char *nm)
433
{
-
 
434
    boolean b = 0 ;
-
 
435
    FILE *f = fopen ( nm, "rb" ) ;
-
 
436
    if ( f == null ) return ( b ) ;
-
 
437
    if ( fgets ( buffer, 20, f ) && streq ( buffer, ARCHIVE_HEADER ) ) {
-
 
438
	b = 1 ;
-
 
439
    }
-
 
440
    IGNORE fclose ( f ) ;
-
 
441
    return ( b ) ;
-
 
442
}
-
 
443
 
-
 
444
 
-
 
445
/*
-
 
446
    ARCHIVE FLAGS
-
 
447
 
-
 
448
    These flags control the output of the file names and options in the
-
 
449
    output TDF archive.
-
 
450
*/
-
 
451
 
-
 
452
int archive_type = TDF_ARCHIVE ;
-
 
453
static boolean archive_full = 1 ;
-
 
454
static boolean archive_links = 0 ;
-
 
455
static boolean archive_names = 1 ;
-
 
456
static boolean archive_options = 1 ;
-
 
457
 
-
 
458
 
-
 
459
/*
-
 
460
    PROCESS ARCHIVE OPTIONS
-
 
461
 
-
 
462
    This routine processes any outstanding archive options.
-
 
463
*/
-
 
464
 
-
 
465
void process_archive_opt
-
 
466
    PROTO_Z ()
-
 
467
{
483
{
468
    list *p ;
484
	boolean b = 0;
469
    for ( p = opt_joiner ; p != null ; p = p->next ) {
-
 
470
	char *opt = p->item ;
485
	FILE *f = fopen(nm, "rb");
471
	if ( streq ( opt, "-copy" ) || streq ( opt, "-c" ) ) {
-
 
472
	    archive_links = 0 ;
-
 
473
	    link_specs = 0 ;
-
 
474
	} else if ( streq ( opt, "-full" ) || streq ( opt, "-f" ) ) {
-
 
475
	    archive_full = 1 ;
-
 
476
	} else if ( streq ( opt, "-link" ) || streq ( opt, "-l" ) ) {
-
 
477
	    archive_links = 1 ;
-
 
478
	    link_specs = 1 ;
-
 
479
	} else if ( streq ( opt, "-names" ) || streq ( opt, "-n" ) ) {
-
 
480
	    archive_names = 1 ;
-
 
481
	} else if ( streq ( opt, "-no_names" ) || streq ( opt, "-nn" ) ) {
-
 
482
	    archive_names = 0 ;
-
 
483
	} else if ( streq ( opt, "-no_options" ) || streq ( opt, "-no" ) ) {
-
 
484
	    archive_options = 0 ;
-
 
485
	} else if ( streq ( opt, "-options" ) || streq ( opt, "-o" ) ) {
-
 
486
	    archive_options = 1 ;
-
 
487
	} else if ( streq ( opt, "-short" ) || streq ( opt, "-s" ) ) {
-
 
488
	    archive_full = 0 ;
486
	if (f == null) {
489
	} else {
487
		return (b);
490
	    error ( WARNING, "Unknown archiver option, '%s'", opt ) ;
-
 
491
	}
488
	}
-
 
489
	if (fgets(buffer, 20, f) && streq(buffer, ARCHIVE_HEADER)) {
492
    }
490
		b = 1;
-
 
491
	}
493
    opt_joiner = null ;
492
	IGNORE fclose(f);
494
    return ;
493
	return (b);
495
}
494
}
496
 
495
 
497
 
496
 
498
/*
497
/*
-
 
498
 * ARCHIVE FLAGS
-
 
499
 *
-
 
500
 * These flags control the output of the file names and options in the output
-
 
501
 * TDF archive.
-
 
502
 */
-
 
503
 
499
    BUILD AN ARCHIVE
504
int archive_type = TDF_ARCHIVE;
-
 
505
static boolean archive_full = 1;
-
 
506
static boolean archive_links = 0;
-
 
507
static boolean archive_names = 1;
-
 
508
static boolean archive_options = 1;
500
 
509
 
501
    This routine creates a TDF archive called arch from the null-terminated
-
 
502
    list of files and options, input.  The string ARCHIVE_OPTION_START is
-
 
503
    uses to indicate the end of the files and the beginning of the options.
-
 
504
    The routine returns zero if it is successful.
-
 
505
*/
-
 
506
 
510
 
-
 
511
/*
507
int build_archive
512
 * PROCESS ARCHIVE OPTIONS
-
 
513
 *
508
    PROTO_N ( ( arch, input ) )
514
 * This routine processes any outstanding archive options.
-
 
515
 */
-
 
516
 
-
 
517
void
509
    PROTO_T ( char *arch X char **input )
518
process_archive_opt(void)
510
{
519
{
-
 
520
	list *p;
-
 
521
	for (p = opt_joiner; p != null; p = p->next) {
-
 
522
		char *opt = p->item;
-
 
523
		if (streq(opt, "-copy") || streq(opt, "-c")) {
-
 
524
			archive_links = 0;
-
 
525
			link_specs = 0;
-
 
526
		} else if (streq(opt, "-full") || streq(opt, "-f")) {
-
 
527
			archive_full = 1;
-
 
528
		} else if (streq(opt, "-link") || streq(opt, "-l")) {
-
 
529
			archive_links = 1;
-
 
530
			link_specs = 1;
-
 
531
		} else if (streq(opt, "-names") || streq(opt, "-n")) {
-
 
532
			archive_names = 1;
-
 
533
		} else if (streq(opt, "-no_names") || streq(opt, "-nn")) {
-
 
534
			archive_names = 0;
-
 
535
		} else if (streq(opt, "-no_options") || streq(opt, "-no")) {
-
 
536
			archive_options = 0;
-
 
537
		} else if (streq(opt, "-options") || streq(opt, "-o")) {
-
 
538
			archive_options = 1;
-
 
539
		} else if (streq(opt, "-short") || streq(opt, "-s")) {
-
 
540
			archive_full = 0;
-
 
541
		} else {
-
 
542
			error(WARNING, "Unknown archiver option, '%s'", opt);
-
 
543
		}
-
 
544
	}
-
 
545
	opt_joiner = null;
-
 
546
	return;
-
 
547
}
-
 
548
 
-
 
549
 
-
 
550
/*
-
 
551
 * BUILD AN ARCHIVE
-
 
552
 *
-
 
553
 * This routine creates a TDF archive called arch from the null-terminated list
-
 
554
 * of files and options, input. The string ARCHIVE_OPTION_START is uses to
-
 
555
 * indicate the end of the files and the beginning of the options. The routine
-
 
556
 * returns zero if it is successful.
-
 
557
 */
-
 
558
 
-
 
559
int
-
 
560
build_archive(char *arch, char **input)
-
 
561
{
511
    FILE *f ;
562
    FILE *f;
512
    char **s ;
563
    char **s;
513
    boolean end = 0 ;
564
    boolean end = 0;
514
    if ( dry_run ) return ( 0 ) ;
565
    if (dry_run) {
-
 
566
	    return (0);
-
 
567
    }
515
    f = fopen ( arch, "wb" ) ;
568
    f = fopen(arch, "wb");
516
    if ( f == null ) {
569
    if (f == null) {
517
	error ( SERIOUS, "Can't open output archive, '%s'", arch ) ;
570
	error(SERIOUS, "Can't open output archive, '%s'", arch);
518
	return ( 1 ) ;
571
	return (1);
519
    }
572
    }
520
    IGNORE fputs ( ARCHIVE_HEADER, f ) ;
573
    IGNORE fputs(ARCHIVE_HEADER, f);
521
    for ( s = input ; *s ; s++ ) {
574
    for (s = input; *s; s++) {
522
	if ( end ) {
575
	if (end) {
523
	    /* Archive options */
576
	    /* Archive options */
524
	    if ( archive_options ) {
577
	    if (archive_options) {
525
		if ( verbose ) {
578
		if (verbose) {
526
		    comment ( 1, "... archive option %s\n", *s ) ;
579
		    comment(1, "... archive option %s\n", *s);
527
		}
580
		}
528
		IGNORE fprintf ( f, "%s\n", *s ) ;
581
		IGNORE fprintf(f, "%s\n", *s);
529
	    }
582
	    }
530
	} else if ( streq ( *s, ARCHIVE_OPTION_START ) ) {
583
	} else if (streq(*s, ARCHIVE_OPTION_START)) {
531
	    /* Start of archive options */
584
	    /* Start of archive options */
532
	    IGNORE fputs ( ARCHIVE_TRAILER, f ) ;
585
	    IGNORE fputs(ARCHIVE_TRAILER, f);
533
	    end = 1 ;
586
	    end = 1;
534
	} else if ( archive_links && archive_type != TDF_ARCHIVE ) {
587
	} else if (archive_links && archive_type != TDF_ARCHIVE) {
535
	    /* Archive file - link */
588
	    /* Archive file - link */
536
	    char *ln = *s ;
589
	    char *ln = *s;
537
	    if ( verbose ) {
590
	    if (verbose) {
538
		comment ( 1, "... archive file %s (link)\n", ln ) ;
591
		comment(1, "... archive file %s (link)\n", ln);
539
	    }
592
	    }
-
 
593
	    if (archive_full) {
540
	    if ( archive_full ) ln = find_fullname ( ln ) ;
594
		    ln = find_fullname(ln);
-
 
595
	    }
541
	    IGNORE fprintf ( f, "> %ld %s\n", file_time ( ln ), ln ) ;
596
	    IGNORE fprintf(f, "> %ld %s\n", file_time(ln), ln);
542
	} else {
597
	} else {
543
	    /* Archive file - copy */
598
	    /* Archive file - copy */
544
	    FILE *g ;
599
	    FILE *g;
545
	    char *n = find_basename ( *s ) ;
600
	    char *n = find_basename(*s);
546
	    if ( !archive_names ) {
601
	    if (!archive_names) {
547
		int i, m = ( int ) strlen ( n ) ;
602
		int i, m = (int)strlen(n);
548
		buffer [0] = '*' ;
603
		buffer [0] = '*';
549
		buffer [1] = 0 ;
604
		buffer [1] = 0;
550
		for ( i = m - 1 ; i >= 0 ; i-- ) {
605
		for (i = m - 1; i >= 0; i--) {
551
		    if ( n [i] == '.' ) {
606
		    if (n [i] == '.') {
552
			IGNORE strcpy ( buffer + 1, n + i ) ;
607
			IGNORE strcpy(buffer + 1, n + i);
553
			break ;
608
			break;
554
		    }
609
		    }
555
		}
610
		}
556
		n = buffer ;
611
		n = buffer;
557
	    }
612
	    }
-
 
613
	    if (verbose) {
558
	    if ( verbose ) comment ( 1, "... archive file %s\n", *s ) ;
614
		    comment(1, "... archive file %s\n", *s);
-
 
615
	    }
559
	    g = fopen ( *s, "rb" ) ;
616
	    g = fopen(*s, "rb");
560
	    if ( g == null ) {
617
	    if (g == null) {
561
		error ( SERIOUS, "Can't open '%s' for archiving", *s ) ;
618
		error(SERIOUS, "Can't open '%s' for archiving", *s);
562
		IGNORE fclose ( f ) ;
619
		IGNORE fclose(f);
563
		return ( 1 ) ;
620
		return (1);
564
	    } else {
621
	    } else {
565
		pointer p = ( pointer ) buffer ;
622
		pointer p = (pointer)buffer;
566
		size_t m = fread ( p, sizeof ( char ), ( size_t ) block_size, g ) ;
623
		size_t m = fread(p, sizeof(char), (size_t)block_size, g);
567
		IGNORE fprintf ( f, "+ %ld %s\n", ( long ) m, n ) ;
624
		IGNORE fprintf(f, "+ %ld %s\n",(long)m, n);
568
		while ( m ) {
625
		while (m) {
569
		    if ( fwrite ( p, sizeof ( char ), m, f ) != m ) {
626
		    if (fwrite(p, sizeof(char), m, f)!= m) {
570
			error ( SERIOUS, "Write error in archive '%s'", arch ) ;
627
			error(SERIOUS, "Write error in archive '%s'", arch);
571
			IGNORE fclose ( f ) ;
628
			IGNORE fclose(f);
572
			return ( 1 ) ;
629
			return (1);
573
		    }
630
		    }
574
		    m = fread ( p, sizeof ( char ), ( size_t ) block_size, g ) ;
631
		    m = fread(p, sizeof(char), (size_t)block_size, g);
-
 
632
		    if (m) {
575
		    if ( m ) IGNORE fprintf ( f, "+ %ld +\n", ( long ) m ) ;
633
			    IGNORE fprintf(f, "+ %ld +\n", (long)m);
-
 
634
		    }
576
		}
635
		}
577
		IGNORE fclose ( g ) ;
636
		IGNORE fclose(g);
578
	    }
637
	    }
579
	}
638
	}
-
 
639
    }
-
 
640
    if (!end) {
-
 
641
	    IGNORE fputs(ARCHIVE_TRAILER, f);
580
    }
642
    }
581
    if ( !end ) IGNORE fputs ( ARCHIVE_TRAILER, f ) ;
-
 
582
    IGNORE fclose ( f ) ;
643
    IGNORE fclose(f);
583
    return ( 0 ) ;
644
    return (0);
584
}
645
}
585
 
646
 
586
 
647
 
587
/*
648
/*
588
    SPLIT AN ARCHIVE
649
 * SPLIT AN ARCHIVE
589
 
650
 *
590
    This routine splits the TDF archive named arch into it consistuent
651
 * This routine splits the TDF archive named arch into it consistuent
591
    components.  Any files from the archive are stored in the location
652
 * components. Any files from the archive are stored in the location indicated
592
    indicated by ret.  The routine returns zero if it is successful.
653
 * by ret. The routine returns zero if it is successful.
593
*/
654
 */
594
 
655
 
595
int split_archive
656
int
596
    PROTO_N ( ( arch, ret ) )
-
 
597
    PROTO_T ( char *arch X filename **ret )
657
split_archive(char *arch, filename **ret)
598
{
658
{
599
    boolean go = 1 ;
659
    boolean go = 1;
600
    char *emsg = null ;
660
    char *emsg = null;
601
    list *opts = null ;
661
    list *opts = null;
602
    filename *q = null ;
662
    filename *q = null;
603
    filename *output = null ;
663
    filename *output = null;
604
    boolean need_moves = 0 ;
664
    boolean need_moves = 0;
605
 
665
 
606
    /* Open archive file */
666
    /* Open archive file */
607
    FILE *f = fopen ( arch, "rb" ) ;
667
    FILE *f = fopen(arch, "rb");
608
    if ( f == null ) {
668
    if (f == null) {
609
	emsg = "Can't open input archive, '%s'" ;
669
	emsg = "Can't open input archive, '%s'";
610
	goto archive_error ;
670
	goto archive_error;
611
    }
671
    }
612
 
672
 
613
    /* Check for archive header */
673
    /* Check for archive header */
614
    if ( fgets ( buffer, buffer_size, f ) == null ||
674
    if (fgets(buffer, buffer_size, f) == null ||
615
	 !streq ( buffer, ARCHIVE_HEADER ) ) {
675
	 !streq(buffer, ARCHIVE_HEADER)) {
616
	emsg = "Illegal input archive, '%s'" ;
676
	emsg = "Illegal input archive, '%s'";
617
	goto archive_error ;
677
	goto archive_error;
618
    }
678
    }
619
 
679
 
620
    /* Extract archived files */
680
    /* Extract archived files */
621
    do {
681
    do {
622
	if ( fgets ( buffer, buffer_size, f ) == null ) {
682
	if (fgets(buffer, buffer_size, f) == null) {
623
	    emsg = "Premature end of archive '%s'" ;
683
	    emsg = "Premature end of archive '%s'";
624
	    goto archive_error ;
684
	    goto archive_error;
625
	}
685
	}
626
	if ( buffer [0] == '+' && buffer [1] == ' ' ) {
686
	if (buffer [0] == '+' && buffer [1] == ' ') {
627
	    /* Archived file - copy */
687
	    /* Archived file - copy */
628
	    char c ;
688
	    char c;
629
	    long n = 0 ;
689
	    long n = 0;
630
	    char *w = "wb" ;
690
	    char *w = "wb";
631
	    char *p = buffer + 2 ;
691
	    char *p = buffer + 2;
632
	    int m = ( int ) strlen ( buffer ) - 1 ;
692
	    int m = (int)strlen(buffer) - 1;
633
	    if ( buffer [m] == '\n' ) buffer [m] = 0 ;
693
	    if (buffer [m] == '\n') {
-
 
694
		    buffer [m] = 0;
-
 
695
	    }
634
	    while ( c = *( p++ ), c != ' ' ) {
696
	    while (c = *(p++), c != ' ') {
635
		if ( c < '0' || c > '9' ) {
697
		if (c < '0' || c > '9') {
636
		    emsg = "Illegal file length specifier in archive '%s'" ;
698
		    emsg = "Illegal file length specifier in archive '%s'";
637
		    goto archive_error ;
699
		    goto archive_error;
638
		}
700
		}
639
		n = 10 * n + ( c - '0' ) ;
701
		n = 10 * n + (c - '0');
640
	    }
702
	    }
641
	    if ( streq ( p, "+" ) ) {
703
	    if (streq(p, "+")) {
642
		/* File continuations */
704
		/* File continuations */
643
		if ( q == null ) {
705
		if (q == null) {
644
		    emsg = "Illegal file continuation in archive '%s'" ;
706
		    emsg = "Illegal file continuation in archive '%s'";
645
		    goto archive_error ;
707
		    goto archive_error;
646
		}
708
		}
647
		w = "ab" ;
709
		w = "ab";
648
	    } else {
710
	    } else {
649
		filename *qo = q ;
711
		filename *qo = q;
650
		if ( streq ( p, "*" ) ) {
712
		if (streq(p, "*")) {
651
		    /* Old form hidden names */
713
		    /* Old form hidden names */
652
		    int k = where ( INDEP_TDF ) ;
714
		    int k = where(INDEP_TDF);
653
		    q = make_filename ( no_filename, INDEP_TDF, k ) ;
715
		    q = make_filename(no_filename, INDEP_TDF, k);
654
		} else if ( strneq ( p, "*.", 2 ) ) {
716
		} else if (strneq(p, "*.", 2)) {
655
		    /* New form hidden names */
717
		    /* New form hidden names */
656
		    int t ;
718
		    int t;
657
		    p = string_copy ( p ) ;
719
		    p = string_copy(p);
658
		    q = find_filename ( p, UNKNOWN_TYPE ) ;
720
		    q = find_filename(p, UNKNOWN_TYPE);
659
		    t = q->type ;
721
		    t = q->type;
660
		    q = make_filename ( no_filename, t, where ( t ) ) ;
722
		    q = make_filename(no_filename, t, where(t));
661
		} else {
723
		} else {
662
		    /* Unhidden names */
724
		    /* Unhidden names */
663
		    p = string_copy ( p ) ;
725
		    p = string_copy(p);
664
		    q = find_filename ( p, UNKNOWN_TYPE ) ;
726
		    q = find_filename(p, UNKNOWN_TYPE);
665
		    q = make_filename ( q, q->type, where ( q->type ) ) ;
727
		    q = make_filename(q, q->type, where(q->type));
666
		}
728
		}
667
		if ( archive_type != TDF_ARCHIVE && qo ) q->uniq = qo->uniq ;
729
		if (archive_type != TDF_ARCHIVE && qo) {
-
 
730
			q->uniq = qo->uniq;
-
 
731
		}
668
		if ( q->type == archive_type && q->storage != TEMP_FILE ) {
732
		if (q->type == archive_type && q->storage != TEMP_FILE) {
669
		    filename *qn = make_filename ( q, q->type, TEMP_FILE ) ;
733
		    filename *qn = make_filename(q, q->type, TEMP_FILE);
670
		    qn->aux = q ;
734
		    qn->aux = q;
671
		    qn->uniq = q->uniq ;
735
		    qn->uniq = q->uniq;
672
		    q = qn ;
736
		    q = qn;
673
		    need_moves = 1 ;
737
		    need_moves = 1;
674
		}
738
		}
675
		output = add_filename ( output, q ) ;
739
		output = add_filename(output, q);
676
		if ( verbose ) {
740
		if (verbose) {
677
		    comment ( 1, "... extract file %s\n", q->name ) ;
741
		    comment(1, "... extract file %s\n", q->name);
678
		}
742
		}
679
	    }
743
	    }
680
	    if ( read_file ( q->name, w, n, f ) ) {
744
	    if (read_file(q->name, w, n, f)) {
681
		emsg = "Read error in archive '%s'" ;
745
		emsg = "Read error in archive '%s'";
682
		goto archive_error ;
746
		goto archive_error;
683
	    }
747
	    }
684
	} else if ( buffer [0] == '>' && buffer [1] == ' ' ) {
748
	} else if (buffer [0] == '>' && buffer [1] == ' ') {
685
	    /* Archived file - link */
749
	    /* Archived file - link */
686
	    char c ;
750
	    char c;
687
	    long ad = 0, fd ;
751
	    long ad = 0, fd;
688
	    filename *qo = q ;
752
	    filename *qo = q;
689
	    char *p = buffer + 2 ;
753
	    char *p = buffer + 2;
690
	    int m = ( int ) strlen ( buffer ) - 1 ;
754
	    int m = (int)strlen(buffer) - 1;
691
	    if ( buffer [m] == '\n' ) buffer [m] = 0 ;
755
	    if (buffer [m] == '\n') {
-
 
756
		    buffer [m] = 0;
-
 
757
	    }
692
	    while ( c = *( p++ ), c != ' ' ) {
758
	    while (c = *(p++), c != ' ') {
693
		if ( c < '0' || c > '9' ) {
759
		if (c < '0' || c > '9') {
694
		    emsg = "Illegal link information in archive '%s'" ;
760
		    emsg = "Illegal link information in archive '%s'";
695
		    goto archive_error ;
761
		    goto archive_error;
696
		}
762
		}
697
		ad = 10 * ad + ( c - '0' ) ;
763
		ad = 10 * ad + (c - '0');
-
 
764
	    }
-
 
765
	    q = find_filename(string_copy(p), UNKNOWN_TYPE);
-
 
766
	    q->storage = PRESERVED_FILE;
-
 
767
	    if (archive_type != TDF_ARCHIVE && qo) {
-
 
768
		    q->uniq = qo->uniq;
698
	    }
769
	    }
699
	    q = find_filename ( string_copy ( p ), UNKNOWN_TYPE ) ;
-
 
700
	    q->storage = PRESERVED_FILE ;
-
 
701
	    if ( archive_type != TDF_ARCHIVE && qo ) q->uniq = qo->uniq ;
-
 
702
	    output = add_filename ( output, q ) ;
770
	    output = add_filename(output, q);
703
	    if ( verbose ) {
771
	    if (verbose) {
704
		comment ( 1, "... extract file %s (link)\n", q->name ) ;
772
		comment(1, "... extract file %s (link)\n", q->name);
705
	    }
773
	    }
706
	    fd = file_time ( q->name ) ;
774
	    fd = file_time(q->name);
707
	    if ( ad && fd && ad != fd ) {
775
	    if (ad && fd && ad != fd) {
708
		error ( WARNING, "Date stamp on file '%s' has changed",
776
		error(WARNING, "Date stamp on file '%s' has changed",
709
			q->name ) ;
777
			q->name);
710
	    }
778
	    }
711
	} else if ( streq ( buffer, ARCHIVE_TRAILER ) ) {
779
	} else if (streq(buffer, ARCHIVE_TRAILER)) {
712
	    /* Archived options */
780
	    /* Archived options */
713
	    char *p ;
781
	    char *p;
714
	    int c, m ;
782
	    int c, m;
715
	    while ( c = getc ( f ), c != EOF ) {
783
	    while (c = getc(f), c != EOF) {
716
		buffer [0] = ( char ) c ;
784
		buffer [0] = (char)c;
717
		if ( fgets ( buffer + 1, buffer_size - 1, f ) == null ) {
785
		if (fgets(buffer + 1, buffer_size - 1, f) == null) {
718
		    emsg = "Premature end of archive '%s'" ;
786
		    emsg = "Premature end of archive '%s'";
719
		    goto archive_error ;
787
		    goto archive_error;
720
		}
788
		}
721
		m = ( int ) strlen ( buffer ) - 1 ;
789
		m = (int)strlen(buffer) - 1;
722
		if ( buffer [m] == '\n' ) buffer [m] = 0 ;
790
		if (buffer [m] == '\n') {
-
 
791
			buffer [m] = 0;
-
 
792
		}
723
		p = string_copy ( buffer ) ;
793
		p = string_copy(buffer);
-
 
794
		if (verbose) {
724
		if ( verbose ) comment ( 1, "... extract option %s\n", p ) ;
795
			comment(1, "... extract option %s\n", p);
-
 
796
		}
725
		opts = add_item ( opts, p ) ;
797
		opts = add_item(opts, p);
726
	    }
798
	    }
727
	    go = 0 ;
799
	    go = 0;
728
	} else {
800
	} else {
729
	    emsg = "Illegal file description in archive '%s'" ;
801
	    emsg = "Illegal file description in archive '%s'";
730
	    goto archive_error ;
802
	    goto archive_error;
731
	}
803
	}
732
    } while ( go ) ;
804
    } while (go);
733
 
805
 
734
    /* Return */
806
    /* Return */
735
    archive_error : {
807
archive_error:
-
 
808
    if (emsg) {
736
	if ( emsg ) error ( SERIOUS, emsg, arch ) ;
809
	    error(SERIOUS, emsg, arch);
-
 
810
    }
737
	IGNORE fclose ( f ) ;
811
    IGNORE fclose(f);
738
	if ( need_moves ) {
812
    if (need_moves) {
739
	    for ( q = output ; q != null ; q = q->next ) {
813
	    for (q = output; q != null; q = q->next) {
740
		if ( q->aux && keeps_aux [ archive_type ] ) {
814
		    if (q->aux && keeps_aux [ archive_type ]) {
741
		    if ( verbose ) {
815
			    if (verbose) {
742
			comment ( 1, "... rename %s to %s\n", q->name,
816
				    comment(1, "... rename %s to %s\n",
743
				  q->aux->name ) ;
817
					    q->name, q->aux->name);
744
		    }
818
			    }
745
		    if ( move_file ( q->name, q->aux->name ) ) {
819
			    if (move_file(q->name, q->aux->name)) {
746
			emsg = "rhubarb" ;
820
				    emsg = "rhubarb";
747
		    } else {
821
			    } else {
748
			q->name = q->aux->name ;
822
				    q->name = q->aux->name;
749
			q->storage = q->aux->storage ;
823
				    q->storage = q->aux->storage;
-
 
824
			    }
750
		    }
825
		    }
751
		}
-
 
752
		q->aux = null ;
826
		    q->aux = null;
753
	    }
827
	    }
754
	}
-
 
755
	*ret = output ;
-
 
756
	if ( opts ) {
-
 
757
	    process_options ( opts, main_optmap ) ;
-
 
758
	    opt_archive = add_list ( opt_archive, opts ) ;
-
 
759
	}
-
 
760
	if ( emsg ) return ( 1 ) ;
-
 
761
	return ( 0 ) ;
-
 
762
    }
828
    }
-
 
829
    *ret = output;
-
 
830
    if (opts) {
-
 
831
	    process_options(opts, main_optmap, 0);
-
 
832
	    opt_archive = add_list(opt_archive, opts);
-
 
833
    }
-
 
834
    if (emsg) {
-
 
835
	    return (1);
-
 
836
    }
-
 
837
    return (0);
763
}
838
}