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