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