2 * $Id: desktop.c,v 1.22 2003-01-24 07:08:42 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;
770 memcpy( &vid, ibuf, sizeof( vid ));
771 ibuf += sizeof( vid );
772 if (NULL == ( vol = getvolbyvid( vid )) ) {
773 return( AFPERR_PARAM );
776 memcpy( &did, ibuf, sizeof( did ));
777 ibuf += sizeof( did );
778 if (NULL == ( dir = dirlookup( vol, did )) ) {
782 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
786 if ((u_long)ibuf & 1 ) {
790 clen = (u_char)*ibuf++;
791 clen = min( clen, 199 );
793 upath = path->u_name;
794 if (check_access(upath, OPENACC_WR ) < 0) {
795 return AFPERR_ACCESS;
798 isadir = path_isadir(path);
799 if (isadir || !(of = of_findname(path))) {
800 memset(&ad, 0, sizeof(ad));
805 if (ad_open( upath , vol_noadouble(vol) |
806 (( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
807 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
808 return( AFPERR_ACCESS );
811 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
812 if ( *path->m_name == '\0' ) {
813 name = curdir->d_m_name;
817 ad_setentrylen( adp, ADEID_NAME, strlen( name ));
818 memcpy( ad_entry( adp, ADEID_NAME ), name,
819 ad_getentrylen( adp, ADEID_NAME ));
822 ad_setentrylen( adp, ADEID_COMMENT, clen );
823 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
824 ad_flush( adp, ADFLAGS_HF );
825 ad_close( adp, ADFLAGS_HF );
829 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
832 int ibuflen, *rbuflen;
834 struct adouble ad, *adp;
847 memcpy( &vid, ibuf, sizeof( vid ));
848 ibuf += sizeof( vid );
849 if (NULL == ( vol = getvolbyvid( vid )) ) {
850 return( AFPERR_PARAM );
853 memcpy( &did, ibuf, sizeof( did ));
854 ibuf += sizeof( did );
855 if (NULL == ( dir = dirlookup( vol, did )) ) {
859 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
863 upath = s_path->u_name;
864 isadir = path_isadir(s_path);
865 if (isadir || !(of = of_findname(s_path))) {
866 memset(&ad, 0, sizeof(ad));
871 ( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
872 O_RDONLY, 0666, adp) < 0 ) {
873 return( AFPERR_NOITEM );
877 * Make sure the AD file is not bogus.
879 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
880 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
881 ad_close( adp, ADFLAGS_HF );
882 return( AFPERR_NOITEM );
885 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
886 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
887 ad_getentrylen( adp, ADEID_COMMENT ));
888 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
889 ad_close( adp, ADFLAGS_HF );
891 /* return AFPERR_NOITEM if len == 0 ? */
895 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
898 int ibuflen, *rbuflen;
900 struct adouble ad, *adp;
913 memcpy( &vid, ibuf, sizeof( vid ));
914 ibuf += sizeof( vid );
915 if (NULL == ( vol = getvolbyvid( vid )) ) {
916 return( AFPERR_PARAM );
919 memcpy( &did, ibuf, sizeof( did ));
920 ibuf += sizeof( did );
921 if (NULL == ( dir = dirlookup( vol, did )) ) {
925 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
929 upath = s_path->u_name;
930 if (check_access(upath, OPENACC_WR ) < 0) {
931 return AFPERR_ACCESS;
934 isadir = path_isadir(s_path);
935 if (isadir || !(of = of_findname(s_path))) {
936 memset(&ad, 0, sizeof(ad));
942 (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
943 O_RDWR, 0, adp) < 0 ) {
946 return( AFPERR_NOITEM );
948 return( AFPERR_ACCESS );
950 return( AFPERR_PARAM );
954 ad_setentrylen( adp, ADEID_COMMENT, 0 );
955 ad_flush( adp, ADFLAGS_HF );
956 ad_close( adp, ADFLAGS_HF );