1/* 2 * $Id: nad.c,v 1.18 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/time.h> 13#include <sys/uio.h> 14#include <ctype.h> 15#include <errno.h> 16#include <stdio.h> 17#include <string.h> 18#include <dirent.h> 19#ifdef HAVE_FCNTL_H 20#include <fcntl.h> 21#endif /* HAVE_FCNTL_H */ 22 23#include <atalk/adouble.h> 24#include <atalk/util.h> 25#include <atalk/volinfo.h> 26#include <netatalk/endian.h> 27#include "megatron.h" 28#include "nad.h" 29 30static struct volinfo vol; 31static char hexdig[] = "0123456789abcdef"; 32 33static char mtou_buf[MAXPATHLEN + 1], utom_buf[MAXPATHLEN + 1]; 34static char *mtoupathcap(char *mpath) 35{ 36 char *m, *u, *umax; 37 int i = 0; 38 39 m = mpath; 40 u = mtou_buf; 41 umax = u + sizeof(mtou_buf) - 4; 42 while ( *m != '\0' && u < umax) { 43#if AD_VERSION == AD_VERSION1 44 if ( !isascii( *m ) || *m == '/' || ( i == 0 && *m == '.' )) { 45#else /* AD_VERSION == AD_VERSION1 */ 46 if (!isprint(*m) || *m == '/' || ( i == 0 && (*m == '.' ))) { 47#endif /* AD_VERSION == AD_VERSION1 */ 48 *u++ = ':'; 49 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ]; 50 *u++ = hexdig[ *m & 0x0f ]; 51 } else { 52#ifdef DOWNCASE 53 *u++ = ( isupper( *m )) ? tolower( *m ) : *m; 54#else /* DOWNCASE */ 55 *u++ = *m; 56#endif /* DOWNCASE */ 57 } 58 i++; 59 m++; 60 } 61 *u = '\0'; 62 return( mtou_buf ); 63} 64 65 66#define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' ) 67#define islxdigit(x) (!isupper(x)&&isxdigit(x)) 68 69static char *utompathcap( char *upath) 70{ 71 char *m, *u; 72 int h; 73 74 m = utom_buf; 75 u = upath; 76 while ( *u != '\0' ) { 77 if (*u == ':' && *(u + 1) != '\0' && islxdigit(*(u+1)) && 78 *(u+2) != '\0' && islxdigit(*(u+2))) { 79 u++; 80 h = hextoint(*u) << 4; 81 u++; 82 h |= hextoint(*u); 83 *m = h; 84 } else { 85#ifdef DOWNCASE 86 *m = diatolower(*u); 87#else /* DOWNCASE */ 88 *m = *u; 89#endif /* DOWNCASE */ 90 } 91 u++; 92 m++; 93 } 94 *m = '\0'; 95 return( utom_buf ); 96} 97 98static void euc2sjis( int *p1, int *p2) /* agrees w/ Samba on valid codes */ 99{ 100 int row_offset, cell_offset; 101 unsigned char c1, c2; 102 103 /* first convert EUC to ISO-2022 */ 104 c1 = *p1 & 0x7F; 105 c2 = *p2 & 0x7F; 106 107 /* now convert ISO-2022 to Shift-JIS */ 108 row_offset = c1 < 95 ? 112 : 176; 109 cell_offset = c1 % 2 ? (c2 > 95 ? 32 : 31) : 126; 110 111 *p1 = ((c1 + 1) >> 1) + row_offset; 112 *p2 = c2 + cell_offset; 113} 114 115static void sjis2euc( int *p1, int *p2) /* agrees w/ Samba on valid codes */ 116{ 117 int row_offset, cell_offset, adjust; 118 unsigned char c1, c2; 119 120 c1 = *p1; 121 c2 = *p2; 122 123 /* first convert Shift-JIS to ISO-2022 */ 124 adjust = c2 < 159; 125 row_offset = c1 < 160 ? 112 : 176; 126 cell_offset = adjust ? (c2 > 127 ? 32 : 31) : 126; 127 128 c1 = ((c1 - row_offset) << 1) - adjust; 129 c2 -= cell_offset; 130 131 /* now convert ISO-2022 to EUC */ 132 *p1 = c1 | 0x80; 133 *p2 = c2 | 0x80; 134} 135 136static char *mtoupatheuc( char *from) 137{ 138 unsigned char *in, *out, *maxout; 139 int p, p2, i = 0; 140 141 in = (unsigned char *) from; 142 out = (unsigned char *) mtou_buf; 143 144 if( *in ) { 145 maxout = out + sizeof( mtou_buf) - 3; 146 147 while( out < maxout ) { 148 p = *in++; 149 150 if( ((0x81 <= p) && (p <= 0x9F)) 151 || ((0xE0 <= p) && (p <= 0xEF)) ) { 152 /* JIS X 0208 */ 153 p2 = *in++; 154 if( ((0x40 <= p2) && (p2 <= 0x7E)) 155 || ((0x80 <= p2) && (p2 <= 0xFC)) ) 156 sjis2euc( &p, &p2); 157 *out++ = p; 158 p = p2; 159 160 } else if( (0xA1 <= p) && (p <= 0xDF) ) { 161 *out++ = 0x8E; /* halfwidth katakana */ 162 } else if( p < 0x80 ) { 163#ifdef DOWNCASE 164 p = ( isupper( p )) ? tolower( p ) : p; 165#endif /* DOWNCASE */ 166 } 167 if( ( p == '/') || ( i == 0 && p == '.' ) ) { 168 *out++ = ':'; 169 *out++ = hexdig[ ( p & 0xf0 ) >> 4 ]; 170 p = hexdig[ p & 0x0f ]; 171 } 172 i++; 173 *out++ = p; 174 if( p ) 175 continue; 176 break; 177 } 178 } else { 179 *out++ = '.'; 180 *out = 0; 181 } 182 183 return mtou_buf; 184} 185 186static char *utompatheuc( char *from) 187{ 188 unsigned char *in, *out, *maxout; 189 int p, p2; 190 191 in = (unsigned char *) from; 192 out = (unsigned char *) utom_buf; 193 maxout = out + sizeof( utom_buf) - 3; 194 195 while( out < maxout ) { 196 p = *in++; 197 198 if( (0xA1 <= p) && (p <= 0xFE) ) { /* JIS X 0208 */ 199 p2 = *in++; 200 if( (0xA1 <= p2) && (p2 <= 0xFE) ) 201 euc2sjis( &p, &p2); 202 *out++ = p; 203 p = p2; 204 } else if( p == 0x8E ) { /* halfwidth katakana */ 205 p = *in++; 206 } else if( p < 0x80 ) { 207#ifdef DOWNCASE 208 p = ( isupper( p )) ? tolower( p ) : p; 209#endif /* DOWNCASE */ 210 } 211 if ( p == ':' && *(in) != '\0' && islxdigit( *(in)) && 212 *(in+1) != '\0' && islxdigit( *(in+1))) { 213 p = hextoint( *in ) << 4; 214 in++; 215 p |= hextoint( *in ); 216 in++; 217 } 218 *out++ = p; 219 if( p ) 220 continue; 221 break; 222 } 223 224 return utom_buf; 225} 226 227static char *mtoupathsjis( char *from) 228{ 229 unsigned char *in, *out, *maxout; 230 int p, p2, i = 0; 231 232 in = (unsigned char *) from; 233 out = (unsigned char *) mtou_buf; 234 235 if( *in ) { 236 maxout = out + sizeof( mtou_buf) - 3; 237 238 while( out < maxout ) { 239 p = *in++; 240 241 if( ((0x81 <= p) && (p <= 0x9F)) 242 || ((0xE0 <= p) && (p <= 0xEF)) ) { 243 /* JIS X 0208 */ 244 p2 = *in++; 245 *out++ = p; 246 p = p2; 247 248 } else if( (0xA1 <= p) && (p <= 0xDF) ) { 249 ; /* halfwidth katakana */ 250 } else if(p < 0x80 ) { 251#ifdef DOWNCASE 252 p = ( isupper( p )) ? tolower( p ) : p; 253#endif /* DOWNCASE */ 254 } 255 if( ( p == '/') || ( i == 0 && p == '.' ) ) { 256 *out++ = ':'; 257 *out++ = hexdig[ ( p & 0xf0 ) >> 4 ]; 258 p = hexdig[ p & 0x0f ]; 259 } 260 i++; 261 *out++ = p; 262 if( p ) 263 continue; 264 break; 265 } 266 } else { 267 *out++ = '.'; 268 *out = 0; 269 } 270 271 return mtou_buf; 272} 273 274static char *utompathsjis( char *from) 275{ 276 unsigned char *in, *out, *maxout; 277 int p, p2; 278 279 in = (unsigned char *) from; 280 out = (unsigned char *) utom_buf; 281 maxout = out + sizeof( utom_buf) - 3; 282 283 while( out < maxout ) { 284 p = *in++; 285 286 if( (0xA1 <= p) && (p <= 0xFE) ) { /* JIS X 0208 */ 287 p2 = *in++; 288 *out++ = p; 289 p = p2; 290 } else if( p == 0x8E ) { /* do nothing */ 291 ; 292 } else if( p < 0x80 ) { 293#ifdef DOWNCASE 294 p = ( isupper( p )) ? tolower( p ) : p; 295#endif /* DOWNCASE */ 296 } 297 if ( p == ':' && *(in) != '\0' && islxdigit( *(in)) && 298 *(in+1) != '\0' && islxdigit( *(in+1))) { 299 p = hextoint( *in ) << 4; 300 in++; 301 p |= hextoint( *in ); 302 in++; 303 } 304 *out++ = p; 305 if( p ) 306 continue; 307 break; 308 } 309 310 return utom_buf; 311 } 312 313static char *utompathiconv(char *upath) 314{ 315 char *m, *u; 316 u_int16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX; 317 size_t outlen; 318 static char mpath[MAXPATHLEN +2]; /* for convert_charset dest_len parameter +2 */ 319 320 m = mpath; 321 outlen = strlen(upath); 322 323#if 0 324 if (vol->v_casefold & AFPVOL_UTOMUPPER) 325 flags |= CONV_TOUPPER; 326 else if (vol->v_casefold & AFPVOL_UTOMLOWER) 327 flags |= CONV_TOLOWER; 328#endif 329 330 u = upath; 331 332 /* convert charsets */ 333 if ((size_t)-1 == ( outlen = convert_charset ( vol.v_volcharset, vol.v_maccharset, vol.v_maccharset, u, outlen, mpath, MAXPATHLEN, &flags)) ) { 334 fprintf( stderr, "Conversion from %s to %s for %s failed.", vol.v_volcodepage, vol.v_maccodepage, u); 335 goto utompath_error; 336 } 337 338 if (flags & CONV_REQMANGLE) 339 goto utompath_error; 340 341 return(m); 342 343utompath_error: 344 return(utompathcap( upath )); 345} 346 347static char *mtoupathiconv(char *mpath) 348{ 349 char *m, *u; 350 size_t inplen; 351 size_t outlen; 352 u_int16_t flags = 0; 353 static char upath[MAXPATHLEN +2]; /* for convert_charset dest_len parameter +2 */ 354 355 if ( *mpath == '\0' ) { 356 return( "." ); 357 } 358 359 /* set conversion flags */ 360 if (!(vol.v_flags & AFPVOL_NOHEX)) 361 flags |= CONV_ESCAPEHEX; 362 if (!(vol.v_flags & AFPVOL_USEDOTS)) 363 flags |= CONV_ESCAPEDOTS; 364 365#if 0 366 if ((vol->v_casefold & AFPVOL_MTOUUPPER)) 367 flags |= CONV_TOUPPER; 368 else if ((vol->v_casefold & AFPVOL_MTOULOWER)) 369 flags |= CONV_TOLOWER; 370#endif 371 372 m = mpath; 373 u = upath; 374 375 inplen = strlen(m); 376 outlen = MAXPATHLEN; 377 378 if ((size_t)-1 == (outlen = convert_charset ( vol.v_maccharset, vol.v_volcharset, vol.v_maccharset, m, inplen, u, outlen, &flags)) ) { 379 fprintf (stderr, "conversion from %s to %s for %s failed.", vol.v_maccodepage, vol.v_volcodepage, mpath); 380 return(mtoupathcap( upath )); 381 } 382 383 return( upath ); 384} 385 386 387 388char * (*_mtoupath) ( char *mpath) = mtoupathcap; 389char * (*_utompath) ( char *upath) = utompathcap; 390 391/* choose translators for optional character set */ 392void select_charset( int options) 393{ 394 395 if( options & OPTION_EUCJP ) { 396 _mtoupath = mtoupatheuc; 397 _utompath = utompatheuc; 398 } else if( options & OPTION_SJIS ) { 399 _mtoupath = mtoupathsjis; 400 _utompath = utompathsjis; 401 } else { 402 _mtoupath = mtoupathcap; 403 _utompath = utompathcap; 404 } 405} 406 407 408#if HEXOUTPUT 409 int hexfork[ NUMFORKS ]; 410#endif /* HEXOUTPUT */ 411 412static struct nad_file_data { 413 char macname[ MAXPATHLEN + 1 ]; 414 char adpath[ 2 ][ MAXPATHLEN + 1]; 415 int offset[ NUMFORKS ]; 416 struct adouble ad; 417} nad; 418 419static void initvol(char *path) 420{ 421 if (!loadvolinfo(path, &vol)) { 422 vol_load_charsets(&vol); 423 ad_init(&nad.ad, vol.v_adouble, 0); 424 _mtoupath = mtoupathiconv; 425 _utompath = utompathiconv; 426 } 427 else 428 ad_init(&nad.ad, 0, 0); 429} 430 431 432int nad_open( char *path, int openflags, struct FHeader *fh, int options) 433{ 434 struct stat st; 435 int fork; 436 437/* 438 * Depending upon openflags, set up nad.adpath for the open. If it 439 * is for write, then stat the current directory to get its mode. 440 * Open the file. Either fill or grab the adouble information. 441 */ 442 select_charset( options); 443 memset(&nad.ad, 0, sizeof(nad.ad)); 444 445 if ( openflags == O_RDONLY ) { 446 initvol(path); 447 strcpy( nad.adpath[0], path ); 448 strcpy( nad.adpath[1], 449 nad.ad.ad_ops->ad_path( nad.adpath[0], ADFLAGS_HF )); 450 for ( fork = 0 ; fork < NUMFORKS ; fork++ ) { 451 if ( stat( nad.adpath[ fork ], &st ) < 0 ) { 452 if ( errno == ENOENT ) { 453 fprintf( stderr, "%s is not an adouble file.\n", path ); 454 } else { 455 perror( "stat of adouble file failed" ); 456 } 457 return( -1 ); 458 } 459 } 460 461#if DEBUG 462 fprintf(stderr, "%s is adpath[0]\n", nad.adpath[0]); 463 fprintf(stderr, "%s is adpath[1]\n", nad.adpath[1]); 464#endif /* DEBUG */ 465 if ( ad_open( nad.adpath[ 0 ], ADFLAGS_DF|ADFLAGS_HF, 466 openflags, (int)( st.st_mode & 0666 ), &nad.ad) < 0 ) { 467 perror( nad.adpath[ 0 ] ); 468 return( -1 ); 469 } 470 return( nad_header_read( fh )); 471 472 } else { 473 initvol ("."); 474 strcpy( nad.macname, fh->name ); 475 strcpy( nad.adpath[0], mtoupath( nad.macname )); 476 strcpy( nad.adpath[1], 477 nad.ad.ad_ops->ad_path( nad.adpath[0], ADFLAGS_HF )); 478#if DEBUG 479 fprintf(stderr, "%s\n", nad.macname); 480 fprintf(stderr, "%s is adpath[0]\n", nad.adpath[0]); 481 fprintf(stderr, "%s is adpath[1]\n", nad.adpath[1]); 482#endif /* DEBUG */ 483 if ( stat( ".", &st ) < 0 ) { 484 perror( "stat of . failed" ); 485 return( -1 ); 486 } 487 (void)umask( 0 ); 488 if ( ad_open( nad.adpath[ 0 ], ADFLAGS_DF|ADFLAGS_HF, 489 openflags, (int)( st.st_mode & 0666 ), &nad.ad) < 0 ) { 490 perror( nad.adpath[ 0 ] ); 491 return( -1 ); 492 } 493 return( nad_header_write( fh )); 494 } 495} 496 497int nad_header_read(struct FHeader *fh) 498{ 499 u_int32_t temptime; 500 struct stat st; 501 char *p; 502 503#if 0 504 memcpy( nad.macname, ad_entry( &nad.ad, ADEID_NAME ), 505 ad_getentrylen( &nad.ad, ADEID_NAME )); 506 nad.macname[ ad_getentrylen( &nad.ad, ADEID_NAME ) ] = '\0'; 507 strcpy( fh->name, nad.macname ); 508#endif 509 510 /* just in case there's nothing in macname */ 511 if (*fh->name == '\0') { 512 if ( NULL == (p = strrchr(nad.adpath[DATA], '/')) ) 513 p = nad.adpath[DATA]; 514 else p++; 515#if 0 516 strcpy(fh->name, utompath(nad.adpath[DATA])); 517#endif 518 strcpy(fh->name, utompath(p)); 519 } 520 521 if ( stat( nad.adpath[ DATA ], &st ) < 0 ) { 522 perror( "stat of datafork failed" ); 523 return( -1 ); 524 } 525 fh->forklen[ DATA ] = htonl( st.st_size ); 526 fh->forklen[ RESOURCE ] = htonl( ad_getentrylen( &nad.ad, ADEID_RFORK )); 527 fh->comment[0] = '\0'; 528 529#if DEBUG 530 fprintf( stderr, "macname of file\t\t\t%.*s\n", strlen( fh->name ), 531 fh->name ); 532 fprintf( stderr, "size of data fork\t\t%d\n", 533 ntohl( fh->forklen[ DATA ] )); 534 fprintf( stderr, "size of resource fork\t\t%d\n", 535 ntohl( fh->forklen[ RESOURCE ] )); 536 fprintf( stderr, "get info comment\t\t\"%s\"\n", fh->comment ); 537#endif /* DEBUG */ 538 539 ad_getdate(&nad.ad, AD_DATE_CREATE, &temptime); 540 memcpy( &fh->create_date, &temptime, sizeof( temptime )); 541 ad_getdate(&nad.ad, AD_DATE_MODIFY, &temptime); 542 memcpy( &fh->mod_date, &temptime, sizeof( temptime )); 543 ad_getdate(&nad.ad, AD_DATE_BACKUP, &temptime); 544 memcpy( &fh->backup_date, &temptime, sizeof( temptime )); 545 546#if DEBUG 547 memcpy( &temptime, &fh->create_date, sizeof( temptime )); 548 temptime = AD_DATE_TO_UNIX(temptime); 549 fprintf( stderr, "create_date seconds\t\t%lu\n", temptime ); 550 memcpy( &temptime, &fh->mod_date, sizeof( temptime )); 551 temptime = AD_DATE_TO_UNIX(temptime); 552 fprintf( stderr, "mod_date seconds\t\t%lu\n", temptime ); 553 memcpy( &temptime, &fh->backup_date, sizeof( temptime )); 554 temptime = AD_DATE_TO_UNIX(temptime); 555 fprintf( stderr, "backup_date seconds\t\t%lu\n", temptime ); 556 fprintf( stderr, "size of finder_info\t\t%d\n", sizeof( fh->finder_info )); 557#endif /* DEBUG */ 558 559 memcpy(&fh->finder_info.fdType, 560 ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_TYPE, 561 sizeof( fh->finder_info.fdType )); 562 memcpy(&fh->finder_info.fdCreator, 563 ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_CREATOR, 564 sizeof( fh->finder_info.fdCreator )); 565 memcpy(&fh->finder_info.fdFlags, 566 ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_FLAGS, 567 sizeof( fh->finder_info.fdFlags )); 568 memcpy(&fh->finder_info.fdLocation, 569 ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_LOC, 570 sizeof( fh->finder_info.fdLocation )); 571 memcpy(&fh->finder_info.fdFldr, 572 ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_FLDR, 573 sizeof( fh->finder_info.fdFldr )); 574 memcpy(&fh->finder_xinfo.fdScript, 575 ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_SCRIPT, 576 sizeof(fh->finder_xinfo.fdScript)); 577 memcpy(&fh->finder_xinfo.fdXFlags, 578 ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_XFLAGS, 579 sizeof(fh->finder_xinfo.fdXFlags)); 580 581#if DEBUG 582 { 583 short flags; 584 fprintf( stderr, "finder_info.fdType\t\t%.*s\n", 585 sizeof( fh->finder_info.fdType ), &fh->finder_info.fdType ); 586 fprintf( stderr, "finder_info.fdCreator\t\t%.*s\n", 587 sizeof( fh->finder_info.fdCreator ), 588 &fh->finder_info.fdCreator ); 589 fprintf( stderr, "nad type and creator\t\t%.*s\n\n", 590 sizeof( fh->finder_info.fdType ) + 591 sizeof( fh->finder_info.fdCreator ), 592 ad_entry( &nad.ad, ADEID_FINDERI )); 593 memcpy(&flags, ad_entry( &nad.ad, ADEID_FINDERI ) + 594 FINDERIOFF_FLAGS, sizeof( flags )); 595 fprintf( stderr, "nad.ad flags\t\t\t%x\n", flags ); 596 fprintf( stderr, "fh flags\t\t\t%x\n", fh->finder_info.fdFlags ); 597 fprintf(stderr, "fh script\t\t\t%x\n", fh->finder_xinfo.fdScript); 598 fprintf(stderr, "fh xflags\t\t\t%x\n", fh->finder_xinfo.fdXFlags); 599 } 600#endif /* DEBUG */ 601 602 nad.offset[ DATA ] = nad.offset[ RESOURCE ] = 0; 603 604 return( 0 ); 605 606} 607 608int nad_header_write(struct FHeader *fh) 609{ 610 u_int32_t temptime; 611 612 ad_setentrylen( &nad.ad, ADEID_NAME, strlen( nad.macname )); 613 memcpy( ad_entry( &nad.ad, ADEID_NAME ), nad.macname, 614 ad_getentrylen( &nad.ad, ADEID_NAME )); 615 ad_setentrylen( &nad.ad, ADEID_COMMENT, strlen( fh->comment )); 616 memcpy( ad_entry( &nad.ad, ADEID_COMMENT ), fh->comment, 617 ad_getentrylen( &nad.ad, ADEID_COMMENT )); 618 ad_setentrylen( &nad.ad, ADEID_RFORK, ntohl( fh->forklen[ RESOURCE ] )); 619 620#if DEBUG 621 fprintf( stderr, "ad_getentrylen\n" ); 622 fprintf( stderr, "ADEID_FINDERI\t\t\t%d\n", 623 ad_getentrylen( &nad.ad, ADEID_FINDERI )); 624 fprintf( stderr, "ADEID_RFORK\t\t\t%d\n", 625 ad_getentrylen( &nad.ad, ADEID_RFORK )); 626 fprintf( stderr, "ADEID_NAME\t\t\t%d\n", 627 ad_getentrylen( &nad.ad, ADEID_NAME )); 628 fprintf( stderr, "ad_entry of ADEID_NAME\t\t%.*s\n", 629 ad_getentrylen( &nad.ad, ADEID_NAME ), 630 ad_entry( &nad.ad, ADEID_NAME )); 631 fprintf( stderr, "ADEID_COMMENT\t\t\t%d\n", 632 ad_getentrylen( &nad.ad, ADEID_COMMENT )); 633#endif /* DEBUG */ 634 635 memcpy( &temptime, &fh->create_date, sizeof( temptime )); 636 ad_setdate(&nad.ad, AD_DATE_CREATE, temptime); 637 memcpy( &temptime, &fh->mod_date, sizeof( temptime )); 638 ad_setdate(&nad.ad, AD_DATE_MODIFY, temptime); 639 640#if DEBUG 641 ad_getdate(&nad.ad, AD_DATE_CREATE, &temptime); 642 temptime = AD_DATE_TO_UNIX(temptime); 643 fprintf(stderr, "FILEIOFF_CREATE seconds\t\t%ld\n", temptime ); 644 ad_getdate(&nad.ad, AD_DATE_MODIFY, &temptime); 645 temptime = AD_DATE_TO_UNIX(temptime); 646 fprintf(stderr, "FILEIOFF_MODIFY seconds\t\t%ld\n", temptime ); 647#endif /* DEBUG */ 648 649 memset( ad_entry( &nad.ad, ADEID_FINDERI ), 0, ADEDLEN_FINDERI ); 650 memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_TYPE, 651 &fh->finder_info.fdType, sizeof( fh->finder_info.fdType )); 652 memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_CREATOR, 653 &fh->finder_info.fdCreator, sizeof( fh->finder_info.fdCreator )); 654 memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_FLAGS, 655 &fh->finder_info.fdFlags, sizeof( fh->finder_info.fdFlags )); 656 memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_LOC, 657 &fh->finder_info.fdLocation,sizeof( fh->finder_info.fdLocation )); 658 memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_FLDR, 659 &fh->finder_info.fdFldr, sizeof( fh->finder_info.fdFldr )); 660 memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_SCRIPT, 661 &fh->finder_xinfo.fdScript, sizeof( fh->finder_xinfo.fdScript )); 662 memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_XFLAGS, 663 &fh->finder_xinfo.fdXFlags, sizeof( fh->finder_xinfo.fdXFlags)); 664 665 666#if DEBUG 667 { 668 short flags; 669 memcpy(&flags, ( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_FLAGS), 670 sizeof( flags )); 671 fprintf( stderr, "nad.ad flags\t\t\t%x\n", flags ); 672 fprintf( stderr, "fh flags\t\t\t%x\n", fh->finder_info.fdFlags ); 673 fprintf( stderr, "fh xflags\t\t\t%x\n", fh->finder_xinfo.fdXFlags ); 674 fprintf( stderr, "type and creator\t\t%.*s\n\n", 675 sizeof( fh->finder_info.fdType ) + 676 sizeof( fh->finder_info.fdCreator ), 677 ad_entry( &nad.ad, ADEID_FINDERI )); 678 } 679#endif /* DEBUG */ 680 681#if HEXOUTPUT 682 hexfork[ DATA ] = open( "datafork", O_WRONLY|O_CREAT, 0622 ); 683 hexfork[ RESOURCE ] = open( "resfork", O_WRONLY|O_CREAT, 0622 ); 684#endif /* HEXOUTPUT */ 685 686 nad.offset[ DATA ] = nad.offset[ RESOURCE ] = 0; 687 ad_flush( &nad.ad ); 688 689 return( 0 ); 690} 691 692static int forkeid[] = { ADEID_DFORK, ADEID_RFORK }; 693 694ssize_t nad_read(int fork, char *forkbuf, size_t bufc) 695{ 696 ssize_t cc = 0; 697 698#if DEBUG 699 fprintf( stderr, "Entering nad_read\n" ); 700#endif /* DEBUG */ 701 702 if (( cc = ad_read( &nad.ad, forkeid[ fork ], nad.offset[ fork ], 703 forkbuf, bufc)) < 0 ) { 704 perror( "Reading the appledouble file:" ); 705 return( cc ); 706 } 707 nad.offset[ fork ] += cc; 708 709#if DEBUG 710 fprintf( stderr, "Exiting nad_read\n" ); 711#endif /* DEBUG */ 712 713 return( cc ); 714} 715 716ssize_t nad_write(int fork, char *forkbuf, size_t bufc) 717{ 718 char *buf_ptr; 719 size_t writelen; 720 ssize_t cc = 0; 721 722#if DEBUG 723 fprintf( stderr, "Entering nad_write\n" ); 724#endif /* DEBUG */ 725 726#if HEXOUTPUT 727 write( hexfork[ fork ], forkbuf, bufc ); 728#endif /* HEXOUTPUT */ 729 730 writelen = bufc; 731 buf_ptr = forkbuf; 732 733 while (( writelen > 0 ) && ( cc >= 0 )) { 734 cc = ad_write( &nad.ad, forkeid[ fork ], nad.offset[ fork ], 735 0, buf_ptr, writelen); 736 nad.offset[ fork ] += cc; 737 buf_ptr += cc; 738 writelen -= cc; 739 } 740 if ( cc < 0 ) { 741 perror( "Writing the appledouble file:" ); 742 return( cc ); 743 } 744 745 return( bufc ); 746} 747 748int nad_close(int status) 749{ 750 int rv; 751 if ( status == KEEP ) { 752 if (( rv = ad_flush( &nad.ad )) < 0 ) { 753 fprintf( stderr, "nad_close rv for flush %d\n", rv ); 754 return( rv ); 755 } 756 if (( rv = ad_close( &nad.ad, ADFLAGS_DF|ADFLAGS_HF )) < 0 ) { 757 fprintf( stderr, "nad_close rv for close %d\n", rv ); 758 return( rv ); 759 } 760 } else if ( status == TRASH ) { 761 if ( unlink( nad.adpath[ 0 ] ) < 0 ) { 762 perror ( nad.adpath[ 0 ] ); 763 } 764 if ( unlink( nad.adpath[ 1 ] ) < 0 ) { 765 perror ( nad.adpath[ 1 ] ); 766 } 767 return( 0 ); 768 } else return( -1 ); 769 return( 0 ); 770} 771