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