18 #include <atalk/adouble.h>
19 #include <netatalk/endian.h>
22 static char hexdig[] = "0123456789abcdef";
24 char *mtoupath( mpath )
27 static char upath[ MAXNAMLEN + 1];
33 while ( *m != '\0' ) {
34 #if AD_VERSION == AD_VERSION1
35 if ( !isascii( *m ) || *m == '/' || ( i == 0 && *m == '.' )) {
37 if (!isprint(*m) || *m == '/' || ( i == 0 && (*m == '.' ))) {
40 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
41 *u++ = hexdig[ *m & 0x0f ];
44 *u++ = ( isupper( *m )) ? tolower( *m ) : *m;
57 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
58 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
60 char *utompath( upath )
63 static char mpath[ MAXNAMLEN + 1];
69 while ( *u != '\0' ) {
70 if (*u == ':' && *(u + 1) != '\0' && islxdigit(*(u+1)) &&
71 *(u+2) != '\0' && islxdigit(*(u+2))) {
73 h = hextoint(*u) << 4;
92 int hexfork[ NUMFORKS ];
95 struct nad_file_data {
96 char macname[ MAXPATHLEN + 1 ];
97 char adpath[ 2 ][ MAXPATHLEN + 1];
98 int offset[ NUMFORKS ];
102 nad_open( path, openflags, fh, options )
104 int openflags, options;
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.
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 );
125 perror( "stat of adouble file failed" );
132 fprintf(stderr, "%s is adpath[0]\n", nad.adpath[0]);
133 fprintf(stderr, "%s is adpath[1]\n", nad.adpath[1]);
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 ] );
140 return( nad_header_read( fh ));
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 ));
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]);
152 if ( stat( ".", &st ) < 0 ) {
153 perror( "stat of . failed" );
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 ] );
162 return( nad_header_write( fh ));
166 nad_header_read( fh )
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 );
177 /* just in case there's nothing in macname */
178 if (*fh->name == '\0')
179 strcpy(fh->name, utompath(nad.adpath[DATA]));
181 if ( stat( nad.adpath[ DATA ], &st ) < 0 ) {
182 perror( "stat of datafork failed" );
185 fh->forklen[ DATA ] = htonl( st.st_size );
186 fh->forklen[ RESOURCE ] = htonl( ad_getentrylen( &nad.ad, ADEID_RFORK ));
187 fh->comment[0] = '\0';
190 fprintf( stderr, "macname of file\t\t\t%.*s\n", strlen( 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 );
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 ));
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 ));
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));
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);
262 nad.offset[ DATA ] = nad.offset[ RESOURCE ] = 0;
268 nad_header_write( fh )
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 ] ));
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 ));
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);
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 );
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));
330 memcpy(&flags, ( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_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 ));
343 hexfork[ DATA ] = open( "datafork", O_WRONLY|O_CREAT, 0622 );
344 hexfork[ RESOURCE ] = open( "resfork", O_WRONLY|O_CREAT, 0622 );
347 nad.offset[ DATA ] = nad.offset[ RESOURCE ] = 0;
348 ad_flush( &nad.ad, ADFLAGS_DF|ADFLAGS_HF );
353 int forkeid[] = { ADEID_DFORK, ADEID_RFORK };
355 nad_read( fork, forkbuf, bufc )
363 fprintf( stderr, "Entering nad_read\n" );
366 if (( cc = ad_read( &nad.ad, forkeid[ fork ], nad.offset[ fork ],
367 forkbuf, bufc)) < 0 ) {
368 perror( "Reading the appledouble file:" );
371 nad.offset[ fork ] += cc;
374 fprintf( stderr, "Exiting nad_read\n" );
380 nad_write( fork, forkbuf, bufc )
390 fprintf( stderr, "Entering nad_write\n" );
394 write( hexfork[ fork ], forkbuf, bufc );
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;
408 perror( "Writing the appledouble file:" );
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 );
424 if (( rv = ad_close( &nad.ad, ADFLAGS_DF|ADFLAGS_HF )) < 0 ) {
425 fprintf( stderr, "nad_close rv for close %d\n", rv );
428 } else if ( status == TRASH ) {
429 if ( unlink( nad.adpath[ 0 ] ) < 0 ) {
430 perror ( nad.adpath[ 0 ] );
432 if ( unlink( nad.adpath[ 1 ] ) < 0 ) {
433 perror ( nad.adpath[ 1 ] );