2 * $Id: desktop.c,v 1.4 2001-05-31 18:48:32 srittau Exp $
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");
555 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
556 return( AFPERR_PARAM );
564 static char hexdig[] = "0123456789abcdef";
565 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
567 static char path[ MAXPATHLEN + 1];
571 strcpy( path, vol->v_path );
572 strcat( path, "/.AppleDesktop/" );
573 for ( p = path; *p != '\0'; p++ )
576 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
577 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
578 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
585 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
586 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
587 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
588 *p++ = hexdig[ creator[ i ] & 0x0f ];
599 char *mtoupath(const struct vol *vol, char *mpath)
601 static unsigned char upath[ MAXPATHLEN + 1];
602 unsigned char *m, *u;
605 if ( *mpath == '\0' ) {
611 while ( *m != '\0' ) {
612 /* handle case conversion first */
613 if (vol->v_casefold & AFPVOL_MTOUUPPER)
614 *m = diatoupper( *m );
615 else if (vol->v_casefold & AFPVOL_MTOULOWER)
616 *m = diatolower( *m );
618 /* we have a code page. we only use the ascii range
619 * if we have map ascii specified. */
621 if (vol->v_mtoupage && ((*m > 0x7F) ||
622 vol->v_flags & AFPVOL_MAPASCII)) {
623 *u = vol->v_mtoupage->map[*m].value;
626 #if AD_VERSION == AD_VERSION1
627 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
628 (!isascii(*m) || *m == '/')) ||
629 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
630 ( i == 0 && (*m == '.' )))) {
632 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
633 (!isprint(*m) || *m == '/')) ||
634 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
635 ( i == 0 && (*m == '.' )))) {
637 /* do hex conversion. */
639 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
640 *u = hexdig[ *m & 0x0f ];
652 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
653 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
655 char *utompath(const struct vol *vol, char *upath)
657 static unsigned char mpath[ MAXPATHLEN + 1];
658 unsigned char *m, *u;
661 /* do the hex conversion */
664 while ( *u != '\0' ) {
665 /* we have a code page */
667 if (vol->v_utompage && ((*u > 0x7F) ||
668 (vol->v_flags & AFPVOL_MAPASCII))) {
669 *m = vol->v_utompage->map[*u].value;
672 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
673 *(u+2) != '\0' && islxdigit( *(u+2))) {
675 h = hextoint( *u ) << 4;
682 /* handle case conversion */
683 if (vol->v_casefold & AFPVOL_UTOMLOWER)
684 *m = diatolower( *m );
685 else if (vol->v_casefold & AFPVOL_UTOMUPPER)
686 *m = diatoupper( *m );
695 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
698 int ibuflen, *rbuflen;
700 struct adouble ad, *adp;
712 memcpy( &vid, ibuf, sizeof( vid ));
713 ibuf += sizeof( vid );
714 if (( vol = getvolbyvid( vid )) == NULL ) {
715 return( AFPERR_PARAM );
718 memcpy( &did, ibuf, sizeof( did ));
719 ibuf += sizeof( did );
720 if (( dir = dirsearch( vol, did )) == NULL ) {
721 return( AFPERR_NOOBJ );
724 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
725 return( AFPERR_NOOBJ );
728 if ((u_long)ibuf & 1 ) {
732 clen = (u_char)*ibuf++;
733 clen = min( clen, 199 );
735 if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) {
736 memset(&ad, 0, sizeof(ad));
740 if (ad_open( mtoupath( vol, path ), vol_noadouble(vol) |
741 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
742 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
743 return( AFPERR_ACCESS );
746 if ( ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT ) {
747 if ( *path == '\0' ) {
748 name = curdir->d_name;
752 ad_setentrylen( adp, ADEID_NAME, strlen( name ));
753 memcpy( ad_entry( adp, ADEID_NAME ), name,
754 ad_getentrylen( adp, ADEID_NAME ));
757 ad_setentrylen( adp, ADEID_COMMENT, clen );
758 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
759 ad_flush( adp, ADFLAGS_HF );
760 ad_close( adp, ADFLAGS_HF );
764 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
767 int ibuflen, *rbuflen;
769 struct adouble ad, *adp;
780 memcpy( &vid, ibuf, sizeof( vid ));
781 ibuf += sizeof( vid );
782 if (( vol = getvolbyvid( vid )) == NULL ) {
783 return( AFPERR_PARAM );
786 memcpy( &did, ibuf, sizeof( did ));
787 ibuf += sizeof( did );
788 if (( dir = dirsearch( vol, did )) == NULL ) {
789 return( AFPERR_NOOBJ );
792 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
793 return( AFPERR_NOOBJ );
796 if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) {
797 memset(&ad, 0, sizeof(ad));
801 if ( ad_open( mtoupath( vol, path ),
802 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
803 O_RDONLY, 0666, adp) < 0 ) {
804 return( AFPERR_NOITEM );
808 * Make sure the AD file is not bogus.
810 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
811 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
812 ad_close( adp, ADFLAGS_HF );
813 return( AFPERR_NOITEM );
816 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
817 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
818 ad_getentrylen( adp, ADEID_COMMENT ));
819 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
820 ad_close( adp, ADFLAGS_HF );
824 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
827 int ibuflen, *rbuflen;
829 struct adouble ad, *adp;
840 memcpy( &vid, ibuf, sizeof( vid ));
841 ibuf += sizeof( vid );
842 if (( vol = getvolbyvid( vid )) == NULL ) {
843 return( AFPERR_PARAM );
846 memcpy( &did, ibuf, sizeof( did ));
847 ibuf += sizeof( did );
848 if (( dir = dirsearch( vol, did )) == NULL ) {
849 return( AFPERR_NOOBJ );
852 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
853 return( AFPERR_NOOBJ );
856 if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) {
857 memset(&ad, 0, sizeof(ad));
861 if ( ad_open( mtoupath( vol, path ),
862 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
863 O_RDWR, 0, adp) < 0 ) {
866 return( AFPERR_NOITEM );
868 return( AFPERR_ACCESS );
870 return( AFPERR_PARAM );
874 ad_setentrylen( adp, ADEID_COMMENT, 0 );
875 ad_flush( adp, ADFLAGS_HF );
876 ad_close( adp, ADFLAGS_HF );