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