2 * Copyright (c) 1990,1993 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
10 #include <sys/syslog.h>
12 #include <sys/types.h>
15 #include <sys/param.h>
17 #include <sys/socket.h>
18 #include <netatalk/at.h>
19 #include <netatalk/endian.h>
20 #include <atalk/dsi.h>
21 #include <atalk/atp.h>
22 #include <atalk/asp.h>
23 #include <atalk/afp.h>
24 #include <atalk/adouble.h>
25 #include <atalk/util.h>
34 #include "directory.h"
39 int afp_opendt(obj, ibuf, ibuflen, rbuf, rbuflen )
42 int ibuflen, *rbuflen;
49 memcpy( &vid, ibuf, sizeof(vid));
50 if (( vol = getvolbyvid( vid )) == NULL ) {
52 return( AFPERR_PARAM );
55 memcpy( rbuf, &vid, sizeof(vid));
56 *rbuflen = sizeof(vid);
60 int afp_closedt(obj, ibuf, ibuflen, rbuf, rbuflen )
63 int ibuflen, *rbuflen;
69 struct savedt si = { { 0, 0, 0, 0 }, -1, 0 };
71 static int iconopen( vol, creator, flags, mode )
75 char *dtf, *adt, *adts;
77 if ( si.sdt_fd != -1 ) {
78 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
79 si.sdt_vid == vol->v_vid ) {
86 dtf = dtfile( vol, creator, ".icon" );
88 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
89 if ( errno == ENOENT && ( flags & O_CREAT )) {
90 if (( adts = strrchr( dtf, '/' )) == NULL ) {
94 if (( adt = strrchr( dtf, '/' )) == NULL ) {
98 (void) ad_mkdir( dtf, DIRBITS | 0777 );
100 (void) ad_mkdir( dtf, DIRBITS | 0777 );
103 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
104 syslog( LOG_ERR, "iconopen: open %s: %m", dtf );
112 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
113 si.sdt_vid = vol->v_vid;
118 int afp_addicon(obj, ibuf, ibuflen, rbuf, rbuflen)
121 int ibuflen, *rbuflen;
124 struct iovec iov[ 2 ];
125 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
126 int itype, cc = AFP_OK, iovcnt = 0, buflen;
127 u_int32_t ftype, itag;
128 u_int16_t bsize, rsize, vid;
134 memcpy( &vid, ibuf, sizeof( vid ));
135 ibuf += sizeof( vid );
136 if (( vol = getvolbyvid( vid )) == NULL ) {
141 memcpy( fcreator, ibuf, sizeof( fcreator ));
142 ibuf += sizeof( fcreator );
144 memcpy( &ftype, ibuf, sizeof( ftype ));
145 ibuf += sizeof( ftype );
147 itype = (unsigned char) *ibuf;
150 memcpy( &itag, ibuf, sizeof( itag ));
151 ibuf += sizeof( itag );
153 memcpy( &bsize, ibuf, sizeof( bsize ));
154 bsize = ntohs( bsize );
156 if ( si.sdt_fd != -1 ) {
157 (void)close( si.sdt_fd );
161 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
166 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
169 syslog( LOG_ERR, "afp_addicon: lseek: %m" );
175 * Read icon elements until we find a match to replace, or
176 * we get to the end to insert.
179 memcpy( p, &itag, sizeof( itag ));
181 memcpy( p, &ftype, sizeof( ftype ));
182 p += sizeof( ftype );
185 bsize = htons( bsize );
186 memcpy( p, &bsize, sizeof( bsize ));
187 bsize = ntohs( bsize );
188 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
189 memcpy( &rsize, irh + 10, sizeof( rsize ));
190 rsize = ntohs( rsize );
192 * Is this our set of headers?
194 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
196 * Is the size correct?
198 if ( bsize != rsize )
203 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
204 syslog( LOG_ERR, "afp_addicon: lseek: %m" );
210 * Some error occurred, return.
214 syslog( LOG_ERR, "afp_addicon: %m" );
215 if (obj->proto == AFPPROTO_DSI) {
216 dsi_writeinit(obj->handle, rbuf, buflen);
217 dsi_writeflush(obj->handle);
223 switch (obj->proto) {
227 if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
228 return( AFPERR_PARAM );
230 if (obj->options.flags & OPTION_DEBUG) {
231 printf("(write) len: %d\n", buflen);
232 bprint(rbuf, buflen);
236 * We're at the end of the file, add the headers, etc. */
238 iov[ 0 ].iov_base = (caddr_t)imh;
239 iov[ 0 ].iov_len = sizeof( imh );
240 iov[ 1 ].iov_base = rbuf;
241 iov[ 1 ].iov_len = bsize;
246 * We found an icon to replace.
249 iov[ 0 ].iov_base = rbuf;
250 iov[ 0 ].iov_len = bsize;
254 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
255 syslog( LOG_ERR, "afp_addicon: writev: %m" );
256 return( AFPERR_PARAM );
259 #endif /* no afp/asp */
262 DSI *dsi = obj->handle;
264 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
266 /* add headers at end of file */
267 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
268 syslog(LOG_ERR, "afp_addicon: write: %m");
273 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
274 syslog(LOG_ERR, "afp_addicon: write: %m");
279 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
280 if ( obj->options.flags & OPTION_DEBUG ) {
281 printf("(write) command cont'd: %d\n", iovcnt);
282 bprint(rbuf, iovcnt);
285 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
286 syslog(LOG_ERR, "afp_addicon: write: %m");
300 u_char utag[] = { 0, 0, 0, 0 };
301 u_char ucreator[] = { 'U', 'N', 'I', 'X' };
302 u_char utype[] = { 'T', 'E', 'X', 'T' };
305 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
306 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
307 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
308 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
309 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
310 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
311 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
312 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
313 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
314 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
315 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
316 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
317 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
318 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
319 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
320 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
321 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
322 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
323 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
324 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
325 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
326 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
327 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
328 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
329 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
330 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
331 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
332 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
333 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
334 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
335 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
336 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
339 int afp_geticoninfo(obj, ibuf, ibuflen, rbuf, rbuflen )
342 int ibuflen, *rbuflen;
345 u_char fcreator[ 4 ], ih[ 12 ];
346 u_int16_t vid, iindex, bsize;
351 memcpy( &vid, ibuf, sizeof( vid ));
352 ibuf += sizeof( vid );
353 if (( vol = getvolbyvid( vid )) == NULL ) {
354 return( AFPERR_PARAM );
357 memcpy( fcreator, ibuf, sizeof( fcreator ));
358 ibuf += sizeof( fcreator );
359 memcpy( &iindex, ibuf, sizeof( iindex ));
360 iindex = ntohs( iindex );
362 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
364 return( AFPERR_NOITEM );
366 memcpy( ih, utag, sizeof( utag ));
367 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
368 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
369 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
370 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
372 memcpy( rbuf, ih, sizeof( ih ));
373 *rbuflen = sizeof( ih );
377 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
378 return( AFPERR_NOITEM );
381 if ( iindex < si.sdt_index ) {
382 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
383 return( AFPERR_PARAM );
389 * Position to the correct spot.
392 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
395 return( AFPERR_NOITEM );
397 memcpy( &bsize, ih + 10, sizeof( bsize ));
398 bsize = ntohs(bsize);
399 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
400 syslog( LOG_ERR, "afp_iconinfo: lseek: %m" );
401 return( AFPERR_PARAM );
403 if ( si.sdt_index == iindex ) {
404 memcpy( rbuf, ih, sizeof( ih ));
405 *rbuflen = sizeof( ih );
413 int afp_geticon(obj, ibuf, ibuflen, rbuf, rbuflen )
416 int ibuflen, *rbuflen;
421 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
422 u_int16_t vid, bsize, rsize;
428 memcpy( &vid, ibuf, sizeof( vid ));
429 ibuf += sizeof( vid );
430 if (( vol = getvolbyvid( vid )) == NULL ) {
431 return( AFPERR_PARAM );
434 memcpy( fcreator, ibuf, sizeof( fcreator ));
435 ibuf += sizeof( fcreator );
436 memcpy( ftype, ibuf, sizeof( ftype ));
437 ibuf += sizeof( ftype );
438 itype = (unsigned char) *ibuf++;
440 memcpy( &bsize, ibuf, sizeof( bsize ));
441 bsize = ntohs( bsize );
443 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
444 memcmp( ftype, utype, sizeof( utype )) == 0 &&
447 memcpy( rbuf, uicon, bsize);
452 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
453 return( AFPERR_NOITEM );
456 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
459 syslog(LOG_ERR, "afp_geticon: lseek: %m");
460 return( AFPERR_PARAM );
465 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
467 offset += sizeof(ih);
468 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
469 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
472 memcpy( &rsize, ih + 10, sizeof( rsize ));
473 rsize = ntohs( rsize );
474 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
475 syslog( LOG_ERR, "afp_geticon: lseek: %m" );
476 return( AFPERR_PARAM );
482 syslog(LOG_ERR, "afp_geticon: read: %m");
483 return( AFPERR_PARAM );
487 return( AFPERR_NOITEM );
490 memcpy( &rsize, ih + 10, sizeof( rsize ));
491 rsize = ntohs( rsize );
492 #define min(a,b) ((a)<(b)?(a):(b))
493 rc = min( bsize, rsize );
495 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
496 DSI *dsi = obj->handle;
500 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
501 if (size < rc + offset) {
505 if ((*rbuflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
508 /* do to the streaming nature, we have to exit if we encounter
509 * a problem. much confusion results otherwise. */
510 while (*rbuflen > 0) {
511 #if defined(SENDFILE_FLAVOR_LINUX) || defined(SENDFILE_FLAVOR_BSD)
512 if (!obj->options.flags & OPTION_DEBUG) {
513 #ifdef SENDFILE_FLAVOR_LINUX
514 if (sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0)
518 #ifdef SENDFILE_FLAVOR_BSD
519 if (sendfile(si.sdt_fd, dsi->socket, offset, rc, NULL, NULL, 0) < 0)
527 buflen = read(si.sdt_fd, rbuf, *rbuflen);
531 if (obj->options.flags & OPTION_DEBUG) {
532 printf( "(read) reply: %d, %d\n", buflen, dsi->clientID);
533 bprint(rbuf, buflen);
536 /* dsi_read() also returns buffer size of next allocation */
537 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
549 syslog(LOG_INFO, "afp_geticon: %m");
554 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
555 return( AFPERR_PARAM );
563 static char hexdig[] = "0123456789abcdef";
564 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
566 static char path[ MAXPATHLEN + 1];
570 strcpy( path, vol->v_path );
571 strcat( path, "/.AppleDesktop/" );
572 for ( p = path; *p != '\0'; p++ )
575 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
576 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
577 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
584 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
585 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
586 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
587 *p++ = hexdig[ creator[ i ] & 0x0f ];
598 char *mtoupath(const struct vol *vol, char *mpath)
600 static unsigned char upath[ MAXPATHLEN + 1];
601 unsigned char *m, *u;
604 if ( *mpath == '\0' ) {
610 while ( *m != '\0' ) {
611 /* handle case conversion first */
612 if (vol->v_casefold & AFPVOL_MTOUUPPER)
613 *m = diatoupper( *m );
614 else if (vol->v_casefold & AFPVOL_MTOULOWER)
615 *m = diatolower( *m );
617 /* we have a code page. we only use the ascii range
618 * if we have map ascii specified. */
620 if (vol->v_mtoupage && ((*m > 0x7F) ||
621 vol->v_flags & AFPVOL_MAPASCII)) {
622 *u = vol->v_mtoupage[*m];
625 #if AD_VERSION == AD_VERSION1
626 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
627 (!isascii(*m) || *m == '/')) ||
628 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
629 ( i == 0 && (*m == '.' )))) {
631 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
632 (!isprint(*m) || *m == '/')) ||
633 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
634 ( i == 0 && (*m == '.' )))) {
636 /* do hex conversion. */
638 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
639 *u = hexdig[ *m & 0x0f ];
651 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
652 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
654 char *utompath(const struct vol *vol, char *upath)
656 static unsigned char mpath[ MAXPATHLEN + 1];
657 unsigned char *m, *u;
660 /* do the hex conversion */
663 while ( *u != '\0' ) {
664 /* we have a code page */
666 if (vol->v_utompage && ((*u > 0x7F) ||
667 (vol->v_flags & AFPVOL_MAPASCII))) {
668 *m = vol->v_utompage[*u];
671 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
672 *(u+2) != '\0' && islxdigit( *(u+2))) {
674 h = hextoint( *u ) << 4;
681 /* handle case conversion */
682 if (vol->v_casefold & AFPVOL_UTOMLOWER)
683 *m = diatolower( *m );
684 else if (vol->v_casefold & AFPVOL_UTOMUPPER)
685 *m = diatoupper( *m );
694 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
697 int ibuflen, *rbuflen;
699 struct adouble ad, *adp;
711 memcpy( &vid, ibuf, sizeof( vid ));
712 ibuf += sizeof( vid );
713 if (( vol = getvolbyvid( vid )) == NULL ) {
714 return( AFPERR_PARAM );
717 memcpy( &did, ibuf, sizeof( did ));
718 ibuf += sizeof( did );
719 if (( dir = dirsearch( vol, did )) == NULL ) {
720 return( AFPERR_NOOBJ );
723 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
724 return( AFPERR_NOOBJ );
727 if ((u_long)ibuf & 1 ) {
731 clen = (u_char)*ibuf++;
732 clen = min( clen, 199 );
734 if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) {
735 memset(&ad, 0, sizeof(ad));
739 if (ad_open( mtoupath( vol, path ), vol_noadouble(vol) |
740 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
741 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
742 return( AFPERR_ACCESS );
745 if ( ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT ) {
746 if ( *path == '\0' ) {
747 name = curdir->d_name;
751 ad_setentrylen( adp, ADEID_NAME, strlen( name ));
752 memcpy( ad_entry( adp, ADEID_NAME ), name,
753 ad_getentrylen( adp, ADEID_NAME ));
756 ad_setentrylen( adp, ADEID_COMMENT, clen );
757 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
758 ad_flush( adp, ADFLAGS_HF );
759 ad_close( adp, ADFLAGS_HF );
763 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
766 int ibuflen, *rbuflen;
768 struct adouble ad, *adp;
779 memcpy( &vid, ibuf, sizeof( vid ));
780 ibuf += sizeof( vid );
781 if (( vol = getvolbyvid( vid )) == NULL ) {
782 return( AFPERR_PARAM );
785 memcpy( &did, ibuf, sizeof( did ));
786 ibuf += sizeof( did );
787 if (( dir = dirsearch( vol, did )) == NULL ) {
788 return( AFPERR_NOOBJ );
791 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
792 return( AFPERR_NOOBJ );
795 if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) {
796 memset(&ad, 0, sizeof(ad));
800 if ( ad_open( mtoupath( vol, path ),
801 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
802 O_RDONLY, 0666, adp) < 0 ) {
803 return( AFPERR_NOITEM );
807 * Make sure the AD file is not bogus.
809 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
810 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
811 ad_close( adp, ADFLAGS_HF );
812 return( AFPERR_NOITEM );
815 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
816 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
817 ad_getentrylen( adp, ADEID_COMMENT ));
818 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
819 ad_close( adp, ADFLAGS_HF );
823 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
826 int ibuflen, *rbuflen;
828 struct adouble ad, *adp;
839 memcpy( &vid, ibuf, sizeof( vid ));
840 ibuf += sizeof( vid );
841 if (( vol = getvolbyvid( vid )) == NULL ) {
842 return( AFPERR_PARAM );
845 memcpy( &did, ibuf, sizeof( did ));
846 ibuf += sizeof( did );
847 if (( dir = dirsearch( vol, did )) == NULL ) {
848 return( AFPERR_NOOBJ );
851 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
852 return( AFPERR_NOOBJ );
855 if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) {
856 memset(&ad, 0, sizeof(ad));
860 if ( ad_open( mtoupath( vol, path ),
861 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
862 O_RDWR, 0, adp) < 0 ) {
865 return( AFPERR_NOITEM );
867 return( AFPERR_ACCESS );
869 return( AFPERR_PARAM );
873 ad_setentrylen( adp, ADEID_COMMENT, 0 );
874 ad_flush( adp, ADFLAGS_HF );
875 ad_close( adp, ADFLAGS_HF );