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 23char *forkname[] = { "data", "resource" }; 24static char forkbuf[8192]; 25static char *name[] = { "unhex", 26 "unbin", 27 "unsingle", 28 "macbinary", 29 "hqx2bin", 30 "single2bin", 31 "nadheader", 32 "binheader", 33 "megatron" }; 34 35static 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 60static 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 83static 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 106static 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 126static 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 146static 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 166static 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 274int 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} 344