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 * We're at the end of the file, add the headers, etc. */
229 iov[ 0 ].iov_base = (caddr_t)imh;
230 iov[ 0 ].iov_len = sizeof( imh );
231 iov[ 1 ].iov_base = rbuf;
232 iov[ 1 ].iov_len = bsize;
237 * We found an icon to replace.
240 iov[ 0 ].iov_base = rbuf;
241 iov[ 0 ].iov_len = bsize;
245 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
246 LOG(log_error, logtype_afpd, "afp_addicon(%s): writev: %s", icon_dtfile(vol, fcreator), strerror(errno) );
247 return( AFPERR_PARAM );
250 #endif /* no afp/asp */
253 DSI *dsi = obj->handle;
255 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
257 /* add headers at end of file */
258 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
259 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
264 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
265 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
270 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
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));
286 static const u_char utag[] = { 0, 0, 0, 0 };
287 static const u_char ucreator[] = { 0, 0, 0, 0 };/* { 'U', 'N', 'I', 'X' };*/
288 static const u_char utype[] = { 0, 0, 0, 0 };/* { 'T', 'E', 'X', 'T' };*/
289 static const short usize = 256;
292 static const u_char uicon[] = {
293 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
294 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
295 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
296 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
297 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
298 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
299 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
300 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
301 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
302 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
303 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
304 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
305 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
306 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
307 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
308 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
309 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
310 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
311 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
312 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
313 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
314 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
315 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
316 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
317 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
318 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
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,
328 int afp_geticoninfo(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
331 u_char fcreator[ 4 ], ih[ 12 ];
332 u_int16_t vid, iindex, bsize;
337 memcpy( &vid, ibuf, sizeof( vid ));
338 ibuf += sizeof( vid );
339 if (NULL == ( vol = getvolbyvid( vid )) ) {
340 return( AFPERR_PARAM );
343 memcpy( fcreator, ibuf, sizeof( fcreator ));
344 ibuf += sizeof( fcreator );
345 memcpy( &iindex, ibuf, sizeof( iindex ));
346 iindex = ntohs( iindex );
348 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
350 return( AFPERR_NOITEM );
352 memcpy( ih, utag, sizeof( utag ));
353 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
354 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
355 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
356 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
358 memcpy( rbuf, ih, sizeof( ih ));
359 *rbuflen = sizeof( ih );
363 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
364 return( AFPERR_NOITEM );
367 if ( iindex < si.sdt_index ) {
368 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
369 return( AFPERR_PARAM );
375 * Position to the correct spot.
378 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
381 return( AFPERR_NOITEM );
383 memcpy( &bsize, ih + 10, sizeof( bsize ));
384 bsize = ntohs(bsize);
385 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
386 LOG(log_error, logtype_afpd, "afp_iconinfo(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
387 return( AFPERR_PARAM );
389 if ( si.sdt_index == iindex ) {
390 memcpy( rbuf, ih, sizeof( ih ));
391 *rbuflen = sizeof( ih );
399 int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
404 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
405 u_int16_t vid, bsize, rsize;
411 memcpy( &vid, ibuf, sizeof( vid ));
412 ibuf += sizeof( vid );
413 if (NULL == ( vol = getvolbyvid( vid )) ) {
414 return( AFPERR_PARAM );
417 memcpy( fcreator, ibuf, sizeof( fcreator ));
418 ibuf += sizeof( fcreator );
419 memcpy( ftype, ibuf, sizeof( ftype ));
420 ibuf += sizeof( ftype );
421 itype = (unsigned char) *ibuf++;
423 memcpy( &bsize, ibuf, sizeof( bsize ));
424 bsize = ntohs( bsize );
427 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
428 memcmp( ftype, utype, sizeof( utype )) == 0 &&
431 memcpy( rbuf, uicon, bsize);
437 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
438 return( AFPERR_NOITEM );
441 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
444 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno));
445 return( AFPERR_PARAM );
450 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
452 offset += sizeof(ih);
453 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
454 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
457 memcpy( &rsize, ih + 10, sizeof( rsize ));
458 rsize = ntohs( rsize );
459 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
460 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
461 return( AFPERR_PARAM );
467 LOG(log_error, logtype_afpd, "afp_geticon(%s): read: %s", icon_dtfile(vol, fcreator), strerror(errno));
468 return( AFPERR_PARAM );
472 return( AFPERR_NOITEM );
475 memcpy( &rsize, ih + 10, sizeof( rsize ));
476 rsize = ntohs( rsize );
477 #define min(a,b) ((a)<(b)?(a):(b))
478 rc = min( bsize, rsize );
480 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
481 DSI *dsi = obj->handle;
485 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
486 if (size < rc + offset) {
490 if ((buflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
494 /* do to the streaming nature, we have to exit if we encounter
495 * a problem. much confusion results otherwise. */
496 while (*rbuflen > 0) {
498 if (!obj->options.flags & OPTION_DEBUG) {
499 if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize) < 0) {
502 case EINVAL: /* there's no guarantee that all fs support sendfile */
514 buflen = read(si.sdt_fd, rbuf, *rbuflen);
518 /* dsi_read() also returns buffer size of next allocation */
519 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
530 LOG(log_error, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno));
532 obj->exit(EXITERR_SYS);
536 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
537 return( AFPERR_PARAM );
544 /* ---------------------- */
545 static const char hexdig[] = "0123456789abcdef";
546 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
548 static char path[ MAXPATHLEN + 1];
552 strcpy( path, vol->v_path );
553 strcat( path, "/.AppleDesktop/" );
554 for ( p = path; *p != '\0'; p++ )
557 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
558 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
559 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
566 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
567 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
568 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
569 *p++ = hexdig[ creator[ i ] & 0x0f ];
580 /* ---------------------------
581 * mpath is only a filename
582 * did filename parent directory ID.
585 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
587 static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
593 if ( *mpath == '\0' ) {
598 /* set conversion flags */
599 flags = vol->v_mtou_flags;
601 m = demangle(vol, mpath, did);
612 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)) ) {
613 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
618 LOG(log_debug9, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
626 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
628 static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
634 outlen = strlen(upath);
636 flags = vol->v_utom_flags;
640 /* convert charsets */
641 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)) ) {
642 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
646 flags = !!(flags & CONV_REQMANGLE);
651 m = mangle(vol, mpath, outlen, upath, id, flags);
654 LOG(log_debug9, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
660 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
664 /* ------------------------- */
665 static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
671 struct adouble ad, *adp;
673 clen = (u_char)*ibuf++;
674 clen = min( clen, 199 );
676 upath = path->u_name;
677 if (check_access(upath, OPENACC_WR ) < 0) {
678 return AFPERR_ACCESS;
681 isadir = path_isadir(path);
682 if (isadir || !(of = of_findname(path))) {
683 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
688 if (ad_open(adp, upath,
689 ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0),
692 return( AFPERR_ACCESS );
695 if (ad_getentryoff(adp, ADEID_COMMENT)) {
696 if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
697 if ( *path->m_name == '\0' ) {
698 name = (char *)curdir->d_m_name->data;
702 ad_setname(adp, name);
704 ad_setentrylen( adp, ADEID_COMMENT, clen );
705 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
708 ad_close_metadata( adp);
712 /* ----------------------------- */
713 int afp_addcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
724 memcpy( &vid, ibuf, sizeof( vid ));
725 ibuf += sizeof( vid );
726 if (NULL == ( vol = getvolbyvid( vid )) ) {
727 return( AFPERR_PARAM );
730 memcpy( &did, ibuf, sizeof( did ));
731 ibuf += sizeof( did );
732 if (NULL == ( dir = dirlookup( vol, did )) ) {
736 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
737 return get_afp_errno(AFPERR_NOOBJ);
740 if ((u_long)ibuf & 1 ) {
744 return ad_addcomment(vol, path, ibuf);
747 /* -------------------- */
748 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuflen)
750 struct adouble ad, *adp;
756 upath = path->u_name;
757 isadir = path_isadir(path);
758 if (isadir || !(of = of_findname(path))) {
759 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
764 if ( ad_metadata( upath, ((isadir) ? ADFLAGS_DIR : 0), adp) < 0 ) {
765 return( AFPERR_NOITEM );
768 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
769 ad_close_metadata( adp );
770 return AFPERR_NOITEM;
773 * Make sure the AD file is not bogus.
775 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
776 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
777 ad_close_metadata( adp );
778 return( AFPERR_NOITEM );
781 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
783 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
785 ad_close_metadata( adp);
790 /* -------------------- */
791 int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
802 memcpy( &vid, ibuf, sizeof( vid ));
803 ibuf += sizeof( vid );
804 if (NULL == ( vol = getvolbyvid( vid )) ) {
805 return( AFPERR_PARAM );
808 memcpy( &did, ibuf, sizeof( did ));
809 ibuf += sizeof( did );
810 if (NULL == ( dir = dirlookup( vol, did )) ) {
814 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
815 return get_afp_errno(AFPERR_NOOBJ);
818 return ad_getcomment(vol, s_path, rbuf, rbuflen);
821 /* ----------------------- */
822 static int ad_rmvcomment(struct vol *vol, struct path *path)
824 struct adouble ad, *adp;
829 upath = path->u_name;
830 if (check_access(upath, OPENACC_WR ) < 0) {
831 return AFPERR_ACCESS;
834 isadir = path_isadir(path);
835 if (isadir || !(of = of_findname(path))) {
836 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
841 if ( ad_open(adp, upath, ADFLAGS_HF | (isadir) ? ADFLAGS_DIR : 0, 0) < 0 ) {
844 return( AFPERR_NOITEM );
846 return( AFPERR_ACCESS );
848 return( AFPERR_PARAM );
852 if (ad_getentryoff(adp, ADEID_COMMENT)) {
853 ad_setentrylen( adp, ADEID_COMMENT, 0 );
856 ad_close_metadata( adp);
860 /* ----------------------- */
861 int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
872 memcpy( &vid, ibuf, sizeof( vid ));
873 ibuf += sizeof( vid );
874 if (NULL == ( vol = getvolbyvid( vid )) ) {
875 return( AFPERR_PARAM );
878 memcpy( &did, ibuf, sizeof( did ));
879 ibuf += sizeof( did );
880 if (NULL == ( dir = dirlookup( vol, did )) ) {
884 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
885 return get_afp_errno(AFPERR_NOOBJ);
888 return ad_rmvcomment(vol, s_path);