2 * $Id: desktop.c,v 1.6 2001-08-15 01:37:34 srittau Exp $
9 #endif /* HAVE_CONFIG_H */
11 #include <sys/syslog.h>
13 #include <sys/types.h>
16 #include <sys/param.h>
18 #include <sys/socket.h>
19 #include <netatalk/at.h>
20 #include <netatalk/endian.h>
21 #include <atalk/dsi.h>
22 #include <atalk/atp.h>
23 #include <atalk/asp.h>
24 #include <atalk/afp.h>
25 #include <atalk/adouble.h>
26 #include <atalk/util.h>
30 #endif /* HAVE_FCNTL_H */
36 #endif /* HAVE_FCNTL_H */
39 #include "directory.h"
44 int afp_opendt(obj, ibuf, ibuflen, rbuf, rbuflen )
47 int ibuflen, *rbuflen;
54 memcpy( &vid, ibuf, sizeof(vid));
55 if (( vol = getvolbyvid( vid )) == NULL ) {
57 return( AFPERR_PARAM );
60 memcpy( rbuf, &vid, sizeof(vid));
61 *rbuflen = sizeof(vid);
65 int afp_closedt(obj, ibuf, ibuflen, rbuf, rbuflen )
68 int ibuflen, *rbuflen;
74 struct savedt si = { { 0, 0, 0, 0 }, -1, 0 };
76 static int iconopen( vol, creator, flags, mode )
80 char *dtf, *adt, *adts;
82 if ( si.sdt_fd != -1 ) {
83 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
84 si.sdt_vid == vol->v_vid ) {
91 dtf = dtfile( vol, creator, ".icon" );
93 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
94 if ( errno == ENOENT && ( flags & O_CREAT )) {
95 if (( adts = strrchr( dtf, '/' )) == NULL ) {
99 if (( adt = strrchr( dtf, '/' )) == NULL ) {
103 (void) ad_mkdir( dtf, DIRBITS | 0777 );
105 (void) ad_mkdir( dtf, DIRBITS | 0777 );
108 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
109 syslog( LOG_ERR, "iconopen: open %s: %s", dtf, strerror(errno) );
117 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
118 si.sdt_vid = vol->v_vid;
123 int afp_addicon(obj, ibuf, ibuflen, rbuf, rbuflen)
126 int ibuflen, *rbuflen;
129 struct iovec iov[ 2 ];
130 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
131 int itype, cc = AFP_OK, iovcnt = 0, buflen;
132 u_int32_t ftype, itag;
133 u_int16_t bsize, rsize, vid;
139 memcpy( &vid, ibuf, sizeof( vid ));
140 ibuf += sizeof( vid );
141 if (( vol = getvolbyvid( vid )) == NULL ) {
146 memcpy( fcreator, ibuf, sizeof( fcreator ));
147 ibuf += sizeof( fcreator );
149 memcpy( &ftype, ibuf, sizeof( ftype ));
150 ibuf += sizeof( ftype );
152 itype = (unsigned char) *ibuf;
155 memcpy( &itag, ibuf, sizeof( itag ));
156 ibuf += sizeof( itag );
158 memcpy( &bsize, ibuf, sizeof( bsize ));
159 bsize = ntohs( bsize );
161 if ( si.sdt_fd != -1 ) {
162 (void)close( si.sdt_fd );
166 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
171 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
174 syslog( LOG_ERR, "afp_addicon: lseek: %s", strerror(errno) );
180 * Read icon elements until we find a match to replace, or
181 * we get to the end to insert.
184 memcpy( p, &itag, sizeof( itag ));
186 memcpy( p, &ftype, sizeof( ftype ));
187 p += sizeof( ftype );
190 bsize = htons( bsize );
191 memcpy( p, &bsize, sizeof( bsize ));
192 bsize = ntohs( bsize );
193 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
194 memcpy( &rsize, irh + 10, sizeof( rsize ));
195 rsize = ntohs( rsize );
197 * Is this our set of headers?
199 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
201 * Is the size correct?
203 if ( bsize != rsize )
208 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
209 syslog( LOG_ERR, "afp_addicon: lseek: %s", strerror(errno) );
215 * Some error occurred, return.
219 syslog( LOG_ERR, "afp_addicon: %s", strerror(errno) );
220 if (obj->proto == AFPPROTO_DSI) {
221 dsi_writeinit(obj->handle, rbuf, buflen);
222 dsi_writeflush(obj->handle);
228 switch (obj->proto) {
232 if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
233 return( AFPERR_PARAM );
235 if (obj->options.flags & OPTION_DEBUG) {
236 printf("(write) len: %d\n", buflen);
237 bprint(rbuf, buflen);
241 * We're at the end of the file, add the headers, etc. */
243 iov[ 0 ].iov_base = (caddr_t)imh;
244 iov[ 0 ].iov_len = sizeof( imh );
245 iov[ 1 ].iov_base = rbuf;
246 iov[ 1 ].iov_len = bsize;
251 * We found an icon to replace.
254 iov[ 0 ].iov_base = rbuf;
255 iov[ 0 ].iov_len = bsize;
259 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
260 syslog( LOG_ERR, "afp_addicon: writev: %s", strerror(errno) );
261 return( AFPERR_PARAM );
264 #endif /* no afp/asp */
267 DSI *dsi = obj->handle;
269 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
271 /* add headers at end of file */
272 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
273 syslog(LOG_ERR, "afp_addicon: write: %s", strerror(errno));
278 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
279 syslog(LOG_ERR, "afp_addicon: write: %s", strerror(errno));
284 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
285 if ( obj->options.flags & OPTION_DEBUG ) {
286 printf("(write) command cont'd: %d\n", iovcnt);
287 bprint(rbuf, iovcnt);
290 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
291 syslog(LOG_ERR, "afp_addicon: write: %s", strerror(errno));
305 u_char utag[] = { 0, 0, 0, 0 };
306 u_char ucreator[] = { 'U', 'N', 'I', 'X' };
307 u_char utype[] = { 'T', 'E', 'X', 'T' };
310 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
311 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
312 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
313 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
314 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
315 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
316 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
317 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
318 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
319 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
320 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
321 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
322 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
323 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
324 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
325 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
326 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
327 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
328 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
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,
337 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
338 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
339 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
340 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
341 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
344 int afp_geticoninfo(obj, ibuf, ibuflen, rbuf, rbuflen )
347 int ibuflen, *rbuflen;
350 u_char fcreator[ 4 ], ih[ 12 ];
351 u_int16_t vid, iindex, bsize;
356 memcpy( &vid, ibuf, sizeof( vid ));
357 ibuf += sizeof( vid );
358 if (( vol = getvolbyvid( vid )) == NULL ) {
359 return( AFPERR_PARAM );
362 memcpy( fcreator, ibuf, sizeof( fcreator ));
363 ibuf += sizeof( fcreator );
364 memcpy( &iindex, ibuf, sizeof( iindex ));
365 iindex = ntohs( iindex );
367 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
369 return( AFPERR_NOITEM );
371 memcpy( ih, utag, sizeof( utag ));
372 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
373 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
374 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
375 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
377 memcpy( rbuf, ih, sizeof( ih ));
378 *rbuflen = sizeof( ih );
382 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
383 return( AFPERR_NOITEM );
386 if ( iindex < si.sdt_index ) {
387 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
388 return( AFPERR_PARAM );
394 * Position to the correct spot.
397 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
400 return( AFPERR_NOITEM );
402 memcpy( &bsize, ih + 10, sizeof( bsize ));
403 bsize = ntohs(bsize);
404 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
405 syslog( LOG_ERR, "afp_iconinfo: lseek: %s", strerror(errno) );
406 return( AFPERR_PARAM );
408 if ( si.sdt_index == iindex ) {
409 memcpy( rbuf, ih, sizeof( ih ));
410 *rbuflen = sizeof( ih );
418 int afp_geticon(obj, ibuf, ibuflen, rbuf, rbuflen )
421 int ibuflen, *rbuflen;
426 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
427 u_int16_t vid, bsize, rsize;
433 memcpy( &vid, ibuf, sizeof( vid ));
434 ibuf += sizeof( vid );
435 if (( vol = getvolbyvid( vid )) == NULL ) {
436 return( AFPERR_PARAM );
439 memcpy( fcreator, ibuf, sizeof( fcreator ));
440 ibuf += sizeof( fcreator );
441 memcpy( ftype, ibuf, sizeof( ftype ));
442 ibuf += sizeof( ftype );
443 itype = (unsigned char) *ibuf++;
445 memcpy( &bsize, ibuf, sizeof( bsize ));
446 bsize = ntohs( bsize );
448 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
449 memcmp( ftype, utype, sizeof( utype )) == 0 &&
452 memcpy( rbuf, uicon, bsize);
457 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
458 return( AFPERR_NOITEM );
461 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
464 syslog(LOG_ERR, "afp_geticon: lseek: %s", strerror(errno));
465 return( AFPERR_PARAM );
470 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
472 offset += sizeof(ih);
473 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
474 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
477 memcpy( &rsize, ih + 10, sizeof( rsize ));
478 rsize = ntohs( rsize );
479 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
480 syslog( LOG_ERR, "afp_geticon: lseek: %s", strerror(errno) );
481 return( AFPERR_PARAM );
487 syslog(LOG_ERR, "afp_geticon: read: %s", strerror(errno));
488 return( AFPERR_PARAM );
492 return( AFPERR_NOITEM );
495 memcpy( &rsize, ih + 10, sizeof( rsize ));
496 rsize = ntohs( rsize );
497 #define min(a,b) ((a)<(b)?(a):(b))
498 rc = min( bsize, rsize );
500 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
501 DSI *dsi = obj->handle;
505 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
506 if (size < rc + offset) {
510 if ((*rbuflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
513 /* do to the streaming nature, we have to exit if we encounter
514 * a problem. much confusion results otherwise. */
515 while (*rbuflen > 0) {
516 #if defined(SENDFILE_FLAVOR_LINUX) || defined(SENDFILE_FLAVOR_BSD)
517 if (!obj->options.flags & OPTION_DEBUG) {
518 #ifdef SENDFILE_FLAVOR_LINUX
519 if (sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0)
521 #endif /* SENDFILE_FLAVOR_LINUX */
523 #ifdef SENDFILE_FLAVOR_BSD
524 if (sendfile(si.sdt_fd, dsi->socket, offset, rc, NULL, NULL, 0) < 0)
526 #endif /* SENDFILE_FLAVOR_BSD */
530 #endif /* SENDFILE_FLAVOR_LINUX || SENDFILE_FLAVOR_BSD */
532 buflen = read(si.sdt_fd, rbuf, *rbuflen);
536 if (obj->options.flags & OPTION_DEBUG) {
537 printf( "(read) reply: %d, %d\n", buflen, dsi->clientID);
538 bprint(rbuf, buflen);
541 /* dsi_read() also returns buffer size of next allocation */
542 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
554 syslog(LOG_INFO, "afp_geticon: %s", strerror(errno));
560 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
561 return( AFPERR_PARAM );
569 static char hexdig[] = "0123456789abcdef";
570 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
572 static char path[ MAXPATHLEN + 1];
576 strcpy( path, vol->v_path );
577 strcat( path, "/.AppleDesktop/" );
578 for ( p = path; *p != '\0'; p++ )
581 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
582 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
583 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
590 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
591 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
592 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
593 *p++ = hexdig[ creator[ i ] & 0x0f ];
604 char *mtoupath(const struct vol *vol, char *mpath)
606 static char upath[ MAXPATHLEN + 1];
610 if ( *mpath == '\0' ) {
616 while ( *m != '\0' ) {
617 /* handle case conversion first */
618 if (vol->v_casefold & AFPVOL_MTOUUPPER)
619 *m = diatoupper( *m );
620 else if (vol->v_casefold & AFPVOL_MTOULOWER)
621 *m = diatolower( *m );
623 /* we have a code page. we only use the ascii range
624 * if we have map ascii specified. */
626 if (vol->v_mtoupage && ((*m & 0x80) ||
627 vol->v_flags & AFPVOL_MAPASCII)) {
628 *u = vol->v_mtoupage->map[*m].value;
631 #if AD_VERSION == AD_VERSION1
632 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
633 (!isascii(*m) || *m == '/')) ||
634 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
635 ( i == 0 && (*m == '.' )))) {
636 #else /* AD_VERSION == AD_VERSION1 */
637 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
638 (!isprint(*m) || *m == '/')) ||
639 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
640 ( i == 0 && (*m == '.' )))) {
641 #endif /* AD_VERSION == AD_VERSION1 */
642 /* do hex conversion. */
644 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
645 *u = hexdig[ *m & 0x0f ];
657 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
658 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
660 char *utompath(const struct vol *vol, char *upath)
662 static unsigned char mpath[ MAXPATHLEN + 1];
666 /* do the hex conversion */
669 while ( *u != '\0' ) {
670 /* we have a code page */
672 if (vol->v_utompage && ((*u > 0x7F) ||
673 (vol->v_flags & AFPVOL_MAPASCII))) {
674 *m = vol->v_utompage->map[*u].value;
677 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
678 *(u+2) != '\0' && islxdigit( *(u+2))) {
680 h = hextoint( *u ) << 4;
687 /* handle case conversion */
688 if (vol->v_casefold & AFPVOL_UTOMLOWER)
689 *m = diatolower( *m );
690 else if (vol->v_casefold & AFPVOL_UTOMUPPER)
691 *m = diatoupper( *m );
700 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
703 int ibuflen, *rbuflen;
705 struct adouble ad, *adp;
717 memcpy( &vid, ibuf, sizeof( vid ));
718 ibuf += sizeof( vid );
719 if (( vol = getvolbyvid( vid )) == NULL ) {
720 return( AFPERR_PARAM );
723 memcpy( &did, ibuf, sizeof( did ));
724 ibuf += sizeof( did );
725 if (( dir = dirsearch( vol, did )) == NULL ) {
726 return( AFPERR_NOOBJ );
729 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
730 return( AFPERR_NOOBJ );
733 if ((u_long)ibuf & 1 ) {
737 clen = (u_char)*ibuf++;
738 clen = min( clen, 199 );
740 if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) {
741 memset(&ad, 0, sizeof(ad));
745 if (ad_open( mtoupath( vol, path ), vol_noadouble(vol) |
746 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
747 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
748 return( AFPERR_ACCESS );
751 if ( ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT ) {
752 if ( *path == '\0' ) {
753 name = curdir->d_name;
757 ad_setentrylen( adp, ADEID_NAME, strlen( name ));
758 memcpy( ad_entry( adp, ADEID_NAME ), name,
759 ad_getentrylen( adp, ADEID_NAME ));
762 ad_setentrylen( adp, ADEID_COMMENT, clen );
763 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
764 ad_flush( adp, ADFLAGS_HF );
765 ad_close( adp, ADFLAGS_HF );
769 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
772 int ibuflen, *rbuflen;
774 struct adouble ad, *adp;
785 memcpy( &vid, ibuf, sizeof( vid ));
786 ibuf += sizeof( vid );
787 if (( vol = getvolbyvid( vid )) == NULL ) {
788 return( AFPERR_PARAM );
791 memcpy( &did, ibuf, sizeof( did ));
792 ibuf += sizeof( did );
793 if (( dir = dirsearch( vol, did )) == NULL ) {
794 return( AFPERR_NOOBJ );
797 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
798 return( AFPERR_NOOBJ );
801 if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) {
802 memset(&ad, 0, sizeof(ad));
806 if ( ad_open( mtoupath( vol, path ),
807 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
808 O_RDONLY, 0666, adp) < 0 ) {
809 return( AFPERR_NOITEM );
813 * Make sure the AD file is not bogus.
815 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
816 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
817 ad_close( adp, ADFLAGS_HF );
818 return( AFPERR_NOITEM );
821 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
822 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
823 ad_getentrylen( adp, ADEID_COMMENT ));
824 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
825 ad_close( adp, ADFLAGS_HF );
829 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
832 int ibuflen, *rbuflen;
834 struct adouble ad, *adp;
845 memcpy( &vid, ibuf, sizeof( vid ));
846 ibuf += sizeof( vid );
847 if (( vol = getvolbyvid( vid )) == NULL ) {
848 return( AFPERR_PARAM );
851 memcpy( &did, ibuf, sizeof( did ));
852 ibuf += sizeof( did );
853 if (( dir = dirsearch( vol, did )) == NULL ) {
854 return( AFPERR_NOOBJ );
857 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
858 return( AFPERR_NOOBJ );
861 if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) {
862 memset(&ad, 0, sizeof(ad));
866 if ( ad_open( mtoupath( vol, path ),
867 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
868 O_RDWR, 0, adp) < 0 ) {
871 return( AFPERR_NOITEM );
873 return( AFPERR_ACCESS );
875 return( AFPERR_PARAM );
879 ad_setentrylen( adp, ADEID_COMMENT, 0 );
880 ad_flush( adp, ADFLAGS_HF );
881 ad_close( adp, ADFLAGS_HF );