]> arthur.barton.de Git - netatalk.git/blob - bin/megatron/megatron.c
Remove bdb env on exit
[netatalk.git] / bin / megatron / megatron.c
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
23 char            *forkname[] = { "data", "resource" };
24 static char     forkbuf[8192];
25 static char     *name[] = { "unhex",
26                             "unbin",
27                             "unsingle",
28                             "macbinary",
29                             "hqx2bin",
30                             "single2bin",
31                             "nadheader",
32                             "binheader",
33                             "megatron" };
34
35 static 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
60 static 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
83 static 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
106 static 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
126 static 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
146 static 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
166 static 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
274 int 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 }