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