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