1#ifdef HAVE_CONFIG_H
2#include "config.h"
3#endif /* HAVE_CONFIG_H */
4
5#include <sys/types.h>
6#include <sys/param.h>
7#include <sys/stat.h>
8#include <sys/uio.h>
9#ifdef HAVE_FCNTL_H
10#include <fcntl.h>
11#endif /* HAVE_FCNTL_H */
12#include <time.h>
13#include <ctype.h>
14#include <stdio.h>
15#include <string.h>
16#include <netatalk/endian.h>
17#include "asingle.h"
18#include "megatron.h"
19#include "hqx.h"
20#include "macbin.h"
21#include "nad.h"
22
23char		*forkname[] = { "data", "resource" };
24static char	forkbuf[8192];
25static char	*name[] = { "unhex",
26			    "unbin",
27			    "unsingle",
28			    "macbinary",
29			    "hqx2bin",
30			    "single2bin",
31			    "nadheader",
32			    "binheader",
33			    "megatron" };
34
35static int from_open(int un, char *file, struct FHeader *fh, int flags)
36{
37    switch ( un ) {
38	case MEGATRON :
39	case HEX2NAD :
40	case HEX2BIN :
41	    return( hqx_open( file, O_RDONLY, fh, flags ));
42	    break;
43	case BIN2NAD :
44        case BINHEADER:
45	    return( bin_open( file, O_RDONLY, fh, flags ));
46	    break;
47	case NAD2BIN :
48        case NADHEADER:
49	    return( nad_open( file, O_RDONLY, fh, flags ));
50	    break;
51	case SINGLE2NAD :
52	case SINGLE2BIN :
53	    return( single_open( file, O_RDONLY, fh, flags ));
54	default :
55	    return( -1 );
56	    break;
57    }
58}
59
60static ssize_t from_read(int un, int fork, char *buf, size_t len)
61{
62    switch ( un ) {
63	case MEGATRON :
64	case HEX2NAD :
65	case HEX2BIN :
66	    return( hqx_read( fork, buf, len ));
67	    break;
68	case BIN2NAD :
69	    return( bin_read( fork, buf, len ));
70	    break;
71	case NAD2BIN :
72	    return( nad_read( fork, buf, len ));
73	    break;
74	case SINGLE2NAD :
75	case SINGLE2BIN :
76	    return( single_read( fork, buf, len ));
77	default :
78	    return( -1 );
79	    break;
80    }
81}
82
83static int from_close(int un)
84{
85    switch ( un ) {
86	case MEGATRON :
87	case HEX2NAD :
88	case HEX2BIN :
89	    return( hqx_close( KEEP ));
90	    break;
91	case BIN2NAD :
92	    return( bin_close( KEEP ));
93	    break;
94	case NAD2BIN :
95	    return( nad_close( KEEP ));
96	    break;
97	case SINGLE2NAD :
98	case SINGLE2BIN :
99	    return( single_close( KEEP ));
100	default :
101	    return( -1 );
102	    break;
103    }
104}
105
106static int to_open(int to, char *file, struct FHeader *fh, int flags)
107{
108    switch ( to ) {
109	case MEGATRON :
110	case HEX2NAD :
111	case BIN2NAD :
112	case SINGLE2NAD :
113	    return( nad_open( file, O_RDWR|O_CREAT|O_EXCL, fh, flags ));
114	    break;
115	case NAD2BIN :
116	case HEX2BIN :
117	case SINGLE2BIN :
118	    return( bin_open( file, O_RDWR|O_CREAT|O_EXCL, fh, flags ));
119	    break;
120	default :
121	    return( -1 );
122	    break;
123    }
124}
125
126static ssize_t to_write(int to, int fork, size_t bufc)
127{
128    switch ( to ) {
129	case MEGATRON :
130	case HEX2NAD :
131	case BIN2NAD :
132	case SINGLE2NAD :
133	    return( nad_write( fork, forkbuf, bufc ));
134	    break;
135	case NAD2BIN :
136	case HEX2BIN :
137	case SINGLE2BIN :
138	    return( bin_write( fork, forkbuf, bufc ));
139	    break;
140	default :
141	    return( -1 );
142	    break;
143    }
144}
145
146static int to_close(int to, int keepflag)
147{
148    switch ( to ) {
149	case MEGATRON :
150	case HEX2NAD :
151	case BIN2NAD :
152	case SINGLE2NAD :
153	    return( nad_close( keepflag ));
154	    break;
155	case NAD2BIN :
156	case HEX2BIN :
157	case SINGLE2BIN :
158	    return( bin_close( keepflag ));
159	    break;
160	default :
161	    return( -1 );
162	    break;
163    }
164}
165
166static int megatron( char *path, int module, char *newname, int flags)
167{
168    struct stat		st;
169    struct FHeader	fh;
170    ssize_t		bufc;
171    int			fork;
172    size_t 		forkred;
173
174/*
175 * If the source file is not stdin, make sure it exists and
176 * that it is not a directory.
177 */
178
179    if ( strcmp( path, STDIN ) != 0 ) {
180	if ( stat( path, &st ) < 0 ) {
181	    perror( path );
182	    return( -1 );
183	}
184	if ( S_ISDIR( st.st_mode )) {
185	    fprintf( stderr, "%s is a directory.\n", path );
186	    return( 0 );
187	}
188    }
189
190/*
191 * Open the source file and fill in the file header structure.
192 */
193
194    memset( &fh, 0, sizeof( fh ));
195    if ( from_open( module, path, &fh, flags ) < 0 ) {
196	return( -1 );
197    }
198
199    if ( flags & OPTION_HEADERONLY ) {
200        time_t t;
201	char buf[5] = "";
202        int i;
203
204        printf("name:               %s\n",fh.name);
205        printf("comment:            %s\n",fh.comment);
206	memcpy(&buf, &fh.finder_info.fdCreator, sizeof(u_int32_t));
207	printf("creator:            '%4s'\n", buf);
208	memcpy(&buf, &fh.finder_info.fdType, sizeof(u_int32_t));
209	printf("type:               '%4s'\n", buf);
210        for(i=0; i < NUMFORKS; ++i)
211	  printf("fork length[%d]:     %u\n", i, ntohl(fh.forklen[i]));
212	t = AD_DATE_TO_UNIX(fh.create_date);
213        printf("creation date:      %s", ctime(&t));
214	t = AD_DATE_TO_UNIX(fh.mod_date);
215        printf("modification date:  %s", ctime(&t));
216	t = AD_DATE_TO_UNIX(fh.backup_date);
217        printf("backup date:        %s", ctime(&t));
218	return( from_close( module ));
219    }
220
221/*
222 * Open the target file and write out the file header info.
223 * set the header to the new filename if it has been supplied.
224 */
225
226    if (*newname)
227        strcpy(fh.name, newname);
228
229    if ( to_open( module, path, &fh, flags ) < 0 ) {
230	(void)from_close( module );
231	return( -1 );
232    }
233
234/*
235 * Read in and write out the data and resource forks.
236 */
237
238    for ( fork = 0; fork < NUMFORKS ; fork++ ) {
239	forkred = 0;
240	while(( bufc = from_read( module, fork, forkbuf, sizeof( forkbuf )))
241		> 0 ) {
242	    if ( to_write( module, fork, bufc ) != bufc ) {
243		fprintf( stderr, "%s: Probable write error\n", path );
244		to_close( module, TRASH );
245		(void)from_close( module );
246		return( -1 );
247	    }
248	    forkred += bufc;
249	}
250#if DEBUG
251	fprintf( stderr, "megatron: forkred is \t\t%d\n", forkred );
252	fprintf( stderr, "megatron: fh.forklen[%d] is \t%d\n", fork,
253		ntohl( fh.forklen[ fork ] ));
254#endif /* DEBUG */
255	if (( bufc < 0 ) || ( forkred != ntohl( fh.forklen[ fork ] ))) {
256	    fprintf( stderr, "%s: Problem with input, dude\n", path );
257	    to_close( module, TRASH );
258	    (void)from_close( module );
259	    return( -1 );
260	}
261    }
262
263/*
264 * Close up the files, and get out of here.
265 */
266
267    if ( to_close( module, KEEP ) < 0 ) {
268	perror( "megatron:" );
269	(void)to_close( module, TRASH );
270    }
271    return( from_close( module ));
272}
273
274int main(int argc, char **argv)
275{
276    int		rc, c;
277    int		rv = 0;
278    int		converts = sizeof(name) / sizeof(char *);
279    int		module = -1;
280    int         flags = 0;
281    char	*progname, newname[ADEDLEN_NAME + 1];
282
283    progname = strrchr( argv[ 0 ], '/' );
284    if (( progname == NULL ) || ( *progname == '\0' )) {
285	progname = argv[ 0 ];
286    } else progname++;
287
288#if DEBUG
289    if ( CONVERTS != converts ) {
290	fprintf( stderr, "megatron: list of program links messed up\n" );
291	return( -1 );
292    }
293#endif /* DEBUG */
294
295    for ( c = 0 ; (( c < converts ) && ( module < 0 )) ; ++c ) {
296	if ( strcmp( name[ c ], progname ) == 0 ) module = c;
297    }
298    if ( module == -1 ) module = ( converts - 1 );
299    if ((module == NADHEADER) || (module == BINHEADER))
300      flags |= OPTION_HEADERONLY;
301
302    if ( argc == 1 ) {
303	return( megatron( STDIN, module, newname, flags ));
304    }
305
306    *newname = '\0';
307    for ( c = 1 ; c < argc ; ++c ) {
308        if ( strcmp( argv [ c ], "--version" ) == 0 ) {
309	    printf("%s (Netatalk %s megatron)\n", argv[0], VERSION);
310	    return( -1 );
311	}
312        if ( strcmp( argv [ c ], "-v" ) == 0 ) {
313	    printf("%s (Netatalk %s megatron)\n", argv[0], VERSION);
314	    return( -1 );
315	}
316        if ( strcmp( argv [ c ], "--header" ) == 0 ) {
317	    flags |= OPTION_HEADERONLY;
318	    continue;
319	}
320	if ( strcmp( argv [ c ], "--filename" ) == 0 ) {
321	  if(++c < argc) strncpy(newname,argv[c], ADEDLEN_NAME);
322	  continue;
323	}
324	if (strcmp(argv[c], "--stdout") == 0) {
325	  flags |= OPTION_STDOUT;
326	  continue;
327	}
328	if (strcmp(argv[c], "--euc") == 0) {
329	  flags |= OPTION_EUCJP;
330	  continue;
331	}
332	if (strcmp(argv[c], "--sjis") == 0) {
333	  flags |= OPTION_SJIS;
334	  continue;
335	}
336	rc = megatron( argv[ c ], module, newname, flags);
337	if ( rc != 0 ) {
338	    rv = rc;
339	}
340	*newname = '\0';
341    }
342    return( rv );
343}
344