18 #include <atalk/adouble.h>
19 #include <netatalk/endian.h>
22 static char hexdig[] = "0123456789abcdef";
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);
32 char *mtoupath( mpath )
35 static char upath[ MAXNAMLEN + 1];
41 while ( *m != '\0' ) {
42 #if AD_VERSION == AD_VERSION1
43 if ( !isascii( *m ) || *m == '/' || ( i == 0 && *m == '.' )) {
45 if (!isprint(*m) || *m == '/' || ( i == 0 && (*m == '.' ))) {
48 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
49 *u++ = hexdig[ *m & 0x0f ];
52 *u++ = ( isupper( *m )) ? tolower( *m ) : *m;
65 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
66 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
68 char *utompath( upath )
71 static char mpath[ MAXNAMLEN + 1];
77 while ( *u != '\0' ) {
78 if (*u == ':' && *(u + 1) != '\0' && islxdigit(*(u+1)) &&
79 *(u+2) != '\0' && islxdigit(*(u+2))) {
81 h = hextoint(*u) << 4;
100 int hexfork[ NUMFORKS ];
103 struct nad_file_data {
104 char macname[ MAXPATHLEN + 1 ];
105 char adpath[ 2 ][ MAXPATHLEN + 1];
106 int offset[ NUMFORKS ];
110 int nad_open( path, openflags, fh, options )
112 int openflags, options;
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.
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 );
133 perror( "stat of adouble file failed" );
140 fprintf(stderr, "%s is adpath[0]\n", nad.adpath[0]);
141 fprintf(stderr, "%s is adpath[1]\n", nad.adpath[1]);
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 ] );
148 return( nad_header_read( fh ));
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 ));
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]);
160 if ( stat( ".", &st ) < 0 ) {
161 perror( "stat of . failed" );
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 ] );
170 return( nad_header_write( fh ));
174 int nad_header_read( fh )
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 );
185 /* just in case there's nothing in macname */
186 if (*fh->name == '\0')
187 strcpy(fh->name, utompath(nad.adpath[DATA]));
189 if ( stat( nad.adpath[ DATA ], &st ) < 0 ) {
190 perror( "stat of datafork failed" );
193 fh->forklen[ DATA ] = htonl( st.st_size );
194 fh->forklen[ RESOURCE ] = htonl( ad_getentrylen( &nad.ad, ADEID_RFORK ));
195 fh->comment[0] = '\0';
198 fprintf( stderr, "macname of file\t\t\t%.*s\n", strlen( 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 );
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 ));
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 ));
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));
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);
270 nad.offset[ DATA ] = nad.offset[ RESOURCE ] = 0;
276 int nad_header_write( fh )
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 ] ));
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 ));
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);
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 );
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));
338 memcpy(&flags, ( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_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 ));
351 hexfork[ DATA ] = open( "datafork", O_WRONLY|O_CREAT, 0622 );
352 hexfork[ RESOURCE ] = open( "resfork", O_WRONLY|O_CREAT, 0622 );
355 nad.offset[ DATA ] = nad.offset[ RESOURCE ] = 0;
356 ad_flush( &nad.ad, ADFLAGS_DF|ADFLAGS_HF );
361 int forkeid[] = { ADEID_DFORK, ADEID_RFORK };
363 int nad_read( fork, forkbuf, bufc )
371 fprintf( stderr, "Entering nad_read\n" );
374 if (( cc = ad_read( &nad.ad, forkeid[ fork ], nad.offset[ fork ],
375 forkbuf, bufc)) < 0 ) {
376 perror( "Reading the appledouble file:" );
379 nad.offset[ fork ] += cc;
382 fprintf( stderr, "Exiting nad_read\n" );
388 int nad_write( fork, forkbuf, bufc )
398 fprintf( stderr, "Entering nad_write\n" );
402 write( hexfork[ fork ], forkbuf, bufc );
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;
416 perror( "Writing the appledouble file:" );
423 int nad_close( status )
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 );
432 if (( rv = ad_close( &nad.ad, ADFLAGS_DF|ADFLAGS_HF )) < 0 ) {
433 fprintf( stderr, "nad_close rv for close %d\n", rv );
436 } else if ( status == TRASH ) {
437 if ( unlink( nad.adpath[ 0 ] ) < 0 ) {
438 perror ( nad.adpath[ 0 ] );
440 if ( unlink( nad.adpath[ 1 ] ) < 0 ) {
441 perror ( nad.adpath[ 1 ] );