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);
695 if (ad_open(adp, upath,
696 ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0),
699 return( AFPERR_ACCESS );
702 if (ad_getentryoff(adp, ADEID_COMMENT)) {
703 if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
704 if ( *path->m_name == '\0' ) {
705 name = (char *)curdir->d_m_name->data;
709 ad_setname(adp, name);
711 ad_setentrylen( adp, ADEID_COMMENT, clen );
712 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
716 ad_close_metadata( adp);
720 /* ----------------------------- */
721 int afp_addcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
732 memcpy( &vid, ibuf, sizeof( vid ));
733 ibuf += sizeof( vid );
734 if (NULL == ( vol = getvolbyvid( vid )) ) {
735 return( AFPERR_PARAM );
738 memcpy( &did, ibuf, sizeof( did ));
739 ibuf += sizeof( did );
740 if (NULL == ( dir = dirlookup( vol, did )) ) {
744 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
745 return get_afp_errno(AFPERR_NOOBJ);
748 if ((u_long)ibuf & 1 ) {
752 return ad_addcomment(vol, path, ibuf);
755 /* -------------------- */
756 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuflen)
758 struct adouble ad, *adp;
764 upath = path->u_name;
765 isadir = path_isadir(path);
766 if (isadir || !(of = of_findname(path))) {
767 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
772 if ( ad_metadata( upath, ((isadir) ? ADFLAGS_DIR : 0), adp) < 0 ) {
773 return( AFPERR_NOITEM );
776 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
777 ad_close_metadata( adp );
778 return AFPERR_NOITEM;
781 * Make sure the AD file is not bogus.
783 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
784 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
785 ad_close_metadata( adp );
786 return( AFPERR_NOITEM );
789 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
791 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
793 ad_close_metadata( adp);
798 /* -------------------- */
799 int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
810 memcpy( &vid, ibuf, sizeof( vid ));
811 ibuf += sizeof( vid );
812 if (NULL == ( vol = getvolbyvid( vid )) ) {
813 return( AFPERR_PARAM );
816 memcpy( &did, ibuf, sizeof( did ));
817 ibuf += sizeof( did );
818 if (NULL == ( dir = dirlookup( vol, did )) ) {
822 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
823 return get_afp_errno(AFPERR_NOOBJ);
826 return ad_getcomment(vol, s_path, rbuf, rbuflen);
829 /* ----------------------- */
830 static int ad_rmvcomment(struct vol *vol, struct path *path)
832 struct adouble ad, *adp;
837 upath = path->u_name;
838 if (check_access(upath, OPENACC_WR ) < 0) {
839 return AFPERR_ACCESS;
842 isadir = path_isadir(path);
843 if (isadir || !(of = of_findname(path))) {
844 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
849 if ( ad_open(adp, upath, ADFLAGS_HF | (isadir) ? ADFLAGS_DIR : 0, 0) < 0 ) {
852 return( AFPERR_NOITEM );
854 return( AFPERR_ACCESS );
856 return( AFPERR_PARAM );
860 if (ad_getentryoff(adp, ADEID_COMMENT)) {
861 ad_setentrylen( adp, ADEID_COMMENT, 0 );
864 ad_close_metadata( adp);
868 /* ----------------------- */
869 int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
880 memcpy( &vid, ibuf, sizeof( vid ));
881 ibuf += sizeof( vid );
882 if (NULL == ( vol = getvolbyvid( vid )) ) {
883 return( AFPERR_PARAM );
886 memcpy( &did, ibuf, sizeof( did ));
887 ibuf += sizeof( did );
888 if (NULL == ( dir = dirlookup( vol, did )) ) {
892 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
893 return get_afp_errno(AFPERR_NOOBJ);
896 return ad_rmvcomment(vol, s_path);