2 * $Id: desktop.c,v 1.42 2009-10-22 13:40:11 franklahm 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(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
50 memcpy( &vid, ibuf, sizeof(vid));
51 if (NULL == ( vol = getvolbyvid( vid )) ) {
53 return( AFPERR_PARAM );
56 memcpy( rbuf, &vid, sizeof(vid));
57 *rbuflen = sizeof(vid);
61 int afp_closedt(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
67 static struct savedt si = { { 0, 0, 0, 0 }, -1, 0, 0 };
69 static char *icon_dtfile(struct vol *vol, u_char creator[ 4 ])
71 return dtfile( vol, creator, ".icon" );
74 static int iconopen(struct vol *vol, u_char creator[ 4 ], int flags, int mode)
76 char *dtf, *adt, *adts;
78 if ( si.sdt_fd != -1 ) {
79 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
80 si.sdt_vid == vol->v_vid ) {
87 dtf = icon_dtfile( vol, creator);
89 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
90 if ( errno == ENOENT && ( flags & O_CREAT )) {
91 if (( adts = strrchr( dtf, '/' )) == NULL ) {
95 if (( adt = strrchr( dtf, '/' )) == NULL ) {
99 (void) ad_mkdir( dtf, DIRBITS | 0777 );
101 (void) ad_mkdir( dtf, DIRBITS | 0777 );
104 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
105 LOG(log_error, logtype_afpd, "iconopen(%s): open: %s", dtf, strerror(errno) );
113 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
114 si.sdt_vid = vol->v_vid;
119 int afp_addicon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
123 struct iovec iov[ 2 ];
125 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
126 int itype, cc = AFP_OK, iovcnt = 0;
128 u_int32_t ftype, itag;
129 u_int16_t bsize, rsize, vid;
135 memcpy( &vid, ibuf, sizeof( vid ));
136 ibuf += sizeof( vid );
137 if (NULL == ( vol = getvolbyvid( vid )) ) {
142 memcpy( fcreator, ibuf, sizeof( fcreator ));
143 ibuf += sizeof( fcreator );
145 memcpy( &ftype, ibuf, sizeof( ftype ));
146 ibuf += sizeof( ftype );
148 itype = (unsigned char) *ibuf;
151 memcpy( &itag, ibuf, sizeof( itag ));
152 ibuf += sizeof( itag );
154 memcpy( &bsize, ibuf, sizeof( bsize ));
155 bsize = ntohs( bsize );
157 if ( si.sdt_fd != -1 ) {
158 (void)close( si.sdt_fd );
162 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
167 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
170 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
176 * Read icon elements until we find a match to replace, or
177 * we get to the end to insert.
180 memcpy( p, &itag, sizeof( itag ));
182 memcpy( p, &ftype, sizeof( ftype ));
183 p += sizeof( ftype );
186 bsize = htons( bsize );
187 memcpy( p, &bsize, sizeof( bsize ));
188 bsize = ntohs( bsize );
189 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
190 memcpy( &rsize, irh + 10, sizeof( rsize ));
191 rsize = ntohs( rsize );
193 * Is this our set of headers?
195 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
197 * Is the size correct?
199 if ( bsize != rsize )
204 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
205 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator),strerror(errno) );
211 * Some error occurred, return.
215 if (obj->proto == AFPPROTO_DSI) {
216 dsi_writeinit(obj->handle, rbuf, buflen);
217 dsi_writeflush(obj->handle);
222 switch (obj->proto) {
226 if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
227 return( AFPERR_PARAM );
230 if (obj->options.flags & OPTION_DEBUG) {
231 printf("(write) len: %d\n", buflen);
232 bprint(rbuf, buflen);
237 * We're at the end of the file, add the headers, etc. */
239 iov[ 0 ].iov_base = (caddr_t)imh;
240 iov[ 0 ].iov_len = sizeof( imh );
241 iov[ 1 ].iov_base = rbuf;
242 iov[ 1 ].iov_len = bsize;
247 * We found an icon to replace.
250 iov[ 0 ].iov_base = rbuf;
251 iov[ 0 ].iov_len = bsize;
255 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
256 LOG(log_error, logtype_afpd, "afp_addicon(%s): writev: %s", icon_dtfile(vol, fcreator), strerror(errno) );
257 return( AFPERR_PARAM );
260 #endif /* no afp/asp */
263 DSI *dsi = obj->handle;
265 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
267 /* add headers at end of file */
268 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
269 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
274 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
275 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
280 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
281 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
282 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
296 static const u_char utag[] = { 0, 0, 0, 0 };
297 static const u_char ucreator[] = { 0, 0, 0, 0 };/* { 'U', 'N', 'I', 'X' };*/
298 static const u_char utype[] = { 0, 0, 0, 0 };/* { 'T', 'E', 'X', 'T' };*/
299 static const short usize = 256;
302 static const u_char uicon[] = {
303 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
304 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
305 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
306 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
307 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
308 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
309 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
310 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
311 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
312 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
313 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
314 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
315 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
316 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
317 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
318 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
319 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
320 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
321 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
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,
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,
338 int afp_geticoninfo(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
341 u_char fcreator[ 4 ], ih[ 12 ];
342 u_int16_t vid, iindex, bsize;
347 memcpy( &vid, ibuf, sizeof( vid ));
348 ibuf += sizeof( vid );
349 if (NULL == ( vol = getvolbyvid( vid )) ) {
350 return( AFPERR_PARAM );
353 memcpy( fcreator, ibuf, sizeof( fcreator ));
354 ibuf += sizeof( fcreator );
355 memcpy( &iindex, ibuf, sizeof( iindex ));
356 iindex = ntohs( iindex );
358 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
360 return( AFPERR_NOITEM );
362 memcpy( ih, utag, sizeof( utag ));
363 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
364 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
365 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
366 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
368 memcpy( rbuf, ih, sizeof( ih ));
369 *rbuflen = sizeof( ih );
373 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
374 return( AFPERR_NOITEM );
377 if ( iindex < si.sdt_index ) {
378 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
379 return( AFPERR_PARAM );
385 * Position to the correct spot.
388 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
391 return( AFPERR_NOITEM );
393 memcpy( &bsize, ih + 10, sizeof( bsize ));
394 bsize = ntohs(bsize);
395 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
396 LOG(log_error, logtype_afpd, "afp_iconinfo(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
397 return( AFPERR_PARAM );
399 if ( si.sdt_index == iindex ) {
400 memcpy( rbuf, ih, sizeof( ih ));
401 *rbuflen = sizeof( ih );
409 int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
414 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
415 u_int16_t vid, bsize, rsize;
421 memcpy( &vid, ibuf, sizeof( vid ));
422 ibuf += sizeof( vid );
423 if (NULL == ( vol = getvolbyvid( vid )) ) {
424 return( AFPERR_PARAM );
427 memcpy( fcreator, ibuf, sizeof( fcreator ));
428 ibuf += sizeof( fcreator );
429 memcpy( ftype, ibuf, sizeof( ftype ));
430 ibuf += sizeof( ftype );
431 itype = (unsigned char) *ibuf++;
433 memcpy( &bsize, ibuf, sizeof( bsize ));
434 bsize = ntohs( bsize );
437 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
438 memcmp( ftype, utype, sizeof( utype )) == 0 &&
441 memcpy( rbuf, uicon, bsize);
447 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
448 return( AFPERR_NOITEM );
451 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
454 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno));
455 return( AFPERR_PARAM );
460 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
462 offset += sizeof(ih);
463 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
464 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
467 memcpy( &rsize, ih + 10, sizeof( rsize ));
468 rsize = ntohs( rsize );
469 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
470 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
471 return( AFPERR_PARAM );
477 LOG(log_error, logtype_afpd, "afp_geticon(%s): read: %s", icon_dtfile(vol, fcreator), strerror(errno));
478 return( AFPERR_PARAM );
482 return( AFPERR_NOITEM );
485 memcpy( &rsize, ih + 10, sizeof( rsize ));
486 rsize = ntohs( rsize );
487 #define min(a,b) ((a)<(b)?(a):(b))
488 rc = min( bsize, rsize );
490 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
491 DSI *dsi = obj->handle;
495 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
496 if (size < rc + offset) {
500 if ((buflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
504 /* do to the streaming nature, we have to exit if we encounter
505 * a problem. much confusion results otherwise. */
506 while (*rbuflen > 0) {
508 if (!obj->options.flags & OPTION_DEBUG) {
509 if (sys_sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0) {
512 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_info, 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' ) {
604 /* set conversion flags */
605 if (!(vol->v_flags & AFPVOL_NOHEX))
606 flags |= CONV_ESCAPEHEX;
607 if (!(vol->v_flags & AFPVOL_USEDOTS))
608 flags |= CONV_ESCAPEDOTS;
610 if ((vol->v_casefold & AFPVOL_MTOUUPPER))
611 flags |= CONV_TOUPPER;
612 else if ((vol->v_casefold & AFPVOL_MTOULOWER))
613 flags |= CONV_TOLOWER;
615 if ((vol->v_flags & AFPVOL_EILSEQ)) {
616 flags |= CONV__EILSEQ;
619 m = demangle(vol, mpath, did);
630 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)) ) {
631 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
636 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
644 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
646 static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
648 u_int16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX;
652 outlen = strlen(upath);
654 if ((vol->v_casefold & AFPVOL_UTOMUPPER))
655 flags |= CONV_TOUPPER;
656 else if ((vol->v_casefold & AFPVOL_UTOMLOWER))
657 flags |= CONV_TOLOWER;
659 if ((vol->v_flags & AFPVOL_EILSEQ)) {
660 flags |= CONV__EILSEQ;
665 /* convert charsets */
666 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)) ) {
667 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
671 if (!(flags & CONV_REQMANGLE))
679 m = mangle(vol, mpath, outlen, upath, id, flags);
682 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
688 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
692 /* ------------------------- */
693 static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
699 struct adouble ad, *adp;
701 clen = (u_char)*ibuf++;
702 clen = min( clen, 199 );
704 upath = path->u_name;
705 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
706 return AFPERR_ACCESS;
709 isadir = path_isadir(path);
710 if (isadir || !(of = of_findname(path))) {
711 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
716 if (ad_open_metadata( upath , vol_noadouble(vol) | ( (isadir) ? ADFLAGS_DIR :0),O_CREAT, adp) < 0 ) {
717 return( AFPERR_ACCESS );
720 if (ad_getentryoff(adp, ADEID_COMMENT)) {
721 if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
722 if ( *path->m_name == '\0' ) {
723 name = curdir->d_m_name;
727 ad_setname(adp, name);
729 ad_setentrylen( adp, ADEID_COMMENT, clen );
730 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
733 ad_close_metadata( adp);
737 /* ----------------------------- */
738 int afp_addcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
749 memcpy( &vid, ibuf, sizeof( vid ));
750 ibuf += sizeof( vid );
751 if (NULL == ( vol = getvolbyvid( vid )) ) {
752 return( AFPERR_PARAM );
755 memcpy( &did, ibuf, sizeof( did ));
756 ibuf += sizeof( did );
757 if (NULL == ( dir = dirlookup( vol, did )) ) {
761 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
762 return get_afp_errno(AFPERR_NOOBJ);
765 if ((u_long)ibuf & 1 ) {
769 return ad_addcomment(vol, path, ibuf);
772 /* -------------------- */
773 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuflen)
775 struct adouble ad, *adp;
781 upath = path->u_name;
782 isadir = path_isadir(path);
783 if (isadir || !(of = of_findname(path))) {
784 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
789 if ( ad_metadata( upath,( isadir) ? ADFLAGS_DIR : 0, adp) < 0 ) {
790 return( AFPERR_NOITEM );
793 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
794 ad_close_metadata( adp );
795 return AFPERR_NOITEM;
798 * Make sure the AD file is not bogus.
800 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
801 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
802 ad_close_metadata( adp );
803 return( AFPERR_NOITEM );
806 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
808 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
810 ad_close_metadata( adp);
815 /* -------------------- */
816 int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
827 memcpy( &vid, ibuf, sizeof( vid ));
828 ibuf += sizeof( vid );
829 if (NULL == ( vol = getvolbyvid( vid )) ) {
830 return( AFPERR_PARAM );
833 memcpy( &did, ibuf, sizeof( did ));
834 ibuf += sizeof( did );
835 if (NULL == ( dir = dirlookup( vol, did )) ) {
839 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
840 return get_afp_errno(AFPERR_NOOBJ);
843 return ad_getcomment(vol, s_path, rbuf, rbuflen);
846 /* ----------------------- */
847 static int ad_rmvcomment(struct vol *vol, struct path *path)
849 struct adouble ad, *adp;
854 upath = path->u_name;
855 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
856 return AFPERR_ACCESS;
859 isadir = path_isadir(path);
860 if (isadir || !(of = of_findname(path))) {
861 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
866 if ( ad_open_metadata( upath, (isadir) ? ADFLAGS_DIR : 0, 0, adp) < 0 ) {
869 return( AFPERR_NOITEM );
871 return( AFPERR_ACCESS );
873 return( AFPERR_PARAM );
877 if (ad_getentryoff(adp, ADEID_COMMENT)) {
878 ad_setentrylen( adp, ADEID_COMMENT, 0 );
881 ad_close_metadata( adp);
885 /* ----------------------- */
886 int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
897 memcpy( &vid, ibuf, sizeof( vid ));
898 ibuf += sizeof( vid );
899 if (NULL == ( vol = getvolbyvid( vid )) ) {
900 return( AFPERR_PARAM );
903 memcpy( &did, ibuf, sizeof( did ));
904 ibuf += sizeof( did );
905 if (NULL == ( dir = dirlookup( vol, did )) ) {
909 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
910 return get_afp_errno(AFPERR_NOOBJ);
913 return ad_rmvcomment(vol, s_path);