5 * afp_XXXcomment are (the only) functions able to open
6 * a ressource fork when there's no data fork, eg after
7 * it was removed with samba.
12 #endif /* HAVE_CONFIG_H */
20 #include <atalk/adouble.h>
22 #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/util.h>
31 #include <atalk/logger.h>
33 #include "directory.h"
40 int afp_opendt(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
47 memcpy( &vid, ibuf, sizeof(vid));
48 if (NULL == ( vol = getvolbyvid( vid )) ) {
50 return( AFPERR_PARAM );
53 memcpy( rbuf, &vid, sizeof(vid));
54 *rbuflen = sizeof(vid);
58 int afp_closedt(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
64 static struct savedt si = { { 0, 0, 0, 0 }, -1, 0, 0 };
66 static char *icon_dtfile(struct vol *vol, u_char creator[ 4 ])
68 return dtfile( vol, creator, ".icon" );
71 static int iconopen(struct vol *vol, u_char creator[ 4 ], int flags, int mode)
73 char *dtf, *adt, *adts;
75 if ( si.sdt_fd != -1 ) {
76 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
77 si.sdt_vid == vol->v_vid ) {
84 dtf = icon_dtfile( vol, creator);
86 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
87 if ( errno == ENOENT && ( flags & O_CREAT )) {
88 if (( adts = strrchr( dtf, '/' )) == NULL ) {
92 if (( adt = strrchr( dtf, '/' )) == NULL ) {
96 (void) ad_mkdir( dtf, DIRBITS | 0777 );
98 (void) ad_mkdir( dtf, DIRBITS | 0777 );
101 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
102 LOG(log_error, logtype_afpd, "iconopen(%s): open: %s", dtf, strerror(errno) );
110 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
111 si.sdt_vid = vol->v_vid;
116 int afp_addicon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
120 struct iovec iov[ 2 ];
122 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
123 int itype, cc = AFP_OK, iovcnt = 0;
125 u_int32_t ftype, itag;
126 u_int16_t bsize, rsize, vid;
132 memcpy( &vid, ibuf, sizeof( vid ));
133 ibuf += sizeof( vid );
134 if (NULL == ( vol = getvolbyvid( vid )) ) {
139 memcpy( fcreator, ibuf, sizeof( fcreator ));
140 ibuf += sizeof( fcreator );
142 memcpy( &ftype, ibuf, sizeof( ftype ));
143 ibuf += sizeof( ftype );
145 itype = (unsigned char) *ibuf;
148 memcpy( &itag, ibuf, sizeof( itag ));
149 ibuf += sizeof( itag );
151 memcpy( &bsize, ibuf, sizeof( bsize ));
152 bsize = ntohs( bsize );
154 if ( si.sdt_fd != -1 ) {
155 (void)close( si.sdt_fd );
159 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
164 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
167 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
173 * Read icon elements until we find a match to replace, or
174 * we get to the end to insert.
177 memcpy( p, &itag, sizeof( itag ));
179 memcpy( p, &ftype, sizeof( ftype ));
180 p += sizeof( ftype );
183 bsize = htons( bsize );
184 memcpy( p, &bsize, sizeof( bsize ));
185 bsize = ntohs( bsize );
186 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
187 memcpy( &rsize, irh + 10, sizeof( rsize ));
188 rsize = ntohs( rsize );
190 * Is this our set of headers?
192 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
194 * Is the size correct?
196 if ( bsize != rsize )
201 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
202 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator),strerror(errno) );
208 * Some error occurred, return.
212 if (obj->proto == AFPPROTO_DSI) {
213 dsi_writeinit(obj->handle, rbuf, buflen);
214 dsi_writeflush(obj->handle);
219 switch (obj->proto) {
223 if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
224 return( AFPERR_PARAM );
227 if (obj->options.flags & OPTION_DEBUG) {
228 printf("(write) len: %d\n", buflen);
229 bprint(rbuf, buflen);
234 * We're at the end of the file, add the headers, etc. */
236 iov[ 0 ].iov_base = (caddr_t)imh;
237 iov[ 0 ].iov_len = sizeof( imh );
238 iov[ 1 ].iov_base = rbuf;
239 iov[ 1 ].iov_len = bsize;
244 * We found an icon to replace.
247 iov[ 0 ].iov_base = rbuf;
248 iov[ 0 ].iov_len = bsize;
252 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
253 LOG(log_error, logtype_afpd, "afp_addicon(%s): writev: %s", icon_dtfile(vol, fcreator), strerror(errno) );
254 return( AFPERR_PARAM );
257 #endif /* no afp/asp */
260 DSI *dsi = obj->handle;
262 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
264 /* add headers at end of file */
265 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
266 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
271 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
272 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
277 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
278 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
279 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
293 static const u_char utag[] = { 0, 0, 0, 0 };
294 static const u_char ucreator[] = { 0, 0, 0, 0 };/* { 'U', 'N', 'I', 'X' };*/
295 static const u_char utype[] = { 0, 0, 0, 0 };/* { 'T', 'E', 'X', 'T' };*/
296 static const short usize = 256;
299 static const u_char uicon[] = {
300 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
301 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
302 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
303 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
304 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
305 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
306 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
307 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
308 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
309 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
310 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
311 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
312 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
313 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
314 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
315 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
316 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
317 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
318 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
319 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
320 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
321 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
322 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
323 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
324 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
325 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
326 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
327 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
328 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
329 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
330 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
331 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
335 int afp_geticoninfo(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
338 u_char fcreator[ 4 ], ih[ 12 ];
339 u_int16_t vid, iindex, bsize;
344 memcpy( &vid, ibuf, sizeof( vid ));
345 ibuf += sizeof( vid );
346 if (NULL == ( vol = getvolbyvid( vid )) ) {
347 return( AFPERR_PARAM );
350 memcpy( fcreator, ibuf, sizeof( fcreator ));
351 ibuf += sizeof( fcreator );
352 memcpy( &iindex, ibuf, sizeof( iindex ));
353 iindex = ntohs( iindex );
355 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
357 return( AFPERR_NOITEM );
359 memcpy( ih, utag, sizeof( utag ));
360 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
361 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
362 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
363 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
365 memcpy( rbuf, ih, sizeof( ih ));
366 *rbuflen = sizeof( ih );
370 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
371 return( AFPERR_NOITEM );
374 if ( iindex < si.sdt_index ) {
375 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
376 return( AFPERR_PARAM );
382 * Position to the correct spot.
385 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
388 return( AFPERR_NOITEM );
390 memcpy( &bsize, ih + 10, sizeof( bsize ));
391 bsize = ntohs(bsize);
392 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
393 LOG(log_error, logtype_afpd, "afp_iconinfo(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
394 return( AFPERR_PARAM );
396 if ( si.sdt_index == iindex ) {
397 memcpy( rbuf, ih, sizeof( ih ));
398 *rbuflen = sizeof( ih );
406 int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
411 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
412 u_int16_t vid, bsize, rsize;
418 memcpy( &vid, ibuf, sizeof( vid ));
419 ibuf += sizeof( vid );
420 if (NULL == ( vol = getvolbyvid( vid )) ) {
421 return( AFPERR_PARAM );
424 memcpy( fcreator, ibuf, sizeof( fcreator ));
425 ibuf += sizeof( fcreator );
426 memcpy( ftype, ibuf, sizeof( ftype ));
427 ibuf += sizeof( ftype );
428 itype = (unsigned char) *ibuf++;
430 memcpy( &bsize, ibuf, sizeof( bsize ));
431 bsize = ntohs( bsize );
434 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
435 memcmp( ftype, utype, sizeof( utype )) == 0 &&
438 memcpy( rbuf, uicon, bsize);
444 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
445 return( AFPERR_NOITEM );
448 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
451 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno));
452 return( AFPERR_PARAM );
457 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
459 offset += sizeof(ih);
460 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
461 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
464 memcpy( &rsize, ih + 10, sizeof( rsize ));
465 rsize = ntohs( rsize );
466 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
467 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
468 return( AFPERR_PARAM );
474 LOG(log_error, logtype_afpd, "afp_geticon(%s): read: %s", icon_dtfile(vol, fcreator), strerror(errno));
475 return( AFPERR_PARAM );
479 return( AFPERR_NOITEM );
482 memcpy( &rsize, ih + 10, sizeof( rsize ));
483 rsize = ntohs( rsize );
484 #define min(a,b) ((a)<(b)?(a):(b))
485 rc = min( bsize, rsize );
487 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
488 DSI *dsi = obj->handle;
492 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
493 if (size < rc + offset) {
497 if ((buflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
501 /* do to the streaming nature, we have to exit if we encounter
502 * a problem. much confusion results otherwise. */
503 while (*rbuflen > 0) {
505 if (!obj->options.flags & OPTION_DEBUG) {
506 if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize) < 0) {
509 case EINVAL: /* there's no guarantee that all fs support sendfile */
521 buflen = read(si.sdt_fd, rbuf, *rbuflen);
525 /* dsi_read() also returns buffer size of next allocation */
526 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
537 LOG(log_error, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno));
539 obj->exit(EXITERR_SYS);
543 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
544 return( AFPERR_PARAM );
551 /* ---------------------- */
552 static const char hexdig[] = "0123456789abcdef";
553 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
555 static char path[ MAXPATHLEN + 1];
559 strcpy( path, vol->v_path );
560 strcat( path, "/.AppleDesktop/" );
561 for ( p = path; *p != '\0'; p++ )
564 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
565 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
566 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
573 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
574 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
575 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
576 *p++ = hexdig[ creator[ i ] & 0x0f ];
587 /* ---------------------------
588 * mpath is only a filename
589 * did filename parent directory ID.
592 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
594 static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
600 if ( *mpath == '\0' ) {
605 /* set conversion flags */
606 flags = vol->v_mtou_flags;
608 m = demangle(vol, mpath, did);
619 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)) ) {
620 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
625 LOG(log_debug9, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
633 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
635 static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
641 outlen = strlen(upath);
643 flags = vol->v_utom_flags;
647 /* convert charsets */
648 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)) ) {
649 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
653 flags = !!(flags & CONV_REQMANGLE);
658 m = mangle(vol, mpath, outlen, upath, id, flags);
661 LOG(log_debug9, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
667 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
671 /* ------------------------- */
672 static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
678 struct adouble ad, *adp;
680 clen = (u_char)*ibuf++;
681 clen = min( clen, 199 );
683 upath = path->u_name;
684 if (check_access(upath, OPENACC_WR ) < 0) {
685 return AFPERR_ACCESS;
688 isadir = path_isadir(path);
689 if (isadir || !(of = of_findname(path))) {
690 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
696 ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0),
700 return( AFPERR_ACCESS );
703 if (ad_getentryoff(adp, ADEID_COMMENT)) {
704 if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
705 if ( *path->m_name == '\0' ) {
706 name = (char *)curdir->d_m_name->data;
710 ad_setname(adp, name);
712 ad_setentrylen( adp, ADEID_COMMENT, clen );
713 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
717 ad_close_metadata( adp);
721 /* ----------------------------- */
722 int afp_addcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
733 memcpy( &vid, ibuf, sizeof( vid ));
734 ibuf += sizeof( vid );
735 if (NULL == ( vol = getvolbyvid( vid )) ) {
736 return( AFPERR_PARAM );
739 memcpy( &did, ibuf, sizeof( did ));
740 ibuf += sizeof( did );
741 if (NULL == ( dir = dirlookup( vol, did )) ) {
745 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
746 return get_afp_errno(AFPERR_NOOBJ);
749 if ((u_long)ibuf & 1 ) {
753 return ad_addcomment(vol, path, ibuf);
756 /* -------------------- */
757 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuflen)
759 struct adouble ad, *adp;
765 upath = path->u_name;
766 isadir = path_isadir(path);
767 if (isadir || !(of = of_findname(path))) {
768 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
773 if ( ad_metadata( upath, ((isadir) ? ADFLAGS_DIR : 0), adp) < 0 ) {
774 return( AFPERR_NOITEM );
777 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
778 ad_close_metadata( adp );
779 return AFPERR_NOITEM;
782 * Make sure the AD file is not bogus.
784 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
785 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
786 ad_close_metadata( adp );
787 return( AFPERR_NOITEM );
790 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
792 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
794 ad_close_metadata( adp);
799 /* -------------------- */
800 int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
811 memcpy( &vid, ibuf, sizeof( vid ));
812 ibuf += sizeof( vid );
813 if (NULL == ( vol = getvolbyvid( vid )) ) {
814 return( AFPERR_PARAM );
817 memcpy( &did, ibuf, sizeof( did ));
818 ibuf += sizeof( did );
819 if (NULL == ( dir = dirlookup( vol, did )) ) {
823 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
824 return get_afp_errno(AFPERR_NOOBJ);
827 return ad_getcomment(vol, s_path, rbuf, rbuflen);
830 /* ----------------------- */
831 static int ad_rmvcomment(struct vol *vol, struct path *path)
833 struct adouble ad, *adp;
838 upath = path->u_name;
839 if (check_access(upath, OPENACC_WR ) < 0) {
840 return AFPERR_ACCESS;
843 isadir = path_isadir(path);
844 if (isadir || !(of = of_findname(path))) {
845 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
850 if ( ad_open_metadata( upath, (isadir) ? ADFLAGS_DIR : 0, 0, adp) < 0 ) {
853 return( AFPERR_NOITEM );
855 return( AFPERR_ACCESS );
857 return( AFPERR_PARAM );
861 if (ad_getentryoff(adp, ADEID_COMMENT)) {
862 ad_setentrylen( adp, ADEID_COMMENT, 0 );
865 ad_close_metadata( adp);
869 /* ----------------------- */
870 int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
881 memcpy( &vid, ibuf, sizeof( vid ));
882 ibuf += sizeof( vid );
883 if (NULL == ( vol = getvolbyvid( vid )) ) {
884 return( AFPERR_PARAM );
887 memcpy( &did, ibuf, sizeof( did ));
888 ibuf += sizeof( did );
889 if (NULL == ( dir = dirlookup( vol, did )) ) {
893 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
894 return get_afp_errno(AFPERR_NOOBJ);
897 return ad_rmvcomment(vol, s_path);