2 * $Id: desktop.c,v 1.38 2009-10-13 22:55:36 didg 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, int ibuflen _U_, char *rbuf, int *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_, int ibuflen _U_, char *rbuf _U_, int *rbuflen)
67 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, int ibuflen _U_, char *rbuf, int *rbuflen)
123 struct iovec iov[ 2 ];
125 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
126 int itype, cc = AFP_OK, iovcnt = 0, buflen;
127 u_int32_t ftype, itag;
128 u_int16_t bsize, rsize, vid;
134 memcpy( &vid, ibuf, sizeof( vid ));
135 ibuf += sizeof( vid );
136 if (NULL == ( vol = getvolbyvid( vid )) ) {
141 memcpy( fcreator, ibuf, sizeof( fcreator ));
142 ibuf += sizeof( fcreator );
144 memcpy( &ftype, ibuf, sizeof( ftype ));
145 ibuf += sizeof( ftype );
147 itype = (unsigned char) *ibuf;
150 memcpy( &itag, ibuf, sizeof( itag ));
151 ibuf += sizeof( itag );
153 memcpy( &bsize, ibuf, sizeof( bsize ));
154 bsize = ntohs( bsize );
156 if ( si.sdt_fd != -1 ) {
157 (void)close( si.sdt_fd );
161 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
166 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
169 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
175 * Read icon elements until we find a match to replace, or
176 * we get to the end to insert.
179 memcpy( p, &itag, sizeof( itag ));
181 memcpy( p, &ftype, sizeof( ftype ));
182 p += sizeof( ftype );
185 bsize = htons( bsize );
186 memcpy( p, &bsize, sizeof( bsize ));
187 bsize = ntohs( bsize );
188 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
189 memcpy( &rsize, irh + 10, sizeof( rsize ));
190 rsize = ntohs( rsize );
192 * Is this our set of headers?
194 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
196 * Is the size correct?
198 if ( bsize != rsize )
203 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
204 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator),strerror(errno) );
210 * Some error occurred, return.
214 if (obj->proto == AFPPROTO_DSI) {
215 dsi_writeinit(obj->handle, rbuf, buflen);
216 dsi_writeflush(obj->handle);
221 switch (obj->proto) {
225 if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
226 return( AFPERR_PARAM );
229 if (obj->options.flags & OPTION_DEBUG) {
230 printf("(write) len: %d\n", buflen);
231 bprint(rbuf, buflen);
236 * We're at the end of the file, add the headers, etc. */
238 iov[ 0 ].iov_base = (caddr_t)imh;
239 iov[ 0 ].iov_len = sizeof( imh );
240 iov[ 1 ].iov_base = rbuf;
241 iov[ 1 ].iov_len = bsize;
246 * We found an icon to replace.
249 iov[ 0 ].iov_base = rbuf;
250 iov[ 0 ].iov_len = bsize;
254 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
255 LOG(log_error, logtype_afpd, "afp_addicon(%s): writev: %s", icon_dtfile(vol, fcreator), strerror(errno) );
256 return( AFPERR_PARAM );
259 #endif /* no afp/asp */
262 DSI *dsi = obj->handle;
264 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
266 /* add headers at end of file */
267 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
268 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
273 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
274 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
279 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
281 if ( obj->options.flags & OPTION_DEBUG ) {
282 printf("(write) command cont'd: %d\n", iovcnt);
283 bprint(rbuf, iovcnt);
286 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
287 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
301 static const u_char utag[] = { 0, 0, 0, 0 };
302 static const u_char ucreator[] = { 0, 0, 0, 0 };/* { 'U', 'N', 'I', 'X' };*/
303 static const u_char utype[] = { 0, 0, 0, 0 };/* { 'T', 'E', 'X', 'T' };*/
304 static const short usize = 256;
307 static const u_char uicon[] = {
308 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
309 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
310 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
311 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
312 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
313 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
314 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
315 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
316 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
317 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
318 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
319 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
320 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
321 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
322 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
323 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
324 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
325 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
326 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
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,
335 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
336 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
337 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
338 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
339 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
343 int afp_geticoninfo(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int *rbuflen)
346 u_char fcreator[ 4 ], ih[ 12 ];
347 u_int16_t vid, iindex, bsize;
352 memcpy( &vid, ibuf, sizeof( vid ));
353 ibuf += sizeof( vid );
354 if (NULL == ( vol = getvolbyvid( vid )) ) {
355 return( AFPERR_PARAM );
358 memcpy( fcreator, ibuf, sizeof( fcreator ));
359 ibuf += sizeof( fcreator );
360 memcpy( &iindex, ibuf, sizeof( iindex ));
361 iindex = ntohs( iindex );
363 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
365 return( AFPERR_NOITEM );
367 memcpy( ih, utag, sizeof( utag ));
368 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
369 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
370 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
371 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
373 memcpy( rbuf, ih, sizeof( ih ));
374 *rbuflen = sizeof( ih );
378 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
379 return( AFPERR_NOITEM );
382 if ( iindex < si.sdt_index ) {
383 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
384 return( AFPERR_PARAM );
390 * Position to the correct spot.
393 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
396 return( AFPERR_NOITEM );
398 memcpy( &bsize, ih + 10, sizeof( bsize ));
399 bsize = ntohs(bsize);
400 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
401 LOG(log_error, logtype_afpd, "afp_iconinfo(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
402 return( AFPERR_PARAM );
404 if ( si.sdt_index == iindex ) {
405 memcpy( rbuf, ih, sizeof( ih ));
406 *rbuflen = sizeof( ih );
414 int afp_geticon(AFPObj *obj, char *ibuf, int ibuflen _U_, char *rbuf, int *rbuflen)
419 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
420 u_int16_t vid, bsize, rsize;
426 memcpy( &vid, ibuf, sizeof( vid ));
427 ibuf += sizeof( vid );
428 if (NULL == ( vol = getvolbyvid( vid )) ) {
429 return( AFPERR_PARAM );
432 memcpy( fcreator, ibuf, sizeof( fcreator ));
433 ibuf += sizeof( fcreator );
434 memcpy( ftype, ibuf, sizeof( ftype ));
435 ibuf += sizeof( ftype );
436 itype = (unsigned char) *ibuf++;
438 memcpy( &bsize, ibuf, sizeof( bsize ));
439 bsize = ntohs( bsize );
442 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
443 memcmp( ftype, utype, sizeof( utype )) == 0 &&
446 memcpy( rbuf, uicon, bsize);
452 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
453 return( AFPERR_NOITEM );
456 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
459 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno));
460 return( AFPERR_PARAM );
465 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
467 offset += sizeof(ih);
468 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
469 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
472 memcpy( &rsize, ih + 10, sizeof( rsize ));
473 rsize = ntohs( rsize );
474 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
475 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
476 return( AFPERR_PARAM );
482 LOG(log_error, logtype_afpd, "afp_geticon(%s): read: %s", icon_dtfile(vol, fcreator), strerror(errno));
483 return( AFPERR_PARAM );
487 return( AFPERR_NOITEM );
490 memcpy( &rsize, ih + 10, sizeof( rsize ));
491 rsize = ntohs( rsize );
492 #define min(a,b) ((a)<(b)?(a):(b))
493 rc = min( bsize, rsize );
495 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
496 DSI *dsi = obj->handle;
500 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
501 if (size < rc + offset) {
505 if ((*rbuflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
508 /* do to the streaming nature, we have to exit if we encounter
509 * a problem. much confusion results otherwise. */
510 while (*rbuflen > 0) {
512 if (!obj->options.flags & OPTION_DEBUG) {
513 if (sys_sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0) {
516 case EINVAL: /* there's no guarantee that all fs support sendfile */
525 buflen = read(si.sdt_fd, rbuf, *rbuflen);
530 if (obj->options.flags & OPTION_DEBUG) {
531 printf( "(read) reply: %d, %d\n", buflen, dsi->clientID);
532 bprint(rbuf, buflen);
535 /* dsi_read() also returns buffer size of next allocation */
536 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
548 LOG(log_info, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno));
550 obj->exit(EXITERR_SYS);
554 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
555 return( AFPERR_PARAM );
562 /* ---------------------- */
563 static const char hexdig[] = "0123456789abcdef";
564 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
566 static char path[ MAXPATHLEN + 1];
570 strcpy( path, vol->v_path );
571 strcat( path, "/.AppleDesktop/" );
572 for ( p = path; *p != '\0'; p++ )
575 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
576 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
577 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
584 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
585 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
586 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
587 *p++ = hexdig[ creator[ i ] & 0x0f ];
598 /* ---------------------------
599 * mpath is only a filename
600 * did filename parent directory ID.
603 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
605 static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
611 if ( *mpath == '\0' ) {
615 /* set conversion flags */
616 if (!(vol->v_flags & AFPVOL_NOHEX))
617 flags |= CONV_ESCAPEHEX;
618 if (!(vol->v_flags & AFPVOL_USEDOTS))
619 flags |= CONV_ESCAPEDOTS;
621 if ((vol->v_casefold & AFPVOL_MTOUUPPER))
622 flags |= CONV_TOUPPER;
623 else if ((vol->v_casefold & AFPVOL_MTOULOWER))
624 flags |= CONV_TOLOWER;
626 if ((vol->v_flags & AFPVOL_EILSEQ)) {
627 flags |= CONV__EILSEQ;
630 m = demangle(vol, mpath, did);
641 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)) ) {
642 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
647 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
655 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
657 static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
659 u_int16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX;
663 outlen = strlen(upath);
665 if ((vol->v_casefold & AFPVOL_UTOMUPPER))
666 flags |= CONV_TOUPPER;
667 else if ((vol->v_casefold & AFPVOL_UTOMLOWER))
668 flags |= CONV_TOLOWER;
670 if ((vol->v_flags & AFPVOL_EILSEQ)) {
671 flags |= CONV__EILSEQ;
676 /* convert charsets */
677 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)) ) {
678 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
682 if (!(flags & CONV_REQMANGLE))
690 m = mangle(vol, mpath, outlen, upath, id, flags);
693 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
699 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
703 /* ------------------------- */
704 static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
710 struct adouble ad, *adp;
712 clen = (u_char)*ibuf++;
713 clen = min( clen, 199 );
715 upath = path->u_name;
716 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
717 return AFPERR_ACCESS;
720 isadir = path_isadir(path);
721 if (isadir || !(of = of_findname(path))) {
722 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
727 if (ad_open_metadata( upath , vol_noadouble(vol) | ( (isadir) ? ADFLAGS_DIR :0),O_CREAT, adp) < 0 ) {
728 return( AFPERR_ACCESS );
731 if (ad_getentryoff(adp, ADEID_COMMENT)) {
732 if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
733 if ( *path->m_name == '\0' ) {
734 name = curdir->d_m_name;
738 ad_setname(adp, name);
740 ad_setentrylen( adp, ADEID_COMMENT, clen );
741 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
744 ad_close_metadata( adp);
748 /* ----------------------------- */
749 int afp_addcomment(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf _U_, int *rbuflen)
760 memcpy( &vid, ibuf, sizeof( vid ));
761 ibuf += sizeof( vid );
762 if (NULL == ( vol = getvolbyvid( vid )) ) {
763 return( AFPERR_PARAM );
766 memcpy( &did, ibuf, sizeof( did ));
767 ibuf += sizeof( did );
768 if (NULL == ( dir = dirlookup( vol, did )) ) {
772 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
773 return get_afp_errno(AFPERR_NOOBJ);
776 if ((u_long)ibuf & 1 ) {
780 return ad_addcomment(vol, path, ibuf);
783 /* -------------------- */
784 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, int *rbuflen)
786 struct adouble ad, *adp;
792 upath = path->u_name;
793 isadir = path_isadir(path);
794 if (isadir || !(of = of_findname(path))) {
795 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
800 if ( ad_metadata( upath,( isadir) ? ADFLAGS_DIR : 0, adp) < 0 ) {
801 return( AFPERR_NOITEM );
804 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
805 ad_close_metadata( adp );
806 return AFPERR_NOITEM;
809 * Make sure the AD file is not bogus.
811 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
812 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
813 ad_close_metadata( adp );
814 return( AFPERR_NOITEM );
817 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
819 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
821 ad_close_metadata( adp);
826 /* -------------------- */
827 int afp_getcomment(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf, int *rbuflen)
838 memcpy( &vid, ibuf, sizeof( vid ));
839 ibuf += sizeof( vid );
840 if (NULL == ( vol = getvolbyvid( vid )) ) {
841 return( AFPERR_PARAM );
844 memcpy( &did, ibuf, sizeof( did ));
845 ibuf += sizeof( did );
846 if (NULL == ( dir = dirlookup( vol, did )) ) {
850 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
851 return get_afp_errno(AFPERR_NOOBJ);
854 return ad_getcomment(vol, s_path, rbuf, rbuflen);
857 /* ----------------------- */
858 static int ad_rmvcomment(struct vol *vol, struct path *path)
860 struct adouble ad, *adp;
865 upath = path->u_name;
866 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
867 return AFPERR_ACCESS;
870 isadir = path_isadir(path);
871 if (isadir || !(of = of_findname(path))) {
872 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
877 if ( ad_open_metadata( upath, (isadir) ? ADFLAGS_DIR : 0, 0, adp) < 0 ) {
880 return( AFPERR_NOITEM );
882 return( AFPERR_ACCESS );
884 return( AFPERR_PARAM );
888 if (ad_getentryoff(adp, ADEID_COMMENT)) {
889 ad_setentrylen( adp, ADEID_COMMENT, 0 );
892 ad_close_metadata( adp);
896 /* ----------------------- */
897 int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, int ibuflen _U_, char *rbuf _U_, int *rbuflen)
908 memcpy( &vid, ibuf, sizeof( vid ));
909 ibuf += sizeof( vid );
910 if (NULL == ( vol = getvolbyvid( vid )) ) {
911 return( AFPERR_PARAM );
914 memcpy( &did, ibuf, sizeof( did ));
915 ibuf += sizeof( did );
916 if (NULL == ( dir = dirlookup( vol, did )) ) {
920 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
921 return get_afp_errno(AFPERR_NOOBJ);
924 return ad_rmvcomment(vol, s_path);