2 * Copyright (c) 1990,1993 Regents of The University of Michigan.
3 * All Rights Reserved. See COPYRIGHT.
6 #include <sys/syslog.h>
11 #include <sys/param.h>
13 #include <sys/socket.h>
14 #include <netatalk/at.h>
15 #include <netatalk/endian.h>
16 #include <atalk/dsi.h>
17 #include <atalk/atp.h>
18 #include <atalk/asp.h>
19 #include <atalk/afp.h>
20 #include <atalk/adouble.h>
21 #include <atalk/util.h>
30 #include "directory.h"
35 int afp_opendt(obj, ibuf, ibuflen, rbuf, rbuflen )
38 int ibuflen, *rbuflen;
45 memcpy( &vid, ibuf, sizeof(vid));
46 if (( vol = getvolbyvid( vid )) == NULL ) {
48 return( AFPERR_PARAM );
51 memcpy( rbuf, &vid, sizeof(vid));
52 *rbuflen = sizeof(vid);
56 int afp_closedt(obj, ibuf, ibuflen, rbuf, rbuflen )
59 int ibuflen, *rbuflen;
65 struct savedt si = { { 0, 0, 0, 0 }, -1, 0 };
67 static int iconopen( vol, creator, flags, mode )
71 char *dtf, *adt, *adts;
73 if ( si.sdt_fd != -1 ) {
74 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
75 si.sdt_vid == vol->v_vid ) {
82 dtf = dtfile( vol, creator, ".icon" );
84 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
85 if ( errno == ENOENT && ( flags & O_CREAT )) {
86 if (( adts = strrchr( dtf, '/' )) == NULL ) {
90 if (( adt = strrchr( dtf, '/' )) == NULL ) {
94 (void) ad_mkdir( dtf, DIRBITS | 0777 );
96 (void) ad_mkdir( dtf, DIRBITS | 0777 );
99 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
100 syslog( LOG_ERR, "iconopen: open %s: %m", dtf );
108 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
109 si.sdt_vid = vol->v_vid;
114 int afp_addicon(obj, ibuf, ibuflen, rbuf, rbuflen)
117 int ibuflen, *rbuflen;
120 struct iovec iov[ 2 ];
121 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
122 int itype, cc = AFP_OK, iovcnt = 0, buflen;
123 u_int32_t ftype, itag;
124 u_int16_t bsize, rsize, vid;
130 memcpy( &vid, ibuf, sizeof( vid ));
131 ibuf += sizeof( vid );
132 if (( vol = getvolbyvid( vid )) == NULL ) {
137 memcpy( fcreator, ibuf, sizeof( fcreator ));
138 ibuf += sizeof( fcreator );
140 memcpy( &ftype, ibuf, sizeof( ftype ));
141 ibuf += sizeof( ftype );
143 itype = (unsigned char) *ibuf;
146 memcpy( &itag, ibuf, sizeof( itag ));
147 ibuf += sizeof( itag );
149 memcpy( &bsize, ibuf, sizeof( bsize ));
150 bsize = ntohs( bsize );
152 if ( si.sdt_fd != -1 ) {
153 (void)close( si.sdt_fd );
157 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
162 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
165 syslog( LOG_ERR, "afp_addicon: lseek: %m" );
171 * Read icon elements until we find a match to replace, or
172 * we get to the end to insert.
175 memcpy( p, &itag, sizeof( itag ));
177 memcpy( p, &ftype, sizeof( ftype ));
178 p += sizeof( ftype );
181 bsize = htons( bsize );
182 memcpy( p, &bsize, sizeof( bsize ));
183 bsize = ntohs( bsize );
184 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
185 memcpy( &rsize, irh + 10, sizeof( rsize ));
186 rsize = ntohs( rsize );
188 * Is this our set of headers?
190 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
192 * Is the size correct?
194 if ( bsize != rsize )
199 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
200 syslog( LOG_ERR, "afp_addicon: lseek: %m" );
206 * Some error occurred, return.
210 syslog( LOG_ERR, "afp_addicon: %m" );
211 if (obj->proto == AFPPROTO_DSI) {
212 dsi_writeinit(obj->handle, rbuf, buflen);
213 dsi_writeflush(obj->handle);
219 switch (obj->proto) {
223 if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
224 return( AFPERR_PARAM );
226 if (obj->options.flags & OPTION_DEBUG) {
227 printf("(write) len: %d\n", buflen);
228 bprint(rbuf, buflen);
232 * We're at the end of the file, add the headers, etc. */
234 iov[ 0 ].iov_base = (caddr_t)imh;
235 iov[ 0 ].iov_len = sizeof( imh );
236 iov[ 1 ].iov_base = rbuf;
237 iov[ 1 ].iov_len = bsize;
242 * We found an icon to replace.
245 iov[ 0 ].iov_base = rbuf;
246 iov[ 0 ].iov_len = bsize;
250 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
251 syslog( LOG_ERR, "afp_addicon: writev: %m" );
252 return( AFPERR_PARAM );
255 #endif /* no afp/asp */
258 DSI *dsi = obj->handle;
260 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
262 /* add headers at end of file */
263 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
264 syslog(LOG_ERR, "afp_addicon: write: %m");
269 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
270 syslog(LOG_ERR, "afp_addicon: write: %m");
275 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
276 if ( obj->options.flags & OPTION_DEBUG ) {
277 printf("(write) command cont'd: %d\n", iovcnt);
278 bprint(rbuf, iovcnt);
281 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
282 syslog(LOG_ERR, "afp_addicon: write: %m");
296 u_char utag[] = { 0, 0, 0, 0 };
297 u_char ucreator[] = { 'U', 'N', 'I', 'X' };
298 u_char utype[] = { 'T', 'E', 'X', 'T' };
301 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
302 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
303 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
304 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
305 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
306 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
307 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
308 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
309 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
310 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
311 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
312 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
313 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
314 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
315 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
316 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
317 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
318 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
319 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
320 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
321 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
322 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
323 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
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,
335 int afp_geticoninfo(obj, ibuf, ibuflen, rbuf, rbuflen )
338 int ibuflen, *rbuflen;
341 u_char fcreator[ 4 ], ih[ 12 ];
342 u_int16_t vid, iindex, bsize;
347 memcpy( &vid, ibuf, sizeof( vid ));
348 ibuf += sizeof( vid );
349 if (( vol = getvolbyvid( vid )) == NULL ) {
350 return( AFPERR_PARAM );
353 memcpy( fcreator, ibuf, sizeof( fcreator ));
354 ibuf += sizeof( fcreator );
355 memcpy( &iindex, ibuf, sizeof( iindex ));
356 iindex = ntohs( iindex );
358 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
360 return( AFPERR_NOITEM );
362 memcpy( ih, utag, sizeof( utag ));
363 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
364 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
365 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
366 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
368 memcpy( rbuf, ih, sizeof( ih ));
369 *rbuflen = sizeof( ih );
373 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
374 return( AFPERR_NOITEM );
377 if ( iindex < si.sdt_index ) {
378 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
379 return( AFPERR_PARAM );
385 * Position to the correct spot.
388 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
391 return( AFPERR_NOITEM );
393 memcpy( &bsize, ih + 10, sizeof( bsize ));
394 bsize = ntohs(bsize);
395 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
396 syslog( LOG_ERR, "afp_iconinfo: lseek: %m" );
397 return( AFPERR_PARAM );
399 if ( si.sdt_index == iindex ) {
400 memcpy( rbuf, ih, sizeof( ih ));
401 *rbuflen = sizeof( ih );
409 int afp_geticon(obj, ibuf, ibuflen, rbuf, rbuflen )
412 int ibuflen, *rbuflen;
417 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
418 u_int16_t vid, bsize, rsize;
424 memcpy( &vid, ibuf, sizeof( vid ));
425 ibuf += sizeof( vid );
426 if (( vol = getvolbyvid( vid )) == NULL ) {
427 return( AFPERR_PARAM );
430 memcpy( fcreator, ibuf, sizeof( fcreator ));
431 ibuf += sizeof( fcreator );
432 memcpy( ftype, ibuf, sizeof( ftype ));
433 ibuf += sizeof( ftype );
434 itype = (unsigned char) *ibuf++;
436 memcpy( &bsize, ibuf, sizeof( bsize ));
437 bsize = ntohs( bsize );
439 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
440 memcmp( ftype, utype, sizeof( utype )) == 0 &&
443 memcpy( rbuf, uicon, bsize);
448 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
449 return( AFPERR_NOITEM );
452 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
455 syslog(LOG_ERR, "afp_geticon: lseek: %m");
456 return( AFPERR_PARAM );
461 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
463 offset += sizeof(ih);
464 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
465 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
468 memcpy( &rsize, ih + 10, sizeof( rsize ));
469 rsize = ntohs( rsize );
470 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
471 syslog( LOG_ERR, "afp_geticon: lseek: %m" );
472 return( AFPERR_PARAM );
478 syslog(LOG_ERR, "afp_geticon: read: %m");
479 return( AFPERR_PARAM );
483 return( AFPERR_NOITEM );
486 memcpy( &rsize, ih + 10, sizeof( rsize ));
487 rsize = ntohs( rsize );
488 #define min(a,b) ((a)<(b)?(a):(b))
489 rc = min( bsize, rsize );
491 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
492 DSI *dsi = obj->handle;
496 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
497 if (size < rc + offset) {
501 if ((*rbuflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
504 /* do to the streaming nature, we have to exit if we encounter
505 * a problem. much confusion results otherwise. */
506 while (*rbuflen > 0) {
507 #if defined(SENDFILE_FLAVOR_LINUX) || defined(SENDFILE_FLAVOR_BSD)
508 if (!obj->options.flags & OPTION_DEBUG) {
509 #ifdef SENDFILE_FLAVOR_LINUX
510 if (sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0)
514 #ifdef SENDFILE_FLAVOR_BSD
515 if (sendfile(si.sdt_fd, dsi->socket, offset, rc, NULL, NULL, 0) < 0)
523 buflen = read(si.sdt_fd, rbuf, *rbuflen);
527 if (obj->options.flags & OPTION_DEBUG) {
528 printf( "(read) reply: %d, %d\n", buflen, dsi->clientID);
529 bprint(rbuf, buflen);
532 /* dsi_read() also returns buffer size of next allocation */
533 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
545 syslog(LOG_INFO, "afp_geticon: %m");
550 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
551 return( AFPERR_PARAM );
559 static char hexdig[] = "0123456789abcdef";
560 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
562 static char path[ MAXPATHLEN + 1];
566 strcpy( path, vol->v_path );
567 strcat( path, "/.AppleDesktop/" );
568 for ( p = path; *p != '\0'; p++ )
571 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
572 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
573 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
580 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
581 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
582 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
583 *p++ = hexdig[ creator[ i ] & 0x0f ];
594 char *mtoupath(const struct vol *vol, char *mpath)
596 static unsigned char upath[ MAXPATHLEN + 1];
597 unsigned char *m, *u;
600 if ( *mpath == '\0' ) {
606 while ( *m != '\0' ) {
607 /* handle case conversion first */
608 if (vol->v_casefold & AFPVOL_MTOUUPPER)
609 *m = diatoupper( *m );
610 else if (vol->v_casefold & AFPVOL_MTOULOWER)
611 *m = diatolower( *m );
613 /* we have a code page. we only use the ascii range
614 * if we have map ascii specified. */
616 if (vol->v_mtoupage && ((*m > 0x7F) ||
617 vol->v_flags & AFPVOL_MAPASCII)) {
618 *u = vol->v_mtoupage[*m];
621 #if AD_VERSION == AD_VERSION1
622 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
623 (!isascii(*m) || *m == '/')) ||
624 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
625 ( i == 0 && (*m == '.' )))) {
627 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
628 (!isprint(*m) || *m == '/')) ||
629 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
630 ( i == 0 && (*m == '.' )))) {
632 /* do hex conversion. */
634 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
635 *u = hexdig[ *m & 0x0f ];
647 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
648 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
650 char *utompath(const struct vol *vol, char *upath)
652 static unsigned char mpath[ MAXPATHLEN + 1];
653 unsigned char *m, *u;
656 /* do the hex conversion */
659 while ( *u != '\0' ) {
660 /* we have a code page */
662 if (vol->v_utompage && ((*u > 0x7F) ||
663 (vol->v_flags & AFPVOL_MAPASCII))) {
664 *m = vol->v_utompage[*u];
667 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
668 *(u+2) != '\0' && islxdigit( *(u+2))) {
670 h = hextoint( *u ) << 4;
677 /* handle case conversion */
678 if (vol->v_casefold & AFPVOL_UTOMLOWER)
679 *m = diatolower( *m );
680 else if (vol->v_casefold & AFPVOL_UTOMUPPER)
681 *m = diatoupper( *m );
690 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
693 int ibuflen, *rbuflen;
695 struct adouble ad, *adp;
707 memcpy( &vid, ibuf, sizeof( vid ));
708 ibuf += sizeof( vid );
709 if (( vol = getvolbyvid( vid )) == NULL ) {
710 return( AFPERR_PARAM );
713 memcpy( &did, ibuf, sizeof( did ));
714 ibuf += sizeof( did );
715 if (( dir = dirsearch( vol, did )) == NULL ) {
716 return( AFPERR_NOOBJ );
719 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
720 return( AFPERR_NOOBJ );
723 if ((u_long)ibuf & 1 ) {
727 clen = (u_char)*ibuf++;
728 clen = min( clen, 199 );
730 if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) {
731 memset(&ad, 0, sizeof(ad));
735 if (ad_open( mtoupath( vol, path ), vol_noadouble(vol) |
736 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
737 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
738 return( AFPERR_ACCESS );
741 if ( ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT ) {
742 if ( *path == '\0' ) {
743 name = curdir->d_name;
747 ad_setentrylen( adp, ADEID_NAME, strlen( name ));
748 memcpy( ad_entry( adp, ADEID_NAME ), name,
749 ad_getentrylen( adp, ADEID_NAME ));
752 ad_setentrylen( adp, ADEID_COMMENT, clen );
753 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
754 ad_flush( adp, ADFLAGS_HF );
755 ad_close( adp, ADFLAGS_HF );
759 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
762 int ibuflen, *rbuflen;
764 struct adouble ad, *adp;
775 memcpy( &vid, ibuf, sizeof( vid ));
776 ibuf += sizeof( vid );
777 if (( vol = getvolbyvid( vid )) == NULL ) {
778 return( AFPERR_PARAM );
781 memcpy( &did, ibuf, sizeof( did ));
782 ibuf += sizeof( did );
783 if (( dir = dirsearch( vol, did )) == NULL ) {
784 return( AFPERR_NOOBJ );
787 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
788 return( AFPERR_NOOBJ );
791 if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) {
792 memset(&ad, 0, sizeof(ad));
796 if ( ad_open( mtoupath( vol, path ),
797 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
798 O_RDONLY, 0666, adp) < 0 ) {
799 return( AFPERR_NOITEM );
803 * Make sure the AD file is not bogus.
805 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
806 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
807 ad_close( adp, ADFLAGS_HF );
808 return( AFPERR_NOITEM );
811 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
812 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
813 ad_getentrylen( adp, ADEID_COMMENT ));
814 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
815 ad_close( adp, ADFLAGS_HF );
819 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
822 int ibuflen, *rbuflen;
824 struct adouble ad, *adp;
835 memcpy( &vid, ibuf, sizeof( vid ));
836 ibuf += sizeof( vid );
837 if (( vol = getvolbyvid( vid )) == NULL ) {
838 return( AFPERR_PARAM );
841 memcpy( &did, ibuf, sizeof( did ));
842 ibuf += sizeof( did );
843 if (( dir = dirsearch( vol, did )) == NULL ) {
844 return( AFPERR_NOOBJ );
847 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
848 return( AFPERR_NOOBJ );
851 if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) {
852 memset(&ad, 0, sizeof(ad));
856 if ( ad_open( mtoupath( vol, path ),
857 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
858 O_RDWR, 0, adp) < 0 ) {
861 return( AFPERR_NOITEM );
863 return( AFPERR_ACCESS );
865 return( AFPERR_PARAM );
869 ad_setentrylen( adp, ADEID_COMMENT, 0 );
870 ad_flush( adp, ADFLAGS_HF );
871 ad_close( adp, ADFLAGS_HF );