]> arthur.barton.de Git - netatalk.git/blob - bin/megatron/nad.c
merged logging code into main branch. use configure option --without-logfile to...
[netatalk.git] / bin / megatron / nad.c
1 /*
2  * $Id: nad.c,v 1.9 2002-01-04 04:45:47 sibaz 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 <atalk/logger.h>
19 #include <dirent.h>
20 #ifdef HAVE_FCNTL_H
21 #include <fcntl.h>
22 #endif /* HAVE_FCNTL_H */
23
24 #include <atalk/adouble.h>
25 #include <netatalk/endian.h>
26 #include "megatron.h"
27 #include "nad.h"
28
29 static char             hexdig[] = "0123456789abcdef";
30
31 char *mtoupath( mpath )
32     char        *mpath;
33 {
34     static char upath[ MAXNAMLEN  + 1];
35     char        *m, *u;
36     int         i = 0;
37
38     m = mpath;
39     u = upath;
40     while ( *m != '\0' ) {
41 #if AD_VERSION == AD_VERSION1
42         if ( !isascii( *m ) || *m == '/' || ( i == 0 && *m == '.' )) {
43 #else /* AD_VERSION == AD_VERSION1 */
44         if (!isprint(*m) || *m == '/' || ( i == 0 && (*m == '.' ))) {
45 #endif /* AD_VERSION == AD_VERSION1 */
46             *u++ = ':';
47             *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
48             *u++ = hexdig[ *m & 0x0f ];
49         } else {
50 #ifdef DOWNCASE
51             *u++ = ( isupper( *m )) ? tolower( *m ) : *m;
52 #else /* DOWNCASE */
53             *u++ = *m;
54 #endif /* DOWNCASE */
55         }
56         i++;
57         m++;
58     }
59     *u = '\0';
60     return( upath );
61 }
62
63
64 #define hextoint( c )   ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
65 #define islxdigit(x)    (!isupper(x)&&isxdigit(x))
66
67 char *utompath( upath )
68     char        *upath;
69 {
70     static char mpath[ MAXNAMLEN  + 1];
71     char        *m, *u;
72     int h;
73
74     m = mpath;
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( mpath );
96 }
97
98 #if HEXOUTPUT
99     int                 hexfork[ NUMFORKS ];
100 #endif /* HEXOUTPUT */
101
102 struct nad_file_data {
103     char                macname[ MAXPATHLEN + 1 ];
104     char                adpath[ 2 ][ MAXPATHLEN + 1];
105     int                 offset[ NUMFORKS ];
106     struct adouble      ad;
107 } nad;
108
109 int nad_open( path, openflags, fh, options )
110     char                *path;
111     int                 openflags, options;
112     struct FHeader      *fh;
113 {
114     struct stat         st;
115     int                 fork;
116
117 /*
118  * Depending upon openflags, set up nad.adpath for the open.  If it 
119  * is for write, then stat the current directory to get its mode.
120  * Open the file.  Either fill or grab the adouble information.
121  */
122     memset(&nad.ad, 0, sizeof(nad.ad));
123     if ( openflags == O_RDONLY ) {
124         strcpy( nad.adpath[0], path );
125         strcpy( nad.adpath[1], 
126                 ad_path( nad.adpath[0], ADFLAGS_DF|ADFLAGS_HF ));
127         for ( fork = 0 ; fork < NUMFORKS ; fork++ ) {
128             if ( stat( nad.adpath[ fork ], &st ) < 0 ) {
129                 if ( errno == ENOENT ) {
130                     fprintf( stderr, "%s is not an adouble file.\n", path );
131                 } else {
132                     perror( "stat of adouble file failed" );
133                 }
134                 return( -1 );
135             }
136         }
137
138 #if DEBUG
139     fprintf(stderr, "%s is adpath[0]\n", nad.adpath[0]);
140     fprintf(stderr, "%s is adpath[1]\n", nad.adpath[1]);
141 #endif /* DEBUG */
142         if ( ad_open( nad.adpath[ 0 ], ADFLAGS_DF|ADFLAGS_HF,
143                 openflags, (int)( st.st_mode & 0666 ), &nad.ad) < 0 ) {
144             perror( nad.adpath[ 0 ] );
145             return( -1 );
146         }
147         return( nad_header_read( fh ));
148
149     } else {
150         strcpy( nad.macname, fh->name );
151         strcpy( nad.adpath[0], mtoupath( nad.macname ));
152         strcpy( nad.adpath[1], 
153                 ad_path( nad.adpath[0], ADFLAGS_DF|ADFLAGS_HF ));
154 #if DEBUG
155     fprintf(stderr, "%s\n", nad.macname);
156     fprintf(stderr, "%s is adpath[0]\n", nad.adpath[0]);
157     fprintf(stderr, "%s is adpath[1]\n", nad.adpath[1]);
158 #endif /* DEBUG */
159         if ( stat( ".", &st ) < 0 ) {
160             perror( "stat of . failed" );
161             return( -1 );
162         }
163         (void)umask( 0 );
164         if ( ad_open( nad.adpath[ 0 ], ADFLAGS_DF|ADFLAGS_HF,
165                 openflags, (int)( st.st_mode & 0666 ), &nad.ad) < 0 ) {
166             perror( nad.adpath[ 0 ] );
167             return( -1 );
168         }
169         return( nad_header_write( fh ));
170     }
171 }
172
173 int nad_header_read( fh )
174     struct FHeader      *fh;
175 {
176     u_int32_t           temptime;
177     struct stat         st;
178
179     memcpy( nad.macname, ad_entry( &nad.ad, ADEID_NAME ), 
180             ad_getentrylen( &nad.ad, ADEID_NAME ));
181     nad.macname[ ad_getentrylen( &nad.ad, ADEID_NAME ) ] = '\0';
182     strcpy( fh->name, nad.macname );
183
184     /* just in case there's nothing in macname */
185     if (*fh->name == '\0')
186       strcpy(fh->name, utompath(nad.adpath[DATA]));
187
188     if ( stat( nad.adpath[ DATA ], &st ) < 0 ) {
189         perror( "stat of datafork failed" );
190         return( -1 );
191     }
192     fh->forklen[ DATA ] = htonl( st.st_size );
193     fh->forklen[ RESOURCE ] = htonl( ad_getentrylen( &nad.ad, ADEID_RFORK ));
194     fh->comment[0] = '\0';
195
196 #if DEBUG
197     fprintf( stderr, "macname of file\t\t\t%.*s\n", strlen( fh->name ), 
198             fh->name );
199     fprintf( stderr, "size of data fork\t\t%d\n", 
200             ntohl( fh->forklen[ DATA ] ));
201     fprintf( stderr, "size of resource fork\t\t%d\n", 
202             ntohl( fh->forklen[ RESOURCE ] ));
203     fprintf( stderr, "get info comment\t\t\"%s\"\n", fh->comment );
204 #endif /* DEBUG */
205
206     ad_getdate(&nad.ad, AD_DATE_CREATE, &temptime);
207     memcpy( &fh->create_date, &temptime, sizeof( temptime ));
208     ad_getdate(&nad.ad, AD_DATE_MODIFY, &temptime);
209     memcpy( &fh->mod_date, &temptime, sizeof( temptime ));
210     ad_getdate(&nad.ad, AD_DATE_BACKUP, &temptime);
211     memcpy( &fh->backup_date, &temptime, sizeof( temptime ));
212
213 #if DEBUG
214     memcpy( &temptime, &fh->create_date, sizeof( temptime ));
215     temptime = AD_DATE_TO_UNIX(temptime);
216     fprintf( stderr, "create_date seconds\t\t%lu\n", temptime );
217     memcpy( &temptime, &fh->mod_date, sizeof( temptime ));
218     temptime = AD_DATE_TO_UNIX(temptime);
219     fprintf( stderr, "mod_date seconds\t\t%lu\n", temptime );
220     memcpy( &temptime, &fh->backup_date, sizeof( temptime ));
221     temptime = AD_DATE_TO_UNIX(temptime);
222     fprintf( stderr, "backup_date seconds\t\t%lu\n", temptime );
223     fprintf( stderr, "size of finder_info\t\t%d\n", sizeof( fh->finder_info ));
224 #endif /* DEBUG */
225
226     memcpy(&fh->finder_info.fdType,
227             ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_TYPE,
228            sizeof( fh->finder_info.fdType ));
229     memcpy(&fh->finder_info.fdCreator,
230            ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_CREATOR,
231            sizeof( fh->finder_info.fdCreator ));
232     memcpy(&fh->finder_info.fdFlags,
233            ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_FLAGS,
234            sizeof( fh->finder_info.fdFlags ));
235     memcpy(&fh->finder_info.fdLocation,
236            ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_LOC,
237            sizeof( fh->finder_info.fdLocation ));
238     memcpy(&fh->finder_info.fdFldr,
239           ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_FLDR,
240           sizeof( fh->finder_info.fdFldr ));
241     memcpy(&fh->finder_xinfo.fdScript,
242            ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_SCRIPT,
243            sizeof(fh->finder_xinfo.fdScript));
244     memcpy(&fh->finder_xinfo.fdXFlags,
245            ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_XFLAGS,
246            sizeof(fh->finder_xinfo.fdXFlags));
247
248 #if DEBUG
249     {
250         short           flags;
251         fprintf( stderr, "finder_info.fdType\t\t%.*s\n", 
252                 sizeof( fh->finder_info.fdType ), &fh->finder_info.fdType );
253         fprintf( stderr, "finder_info.fdCreator\t\t%.*s\n", 
254                 sizeof( fh->finder_info.fdCreator ),
255                 &fh->finder_info.fdCreator );
256         fprintf( stderr, "nad type and creator\t\t%.*s\n\n", 
257                 sizeof( fh->finder_info.fdType ) + 
258                 sizeof( fh->finder_info.fdCreator ), 
259                 ad_entry( &nad.ad, ADEID_FINDERI ));
260         memcpy(&flags, ad_entry( &nad.ad, ADEID_FINDERI ) + 
261                FINDERIOFF_FLAGS, sizeof( flags ));
262         fprintf( stderr, "nad.ad flags\t\t\t%x\n", flags );
263         fprintf( stderr, "fh flags\t\t\t%x\n", fh->finder_info.fdFlags );
264         fprintf(stderr, "fh script\t\t\t%x\n", fh->finder_xinfo.fdScript);
265         fprintf(stderr, "fh xflags\t\t\t%x\n", fh->finder_xinfo.fdXFlags);
266     }
267 #endif /* DEBUG */
268
269     nad.offset[ DATA ] = nad.offset[ RESOURCE ] = 0;
270
271     return( 0 );
272
273 }
274
275 int nad_header_write( fh )
276     struct FHeader      *fh;
277 {
278     u_int32_t           temptime;
279
280     ad_setentrylen( &nad.ad, ADEID_NAME, strlen( nad.macname ));
281     memcpy( ad_entry( &nad.ad, ADEID_NAME ), nad.macname, 
282             ad_getentrylen( &nad.ad, ADEID_NAME ));
283     ad_setentrylen( &nad.ad, ADEID_COMMENT, strlen( fh->comment ));
284     memcpy( ad_entry( &nad.ad, ADEID_COMMENT ), fh->comment, 
285             ad_getentrylen( &nad.ad, ADEID_COMMENT ));
286     ad_setentrylen( &nad.ad, ADEID_RFORK, ntohl( fh->forklen[ RESOURCE ] ));
287
288 #if DEBUG
289     fprintf( stderr, "ad_getentrylen\n" );
290     fprintf( stderr, "ADEID_FINDERI\t\t\t%d\n", 
291             ad_getentrylen( &nad.ad, ADEID_FINDERI ));
292     fprintf( stderr, "ADEID_RFORK\t\t\t%d\n", 
293             ad_getentrylen( &nad.ad, ADEID_RFORK ));
294     fprintf( stderr, "ADEID_NAME\t\t\t%d\n",
295             ad_getentrylen( &nad.ad, ADEID_NAME ));
296     fprintf( stderr, "ad_entry of ADEID_NAME\t\t%.*s\n",
297             ad_getentrylen( &nad.ad, ADEID_NAME ), 
298             ad_entry( &nad.ad, ADEID_NAME ));
299     fprintf( stderr, "ADEID_COMMENT\t\t\t%d\n",
300              ad_getentrylen( &nad.ad, ADEID_COMMENT ));
301 #endif /* DEBUG */
302
303     memcpy( &temptime, &fh->create_date, sizeof( temptime ));
304     ad_setdate(&nad.ad, AD_DATE_CREATE, temptime);
305     memcpy( &temptime, &fh->mod_date, sizeof( temptime ));
306     ad_setdate(&nad.ad, AD_DATE_MODIFY, temptime);
307
308 #if DEBUG
309     ad_getdate(&nad.ad, AD_DATE_CREATE, &temptime);
310     temptime = AD_DATE_TO_UNIX(temptime);
311     fprintf(stderr, "FILEIOFF_CREATE seconds\t\t%ld\n", temptime );
312     ad_getdate(&nad.ad, AD_DATE_MODIFY, &temptime);
313     temptime = AD_DATE_TO_UNIX(temptime);
314     fprintf(stderr, "FILEIOFF_MODIFY seconds\t\t%ld\n", temptime );
315 #endif /* DEBUG */
316
317     memset( ad_entry( &nad.ad, ADEID_FINDERI ), 0, ADEDLEN_FINDERI );
318     memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_TYPE, 
319             &fh->finder_info.fdType, sizeof( fh->finder_info.fdType ));
320     memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_CREATOR,
321            &fh->finder_info.fdCreator, sizeof( fh->finder_info.fdCreator ));
322     memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_FLAGS,
323             &fh->finder_info.fdFlags, sizeof( fh->finder_info.fdFlags ));
324     memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_LOC,
325             &fh->finder_info.fdLocation,sizeof( fh->finder_info.fdLocation ));
326     memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_FLDR,
327             &fh->finder_info.fdFldr, sizeof( fh->finder_info.fdFldr ));
328     memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_SCRIPT,
329             &fh->finder_xinfo.fdScript, sizeof( fh->finder_xinfo.fdScript ));
330     memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_XFLAGS,
331             &fh->finder_xinfo.fdXFlags, sizeof( fh->finder_xinfo.fdXFlags));
332
333
334 #if DEBUG
335     {
336         short           flags;
337         memcpy(&flags, ( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_FLAGS),
338                 sizeof( flags ));
339         fprintf( stderr, "nad.ad flags\t\t\t%x\n", flags );
340         fprintf( stderr, "fh flags\t\t\t%x\n", fh->finder_info.fdFlags );
341         fprintf( stderr, "fh xflags\t\t\t%x\n", fh->finder_xinfo.fdXFlags );
342         fprintf( stderr, "type and creator\t\t%.*s\n\n", 
343                 sizeof( fh->finder_info.fdType ) + 
344                 sizeof( fh->finder_info.fdCreator ),
345                 ad_entry( &nad.ad, ADEID_FINDERI ));
346     }
347 #endif /* DEBUG */
348
349 #if HEXOUTPUT
350     hexfork[ DATA ] = open( "datafork", O_WRONLY|O_CREAT, 0622 );
351     hexfork[ RESOURCE ] = open( "resfork", O_WRONLY|O_CREAT, 0622 );
352 #endif /* HEXOUTPUT */
353
354     nad.offset[ DATA ] = nad.offset[ RESOURCE ] = 0;
355     ad_flush( &nad.ad, ADFLAGS_DF|ADFLAGS_HF );
356
357     return( 0 );
358 }
359
360 int                     forkeid[] = { ADEID_DFORK, ADEID_RFORK };
361
362 int nad_read( fork, forkbuf, bufc )
363     int                 fork;
364     char                *forkbuf;
365     int                 bufc;
366 {
367     int                 cc = 0;
368
369 #if DEBUG
370     fprintf( stderr, "Entering nad_read\n" );
371 #endif /* DEBUG */
372
373     if (( cc = ad_read( &nad.ad, forkeid[ fork ], nad.offset[ fork ], 
374             forkbuf, bufc)) < 0 )  {
375         perror( "Reading the appledouble file:" );
376         return( cc );
377     }
378     nad.offset[ fork ] += cc;
379
380 #if DEBUG
381     fprintf( stderr, "Exiting nad_read\n" );
382 #endif /* DEBUG */
383
384     return( cc );
385 }
386
387 int nad_write( fork, forkbuf, bufc )
388     int                 fork;
389     char                *forkbuf;
390     int                 bufc;
391 {
392     char                *buf_ptr;
393     int                 writelen;
394     int                 cc = 0;
395
396 #if DEBUG
397     fprintf( stderr, "Entering nad_write\n" );
398 #endif /* DEBUG */
399
400 #if HEXOUTPUT
401     write( hexfork[ fork ], forkbuf, bufc );
402 #endif /* HEXOUTPUT */
403
404     writelen = bufc;
405     buf_ptr = forkbuf;
406
407     while (( writelen > 0 ) && ( cc >= 0 )) {
408         cc =  ad_write( &nad.ad, forkeid[ fork ], nad.offset[ fork ], 
409                 0, buf_ptr, writelen);
410         nad.offset[ fork ] += cc;
411         buf_ptr += cc;
412         writelen -= cc;
413     }
414     if ( cc < 0 ) {
415         perror( "Writing the appledouble file:" );
416         return( cc );
417     }
418
419     return( bufc );
420 }
421
422 int nad_close( status )
423 int                     status;
424 {
425     int                 rv;
426     if ( status == KEEP ) {
427         if (( rv = ad_flush( &nad.ad, ADFLAGS_DF|ADFLAGS_HF )) < 0 ) {
428             fprintf( stderr, "nad_close rv for flush %d\n", rv );
429             return( rv );
430         }
431         if (( rv = ad_close( &nad.ad, ADFLAGS_DF|ADFLAGS_HF )) < 0 ) {
432             fprintf( stderr, "nad_close rv for close %d\n", rv );
433             return( rv );
434         }
435     } else if ( status == TRASH ) {
436         if ( unlink( nad.adpath[ 0 ] ) < 0 ) {
437             perror ( nad.adpath[ 0 ] );
438         }
439         if ( unlink( nad.adpath[ 1 ] ) < 0 ) {
440             perror ( nad.adpath[ 1 ] );
441         }
442         return( 0 );
443     } else return( -1 );
444     return( 0 );
445 }