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