]> arthur.barton.de Git - netatalk.git/blob - bin/megatron/nad.c
250f51ac196a501be670979e2b5f63d4c06c0886
[netatalk.git] / bin / megatron / nad.c
1 /*
2  * $Id: nad.c,v 1.17 2009-10-14 01:38:28 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
30 static struct volinfo   vol;
31 static char             hexdig[] = "0123456789abcdef";
32
33 static char mtou_buf[MAXPATHLEN + 1], utom_buf[MAXPATHLEN + 1];
34 static 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
69 static 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
98 static 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
115 static 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
136 static 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
186 static 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
227 static 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
274 static 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
313 static 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
343 utompath_error:
344     return(utompathcap( upath ));
345 }
346
347 static 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  
388 char * (*_mtoupath) ( char *mpath) = mtoupathcap;
389 char * (*_utompath) ( char *upath) = utompathcap;
390
391 /* choose translators for optional character set */
392 void 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
412 static 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
419 static 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
432 int 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
497 int 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
608 int 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
692 static int              forkeid[] = { ADEID_DFORK, ADEID_RFORK };
693
694 int nad_read(int fork, char *forkbuf, int bufc)
695 {
696     int                 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
716 int nad_write(int fork, char *forkbuf, int bufc)
717 {
718     char                *buf_ptr;
719     int                 writelen;
720     int                 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
748 int 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 }