2 * $Id: nad.c,v 1.9 2002-01-04 04:45:47 sibaz Exp $
7 #endif /* HAVE_CONFIG_H */
10 #include <sys/param.h>
18 #include <atalk/logger.h>
22 #endif /* HAVE_FCNTL_H */
24 #include <atalk/adouble.h>
25 #include <netatalk/endian.h>
29 static char hexdig[] = "0123456789abcdef";
31 char *mtoupath( mpath )
34 static char upath[ MAXNAMLEN + 1];
40 while ( *m != '\0' ) {
41 #if AD_VERSION == AD_VERSION1
42 if ( !isascii( *m ) || *m == '/' || ( i == 0 && *m == '.' )) {
43 #else /* AD_VERSION == AD_VERSION1 */
44 if (!isprint(*m) || *m == '/' || ( i == 0 && (*m == '.' ))) {
45 #endif /* AD_VERSION == AD_VERSION1 */
47 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
48 *u++ = hexdig[ *m & 0x0f ];
51 *u++ = ( isupper( *m )) ? tolower( *m ) : *m;
64 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
65 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
67 char *utompath( upath )
70 static char mpath[ MAXNAMLEN + 1];
76 while ( *u != '\0' ) {
77 if (*u == ':' && *(u + 1) != '\0' && islxdigit(*(u+1)) &&
78 *(u+2) != '\0' && islxdigit(*(u+2))) {
80 h = hextoint(*u) << 4;
99 int hexfork[ NUMFORKS ];
100 #endif /* HEXOUTPUT */
102 struct nad_file_data {
103 char macname[ MAXPATHLEN + 1 ];
104 char adpath[ 2 ][ MAXPATHLEN + 1];
105 int offset[ NUMFORKS ];
109 int nad_open( path, openflags, fh, options )
111 int openflags, options;
118 * Depending upon openflags, set up nad.adpath for the open. If it
119 * is for write, then stat the current directory to get its mode.
120 * Open the file. Either fill or grab the adouble information.
122 memset(&nad.ad, 0, sizeof(nad.ad));
123 if ( openflags == O_RDONLY ) {
124 strcpy( nad.adpath[0], path );
125 strcpy( nad.adpath[1],
126 ad_path( nad.adpath[0], ADFLAGS_DF|ADFLAGS_HF ));
127 for ( fork = 0 ; fork < NUMFORKS ; fork++ ) {
128 if ( stat( nad.adpath[ fork ], &st ) < 0 ) {
129 if ( errno == ENOENT ) {
130 fprintf( stderr, "%s is not an adouble file.\n", path );
132 perror( "stat of adouble file failed" );
139 fprintf(stderr, "%s is adpath[0]\n", nad.adpath[0]);
140 fprintf(stderr, "%s is adpath[1]\n", nad.adpath[1]);
142 if ( ad_open( nad.adpath[ 0 ], ADFLAGS_DF|ADFLAGS_HF,
143 openflags, (int)( st.st_mode & 0666 ), &nad.ad) < 0 ) {
144 perror( nad.adpath[ 0 ] );
147 return( nad_header_read( fh ));
150 strcpy( nad.macname, fh->name );
151 strcpy( nad.adpath[0], mtoupath( nad.macname ));
152 strcpy( nad.adpath[1],
153 ad_path( nad.adpath[0], ADFLAGS_DF|ADFLAGS_HF ));
155 fprintf(stderr, "%s\n", nad.macname);
156 fprintf(stderr, "%s is adpath[0]\n", nad.adpath[0]);
157 fprintf(stderr, "%s is adpath[1]\n", nad.adpath[1]);
159 if ( stat( ".", &st ) < 0 ) {
160 perror( "stat of . failed" );
164 if ( ad_open( nad.adpath[ 0 ], ADFLAGS_DF|ADFLAGS_HF,
165 openflags, (int)( st.st_mode & 0666 ), &nad.ad) < 0 ) {
166 perror( nad.adpath[ 0 ] );
169 return( nad_header_write( fh ));
173 int nad_header_read( fh )
179 memcpy( nad.macname, ad_entry( &nad.ad, ADEID_NAME ),
180 ad_getentrylen( &nad.ad, ADEID_NAME ));
181 nad.macname[ ad_getentrylen( &nad.ad, ADEID_NAME ) ] = '\0';
182 strcpy( fh->name, nad.macname );
184 /* just in case there's nothing in macname */
185 if (*fh->name == '\0')
186 strcpy(fh->name, utompath(nad.adpath[DATA]));
188 if ( stat( nad.adpath[ DATA ], &st ) < 0 ) {
189 perror( "stat of datafork failed" );
192 fh->forklen[ DATA ] = htonl( st.st_size );
193 fh->forklen[ RESOURCE ] = htonl( ad_getentrylen( &nad.ad, ADEID_RFORK ));
194 fh->comment[0] = '\0';
197 fprintf( stderr, "macname of file\t\t\t%.*s\n", strlen( fh->name ),
199 fprintf( stderr, "size of data fork\t\t%d\n",
200 ntohl( fh->forklen[ DATA ] ));
201 fprintf( stderr, "size of resource fork\t\t%d\n",
202 ntohl( fh->forklen[ RESOURCE ] ));
203 fprintf( stderr, "get info comment\t\t\"%s\"\n", fh->comment );
206 ad_getdate(&nad.ad, AD_DATE_CREATE, &temptime);
207 memcpy( &fh->create_date, &temptime, sizeof( temptime ));
208 ad_getdate(&nad.ad, AD_DATE_MODIFY, &temptime);
209 memcpy( &fh->mod_date, &temptime, sizeof( temptime ));
210 ad_getdate(&nad.ad, AD_DATE_BACKUP, &temptime);
211 memcpy( &fh->backup_date, &temptime, sizeof( temptime ));
214 memcpy( &temptime, &fh->create_date, sizeof( temptime ));
215 temptime = AD_DATE_TO_UNIX(temptime);
216 fprintf( stderr, "create_date seconds\t\t%lu\n", temptime );
217 memcpy( &temptime, &fh->mod_date, sizeof( temptime ));
218 temptime = AD_DATE_TO_UNIX(temptime);
219 fprintf( stderr, "mod_date seconds\t\t%lu\n", temptime );
220 memcpy( &temptime, &fh->backup_date, sizeof( temptime ));
221 temptime = AD_DATE_TO_UNIX(temptime);
222 fprintf( stderr, "backup_date seconds\t\t%lu\n", temptime );
223 fprintf( stderr, "size of finder_info\t\t%d\n", sizeof( fh->finder_info ));
226 memcpy(&fh->finder_info.fdType,
227 ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_TYPE,
228 sizeof( fh->finder_info.fdType ));
229 memcpy(&fh->finder_info.fdCreator,
230 ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_CREATOR,
231 sizeof( fh->finder_info.fdCreator ));
232 memcpy(&fh->finder_info.fdFlags,
233 ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_FLAGS,
234 sizeof( fh->finder_info.fdFlags ));
235 memcpy(&fh->finder_info.fdLocation,
236 ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_LOC,
237 sizeof( fh->finder_info.fdLocation ));
238 memcpy(&fh->finder_info.fdFldr,
239 ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_FLDR,
240 sizeof( fh->finder_info.fdFldr ));
241 memcpy(&fh->finder_xinfo.fdScript,
242 ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_SCRIPT,
243 sizeof(fh->finder_xinfo.fdScript));
244 memcpy(&fh->finder_xinfo.fdXFlags,
245 ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_XFLAGS,
246 sizeof(fh->finder_xinfo.fdXFlags));
251 fprintf( stderr, "finder_info.fdType\t\t%.*s\n",
252 sizeof( fh->finder_info.fdType ), &fh->finder_info.fdType );
253 fprintf( stderr, "finder_info.fdCreator\t\t%.*s\n",
254 sizeof( fh->finder_info.fdCreator ),
255 &fh->finder_info.fdCreator );
256 fprintf( stderr, "nad type and creator\t\t%.*s\n\n",
257 sizeof( fh->finder_info.fdType ) +
258 sizeof( fh->finder_info.fdCreator ),
259 ad_entry( &nad.ad, ADEID_FINDERI ));
260 memcpy(&flags, ad_entry( &nad.ad, ADEID_FINDERI ) +
261 FINDERIOFF_FLAGS, sizeof( flags ));
262 fprintf( stderr, "nad.ad flags\t\t\t%x\n", flags );
263 fprintf( stderr, "fh flags\t\t\t%x\n", fh->finder_info.fdFlags );
264 fprintf(stderr, "fh script\t\t\t%x\n", fh->finder_xinfo.fdScript);
265 fprintf(stderr, "fh xflags\t\t\t%x\n", fh->finder_xinfo.fdXFlags);
269 nad.offset[ DATA ] = nad.offset[ RESOURCE ] = 0;
275 int nad_header_write( fh )
280 ad_setentrylen( &nad.ad, ADEID_NAME, strlen( nad.macname ));
281 memcpy( ad_entry( &nad.ad, ADEID_NAME ), nad.macname,
282 ad_getentrylen( &nad.ad, ADEID_NAME ));
283 ad_setentrylen( &nad.ad, ADEID_COMMENT, strlen( fh->comment ));
284 memcpy( ad_entry( &nad.ad, ADEID_COMMENT ), fh->comment,
285 ad_getentrylen( &nad.ad, ADEID_COMMENT ));
286 ad_setentrylen( &nad.ad, ADEID_RFORK, ntohl( fh->forklen[ RESOURCE ] ));
289 fprintf( stderr, "ad_getentrylen\n" );
290 fprintf( stderr, "ADEID_FINDERI\t\t\t%d\n",
291 ad_getentrylen( &nad.ad, ADEID_FINDERI ));
292 fprintf( stderr, "ADEID_RFORK\t\t\t%d\n",
293 ad_getentrylen( &nad.ad, ADEID_RFORK ));
294 fprintf( stderr, "ADEID_NAME\t\t\t%d\n",
295 ad_getentrylen( &nad.ad, ADEID_NAME ));
296 fprintf( stderr, "ad_entry of ADEID_NAME\t\t%.*s\n",
297 ad_getentrylen( &nad.ad, ADEID_NAME ),
298 ad_entry( &nad.ad, ADEID_NAME ));
299 fprintf( stderr, "ADEID_COMMENT\t\t\t%d\n",
300 ad_getentrylen( &nad.ad, ADEID_COMMENT ));
303 memcpy( &temptime, &fh->create_date, sizeof( temptime ));
304 ad_setdate(&nad.ad, AD_DATE_CREATE, temptime);
305 memcpy( &temptime, &fh->mod_date, sizeof( temptime ));
306 ad_setdate(&nad.ad, AD_DATE_MODIFY, temptime);
309 ad_getdate(&nad.ad, AD_DATE_CREATE, &temptime);
310 temptime = AD_DATE_TO_UNIX(temptime);
311 fprintf(stderr, "FILEIOFF_CREATE seconds\t\t%ld\n", temptime );
312 ad_getdate(&nad.ad, AD_DATE_MODIFY, &temptime);
313 temptime = AD_DATE_TO_UNIX(temptime);
314 fprintf(stderr, "FILEIOFF_MODIFY seconds\t\t%ld\n", temptime );
317 memset( ad_entry( &nad.ad, ADEID_FINDERI ), 0, ADEDLEN_FINDERI );
318 memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_TYPE,
319 &fh->finder_info.fdType, sizeof( fh->finder_info.fdType ));
320 memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_CREATOR,
321 &fh->finder_info.fdCreator, sizeof( fh->finder_info.fdCreator ));
322 memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_FLAGS,
323 &fh->finder_info.fdFlags, sizeof( fh->finder_info.fdFlags ));
324 memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_LOC,
325 &fh->finder_info.fdLocation,sizeof( fh->finder_info.fdLocation ));
326 memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_FLDR,
327 &fh->finder_info.fdFldr, sizeof( fh->finder_info.fdFldr ));
328 memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_SCRIPT,
329 &fh->finder_xinfo.fdScript, sizeof( fh->finder_xinfo.fdScript ));
330 memcpy( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_XFLAGS,
331 &fh->finder_xinfo.fdXFlags, sizeof( fh->finder_xinfo.fdXFlags));
337 memcpy(&flags, ( ad_entry( &nad.ad, ADEID_FINDERI ) + FINDERIOFF_FLAGS),
339 fprintf( stderr, "nad.ad flags\t\t\t%x\n", flags );
340 fprintf( stderr, "fh flags\t\t\t%x\n", fh->finder_info.fdFlags );
341 fprintf( stderr, "fh xflags\t\t\t%x\n", fh->finder_xinfo.fdXFlags );
342 fprintf( stderr, "type and creator\t\t%.*s\n\n",
343 sizeof( fh->finder_info.fdType ) +
344 sizeof( fh->finder_info.fdCreator ),
345 ad_entry( &nad.ad, ADEID_FINDERI ));
350 hexfork[ DATA ] = open( "datafork", O_WRONLY|O_CREAT, 0622 );
351 hexfork[ RESOURCE ] = open( "resfork", O_WRONLY|O_CREAT, 0622 );
352 #endif /* HEXOUTPUT */
354 nad.offset[ DATA ] = nad.offset[ RESOURCE ] = 0;
355 ad_flush( &nad.ad, ADFLAGS_DF|ADFLAGS_HF );
360 int forkeid[] = { ADEID_DFORK, ADEID_RFORK };
362 int nad_read( fork, forkbuf, bufc )
370 fprintf( stderr, "Entering nad_read\n" );
373 if (( cc = ad_read( &nad.ad, forkeid[ fork ], nad.offset[ fork ],
374 forkbuf, bufc)) < 0 ) {
375 perror( "Reading the appledouble file:" );
378 nad.offset[ fork ] += cc;
381 fprintf( stderr, "Exiting nad_read\n" );
387 int nad_write( fork, forkbuf, bufc )
397 fprintf( stderr, "Entering nad_write\n" );
401 write( hexfork[ fork ], forkbuf, bufc );
402 #endif /* HEXOUTPUT */
407 while (( writelen > 0 ) && ( cc >= 0 )) {
408 cc = ad_write( &nad.ad, forkeid[ fork ], nad.offset[ fork ],
409 0, buf_ptr, writelen);
410 nad.offset[ fork ] += cc;
415 perror( "Writing the appledouble file:" );
422 int nad_close( status )
426 if ( status == KEEP ) {
427 if (( rv = ad_flush( &nad.ad, ADFLAGS_DF|ADFLAGS_HF )) < 0 ) {
428 fprintf( stderr, "nad_close rv for flush %d\n", rv );
431 if (( rv = ad_close( &nad.ad, ADFLAGS_DF|ADFLAGS_HF )) < 0 ) {
432 fprintf( stderr, "nad_close rv for close %d\n", rv );
435 } else if ( status == TRASH ) {
436 if ( unlink( nad.adpath[ 0 ] ) < 0 ) {
437 perror ( nad.adpath[ 0 ] );
439 if ( unlink( nad.adpath[ 1 ] ) < 0 ) {
440 perror ( nad.adpath[ 1 ] );