1 /*
2  * Copyright (c) 2003 Regents of The University of Michigan.
3  * All Rights Reserved.  See COPYRIGHT.
4  */
5 
6 #include "config.h"
7 
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <sys/param.h>
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <unistd.h>
17 
18 #include "argcargv.h"
19 #include "code.h"
20 #include "mkdirs.h"
21 #include "pathcmp.h"
22 #include "root.h"
23 
24 int		cksum = 1;
25 int		verbose = 0;
26 int		noupload = 0;
27 int		case_sensitive = 1;
28 extern char   	*version;
29 
30 struct node {
31     char                path[ MAXPATHLEN ];
32     struct node         *next;
33 };
34 
35 struct node* create_node( char *path );
36 void free_node( struct node *node );
37 
38    struct node *
create_node(char * path)39 create_node( char *path )
40 {
41     struct node         *new_node;
42 
43     if (( new_node = (struct node *) malloc( sizeof( struct node ))) == NULL ) {
44 	perror( "malloc" );
45 	return( NULL );
46     }
47     if ( strlen( path ) >= MAXPATHLEN ) {
48 	fprintf( stderr, "%s: path too long\n", path );
49 	return( NULL );
50     }
51     strcpy( new_node->path, path );
52 
53     return( new_node );
54 }
55 
56     void
free_node(struct node * node)57 free_node( struct node *node )
58 {
59     free( node );
60 }
61 
62 struct tran {
63     struct node         *t_next;	/* Next tran in list */
64     FILE                *t_fd;		/* open file descriptor */
65     int                 t_num;		/* Tran num from command line */
66     char                *t_path;	/* Path from command line */
67     int                 t_eof;		/* Tran at end of file */
68     int                 t_linenum;	/* Current line number */
69     int                 t_remove;	/* Current line has '-' */
70     char                t_prepath[ MAXPATHLEN ]; /* for order check */
71     char		t_tran_root[ MAXPATHLEN ];
72     char		t_file_root[ MAXPATHLEN ];
73     char		t_tran_name[ MAXPATHLEN ];
74     char                *t_line;
75     char                t_tline[ 2 * MAXPATHLEN ];
76     char                t_filepath[ MAXPATHLEN ];
77     char                **t_argv;
78     int                 t_tac;
79     ACAV                *t_acav;
80 };
81 
82 int getnextline( struct tran *tran );
83 
84     int
getnextline(struct tran * tran)85 getnextline( struct tran *tran )
86 {
87     int		len;
88     char	*d_path;
89 
90 getline:
91     if ( fgets( tran->t_tline, MAXPATHLEN, tran->t_fd ) == NULL ) {
92 	if ( feof( tran->t_fd )) {
93 	    tran->t_eof = 1;
94 	    return( 0 );
95 	} else {
96 	    perror( tran->t_path );
97 	    return( -1 );
98 	}
99     }
100     tran->t_linenum++;
101 
102     if ( tran->t_line != NULL ) {
103 	free( tran->t_line );
104 	tran->t_line = NULL;
105     }
106 
107     if ( ( tran->t_line = strdup( tran->t_tline ) ) == NULL ) {
108 	perror( tran->t_tline );
109 	return( -1 );
110     }
111 
112     /* Check line length */
113     len = strlen( tran->t_tline );
114     if ( ( tran->t_tline[ len - 1 ] ) != '\n' ) {
115 	fprintf( stderr, "%s: %d: %s: line too long\n", tran->t_tran_name,
116 	    tran->t_linenum, tran->t_tline );
117 	return( -1 );
118     }
119     if ( ( tran->t_tac = acav_parse( tran->t_acav,
120 	    tran->t_tline, &(tran->t_argv) )  ) < 0 ) {
121 	fprintf( stderr, "acav_parse\n" );
122 	return( -1 );
123     }
124     /* Skip blank lines and comments */
125     if (( tran->t_tac == 0 ) || ( *tran->t_argv[ 0 ] == '#' )) {
126 	goto getline;
127     }
128 
129     if ( *tran->t_argv[ 0 ] == '-' ) {
130 	tran->t_remove = 1;
131 	tran->t_argv++;
132     } else {
133 	tran->t_remove = 0;
134     }
135 
136     /* Decode file path */
137     if (( d_path = decode( tran->t_argv[ 1 ] )) == NULL ) {
138 	fprintf( stderr, "%s: line %d: path too long\n", tran->t_tran_name,
139 	    tran->t_linenum );
140 	return( 1 );
141     }
142     if ( strlen( d_path ) >= MAXPATHLEN ) {
143 	fprintf( stderr, "%s: line %d: %s: path too long\n",
144 		tran->t_tran_name, tran->t_linenum, d_path );
145 	return( 1 );
146     }
147     strcpy( tran->t_filepath, d_path );
148 
149     /* Check transcript order */
150     if ( strlen( tran->t_prepath ) != 0 ) {
151 
152 	if ( pathcasecmp( tran->t_filepath, tran->t_prepath,
153 		case_sensitive ) <= 0 ) {
154 	    fprintf( stderr, "%s: line %d: bad sort order\n",
155 			tran->t_tran_name, tran->t_linenum );
156 	    return( 1 );
157 	}
158     }
159     if ( strlen( tran->t_filepath ) >= MAXPATHLEN ) {
160 	fprintf( stderr, "%s: line %d: %s: path too long\n",
161 		tran->t_tran_name, tran->t_linenum, tran->t_filepath );
162 	return( 1 );
163     }
164     strcpy( tran->t_prepath, tran->t_filepath );
165 
166 
167     return( 0 );
168 }
169 
170     static int
copy_file(const char * src_file,const char * dest_file)171 copy_file( const char *src_file, const char *dest_file )
172 {
173     int			src_fd, dest_fd = -1;
174     int			rr, rc = -1;
175     char		buf[ 4096 ];
176     struct stat		st;
177 
178     if (( src_fd = open( src_file, O_RDONLY )) < 0 ) {
179     	fprintf( stderr, "open %s failed: %s\n", src_file, strerror( errno ));
180 	return( rc );
181     }
182     if ( fstat( src_fd, &st ) < 0 ) {
183 	fprintf( stderr, "stat of %s failed: %s\n",
184 		src_file, strerror( errno ));
185 	goto cleanup;
186     }
187 
188     if (( dest_fd = open( dest_file, O_WRONLY | O_CREAT | O_EXCL,
189 	    st.st_mode & 07777 )) < 0 ) {
190 	if ( errno == ENOENT ) {
191 	    rc = errno;
192 	} else {
193 	    fprintf( stderr, "open %s failed: %s\n",
194 		    dest_file, strerror( errno ));
195 	}
196 	goto cleanup;
197     }
198     while (( rr = read( src_fd, buf, sizeof( buf ))) > 0 ) {
199 	if ( write( dest_fd, buf, rr ) != rr ) {
200 	    fprintf( stderr, "write to %s failed: %s\n",
201 		    dest_file, strerror( errno ));
202 	    goto cleanup;
203 	}
204     }
205     if ( rr < 0 ){
206 	fprintf( stderr, "read from %s failed: %s\n",
207 		src_file, strerror( errno ));
208 	goto cleanup;
209     }
210     if ( fchown( dest_fd, st.st_uid, st.st_gid ) != 0 ) {
211 	fprintf( stderr, "chown %d:%d %s failed: %s\n",
212 		st.st_uid, st.st_gid, dest_file, strerror( errno ));
213 	goto cleanup;
214     }
215 
216     rc = 0;
217 
218 cleanup:
219     if ( src_fd >= 0 ) {
220 	if ( close( src_fd ) != 0 ) {
221 	    fprintf( stderr, "close %s failed: %s\n",
222 		    src_file, strerror( errno ));
223 	    rc = -1;
224 	}
225     }
226     if ( dest_fd >= 0 ) {
227 	if ( close( dest_fd ) != 0 ) {
228 	    fprintf( stderr, "close %s failed: %s\n",
229 		    dest_file, strerror( errno ));
230 	    rc = -1;
231 	}
232     }
233 
234     return( rc );
235 }
236 
237 /*
238  * exit codes:
239  *	0  	okay
240  *	2	System error
241  */
242 
243     int
main(int argc,char ** argv)244 main( int argc, char **argv )
245 {
246     int			c, i, j, cmpval, err = 0, tcount = 0, candidate = 0;
247     int			force = 0, ofd, fileloc = 0, match = 0;
248     int			merge_trans_only = 0;
249     int			copy = 0, rc;
250     char		*file = NULL;
251     char		npath[ 2 * MAXPATHLEN ];
252     char		opath[ 2 * MAXPATHLEN ];
253     char		*radmind_path = _RADMIND_PATH;
254     char		cwd[ MAXPATHLEN ];
255     char		file_root[ MAXPATHLEN ];
256     char		tran_root[ MAXPATHLEN ];
257     char		tran_name[ MAXPATHLEN ];
258     char		temp[ MAXPATHLEN ];
259     struct tran		**trans = NULL;
260     struct node		*new_node = NULL;
261     struct node		*node = NULL;
262     struct node		*dirlist = NULL;
263     FILE		*ofs;
264     mode_t		mask;
265 
266     while ( ( c = getopt( argc, argv, "CD:fInTu:Vv" ) ) != EOF ) {
267 	switch( c ) {
268 	case 'C':		/* copy files instead of using hardlinks */
269 	    copy = 1;
270 	    break;
271 	case 'D':
272 	    radmind_path = optarg;
273 	    break;
274 	case 'f':
275 	    force = 1;
276 	    break;
277 	case 'I':
278 	    case_sensitive = 0;
279 	    break;
280 	case 'n':
281 	    noupload = 1;
282 	    break;
283 	case 'u':
284 	    errno = 0;
285 	    mask = (mode_t)strtol( optarg, (char **)NULL, 0 );
286 	    if ( errno != 0 ) {
287 		err++;
288 		break;
289 	    }
290 	    umask( mask );
291 	    break;
292 	case 'V':
293 	    printf( "%s\n", version );
294 	    exit( 0 );
295 	case 'v':
296 	    verbose = 1;
297 	    break;
298 	case 'T':
299 		merge_trans_only = 1;
300 		break;
301 	default:
302 	    err++;
303 	    break;
304 	}
305     }
306 
307     tcount = argc - ( optind + 1 );	/* "+ 1" accounts for dest tran */
308 
309     if ( merge_trans_only && force ) {
310 	err++;
311     }
312     if ( merge_trans_only && copy ) {
313 	err++;
314     }
315     if ( noupload && ( tcount > 2 ) ) {
316 	err++;
317     }
318     /* make sure there's a second transcript */
319     if ( force && ( argv[ optind + 1 ] == NULL )) {
320 	err++;
321     }
322     if ( force && ( tcount > 1 ) ) {
323 	err++;
324     }
325     if ( !force && ( tcount < 2 )) {
326 	err++;
327     }
328 
329     if ( err ) {
330 	fprintf( stderr, "Usage: %s [-vCIVT] [ -D path ] [ -u umask ] ",
331 	    argv[ 0 ] );
332 	fprintf( stderr, "transcript... dest\n" );
333 	fprintf( stderr, "       %s -f [-vCIV] [ -D path ] [ -u umask ] ",
334 	    argv[ 0 ] );
335 	fprintf( stderr, "transcript1 transcript2\n" );
336 	fprintf( stderr, "       %s -n [-vCIVT] [ -D path ] [ -u umask ] ",
337 	    argv[ 0 ] );
338 	fprintf( stderr, "transcript1 transcript2 dest\n" );
339 	exit( 2 );
340     }
341 
342     if ( force ) {
343 	/* Check for write access */
344 	if ( access( argv[ argc - 1 ], W_OK ) != 0 ) {
345 	    perror( argv[ argc - 1 ] );
346 	    exit( 2 );
347 	}
348 	tcount++;			/* add dest to tran merge list */
349     }
350 
351     /* Create array of transcripts */
352     if (( trans = (struct tran**)malloc(
353 	    sizeof( struct tran* ) * ( tcount ))) == NULL ) {
354 	perror( "malloc" );
355 	exit( 2 );
356     }
357     if ( getcwd( cwd, MAXPATHLEN ) == NULL ) {
358         perror( "getcwd" );
359         exit( 2 );
360     }
361 
362     /* loop over array of trans */
363     for ( i = 0;  i < tcount;  i++ ) {
364 
365 	if ( ( trans[ i ] = (struct tran*)malloc( sizeof( struct tran ) ) )
366 		== NULL ) {
367 	    perror( "malloc" );
368 	    return( 1 );
369 	}
370 	memset( trans[ i ], 0, sizeof( struct tran ));
371 	trans[ i ]->t_num = i;
372 	trans[ i ]->t_path = argv[ i + optind ];
373 
374 	if ( get_root( radmind_path, trans[ i ]->t_path, trans[ i ]->t_file_root,
375 		trans[ i ]->t_tran_root, trans[ i ]->t_tran_name ) != 0 ) {
376 	    exit( 2 );
377 	}
378 
379 	/* open tran */
380 	if (( trans[ i ]->t_fd = fopen( trans[ i ]->t_path, "r" )) == NULL ) {
381 	    perror( trans[ i ]->t_path );
382 	    return( 1 );
383 	}
384 
385 	if ( ( trans[ i ]->t_acav = acav_alloc() ) == NULL ) {
386 	    fprintf( stderr, "acav_malloc\n" );
387 	    return( 1 );
388 	}
389 	trans[ i ]->t_line = NULL;
390 	if ( getnextline( trans[ i ] ) < 0 ) {
391 	    exit( 2 );
392 	}
393     }
394 
395     if ( force ) {
396 	if ( strlen( trans[ 1 ]->t_file_root ) >= MAXPATHLEN ) {
397 	    fprintf( stderr, "%s: path too long\n", trans[ 1 ]->t_file_root );
398 	    exit( 2 );
399 	}
400 	strcpy( file_root, trans[ 1 ]->t_file_root );
401 	if ( strlen( trans[ 1 ]->t_tran_root ) >= MAXPATHLEN ) {
402 	    fprintf( stderr, "%s: path too long\n", trans[ 1 ]->t_tran_root );
403 	    exit( 2 );
404 	}
405 	strcpy( tran_root, trans[ 1 ]->t_tran_root );
406 	if ( strlen( trans[ 1 ]->t_tran_name ) >= MAXPATHLEN ) {
407 	    fprintf( stderr, "%s: path too long\n", trans[ 1 ]->t_tran_name );
408 	    exit( 2 );
409 	}
410 	strcpy( tran_name, trans[ 1 ]->t_tran_name );
411     } else {
412 	/* Create tran if missing */
413 	if (( ofd = open( argv[ argc - 1 ], O_WRONLY | O_CREAT, 0666 ) ) < 0 ) {
414 	    perror( argv[ argc - 1 ] );
415 	    exit( 2 );
416 	}
417 	if ( close( ofd ) != 0 ) {
418 	    perror( argv[ argc - 1 ] );
419 	    exit( 2 );
420 	}
421 
422 	/* Get paths */
423 	if ( *argv[ argc - 1 ] == '/' ) {
424 	    if ( strlen( argv[ argc - 1 ] ) >= MAXPATHLEN ) {
425 		fprintf( stderr, "%s: path too long\n", argv[ argc - 1 ] );
426 		exit( 2 );
427 	    }
428 	    strcpy( cwd, argv[ argc - 1 ] );
429 	} else {
430 	    if ( snprintf( temp, MAXPATHLEN, "%s/%s", cwd, argv[ argc - 1 ] )
431 		    >= MAXPATHLEN ) {
432 		fprintf( stderr, "%s/%s: path too long\n", cwd,
433 		    argv[ argc - 1 ] );
434 		exit( 2 );
435 	    }
436 	    strcpy( cwd, temp );
437 	}
438 	if ( get_root( radmind_path, cwd, file_root, tran_root, tran_name ) != 0 ) {
439 	    exit( 2 );
440 	}
441 
442 	/* Create file/tname dir */
443 	if ( snprintf( npath, MAXPATHLEN, "%s/%s.%d", file_root, tran_name,
444 		(int)getpid()) >= MAXPATHLEN ) {
445 	    fprintf( stderr, "%s/%s.%d: path too long\n", file_root, tran_name,
446 		(int)getpid());
447 	    exit( 2 );
448 	}
449 	/* don't bother creating file/tname if only merging trans */
450 	if ( !merge_trans_only ) {
451 	    if ( mkdir( npath, (mode_t)0777 ) != 0 ) {
452 		perror( npath );
453 		exit( 2 );
454 	    }
455 	}
456     }
457 
458     /* Create temp transcript/tname file */
459     if ( snprintf( opath, MAXPATHLEN, "%s/%s.%d", tran_root, tran_name,
460 	    (int)getpid()) >= MAXPATHLEN ) {
461 	fprintf( stderr, "%s/%s.%d: path too long\n", tran_root, tran_name,
462 	    (int)getpid());
463 	exit( 2 );
464     }
465     if (( ofd = open( opath, O_WRONLY | O_CREAT | O_EXCL,
466 	    0666 ) ) < 0 ) {
467 	perror( opath );
468 	exit( 2 );
469     }
470     if ( ( ofs = fdopen( ofd, "w" ) ) == NULL ) {
471 	perror( opath );
472 	exit( 2 );
473     }
474 
475     /* merge */
476     for ( i = 0; i < tcount; i++ ) {
477 	while ( !(trans[ i ]->t_eof)) {
478 	    candidate = i;
479 	    fileloc = i;
480 	    match = 0;
481 
482 	    if ( force && ( candidate == ( tcount - 1 ))) {
483 		match = 1;
484 		goto outputline;
485 	    }
486 
487 	    /* Compare candidate to other transcripts */
488 	    for ( j = i + 1; j < tcount; j++ ) {
489 		if ( trans[ j ]->t_eof ) {
490 		    continue;
491 		}
492 		cmpval = pathcasecmp( trans[ candidate ]->t_filepath,
493 		    trans[ j ]->t_filepath, case_sensitive );
494 		if ( cmpval == 0 ) {
495 		    /* File match */
496 		    match = 1;
497 
498 		    if (( noupload ) &&
499 			    ( *trans[ candidate ]->t_argv[ 0 ] == 'f'
500 			    || *trans[ candidate ]->t_argv[ 0 ] == 'a' )) {
501 			/* Use lower precedence path */
502 			trans[ candidate ]->t_path =
503 			    trans[ j ]->t_path;
504 
505 			/* Select which file should be linked */
506 			if ( ( strcmp( trans[ candidate ]->t_argv[ 6 ],
507 				trans[ j ]->t_argv[ 6 ] ) == 0 ) &&
508 				( strcmp( trans[ candidate ]->t_argv[ 7 ],
509 				trans[ j ]->t_argv[ 7 ] ) == 0 ) ) {
510 			    fileloc = j;
511 			} else {
512 			    /* don't print file only in highest tran */
513 			    goto skipline;
514 			}
515 		    }
516 		    if ( ( force ) && ( *trans[ j ]->t_argv[ 0 ] == 'f'
517 			    || *trans[ j ]->t_argv[ 0 ] == 'a' )) {
518 			/* Remove file from lower precedence transcript */
519 			if ( snprintf( opath, MAXPATHLEN, "%s/%s/%s",
520 				trans[ j ]->t_file_root,
521 				trans[ j ]->t_tran_name,
522 				trans[ j ]->t_filepath ) >= MAXPATHLEN ) {
523 			    fprintf( stderr,
524 				"%s/%s/%s: path too long\n",
525 				trans[ j ]->t_file_root,
526 				trans[ j ]->t_tran_name,
527 				trans[ j ]->t_filepath );
528 			    exit( 2 );
529 			}
530 			if ( unlink( opath ) != 0 ) {
531 			    perror( opath );
532 			    exit( 2 );
533 			}
534 			if ( verbose ) printf( "%s: %s: unlinked\n",
535 			    trans[ j ]->t_tran_name, trans[ j ]->t_filepath);
536 		    }
537 		    /* Advance lower precedence transcript */
538 		    if ( getnextline( trans[ j ] ) < 0 ) {
539 			exit( 2 );
540 		    }
541 		} else if ( cmpval > 0 ) {
542 		    candidate = j;
543 		    fileloc = j;
544 		}
545 	    }
546 	    if ( force && ( candidate == 1 ) ) {
547 		goto outputline;
548 	    }
549 	    /* skip items to be removed or files not uploaded */
550 	    if (( trans[ candidate ]->t_remove ) ||
551 		    (( noupload ) && ( candidate == 0 ) && ( fileloc == 0 ))) {
552 		if ( match && force &&
553 			( *trans[ candidate ]->t_argv[ 0 ] == 'd' )) {
554 		    new_node = create_node( trans[ candidate ]->t_argv[ 1 ] );
555 		    new_node->next = dirlist;
556 		    dirlist = new_node;
557 		}
558 		goto skipline;
559 	    }
560 	    /* output non-files, or if we're only merging transcripts
561 	     * and there is no file linking necessary
562 	     */
563 	    if (( *trans[ candidate ]->t_argv[ 0 ] != 'f'
564 		    && *trans[ candidate ]->t_argv[ 0 ] != 'a')
565 		    || merge_trans_only ) {
566 		goto outputline;
567 	    }
568 
569 	    /*
570 	     * Assume that directory structure is present so the entire path
571 	     * is not recreated for every file.  Only if link fails is
572 	     * mkdirs() called.
573 	     */
574 	    if ( snprintf( opath, MAXPATHLEN, "%s/%s/%s",
575 		    trans[ candidate ]->t_file_root,
576 		    trans[ fileloc ]->t_tran_name,
577 		    trans[ candidate ]->t_filepath ) >= MAXPATHLEN ) {
578 		fprintf( stderr, "%s/%s/%s: path too long\n",
579 		    trans[ candidate ]->t_file_root,
580 		    trans[ fileloc ]->t_tran_name,
581 		    trans[ candidate ]->t_filepath );
582 		exit( 2 );
583 	    }
584 
585 	    if ( !force ) {
586 		if ( snprintf( npath, MAXPATHLEN, "%s/%s.%d/%s",
587 			file_root, tran_name, (int)getpid(),
588 			trans[ candidate ]->t_filepath ) >= MAXPATHLEN ) {
589 		    fprintf( stderr, "%s/%s.%d/%s: path too long\n",
590 			file_root, tran_name, (int)getpid(),
591 			trans[ candidate ]->t_filepath );
592 		    exit( 2 );
593 		}
594 	    } else {
595 		if ( snprintf( npath, MAXPATHLEN, "%s/%s/%s", file_root,
596 			tran_name, trans[ candidate ]->t_filepath )
597 			>= MAXPATHLEN ) {
598 		    fprintf( stderr, "%s/%s/%s: path too long\n",
599 			file_root, tran_name, trans[ candidate ]->t_filepath );
600 		    exit( 2 );
601 		}
602 	    }
603 
604 	    /*
605 	     * copy or link file into new loadset. it's possible the file's
606 	     * directory hierarchy won't exist yet. in that case, we catch
607 	     * ENOENT, call mkdirs to create the parents dirs for the file,
608 	     * and try again. the second error is fatal.
609 	     */
610 	    if ( copy ) {
611 		rc = copy_file( opath, npath );
612 	    } else if (( rc = link( opath, npath )) != 0 ) {
613 		rc = errno;
614 	    }
615 
616 	    if ( rc == ENOENT ) {
617 
618 		/* If that fails, verify directory structure */
619 		if ( ( file = strrchr( trans[ candidate ]->t_argv[ 1 ], '/' ) )
620 			!= NULL ) {
621 		    if ( !force ) {
622 			if ( snprintf( npath, MAXPATHLEN,
623 				"%s/%s.%d/%s",
624 				file_root, tran_name, (int)getpid(),
625 				trans[ candidate ]->t_filepath )
626 				>= MAXPATHLEN ) {
627 			    fprintf( stderr,
628 				"%s/%s.%d/%s: path too long\n",
629 				file_root, tran_name, (int)getpid(),
630 				trans[ candidate ]->t_filepath );
631 			    exit( 2 );
632 			}
633 		    } else {
634 			if ( snprintf( npath, MAXPATHLEN,
635 				"%s/%s/%s", file_root, tran_name,
636 				trans[ candidate ]->t_filepath )
637 				>= MAXPATHLEN ) {
638 			    fprintf( stderr,
639 				"%s/%s/%s: path too long\n", file_root,
640 				tran_name, trans[ candidate ]->t_filepath );
641 			    exit( 2 );
642 			}
643 		    }
644 		    if ( mkdirs( npath ) != 0 ) {
645 			fprintf( stderr, "%s: mkdirs failed\n", npath );
646 			exit( 2 );
647 		    }
648 		}
649 
650 		/* Try copy / link again */
651     		if ( copy ) {
652     		    if (( rc = copy_file( opath, npath )) != 0 ) {
653     			fprintf( stderr, "copy %s to %s failed\n",
654 				opath, npath );
655     			exit( 2 );
656     		    }
657     		} else if ( link( opath, npath ) != 0 ){
658     		    fprintf( stderr, "link %s -> %s: %s\n",
659 			    opath, npath, strerror( errno ));
660     		    exit( 2 );
661     		}
662 	    } else if ( rc ) {
663 		if ( copy ) {
664 		    fprintf( stderr, "copy %s to %s failed\n", opath, npath );
665 		} else {
666 		    fprintf( stderr, "link %s to %s failed: %s\n",
667 			    opath, npath, strerror( rc ));
668 		}
669 		exit( 2 );
670 	    }
671 
672 	    if ( verbose ) printf( "%s: %s: merged into: %s\n",
673 		trans[ candidate ]->t_tran_name, trans[ candidate ]->t_filepath,
674 		tran_name );
675 
676 outputline:
677 	    /* Output line */
678 	    if ( fputs( trans[ candidate ]->t_line, ofs ) == EOF ) {
679 		perror( trans[ candidate ]->t_line );
680 		exit( 2 );
681 	    }
682 skipline:
683 	    /* Don't duplicate remove line if it's not a match, or
684 	     * we got -f and we're just outputing the last
685 	     * transcript.
686 	     */
687 	    if (( trans[ candidate ]->t_remove )
688 		    && !match
689 		    && (!( force && ( candidate == 1 )))) {
690 		/* Recreate unmatched "-" line */
691 		if ( fputs( trans[ candidate ]->t_line, ofs ) == EOF ) {
692 		    perror( trans[ candidate ]->t_line );
693 		    exit( 2 );
694 
695 		}
696 	    }
697 	    if ( getnextline( trans[ candidate ] ) != 0 ) {
698 		exit( 2 );
699 	    }
700 	}
701     }
702 
703     if ( force ) {
704 	while ( dirlist != NULL ) {
705 	    node = dirlist;
706 	    dirlist = node->next;
707 	    if ( snprintf( opath, MAXPATHLEN, "%s/%s/%s", file_root,
708 		    tran_name, node->path ) >= MAXPATHLEN ) {
709 		fprintf( stderr, "%s/%s/%s: path too long\n",
710 		    file_root, tran_name, node->path );
711 		exit( 2 );
712 	    }
713 	    if ( rmdir( opath ) != 0 ) {
714 		if (( errno == EEXIST ) || ( errno == ENOTEMPTY )) {
715 		    fprintf( stderr, "%s: %s: Not empty, continuing...\n",
716 			tran_name, node->path );
717 		} else if ( errno != ENOENT ) {
718 		    perror( opath );
719 		    exit( 2 );
720 		}
721 	    } else {
722 		if ( verbose ) printf( "%s: %s: unlinked\n", tran_name,
723 		    node->path );
724 	    }
725 	    free_node( node );
726 	}
727     }
728 
729     /* Rename temp transcript and file structure */
730     if ( !force ) {
731 	if ( snprintf( opath, MAXPATHLEN, "%s/%s.%d", file_root,
732 		tran_name, (int)getpid()) >= MAXPATHLEN ) {
733 	    fprintf( stderr, "%s/%s.%d: path too long\n",
734 		file_root, tran_name, (int)getpid());
735 	    exit( 2 );
736 	}
737 	if ( snprintf( npath, MAXPATHLEN, "%s/%s", file_root, tran_name )
738 		>= MAXPATHLEN ) {
739 	    fprintf( stderr, "%s/%s: path too long\n", file_root, tran_name );
740 	    exit( 2 );
741 	}
742 	/* don't try and move file/tname if doing client only merge,
743 	 * it was never created.
744 	 */
745 	if ( !merge_trans_only ) {
746 	    if ( rename( opath, npath ) != 0 ) {
747 		perror( npath );
748 		exit( 2 );
749 	    }
750 	}
751     }
752     if ( snprintf( opath, MAXPATHLEN, "%s/%s.%d", tran_root, tran_name,
753 	    (int)getpid()) >= MAXPATHLEN ) {
754 	fprintf( stderr, "%s/%s.%d: path too long\n", tran_root, tran_name,
755 	    (int)getpid());
756 	exit( 2 );
757     }
758     if ( snprintf( npath, MAXPATHLEN, "%s/%s", tran_root, tran_name )
759 	    >= MAXPATHLEN ) {
760 	fprintf( stderr, "%s/%s: path too long\n", tran_root, tran_name );
761 	exit( 2 );
762     }
763 
764     if ( rename( opath, npath ) != 0 ) {
765 	perror( npath );
766 	exit( 2 );
767     }
768 
769     exit( 0 );
770 }
771