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