2 * $Id: desktop.c,v 1.16 2002-09-09 01:21:59 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];
673 /* do the hex conversion */
676 while ( *u != '\0' ) {
677 /* we have a code page */
679 if (vol->v_utompage && ((*u & 0x80) ||
680 (vol->v_flags & AFPVOL_MAPASCII))) {
681 *m = vol->v_utompage->map[(unsigned char) *u].value;
684 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
685 *(u+2) != '\0' && islxdigit( *(u+2))) {
687 h = hextoint( *u ) << 4;
694 /* handle case conversion */
695 if (vol->v_casefold & AFPVOL_UTOMLOWER)
696 *m = diatolower( *m );
697 else if (vol->v_casefold & AFPVOL_UTOMUPPER)
698 *m = diatoupper( *m );
706 strcpy(mpath,mangle(vol, mpath));
707 #endif /* FILE_MANGLING */
712 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
715 int ibuflen, *rbuflen;
717 struct adouble ad, *adp;
721 char *path, *name, *upath;
729 memcpy( &vid, ibuf, sizeof( vid ));
730 ibuf += sizeof( vid );
731 if (( vol = getvolbyvid( vid )) == NULL ) {
732 return( AFPERR_PARAM );
735 memcpy( &did, ibuf, sizeof( did ));
736 ibuf += sizeof( did );
737 if (( dir = dirsearch( vol, did )) == NULL ) {
738 return( AFPERR_NOOBJ );
741 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
742 return( AFPERR_NOOBJ );
745 if ((u_long)ibuf & 1 ) {
749 clen = (u_char)*ibuf++;
750 clen = min( clen, 199 );
751 upath = mtoupath( vol, path );
752 if ((*path == '\0') || !(of = of_findname(upath, NULL))) {
753 memset(&ad, 0, sizeof(ad));
757 if (ad_open( upath , vol_noadouble(vol) |
758 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
759 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
760 return( AFPERR_ACCESS );
763 if ( ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT ) {
764 if ( *path == '\0' ) {
765 name = curdir->d_name;
769 ad_setentrylen( adp, ADEID_NAME, strlen( name ));
770 memcpy( ad_entry( adp, ADEID_NAME ), name,
771 ad_getentrylen( adp, ADEID_NAME ));
774 ad_setentrylen( adp, ADEID_COMMENT, clen );
775 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
776 ad_flush( adp, ADFLAGS_HF );
777 ad_close( adp, ADFLAGS_HF );
781 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
784 int ibuflen, *rbuflen;
786 struct adouble ad, *adp;
797 memcpy( &vid, ibuf, sizeof( vid ));
798 ibuf += sizeof( vid );
799 if (( vol = getvolbyvid( vid )) == NULL ) {
800 return( AFPERR_PARAM );
803 memcpy( &did, ibuf, sizeof( did ));
804 ibuf += sizeof( did );
805 if (( dir = dirsearch( vol, did )) == NULL ) {
806 return( AFPERR_NOOBJ );
809 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
810 return( AFPERR_NOOBJ );
814 upath = mtoupath( vol, path );
815 if ((*path == '\0') || !(of = of_findname(upath, NULL))) {
816 memset(&ad, 0, sizeof(ad));
821 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
822 O_RDONLY, 0666, adp) < 0 ) {
823 return( AFPERR_NOITEM );
827 * Make sure the AD file is not bogus.
829 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
830 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
831 ad_close( adp, ADFLAGS_HF );
832 return( AFPERR_NOITEM );
835 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
836 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
837 ad_getentrylen( adp, ADEID_COMMENT ));
838 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
839 ad_close( adp, ADFLAGS_HF );
843 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
846 int ibuflen, *rbuflen;
848 struct adouble ad, *adp;
859 memcpy( &vid, ibuf, sizeof( vid ));
860 ibuf += sizeof( vid );
861 if (( vol = getvolbyvid( vid )) == NULL ) {
862 return( AFPERR_PARAM );
865 memcpy( &did, ibuf, sizeof( did ));
866 ibuf += sizeof( did );
867 if (( dir = dirsearch( vol, did )) == NULL ) {
868 return( AFPERR_NOOBJ );
871 if (( path = cname( vol, dir, &ibuf )) == NULL ) {
872 return( AFPERR_NOOBJ );
875 upath = mtoupath( vol, path );
876 if ((*path == '\0') || !(of = of_findname(upath, NULL))) {
877 memset(&ad, 0, sizeof(ad));
883 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
884 O_RDWR, 0, adp) < 0 ) {
887 return( AFPERR_NOITEM );
889 return( AFPERR_ACCESS );
891 return( AFPERR_PARAM );
895 ad_setentrylen( adp, ADEID_COMMENT, 0 );
896 ad_flush( adp, ADFLAGS_HF );
897 ad_close( adp, ADFLAGS_HF );