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