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 27char *forkname[] = { "data", "resource" }; 28static char forkbuf[8192]; 29static char *name[] = { "unhex", 30 "unbin", 31 "unsingle", 32 "macbinary", 33 "hqx2bin", 34 "single2bin", 35 "nadheader", 36 "binheader", 37 "megatron" }; 38 39static 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 64static 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 87static 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 110static 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 130static 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 150static 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 170static 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 278int 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 341