2 * $Id: desktop.c,v 1.26.2.4.2.10 2004-03-11 02:01:59 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 */
23 #include <atalk/adouble.h>
25 #include <sys/param.h>
26 #include <sys/socket.h>
27 #include <netatalk/at.h>
28 #include <netatalk/endian.h>
29 #include <atalk/dsi.h>
30 #include <atalk/atp.h>
31 #include <atalk/asp.h>
32 #include <atalk/afp.h>
33 #include <atalk/util.h>
34 #include <atalk/logger.h>
36 #include "directory.h"
43 int afp_opendt(obj, ibuf, ibuflen, rbuf, rbuflen )
46 int ibuflen, *rbuflen;
53 memcpy( &vid, ibuf, sizeof(vid));
54 if (NULL == ( vol = getvolbyvid( vid )) ) {
56 return( AFPERR_PARAM );
59 memcpy( rbuf, &vid, sizeof(vid));
60 *rbuflen = sizeof(vid);
64 int afp_closedt(obj, ibuf, ibuflen, rbuf, rbuflen )
67 int ibuflen, *rbuflen;
73 struct savedt si = { { 0, 0, 0, 0 }, -1, 0 };
75 static int iconopen( vol, creator, flags, mode )
79 char *dtf, *adt, *adts;
81 if ( si.sdt_fd != -1 ) {
82 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
83 si.sdt_vid == vol->v_vid ) {
90 dtf = dtfile( vol, creator, ".icon" );
92 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
93 if ( errno == ENOENT && ( flags & O_CREAT )) {
94 if (( adts = strrchr( dtf, '/' )) == NULL ) {
98 if (( adt = strrchr( dtf, '/' )) == NULL ) {
102 (void) ad_mkdir( dtf, DIRBITS | 0777 );
104 (void) ad_mkdir( dtf, DIRBITS | 0777 );
107 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
108 LOG(log_error, logtype_afpd, "iconopen: open %s: %s", dtf, strerror(errno) );
116 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
117 si.sdt_vid = vol->v_vid;
122 int afp_addicon(obj, ibuf, ibuflen, rbuf, rbuflen)
125 int ibuflen, *rbuflen;
128 struct iovec iov[ 2 ];
129 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
130 int itype, cc = AFP_OK, iovcnt = 0, buflen;
131 u_int32_t ftype, itag;
132 u_int16_t bsize, rsize, vid;
138 memcpy( &vid, ibuf, sizeof( vid ));
139 ibuf += sizeof( vid );
140 if (NULL == ( vol = getvolbyvid( vid )) ) {
145 memcpy( fcreator, ibuf, sizeof( fcreator ));
146 ibuf += sizeof( fcreator );
148 memcpy( &ftype, ibuf, sizeof( ftype ));
149 ibuf += sizeof( ftype );
151 itype = (unsigned char) *ibuf;
154 memcpy( &itag, ibuf, sizeof( itag ));
155 ibuf += sizeof( itag );
157 memcpy( &bsize, ibuf, sizeof( bsize ));
158 bsize = ntohs( bsize );
160 if ( si.sdt_fd != -1 ) {
161 (void)close( si.sdt_fd );
165 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
170 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
173 LOG(log_error, logtype_afpd, "afp_addicon: lseek: %s", strerror(errno) );
179 * Read icon elements until we find a match to replace, or
180 * we get to the end to insert.
183 memcpy( p, &itag, sizeof( itag ));
185 memcpy( p, &ftype, sizeof( ftype ));
186 p += sizeof( ftype );
189 bsize = htons( bsize );
190 memcpy( p, &bsize, sizeof( bsize ));
191 bsize = ntohs( bsize );
192 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
193 memcpy( &rsize, irh + 10, sizeof( rsize ));
194 rsize = ntohs( rsize );
196 * Is this our set of headers?
198 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
200 * Is the size correct?
202 if ( bsize != rsize )
207 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
208 LOG(log_error, logtype_afpd, "afp_addicon: lseek: %s", strerror(errno) );
214 * Some error occurred, return.
218 LOG(log_error, logtype_afpd, "afp_addicon: %s", strerror(errno) );
219 if (obj->proto == AFPPROTO_DSI) {
220 dsi_writeinit(obj->handle, rbuf, buflen);
221 dsi_writeflush(obj->handle);
227 switch (obj->proto) {
231 if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
232 return( AFPERR_PARAM );
235 if (obj->options.flags & OPTION_DEBUG) {
236 printf("(write) len: %d\n", buflen);
237 bprint(rbuf, buflen);
242 * We're at the end of the file, add the headers, etc. */
244 iov[ 0 ].iov_base = (caddr_t)imh;
245 iov[ 0 ].iov_len = sizeof( imh );
246 iov[ 1 ].iov_base = rbuf;
247 iov[ 1 ].iov_len = bsize;
252 * We found an icon to replace.
255 iov[ 0 ].iov_base = rbuf;
256 iov[ 0 ].iov_len = bsize;
260 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
261 LOG(log_error, logtype_afpd, "afp_addicon: writev: %s", strerror(errno) );
262 return( AFPERR_PARAM );
265 #endif /* no afp/asp */
268 DSI *dsi = obj->handle;
270 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
272 /* add headers at end of file */
273 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
274 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
279 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
280 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
285 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
287 if ( obj->options.flags & OPTION_DEBUG ) {
288 printf("(write) command cont'd: %d\n", iovcnt);
289 bprint(rbuf, iovcnt);
292 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
293 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
307 u_char utag[] = { 0, 0, 0, 0 };
308 u_char ucreator[] = { 'U', 'N', 'I', 'X' };
309 u_char utype[] = { 'T', 'E', 'X', 'T' };
312 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
313 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
314 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
315 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
316 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
317 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
318 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
319 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
320 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
321 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
322 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
323 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
324 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
325 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
326 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
327 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
328 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
329 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
330 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
331 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
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,
346 int afp_geticoninfo(obj, ibuf, ibuflen, rbuf, rbuflen )
349 int ibuflen, *rbuflen;
352 u_char fcreator[ 4 ], ih[ 12 ];
353 u_int16_t vid, iindex, bsize;
358 memcpy( &vid, ibuf, sizeof( vid ));
359 ibuf += sizeof( vid );
360 if (NULL == ( vol = getvolbyvid( vid )) ) {
361 return( AFPERR_PARAM );
364 memcpy( fcreator, ibuf, sizeof( fcreator ));
365 ibuf += sizeof( fcreator );
366 memcpy( &iindex, ibuf, sizeof( iindex ));
367 iindex = ntohs( iindex );
369 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
371 return( AFPERR_NOITEM );
373 memcpy( ih, utag, sizeof( utag ));
374 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
375 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
376 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
377 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
379 memcpy( rbuf, ih, sizeof( ih ));
380 *rbuflen = sizeof( ih );
384 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
385 return( AFPERR_NOITEM );
388 if ( iindex < si.sdt_index ) {
389 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
390 return( AFPERR_PARAM );
396 * Position to the correct spot.
399 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
402 return( AFPERR_NOITEM );
404 memcpy( &bsize, ih + 10, sizeof( bsize ));
405 bsize = ntohs(bsize);
406 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
407 LOG(log_error, logtype_afpd, "afp_iconinfo: lseek: %s", strerror(errno) );
408 return( AFPERR_PARAM );
410 if ( si.sdt_index == iindex ) {
411 memcpy( rbuf, ih, sizeof( ih ));
412 *rbuflen = sizeof( ih );
420 int afp_geticon(obj, ibuf, ibuflen, rbuf, rbuflen )
423 int ibuflen, *rbuflen;
428 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
429 u_int16_t vid, bsize, rsize;
435 memcpy( &vid, ibuf, sizeof( vid ));
436 ibuf += sizeof( vid );
437 if (NULL == ( vol = getvolbyvid( vid )) ) {
438 return( AFPERR_PARAM );
441 memcpy( fcreator, ibuf, sizeof( fcreator ));
442 ibuf += sizeof( fcreator );
443 memcpy( ftype, ibuf, sizeof( ftype ));
444 ibuf += sizeof( ftype );
445 itype = (unsigned char) *ibuf++;
447 memcpy( &bsize, ibuf, sizeof( bsize ));
448 bsize = ntohs( bsize );
450 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
451 memcmp( ftype, utype, sizeof( utype )) == 0 &&
454 memcpy( rbuf, uicon, bsize);
459 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
460 return( AFPERR_NOITEM );
463 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
466 LOG(log_error, logtype_afpd, "afp_geticon: lseek: %s", strerror(errno));
467 return( AFPERR_PARAM );
472 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
474 offset += sizeof(ih);
475 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
476 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
479 memcpy( &rsize, ih + 10, sizeof( rsize ));
480 rsize = ntohs( rsize );
481 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
482 LOG(log_error, logtype_afpd, "afp_geticon: lseek: %s", strerror(errno) );
483 return( AFPERR_PARAM );
489 LOG(log_error, logtype_afpd, "afp_geticon: read: %s", strerror(errno));
490 return( AFPERR_PARAM );
494 return( AFPERR_NOITEM );
497 memcpy( &rsize, ih + 10, sizeof( rsize ));
498 rsize = ntohs( rsize );
499 #define min(a,b) ((a)<(b)?(a):(b))
500 rc = min( bsize, rsize );
502 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
503 DSI *dsi = obj->handle;
507 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
508 if (size < rc + offset) {
512 if ((*rbuflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
515 /* do to the streaming nature, we have to exit if we encounter
516 * a problem. much confusion results otherwise. */
517 while (*rbuflen > 0) {
519 if (!obj->options.flags & OPTION_DEBUG) {
520 if (sys_sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0) {
523 case EINVAL: /* there's no guarantee that all fs support sendfile */
532 buflen = read(si.sdt_fd, rbuf, *rbuflen);
537 if (obj->options.flags & OPTION_DEBUG) {
538 printf( "(read) reply: %d, %d\n", buflen, dsi->clientID);
539 bprint(rbuf, buflen);
542 /* dsi_read() also returns buffer size of next allocation */
543 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
555 LOG(log_info, logtype_afpd, "afp_geticon: %s", strerror(errno));
561 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
562 return( AFPERR_PARAM );
569 /* ---------------------- */
570 static char hexdig[] = "0123456789abcdef";
571 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
573 static char path[ MAXPATHLEN + 1];
577 strcpy( path, vol->v_path );
578 strcat( path, "/.AppleDesktop/" );
579 for ( p = path; *p != '\0'; p++ )
582 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
583 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
584 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
591 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
592 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
593 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
594 *p++ = hexdig[ creator[ i ] & 0x0f ];
605 /* ---------------------------
606 * mpath is only a filename
607 * did filename parent directory ID.
609 static char upath[ MAXPATHLEN + 1];
610 static char mpath[ MAXPATHLEN + 1];
612 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
619 if ( *mpath == '\0' ) {
623 /* set conversion flags */
624 if (!(vol->v_flags & AFPVOL_NOHEX))
625 flags |= CONV_ESCAPEHEX;
626 if (!(vol->v_flags & AFPVOL_USEDOTS))
627 flags |= CONV_ESCAPEDOTS;
629 if ((vol->v_casefold & AFPVOL_MTOUUPPER))
630 flags |= CONV_TOUPPER;
631 else if ((vol->v_casefold & AFPVOL_MTOULOWER))
632 flags |= CONV_TOLOWER;
634 m = demangle(vol, mpath, did);
645 if ((size_t)-1 == (outlen = convert_charset ( (utf8)?CH_UTF8_MAC:vol->v_maccharset, vol->v_volcharset, vol->v_maccharset, m, inplen, u, outlen, &flags)) ) {
646 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
652 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
660 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
663 u_int16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX;
667 outlen = strlen(upath);
669 if (vol->v_casefold & AFPVOL_UTOMUPPER)
670 flags |= CONV_TOUPPER;
671 else if (vol->v_casefold & AFPVOL_UTOMLOWER)
672 flags |= CONV_TOLOWER;
676 /* convert charsets */
677 if ((size_t)-1 == ( outlen = convert_charset ( vol->v_volcharset, (utf8)?CH_UTF8_MAC:vol->v_maccharset, vol->v_maccharset, u, outlen, mpath, MAXPATHLEN, &flags)) ) {
678 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
683 if (!(flags & CONV_REQMANGLE))
686 m = mangle(vol, mpath, upath, id, flags);
689 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
695 m = mangle(vol, u, upath, id, 1);
699 /* ------------------------- */
700 static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
706 struct adouble ad, *adp;
708 clen = (u_char)*ibuf++;
709 clen = min( clen, 199 );
711 upath = path->u_name;
712 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
713 return AFPERR_ACCESS;
716 isadir = path_isadir(path);
717 if (isadir || !(of = of_findname(path))) {
718 ad_init(&ad, vol->v_adouble);
723 if (ad_open( upath , vol_noadouble(vol) |
724 (( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
725 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
726 return( AFPERR_ACCESS );
729 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
730 /* not defined, save nothing but return success */
734 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
735 if ( *path->m_name == '\0' ) {
736 name = curdir->d_m_name;
740 ad_setentrylen( adp, ADEID_NAME, strlen( name ));
741 memcpy( ad_entry( adp, ADEID_NAME ), name,
742 ad_getentrylen( adp, ADEID_NAME ));
745 ad_setentrylen( adp, ADEID_COMMENT, clen );
746 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
747 ad_flush( adp, ADFLAGS_HF );
748 ad_close( adp, ADFLAGS_HF );
752 /* ----------------------------- */
753 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
756 int ibuflen, *rbuflen;
767 memcpy( &vid, ibuf, sizeof( vid ));
768 ibuf += sizeof( vid );
769 if (NULL == ( vol = getvolbyvid( vid )) ) {
770 return( AFPERR_PARAM );
773 memcpy( &did, ibuf, sizeof( did ));
774 ibuf += sizeof( did );
775 if (NULL == ( dir = dirlookup( vol, did )) ) {
779 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
780 return get_afp_errno(AFPERR_NOOBJ);
783 if ((u_long)ibuf & 1 ) {
787 return ad_addcomment(vol, path, ibuf);
790 /* -------------------- */
791 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, int *rbuflen)
793 struct adouble ad, *adp;
799 upath = path->u_name;
800 isadir = path_isadir(path);
801 if (isadir || !(of = of_findname(path))) {
802 ad_init(&ad, vol->v_adouble);
808 ( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
809 O_RDONLY, 0666, adp) < 0 ) {
810 return( AFPERR_NOITEM );
813 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
814 return AFPERR_NOITEM;
817 * Make sure the AD file is not bogus.
819 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
820 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
821 ad_close( adp, ADFLAGS_HF );
822 return( AFPERR_NOITEM );
825 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
826 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
827 ad_getentrylen( adp, ADEID_COMMENT ));
828 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
829 ad_close( adp, ADFLAGS_HF );
831 /* return AFPERR_NOITEM if len == 0 ? */
835 /* -------------------- */
836 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
839 int ibuflen, *rbuflen;
850 memcpy( &vid, ibuf, sizeof( vid ));
851 ibuf += sizeof( vid );
852 if (NULL == ( vol = getvolbyvid( vid )) ) {
853 return( AFPERR_PARAM );
856 memcpy( &did, ibuf, sizeof( did ));
857 ibuf += sizeof( did );
858 if (NULL == ( dir = dirlookup( vol, did )) ) {
862 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
863 return get_afp_errno(AFPERR_NOOBJ);
866 return ad_getcomment(vol, s_path, rbuf, rbuflen);
869 /* ----------------------- */
870 static int ad_rmvcomment(struct vol *vol, struct path *path)
872 struct adouble ad, *adp;
877 upath = path->u_name;
878 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
879 return AFPERR_ACCESS;
882 isadir = path_isadir(path);
883 if (isadir || !(of = of_findname(path))) {
884 ad_init(&ad, vol->v_adouble);
890 (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
891 O_RDWR, 0, adp) < 0 ) {
894 return( AFPERR_NOITEM );
896 return( AFPERR_ACCESS );
898 return( AFPERR_PARAM );
902 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
906 ad_setentrylen( adp, ADEID_COMMENT, 0 );
907 ad_flush( adp, ADFLAGS_HF );
908 ad_close( adp, ADFLAGS_HF );
912 /* ----------------------- */
913 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
916 int ibuflen, *rbuflen;
927 memcpy( &vid, ibuf, sizeof( vid ));
928 ibuf += sizeof( vid );
929 if (NULL == ( vol = getvolbyvid( vid )) ) {
930 return( AFPERR_PARAM );
933 memcpy( &did, ibuf, sizeof( did ));
934 ibuf += sizeof( did );
935 if (NULL == ( dir = dirlookup( vol, did )) ) {
939 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
940 return get_afp_errno(AFPERR_NOOBJ);
943 return ad_rmvcomment(vol, s_path);