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