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 );
715 ad_close_metadata( adp);
719 /* ----------------------------- */
720 int afp_addcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
731 memcpy( &vid, ibuf, sizeof( vid ));
732 ibuf += sizeof( vid );
733 if (NULL == ( vol = getvolbyvid( vid )) ) {
734 return( AFPERR_PARAM );
737 memcpy( &did, ibuf, sizeof( did ));
738 ibuf += sizeof( did );
739 if (NULL == ( dir = dirlookup( vol, did )) ) {
743 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
744 return get_afp_errno(AFPERR_NOOBJ);
747 if ((u_long)ibuf & 1 ) {
751 return ad_addcomment(vol, path, ibuf);
754 /* -------------------- */
755 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuflen)
757 struct adouble ad, *adp;
763 upath = path->u_name;
764 isadir = path_isadir(path);
765 if (isadir || !(of = of_findname(path))) {
766 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
771 if ( ad_metadata( upath, ((isadir) ? ADFLAGS_DIR : 0), adp) < 0 ) {
772 return( AFPERR_NOITEM );
775 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
776 ad_close_metadata( adp );
777 return AFPERR_NOITEM;
780 * Make sure the AD file is not bogus.
782 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
783 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
784 ad_close_metadata( adp );
785 return( AFPERR_NOITEM );
788 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
790 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
792 ad_close_metadata( adp);
797 /* -------------------- */
798 int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
809 memcpy( &vid, ibuf, sizeof( vid ));
810 ibuf += sizeof( vid );
811 if (NULL == ( vol = getvolbyvid( vid )) ) {
812 return( AFPERR_PARAM );
815 memcpy( &did, ibuf, sizeof( did ));
816 ibuf += sizeof( did );
817 if (NULL == ( dir = dirlookup( vol, did )) ) {
821 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
822 return get_afp_errno(AFPERR_NOOBJ);
825 return ad_getcomment(vol, s_path, rbuf, rbuflen);
828 /* ----------------------- */
829 static int ad_rmvcomment(struct vol *vol, struct path *path)
831 struct adouble ad, *adp;
836 upath = path->u_name;
837 if (check_access(upath, OPENACC_WR ) < 0) {
838 return AFPERR_ACCESS;
841 isadir = path_isadir(path);
842 if (isadir || !(of = of_findname(path))) {
843 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
848 if ( ad_open(adp, upath, ADFLAGS_HF | (isadir) ? ADFLAGS_DIR : 0, 0) < 0 ) {
851 return( AFPERR_NOITEM );
853 return( AFPERR_ACCESS );
855 return( AFPERR_PARAM );
859 if (ad_getentryoff(adp, ADEID_COMMENT)) {
860 ad_setentrylen( adp, ADEID_COMMENT, 0 );
863 ad_close_metadata( adp);
867 /* ----------------------- */
868 int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
879 memcpy( &vid, ibuf, sizeof( vid ));
880 ibuf += sizeof( vid );
881 if (NULL == ( vol = getvolbyvid( vid )) ) {
882 return( AFPERR_PARAM );
885 memcpy( &did, ibuf, sizeof( did ));
886 ibuf += sizeof( did );
887 if (NULL == ( dir = dirlookup( vol, did )) ) {
891 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
892 return get_afp_errno(AFPERR_NOOBJ);
895 return ad_rmvcomment(vol, s_path);