2 * $Id: desktop.c,v 1.13 2002-05-29 18:02:59 jmarcus Exp $
9 #endif /* HAVE_CONFIG_H */
11 #include <atalk/logger.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"
47 int afp_opendt(obj, ibuf, ibuflen, rbuf, rbuflen )
50 int ibuflen, *rbuflen;
57 memcpy( &vid, ibuf, sizeof(vid));
58 if (( vol = getvolbyvid( vid )) == NULL ) {
60 return( AFPERR_PARAM );
63 memcpy( rbuf, &vid, sizeof(vid));
64 *rbuflen = sizeof(vid);
68 int afp_closedt(obj, ibuf, ibuflen, rbuf, rbuflen )
71 int ibuflen, *rbuflen;
77 struct savedt si = { { 0, 0, 0, 0 }, -1, 0 };
79 static int iconopen( vol, creator, flags, mode )
83 char *dtf, *adt, *adts;
85 if ( si.sdt_fd != -1 ) {
86 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
87 si.sdt_vid == vol->v_vid ) {
94 dtf = dtfile( vol, creator, ".icon" );
96 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
97 if ( errno == ENOENT && ( flags & O_CREAT )) {
98 if (( adts = strrchr( dtf, '/' )) == NULL ) {
102 if (( adt = strrchr( dtf, '/' )) == NULL ) {
106 (void) ad_mkdir( dtf, DIRBITS | 0777 );
108 (void) ad_mkdir( dtf, DIRBITS | 0777 );
111 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
112 LOG(log_error, logtype_afpd, "iconopen: open %s: %s", dtf, strerror(errno) );
120 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
121 si.sdt_vid = vol->v_vid;
126 int afp_addicon(obj, ibuf, ibuflen, rbuf, rbuflen)
129 int ibuflen, *rbuflen;
132 struct iovec iov[ 2 ];
133 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
134 int itype, cc = AFP_OK, iovcnt = 0, buflen;
135 u_int32_t ftype, itag;
136 u_int16_t bsize, rsize, vid;
142 memcpy( &vid, ibuf, sizeof( vid ));
143 ibuf += sizeof( vid );
144 if (( vol = getvolbyvid( vid )) == NULL ) {
149 memcpy( fcreator, ibuf, sizeof( fcreator ));
150 ibuf += sizeof( fcreator );
152 memcpy( &ftype, ibuf, sizeof( ftype ));
153 ibuf += sizeof( ftype );
155 itype = (unsigned char) *ibuf;
158 memcpy( &itag, ibuf, sizeof( itag ));
159 ibuf += sizeof( itag );
161 memcpy( &bsize, ibuf, sizeof( bsize ));
162 bsize = ntohs( bsize );
164 if ( si.sdt_fd != -1 ) {
165 (void)close( si.sdt_fd );
169 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
174 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
177 LOG(log_error, logtype_afpd, "afp_addicon: lseek: %s", strerror(errno) );
183 * Read icon elements until we find a match to replace, or
184 * we get to the end to insert.
187 memcpy( p, &itag, sizeof( itag ));
189 memcpy( p, &ftype, sizeof( ftype ));
190 p += sizeof( ftype );
193 bsize = htons( bsize );
194 memcpy( p, &bsize, sizeof( bsize ));
195 bsize = ntohs( bsize );
196 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
197 memcpy( &rsize, irh + 10, sizeof( rsize ));
198 rsize = ntohs( rsize );
200 * Is this our set of headers?
202 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
204 * Is the size correct?
206 if ( bsize != rsize )
211 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
212 LOG(log_error, logtype_afpd, "afp_addicon: lseek: %s", strerror(errno) );
218 * Some error occurred, return.
222 LOG(log_error, logtype_afpd, "afp_addicon: %s", strerror(errno) );
223 if (obj->proto == AFPPROTO_DSI) {
224 dsi_writeinit(obj->handle, rbuf, buflen);
225 dsi_writeflush(obj->handle);
231 switch (obj->proto) {
235 if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
236 return( AFPERR_PARAM );
238 if (obj->options.flags & OPTION_DEBUG) {
239 printf("(write) len: %d\n", buflen);
240 bprint(rbuf, buflen);
244 * We're at the end of the file, add the headers, etc. */
246 iov[ 0 ].iov_base = (caddr_t)imh;
247 iov[ 0 ].iov_len = sizeof( imh );
248 iov[ 1 ].iov_base = rbuf;
249 iov[ 1 ].iov_len = bsize;
254 * We found an icon to replace.
257 iov[ 0 ].iov_base = rbuf;
258 iov[ 0 ].iov_len = bsize;
262 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
263 LOG(log_error, logtype_afpd, "afp_addicon: writev: %s", strerror(errno) );
264 return( AFPERR_PARAM );
267 #endif /* no afp/asp */
270 DSI *dsi = obj->handle;
272 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
274 /* add headers at end of file */
275 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
276 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
281 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
282 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
287 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
288 if ( obj->options.flags & OPTION_DEBUG ) {
289 printf("(write) command cont'd: %d\n", iovcnt);
290 bprint(rbuf, iovcnt);
293 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
294 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
308 u_char utag[] = { 0, 0, 0, 0 };
309 u_char ucreator[] = { 'U', 'N', 'I', 'X' };
310 u_char utype[] = { 'T', 'E', 'X', 'T' };
313 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
314 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
315 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
316 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
317 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
318 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
319 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
320 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
321 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
322 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
323 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
324 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
325 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
326 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
327 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
328 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
329 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
330 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
331 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
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,
342 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
343 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
344 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
347 int afp_geticoninfo(obj, ibuf, ibuflen, rbuf, rbuflen )
350 int ibuflen, *rbuflen;
353 u_char fcreator[ 4 ], ih[ 12 ];
354 u_int16_t vid, iindex, bsize;
359 memcpy( &vid, ibuf, sizeof( vid ));
360 ibuf += sizeof( vid );
361 if (( vol = getvolbyvid( vid )) == NULL ) {
362 return( AFPERR_PARAM );
365 memcpy( fcreator, ibuf, sizeof( fcreator ));
366 ibuf += sizeof( fcreator );
367 memcpy( &iindex, ibuf, sizeof( iindex ));
368 iindex = ntohs( iindex );
370 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
372 return( AFPERR_NOITEM );
374 memcpy( ih, utag, sizeof( utag ));
375 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
376 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
377 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
378 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
380 memcpy( rbuf, ih, sizeof( ih ));
381 *rbuflen = sizeof( ih );
385 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
386 return( AFPERR_NOITEM );
389 if ( iindex < si.sdt_index ) {
390 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
391 return( AFPERR_PARAM );
397 * Position to the correct spot.
400 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
403 return( AFPERR_NOITEM );
405 memcpy( &bsize, ih + 10, sizeof( bsize ));
406 bsize = ntohs(bsize);
407 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
408 LOG(log_error, logtype_afpd, "afp_iconinfo: lseek: %s", strerror(errno) );
409 return( AFPERR_PARAM );
411 if ( si.sdt_index == iindex ) {
412 memcpy( rbuf, ih, sizeof( ih ));
413 *rbuflen = sizeof( ih );
421 int afp_geticon(obj, ibuf, ibuflen, rbuf, rbuflen )
424 int ibuflen, *rbuflen;
429 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
430 u_int16_t vid, bsize, rsize;
436 memcpy( &vid, ibuf, sizeof( vid ));
437 ibuf += sizeof( vid );
438 if (( vol = getvolbyvid( vid )) == NULL ) {
439 return( AFPERR_PARAM );
442 memcpy( fcreator, ibuf, sizeof( fcreator ));
443 ibuf += sizeof( fcreator );
444 memcpy( ftype, ibuf, sizeof( ftype ));
445 ibuf += sizeof( ftype );
446 itype = (unsigned char) *ibuf++;
448 memcpy( &bsize, ibuf, sizeof( bsize ));
449 bsize = ntohs( bsize );
451 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
452 memcmp( ftype, utype, sizeof( utype )) == 0 &&
455 memcpy( rbuf, uicon, bsize);
460 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
461 return( AFPERR_NOITEM );
464 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
467 LOG(log_error, logtype_afpd, "afp_geticon: lseek: %s", strerror(errno));
468 return( AFPERR_PARAM );
473 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
475 offset += sizeof(ih);
476 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
477 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
480 memcpy( &rsize, ih + 10, sizeof( rsize ));
481 rsize = ntohs( rsize );
482 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
483 LOG(log_error, logtype_afpd, "afp_geticon: lseek: %s", strerror(errno) );
484 return( AFPERR_PARAM );
490 LOG(log_error, logtype_afpd, "afp_geticon: read: %s", strerror(errno));
491 return( AFPERR_PARAM );
495 return( AFPERR_NOITEM );
498 memcpy( &rsize, ih + 10, sizeof( rsize ));
499 rsize = ntohs( rsize );
500 #define min(a,b) ((a)<(b)?(a):(b))
501 rc = min( bsize, rsize );
503 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
504 DSI *dsi = obj->handle;
508 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
509 if (size < rc + offset) {
513 if ((*rbuflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
516 /* do to the streaming nature, we have to exit if we encounter
517 * a problem. much confusion results otherwise. */
518 while (*rbuflen > 0) {
519 #if defined(SENDFILE_FLAVOR_LINUX) || defined(SENDFILE_FLAVOR_BSD)
520 if (!obj->options.flags & OPTION_DEBUG) {
521 #ifdef SENDFILE_FLAVOR_LINUX
522 if (sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0)
524 #endif /* SENDFILE_FLAVOR_LINUX */
526 #ifdef SENDFILE_FLAVOR_BSD
527 if (sendfile(si.sdt_fd, dsi->socket, offset, rc, NULL, NULL, 0) < 0)
529 #endif /* SENDFILE_FLAVOR_BSD */
533 #endif /* SENDFILE_FLAVOR_LINUX || SENDFILE_FLAVOR_BSD */
535 buflen = read(si.sdt_fd, rbuf, *rbuflen);
539 if (obj->options.flags & OPTION_DEBUG) {
540 printf( "(read) reply: %d, %d\n", buflen, dsi->clientID);
541 bprint(rbuf, buflen);
544 /* dsi_read() also returns buffer size of next allocation */
545 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
557 LOG(log_info, logtype_afpd, "afp_geticon: %s", strerror(errno));
563 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
564 return( AFPERR_PARAM );
572 static char hexdig[] = "0123456789abcdef";
573 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
575 static char path[ MAXPATHLEN + 1];
579 strcpy( path, vol->v_path );
580 strcat( path, "/.AppleDesktop/" );
581 for ( p = path; *p != '\0'; p++ )
584 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
585 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
586 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
593 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
594 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
595 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
596 *p++ = hexdig[ creator[ i ] & 0x0f ];
607 char *mtoupath(const struct vol *vol, char *mpath)
609 static char upath[ MAXPATHLEN + 1];
613 if ( *mpath == '\0' ) {
618 mpath = demangle(vol, mpath);
619 #endif /* FILE_MANGLING */
623 while ( *m != '\0' ) {
624 /* handle case conversion first */
625 if (vol->v_casefold & AFPVOL_MTOUUPPER)
626 *m = diatoupper( *m );
627 else if (vol->v_casefold & AFPVOL_MTOULOWER)
628 *m = diatolower( *m );
630 /* we have a code page. we only use the ascii range
631 * if we have map ascii specified. */
633 if (vol->v_mtoupage && ((*m & 0x80) ||
634 vol->v_flags & AFPVOL_MAPASCII)) {
635 *u = vol->v_mtoupage->map[(unsigned char) *m].value;
638 #if AD_VERSION == AD_VERSION1
639 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
640 (!isascii(*m) || *m == '/')) ||
641 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
642 ( i == 0 && (*m == '.' )))) {
643 #else /* AD_VERSION == AD_VERSION1 */
644 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
645 (!isprint(*m) || *m == '/')) ||
646 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
647 ( i == 0 && (*m == '.' )))) {
648 #endif /* AD_VERSION == AD_VERSION1 */
649 /* do hex conversion. */
651 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
652 *u = hexdig[ *m & 0x0f ];
664 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
665 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
667 char *utompath(const struct vol *vol, char *upath)
669 static char mpath[ MAXPATHLEN + 1];
674 upath = mangle(vol, upath);
675 #endif /* FILE_MANGLING */
677 /* do the hex conversion */
680 while ( *u != '\0' ) {
681 /* we have a code page */
683 if (vol->v_utompage && ((*u & 0x80) ||
684 (vol->v_flags & AFPVOL_MAPASCII))) {
685 *m = vol->v_utompage->map[(unsigned char) *u].value;
688 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
689 *(u+2) != '\0' && islxdigit( *(u+2))) {
691 h = hextoint( *u ) << 4;
698 /* handle case conversion */
699 if (vol->v_casefold & AFPVOL_UTOMLOWER)
700 *m = diatolower( *m );
701 else if (vol->v_casefold & AFPVOL_UTOMUPPER)
702 *m = diatoupper( *m );
711 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
714 int ibuflen, *rbuflen;
716 struct adouble ad, *adp;
728 memcpy( &vid, ibuf, sizeof( vid ));
729 ibuf += sizeof( vid );
730 if (( vol = getvolbyvid( vid )) == NULL ) {
731 return( AFPERR_PARAM );
734 memcpy( &did, ibuf, sizeof( did ));
735 ibuf += sizeof( did );
736 if (( dir = dirsearch( vol, did )) == NULL ) {
737 return( AFPERR_NOOBJ );
740 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
741 return( AFPERR_NOOBJ );
744 if ((u_long)ibuf & 1 ) {
748 clen = (u_char)*ibuf++;
749 clen = min( clen, 199 );
751 if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) {
752 memset(&ad, 0, sizeof(ad));
756 if (ad_open( mtoupath( vol, path ), vol_noadouble(vol) |
757 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
758 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
759 return( AFPERR_ACCESS );
762 if ( ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT ) {
763 if ( *path == '\0' ) {
764 name = curdir->d_name;
768 ad_setentrylen( adp, ADEID_NAME, strlen( name ));
769 memcpy( ad_entry( adp, ADEID_NAME ), name,
770 ad_getentrylen( adp, ADEID_NAME ));
773 ad_setentrylen( adp, ADEID_COMMENT, clen );
774 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
775 ad_flush( adp, ADFLAGS_HF );
776 ad_close( adp, ADFLAGS_HF );
780 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
783 int ibuflen, *rbuflen;
785 struct adouble ad, *adp;
796 memcpy( &vid, ibuf, sizeof( vid ));
797 ibuf += sizeof( vid );
798 if (( vol = getvolbyvid( vid )) == NULL ) {
799 return( AFPERR_PARAM );
802 memcpy( &did, ibuf, sizeof( did ));
803 ibuf += sizeof( did );
804 if (( dir = dirsearch( vol, did )) == NULL ) {
805 return( AFPERR_NOOBJ );
808 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
809 return( AFPERR_NOOBJ );
812 if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) {
813 memset(&ad, 0, sizeof(ad));
817 if ( ad_open( mtoupath( vol, path ),
818 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
819 O_RDONLY, 0666, adp) < 0 ) {
820 return( AFPERR_NOITEM );
824 * Make sure the AD file is not bogus.
826 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
827 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
828 ad_close( adp, ADFLAGS_HF );
829 return( AFPERR_NOITEM );
832 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
833 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
834 ad_getentrylen( adp, ADEID_COMMENT ));
835 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
836 ad_close( adp, ADFLAGS_HF );
840 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
843 int ibuflen, *rbuflen;
845 struct adouble ad, *adp;
856 memcpy( &vid, ibuf, sizeof( vid ));
857 ibuf += sizeof( vid );
858 if (( vol = getvolbyvid( vid )) == NULL ) {
859 return( AFPERR_PARAM );
862 memcpy( &did, ibuf, sizeof( did ));
863 ibuf += sizeof( did );
864 if (( dir = dirsearch( vol, did )) == NULL ) {
865 return( AFPERR_NOOBJ );
868 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
869 return( AFPERR_NOOBJ );
872 if ((*path == '\0') || !(of = of_findname(vol, curdir, path))) {
873 memset(&ad, 0, sizeof(ad));
877 if ( ad_open( mtoupath( vol, path ),
878 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
879 O_RDWR, 0, adp) < 0 ) {
882 return( AFPERR_NOITEM );
884 return( AFPERR_ACCESS );
886 return( AFPERR_PARAM );
890 ad_setentrylen( adp, ADEID_COMMENT, 0 );
891 ad_flush( adp, ADFLAGS_HF );
892 ad_close( adp, ADFLAGS_HF );