2 * $Id: desktop.c,v 1.21 2003-01-12 14:39:58 didg Exp $
7 * afp_XXXcomment are (the only) functions able to open
8 * a ressource fork when there's no data fork, eg after
9 * it was removed with samba.
14 #endif /* HAVE_CONFIG_H */
16 #include <atalk/logger.h>
18 #include <sys/types.h>
21 #include <sys/param.h>
23 #include <sys/socket.h>
24 #include <netatalk/at.h>
25 #include <netatalk/endian.h>
26 #include <atalk/dsi.h>
27 #include <atalk/atp.h>
28 #include <atalk/asp.h>
29 #include <atalk/afp.h>
30 #include <atalk/adouble.h>
31 #include <atalk/util.h>
35 #endif /* HAVE_FCNTL_H */
41 #endif /* HAVE_FCNTL_H */
44 #include "directory.h"
52 int afp_opendt(obj, ibuf, ibuflen, rbuf, rbuflen )
55 int ibuflen, *rbuflen;
62 memcpy( &vid, ibuf, sizeof(vid));
63 if (NULL == ( vol = getvolbyvid( vid )) ) {
65 return( AFPERR_PARAM );
68 memcpy( rbuf, &vid, sizeof(vid));
69 *rbuflen = sizeof(vid);
73 int afp_closedt(obj, ibuf, ibuflen, rbuf, rbuflen )
76 int ibuflen, *rbuflen;
82 struct savedt si = { { 0, 0, 0, 0 }, -1, 0 };
84 static int iconopen( vol, creator, flags, mode )
88 char *dtf, *adt, *adts;
90 if ( si.sdt_fd != -1 ) {
91 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
92 si.sdt_vid == vol->v_vid ) {
99 dtf = dtfile( vol, creator, ".icon" );
101 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
102 if ( errno == ENOENT && ( flags & O_CREAT )) {
103 if (( adts = strrchr( dtf, '/' )) == NULL ) {
107 if (( adt = strrchr( dtf, '/' )) == NULL ) {
111 (void) ad_mkdir( dtf, DIRBITS | 0777 );
113 (void) ad_mkdir( dtf, DIRBITS | 0777 );
116 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
117 LOG(log_error, logtype_afpd, "iconopen: open %s: %s", dtf, strerror(errno) );
125 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
126 si.sdt_vid = vol->v_vid;
131 int afp_addicon(obj, ibuf, ibuflen, rbuf, rbuflen)
134 int ibuflen, *rbuflen;
137 struct iovec iov[ 2 ];
138 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
139 int itype, cc = AFP_OK, iovcnt = 0, buflen;
140 u_int32_t ftype, itag;
141 u_int16_t bsize, rsize, vid;
147 memcpy( &vid, ibuf, sizeof( vid ));
148 ibuf += sizeof( vid );
149 if (( vol = getvolbyvid( vid )) == NULL ) {
154 memcpy( fcreator, ibuf, sizeof( fcreator ));
155 ibuf += sizeof( fcreator );
157 memcpy( &ftype, ibuf, sizeof( ftype ));
158 ibuf += sizeof( ftype );
160 itype = (unsigned char) *ibuf;
163 memcpy( &itag, ibuf, sizeof( itag ));
164 ibuf += sizeof( itag );
166 memcpy( &bsize, ibuf, sizeof( bsize ));
167 bsize = ntohs( bsize );
169 if ( si.sdt_fd != -1 ) {
170 (void)close( si.sdt_fd );
174 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
179 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
182 LOG(log_error, logtype_afpd, "afp_addicon: lseek: %s", strerror(errno) );
188 * Read icon elements until we find a match to replace, or
189 * we get to the end to insert.
192 memcpy( p, &itag, sizeof( itag ));
194 memcpy( p, &ftype, sizeof( ftype ));
195 p += sizeof( ftype );
198 bsize = htons( bsize );
199 memcpy( p, &bsize, sizeof( bsize ));
200 bsize = ntohs( bsize );
201 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
202 memcpy( &rsize, irh + 10, sizeof( rsize ));
203 rsize = ntohs( rsize );
205 * Is this our set of headers?
207 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
209 * Is the size correct?
211 if ( bsize != rsize )
216 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
217 LOG(log_error, logtype_afpd, "afp_addicon: lseek: %s", strerror(errno) );
223 * Some error occurred, return.
227 LOG(log_error, logtype_afpd, "afp_addicon: %s", strerror(errno) );
228 if (obj->proto == AFPPROTO_DSI) {
229 dsi_writeinit(obj->handle, rbuf, buflen);
230 dsi_writeflush(obj->handle);
236 switch (obj->proto) {
240 if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
241 return( AFPERR_PARAM );
243 if (obj->options.flags & OPTION_DEBUG) {
244 printf("(write) len: %d\n", buflen);
245 bprint(rbuf, buflen);
249 * We're at the end of the file, add the headers, etc. */
251 iov[ 0 ].iov_base = (caddr_t)imh;
252 iov[ 0 ].iov_len = sizeof( imh );
253 iov[ 1 ].iov_base = rbuf;
254 iov[ 1 ].iov_len = bsize;
259 * We found an icon to replace.
262 iov[ 0 ].iov_base = rbuf;
263 iov[ 0 ].iov_len = bsize;
267 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
268 LOG(log_error, logtype_afpd, "afp_addicon: writev: %s", strerror(errno) );
269 return( AFPERR_PARAM );
272 #endif /* no afp/asp */
275 DSI *dsi = obj->handle;
277 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
279 /* add headers at end of file */
280 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
281 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
286 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
287 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
292 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
293 if ( obj->options.flags & OPTION_DEBUG ) {
294 printf("(write) command cont'd: %d\n", iovcnt);
295 bprint(rbuf, iovcnt);
298 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
299 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
313 u_char utag[] = { 0, 0, 0, 0 };
314 u_char ucreator[] = { 'U', 'N', 'I', 'X' };
315 u_char utype[] = { 'T', 'E', 'X', 'T' };
318 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
319 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
320 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
321 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
322 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
323 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
324 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
325 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
326 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
327 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
328 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
329 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
330 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
331 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
332 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
333 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
334 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
335 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
336 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
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,
345 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
346 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
347 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
348 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
349 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
352 int afp_geticoninfo(obj, ibuf, ibuflen, rbuf, rbuflen )
355 int ibuflen, *rbuflen;
358 u_char fcreator[ 4 ], ih[ 12 ];
359 u_int16_t vid, iindex, bsize;
364 memcpy( &vid, ibuf, sizeof( vid ));
365 ibuf += sizeof( vid );
366 if (( vol = getvolbyvid( vid )) == NULL ) {
367 return( AFPERR_PARAM );
370 memcpy( fcreator, ibuf, sizeof( fcreator ));
371 ibuf += sizeof( fcreator );
372 memcpy( &iindex, ibuf, sizeof( iindex ));
373 iindex = ntohs( iindex );
375 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
377 return( AFPERR_NOITEM );
379 memcpy( ih, utag, sizeof( utag ));
380 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
381 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
382 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
383 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
385 memcpy( rbuf, ih, sizeof( ih ));
386 *rbuflen = sizeof( ih );
390 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
391 return( AFPERR_NOITEM );
394 if ( iindex < si.sdt_index ) {
395 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
396 return( AFPERR_PARAM );
402 * Position to the correct spot.
405 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
408 return( AFPERR_NOITEM );
410 memcpy( &bsize, ih + 10, sizeof( bsize ));
411 bsize = ntohs(bsize);
412 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
413 LOG(log_error, logtype_afpd, "afp_iconinfo: lseek: %s", strerror(errno) );
414 return( AFPERR_PARAM );
416 if ( si.sdt_index == iindex ) {
417 memcpy( rbuf, ih, sizeof( ih ));
418 *rbuflen = sizeof( ih );
426 int afp_geticon(obj, ibuf, ibuflen, rbuf, rbuflen )
429 int ibuflen, *rbuflen;
434 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
435 u_int16_t vid, bsize, rsize;
441 memcpy( &vid, ibuf, sizeof( vid ));
442 ibuf += sizeof( vid );
443 if (( vol = getvolbyvid( vid )) == NULL ) {
444 return( AFPERR_PARAM );
447 memcpy( fcreator, ibuf, sizeof( fcreator ));
448 ibuf += sizeof( fcreator );
449 memcpy( ftype, ibuf, sizeof( ftype ));
450 ibuf += sizeof( ftype );
451 itype = (unsigned char) *ibuf++;
453 memcpy( &bsize, ibuf, sizeof( bsize ));
454 bsize = ntohs( bsize );
456 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
457 memcmp( ftype, utype, sizeof( utype )) == 0 &&
460 memcpy( rbuf, uicon, bsize);
465 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
466 return( AFPERR_NOITEM );
469 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
472 LOG(log_error, logtype_afpd, "afp_geticon: lseek: %s", strerror(errno));
473 return( AFPERR_PARAM );
478 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
480 offset += sizeof(ih);
481 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
482 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
485 memcpy( &rsize, ih + 10, sizeof( rsize ));
486 rsize = ntohs( rsize );
487 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
488 LOG(log_error, logtype_afpd, "afp_geticon: lseek: %s", strerror(errno) );
489 return( AFPERR_PARAM );
495 LOG(log_error, logtype_afpd, "afp_geticon: read: %s", strerror(errno));
496 return( AFPERR_PARAM );
500 return( AFPERR_NOITEM );
503 memcpy( &rsize, ih + 10, sizeof( rsize ));
504 rsize = ntohs( rsize );
505 #define min(a,b) ((a)<(b)?(a):(b))
506 rc = min( bsize, rsize );
508 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
509 DSI *dsi = obj->handle;
513 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
514 if (size < rc + offset) {
518 if ((*rbuflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
521 /* do to the streaming nature, we have to exit if we encounter
522 * a problem. much confusion results otherwise. */
523 while (*rbuflen > 0) {
524 #if defined(SENDFILE_FLAVOR_LINUX) || defined(SENDFILE_FLAVOR_BSD)
525 if (!obj->options.flags & OPTION_DEBUG) {
526 #ifdef SENDFILE_FLAVOR_LINUX
527 if (sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0)
529 #endif /* SENDFILE_FLAVOR_LINUX */
531 #ifdef SENDFILE_FLAVOR_BSD
532 if (sendfile(si.sdt_fd, dsi->socket, offset, rc, NULL, NULL, 0) < 0)
534 #endif /* SENDFILE_FLAVOR_BSD */
538 #endif /* SENDFILE_FLAVOR_LINUX || SENDFILE_FLAVOR_BSD */
540 buflen = read(si.sdt_fd, rbuf, *rbuflen);
544 if (obj->options.flags & OPTION_DEBUG) {
545 printf( "(read) reply: %d, %d\n", buflen, dsi->clientID);
546 bprint(rbuf, buflen);
549 /* dsi_read() also returns buffer size of next allocation */
550 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
562 LOG(log_info, logtype_afpd, "afp_geticon: %s", strerror(errno));
568 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
569 return( AFPERR_PARAM );
577 static char hexdig[] = "0123456789abcdef";
578 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
580 static char path[ MAXPATHLEN + 1];
584 strcpy( path, vol->v_path );
585 strcat( path, "/.AppleDesktop/" );
586 for ( p = path; *p != '\0'; p++ )
589 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
590 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
591 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
598 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
599 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
600 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
601 *p++ = hexdig[ creator[ i ] & 0x0f ];
613 * mpath is only a filename
615 char *mtoupath(const struct vol *vol, char *mpath)
617 static char upath[ MAXPATHLEN + 1];
622 if ( *mpath == '\0' ) {
627 m = demangle(vol, mpath);
632 #endif /* FILE_MANGLING */
635 while ( *m != '\0' ) {
636 /* handle case conversion first */
637 if (vol->v_casefold & AFPVOL_MTOUUPPER)
638 *m = diatoupper( *m );
639 else if (vol->v_casefold & AFPVOL_MTOULOWER)
640 *m = diatolower( *m );
642 /* we have a code page. we only use the ascii range
643 * if we have map ascii specified. */
644 if (vol->v_mtoupage && ((*m & 0x80) ||
645 vol->v_flags & AFPVOL_MAPASCII)) {
646 *u = vol->v_mtoupage->map[(unsigned char) *m].value;
649 /* if conversion failed, encode in hex
650 * to prevent silly truncation
651 * H.P. Jansen <hpj@urpla.net> */
653 LOG(log_debug, logtype_afpd, "mtoupath: hex encode: 0x%x", (unsigned char) *m);
656 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
657 *u = hexdig[ *m & 0x0f ];
660 #if AD_VERSION == AD_VERSION1
661 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
662 (!isascii(*m) || *m == '/')) ||
663 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
664 ( i == 0 && (*m == '.' )))) {
665 #else /* AD_VERSION == AD_VERSION1 */
666 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
667 (!isprint(*m) || *m == '/')) ||
668 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
669 ( i == 0 && (*m == '.' )))) {
670 #endif /* AD_VERSION == AD_VERSION1 */
671 /* do hex conversion. */
673 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
674 *u = hexdig[ *m & 0x0f ];
686 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
689 return( (changed)?upath:mpath );
692 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
693 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
695 char *utompath(const struct vol *vol, char *upath)
697 static char mpath[ MAXPATHLEN + 1];
702 /* do the hex conversion */
705 while ( *u != '\0' ) {
706 /* we have a code page */
708 if (vol->v_utompage && ((*u & 0x80) ||
709 (vol->v_flags & AFPVOL_MAPASCII))) {
710 *m = vol->v_utompage->map[(unsigned char) *u].value;
714 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
715 *(u+2) != '\0' && islxdigit( *(u+2))) {
717 h = hextoint( *u ) << 4;
725 /* handle case conversion */
726 if (vol->v_casefold & AFPVOL_UTOMLOWER)
727 *m = diatolower( *m );
728 else if (vol->v_casefold & AFPVOL_UTOMUPPER)
729 *m = diatoupper( *m );
738 m = mangle(vol, mpath);
742 #endif /* FILE_MANGLING */
745 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s'", upath, mpath);
748 return((changed)? m:upath );
751 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
754 int ibuflen, *rbuflen;
756 struct adouble ad, *adp;
769 memcpy( &vid, ibuf, sizeof( vid ));
770 ibuf += sizeof( vid );
771 if (NULL == ( vol = getvolbyvid( vid )) ) {
772 return( AFPERR_PARAM );
775 memcpy( &did, ibuf, sizeof( did ));
776 ibuf += sizeof( did );
777 if (NULL == ( dir = dirlookup( vol, did )) ) {
781 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
785 if ((u_long)ibuf & 1 ) {
789 clen = (u_char)*ibuf++;
790 clen = min( clen, 199 );
792 upath = path->u_name;
793 if (check_access(upath, OPENACC_WR ) < 0) {
794 return AFPERR_ACCESS;
797 if (*path->m_name == '\0' || !(of = of_findname(path))) {
798 memset(&ad, 0, sizeof(ad));
803 if (ad_open( upath , vol_noadouble(vol) |
804 (( *path->m_name == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
805 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
806 return( AFPERR_ACCESS );
809 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
810 if ( *path->m_name == '\0' ) {
811 name = curdir->d_m_name;
815 ad_setentrylen( adp, ADEID_NAME, strlen( name ));
816 memcpy( ad_entry( adp, ADEID_NAME ), name,
817 ad_getentrylen( adp, ADEID_NAME ));
820 ad_setentrylen( adp, ADEID_COMMENT, clen );
821 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
822 ad_flush( adp, ADFLAGS_HF );
823 ad_close( adp, ADFLAGS_HF );
827 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
830 int ibuflen, *rbuflen;
832 struct adouble ad, *adp;
844 memcpy( &vid, ibuf, sizeof( vid ));
845 ibuf += sizeof( vid );
846 if (NULL == ( vol = getvolbyvid( vid )) ) {
847 return( AFPERR_PARAM );
850 memcpy( &did, ibuf, sizeof( did ));
851 ibuf += sizeof( did );
852 if (NULL == ( dir = dirlookup( vol, did )) ) {
856 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
860 upath = s_path->u_name;
861 path = s_path->m_name;
863 if (*path == '\0' || !(of = of_findname(s_path))) {
864 memset(&ad, 0, sizeof(ad));
869 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
870 O_RDONLY, 0666, adp) < 0 ) {
871 return( AFPERR_NOITEM );
875 * Make sure the AD file is not bogus.
877 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
878 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
879 ad_close( adp, ADFLAGS_HF );
880 return( AFPERR_NOITEM );
883 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
884 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
885 ad_getentrylen( adp, ADEID_COMMENT ));
886 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
887 ad_close( adp, ADFLAGS_HF );
889 /* return AFPERR_NOITEM if len == 0 ? */
893 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
896 int ibuflen, *rbuflen;
898 struct adouble ad, *adp;
910 memcpy( &vid, ibuf, sizeof( vid ));
911 ibuf += sizeof( vid );
912 if (NULL == ( vol = getvolbyvid( vid )) ) {
913 return( AFPERR_PARAM );
916 memcpy( &did, ibuf, sizeof( did ));
917 ibuf += sizeof( did );
918 if (NULL == ( dir = dirlookup( vol, did )) ) {
922 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
926 upath = s_path->u_name;
927 path = s_path->m_name;
928 if (check_access(upath, OPENACC_WR ) < 0) {
929 return AFPERR_ACCESS;
932 if (path == '\0' || !(of = of_findname(s_path))) {
933 memset(&ad, 0, sizeof(ad));
939 (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
940 O_RDWR, 0, adp) < 0 ) {
943 return( AFPERR_NOITEM );
945 return( AFPERR_ACCESS );
947 return( AFPERR_PARAM );
951 ad_setentrylen( adp, ADEID_COMMENT, 0 );
952 ad_flush( adp, ADFLAGS_HF );
953 ad_close( adp, ADFLAGS_HF );