2 * $Id: desktop.c,v 1.15 2002-09-05 14:52:05 didg 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;
720 char *path, *name, *upath;
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 );
750 upath = mtoupath( vol, path );
751 if ((*path == '\0') || !(of = of_findname(upath, NULL))) {
752 memset(&ad, 0, sizeof(ad));
756 if (ad_open( upath , 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 );
813 upath = mtoupath( vol, path );
814 if ((*path == '\0') || !(of = of_findname(upath, NULL))) {
815 memset(&ad, 0, sizeof(ad));
820 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
821 O_RDONLY, 0666, adp) < 0 ) {
822 return( AFPERR_NOITEM );
826 * Make sure the AD file is not bogus.
828 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
829 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
830 ad_close( adp, ADFLAGS_HF );
831 return( AFPERR_NOITEM );
834 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
835 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
836 ad_getentrylen( adp, ADEID_COMMENT ));
837 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
838 ad_close( adp, ADFLAGS_HF );
842 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
845 int ibuflen, *rbuflen;
847 struct adouble ad, *adp;
858 memcpy( &vid, ibuf, sizeof( vid ));
859 ibuf += sizeof( vid );
860 if (( vol = getvolbyvid( vid )) == NULL ) {
861 return( AFPERR_PARAM );
864 memcpy( &did, ibuf, sizeof( did ));
865 ibuf += sizeof( did );
866 if (( dir = dirsearch( vol, did )) == NULL ) {
867 return( AFPERR_NOOBJ );
870 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
871 return( AFPERR_NOOBJ );
874 upath = mtoupath( vol, path );
875 if ((*path == '\0') || !(of = of_findname(upath, NULL))) {
876 memset(&ad, 0, sizeof(ad));
882 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
883 O_RDWR, 0, adp) < 0 ) {
886 return( AFPERR_NOITEM );
888 return( AFPERR_ACCESS );
890 return( AFPERR_PARAM );
894 ad_setentrylen( adp, ADEID_COMMENT, 0 );
895 ad_flush( adp, ADFLAGS_HF );
896 ad_close( adp, ADFLAGS_HF );