2 * $Id: desktop.c,v 1.37 2006-09-29 09:39:16 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(obj, ibuf, ibuflen, rbuf, rbuflen )
46 int ibuflen _U_, *rbuflen;
53 memcpy( &vid, ibuf, sizeof(vid));
54 if (NULL == ( vol = getvolbyvid( vid )) ) {
56 return( AFPERR_PARAM );
59 memcpy( rbuf, &vid, sizeof(vid));
60 *rbuflen = sizeof(vid);
64 int afp_closedt(obj, ibuf, ibuflen, rbuf, rbuflen )
66 char *ibuf _U_, *rbuf _U_;
67 int ibuflen _U_, *rbuflen;
73 struct savedt si = { { 0, 0, 0, 0 }, -1, 0, 0 };
75 static char *icon_dtfile(struct vol *vol, u_char creator[ 4 ])
77 return dtfile( vol, creator, ".icon" );
80 static int iconopen( vol, creator, flags, mode )
86 char *dtf, *adt, *adts;
88 if ( si.sdt_fd != -1 ) {
89 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
90 si.sdt_vid == vol->v_vid ) {
97 dtf = icon_dtfile( vol, creator);
99 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
100 if ( errno == ENOENT && ( flags & O_CREAT )) {
101 if (( adts = strrchr( dtf, '/' )) == NULL ) {
105 if (( adt = strrchr( dtf, '/' )) == NULL ) {
109 (void) ad_mkdir( dtf, DIRBITS | 0777 );
111 (void) ad_mkdir( dtf, DIRBITS | 0777 );
114 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
115 LOG(log_error, logtype_afpd, "iconopen(%s): open: %s", dtf, strerror(errno) );
123 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
124 si.sdt_vid = vol->v_vid;
129 int afp_addicon(obj, ibuf, ibuflen, rbuf, rbuflen)
132 int ibuflen _U_, *rbuflen;
136 struct iovec iov[ 2 ];
138 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
139 int itype, cc = AFP_OK, iovcnt = 0, buflen;
140 u_int32_t ftype, itag;
141 u_int16_t bsize, rsize, vid;
147 memcpy( &vid, ibuf, sizeof( vid ));
148 ibuf += sizeof( vid );
149 if (NULL == ( vol = getvolbyvid( vid )) ) {
154 memcpy( fcreator, ibuf, sizeof( fcreator ));
155 ibuf += sizeof( fcreator );
157 memcpy( &ftype, ibuf, sizeof( ftype ));
158 ibuf += sizeof( ftype );
160 itype = (unsigned char) *ibuf;
163 memcpy( &itag, ibuf, sizeof( itag ));
164 ibuf += sizeof( itag );
166 memcpy( &bsize, ibuf, sizeof( bsize ));
167 bsize = ntohs( bsize );
169 if ( si.sdt_fd != -1 ) {
170 (void)close( si.sdt_fd );
174 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
179 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
182 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
188 * Read icon elements until we find a match to replace, or
189 * we get to the end to insert.
192 memcpy( p, &itag, sizeof( itag ));
194 memcpy( p, &ftype, sizeof( ftype ));
195 p += sizeof( ftype );
198 bsize = htons( bsize );
199 memcpy( p, &bsize, sizeof( bsize ));
200 bsize = ntohs( bsize );
201 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
202 memcpy( &rsize, irh + 10, sizeof( rsize ));
203 rsize = ntohs( rsize );
205 * Is this our set of headers?
207 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
209 * Is the size correct?
211 if ( bsize != rsize )
216 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
217 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator),strerror(errno) );
223 * Some error occurred, return.
227 if (obj->proto == AFPPROTO_DSI) {
228 dsi_writeinit(obj->handle, rbuf, buflen);
229 dsi_writeflush(obj->handle);
234 switch (obj->proto) {
238 if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
239 return( AFPERR_PARAM );
242 if (obj->options.flags & OPTION_DEBUG) {
243 printf("(write) len: %d\n", buflen);
244 bprint(rbuf, buflen);
249 * We're at the end of the file, add the headers, etc. */
251 iov[ 0 ].iov_base = (caddr_t)imh;
252 iov[ 0 ].iov_len = sizeof( imh );
253 iov[ 1 ].iov_base = rbuf;
254 iov[ 1 ].iov_len = bsize;
259 * We found an icon to replace.
262 iov[ 0 ].iov_base = rbuf;
263 iov[ 0 ].iov_len = bsize;
267 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
268 LOG(log_error, logtype_afpd, "afp_addicon(%s): writev: %s", icon_dtfile(vol, fcreator), strerror(errno) );
269 return( AFPERR_PARAM );
272 #endif /* no afp/asp */
275 DSI *dsi = obj->handle;
277 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
279 /* add headers at end of file */
280 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
281 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
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));
292 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
294 if ( obj->options.flags & OPTION_DEBUG ) {
295 printf("(write) command cont'd: %d\n", iovcnt);
296 bprint(rbuf, iovcnt);
299 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
300 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
314 static const u_char utag[] = { 0, 0, 0, 0 };
315 static const u_char ucreator[] = { 0, 0, 0, 0 };/* { 'U', 'N', 'I', 'X' };*/
316 static const u_char utype[] = { 0, 0, 0, 0 };/* { 'T', 'E', 'X', 'T' };*/
317 static const short usize = 256;
320 static const u_char uicon[] = {
321 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
322 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
323 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
324 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
325 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
326 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
327 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
328 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
329 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
330 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
331 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
332 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
333 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
334 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
335 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
336 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
337 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
338 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
339 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
340 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
341 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
342 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
343 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
344 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
345 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
346 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
347 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
348 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
349 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
350 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
351 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
352 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
356 int afp_geticoninfo(obj, ibuf, ibuflen, rbuf, rbuflen )
359 int ibuflen _U_, *rbuflen;
362 u_char fcreator[ 4 ], ih[ 12 ];
363 u_int16_t vid, iindex, bsize;
368 memcpy( &vid, ibuf, sizeof( vid ));
369 ibuf += sizeof( vid );
370 if (NULL == ( vol = getvolbyvid( vid )) ) {
371 return( AFPERR_PARAM );
374 memcpy( fcreator, ibuf, sizeof( fcreator ));
375 ibuf += sizeof( fcreator );
376 memcpy( &iindex, ibuf, sizeof( iindex ));
377 iindex = ntohs( iindex );
379 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
381 return( AFPERR_NOITEM );
383 memcpy( ih, utag, sizeof( utag ));
384 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
385 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
386 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
387 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
389 memcpy( rbuf, ih, sizeof( ih ));
390 *rbuflen = sizeof( ih );
394 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
395 return( AFPERR_NOITEM );
398 if ( iindex < si.sdt_index ) {
399 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
400 return( AFPERR_PARAM );
406 * Position to the correct spot.
409 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
412 return( AFPERR_NOITEM );
414 memcpy( &bsize, ih + 10, sizeof( bsize ));
415 bsize = ntohs(bsize);
416 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
417 LOG(log_error, logtype_afpd, "afp_iconinfo(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
418 return( AFPERR_PARAM );
420 if ( si.sdt_index == iindex ) {
421 memcpy( rbuf, ih, sizeof( ih ));
422 *rbuflen = sizeof( ih );
430 int afp_geticon(obj, ibuf, ibuflen, rbuf, rbuflen )
433 int ibuflen _U_, *rbuflen;
438 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
439 u_int16_t vid, bsize, rsize;
445 memcpy( &vid, ibuf, sizeof( vid ));
446 ibuf += sizeof( vid );
447 if (NULL == ( vol = getvolbyvid( vid )) ) {
448 return( AFPERR_PARAM );
451 memcpy( fcreator, ibuf, sizeof( fcreator ));
452 ibuf += sizeof( fcreator );
453 memcpy( ftype, ibuf, sizeof( ftype ));
454 ibuf += sizeof( ftype );
455 itype = (unsigned char) *ibuf++;
457 memcpy( &bsize, ibuf, sizeof( bsize ));
458 bsize = ntohs( bsize );
461 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
462 memcmp( ftype, utype, sizeof( utype )) == 0 &&
465 memcpy( rbuf, uicon, bsize);
471 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
472 return( AFPERR_NOITEM );
475 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
478 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno));
479 return( AFPERR_PARAM );
484 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
486 offset += sizeof(ih);
487 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
488 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
491 memcpy( &rsize, ih + 10, sizeof( rsize ));
492 rsize = ntohs( rsize );
493 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
494 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
495 return( AFPERR_PARAM );
501 LOG(log_error, logtype_afpd, "afp_geticon(%s): read: %s", icon_dtfile(vol, fcreator), strerror(errno));
502 return( AFPERR_PARAM );
506 return( AFPERR_NOITEM );
509 memcpy( &rsize, ih + 10, sizeof( rsize ));
510 rsize = ntohs( rsize );
511 #define min(a,b) ((a)<(b)?(a):(b))
512 rc = min( bsize, rsize );
514 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
515 DSI *dsi = obj->handle;
519 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
520 if (size < rc + offset) {
524 if ((*rbuflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
527 /* do to the streaming nature, we have to exit if we encounter
528 * a problem. much confusion results otherwise. */
529 while (*rbuflen > 0) {
531 if (!obj->options.flags & OPTION_DEBUG) {
532 if (sys_sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0) {
535 case EINVAL: /* there's no guarantee that all fs support sendfile */
544 buflen = read(si.sdt_fd, rbuf, *rbuflen);
549 if (obj->options.flags & OPTION_DEBUG) {
550 printf( "(read) reply: %d, %d\n", buflen, dsi->clientID);
551 bprint(rbuf, buflen);
554 /* dsi_read() also returns buffer size of next allocation */
555 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
567 LOG(log_info, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno));
569 obj->exit(EXITERR_SYS);
573 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
574 return( AFPERR_PARAM );
581 /* ---------------------- */
582 static const char hexdig[] = "0123456789abcdef";
583 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
585 static char path[ MAXPATHLEN + 1];
589 strcpy( path, vol->v_path );
590 strcat( path, "/.AppleDesktop/" );
591 for ( p = path; *p != '\0'; p++ )
594 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
595 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
596 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
603 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
604 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
605 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
606 *p++ = hexdig[ creator[ i ] & 0x0f ];
617 /* ---------------------------
618 * mpath is only a filename
619 * did filename parent directory ID.
622 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
624 static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
630 if ( *mpath == '\0' ) {
634 /* set conversion flags */
635 if (!(vol->v_flags & AFPVOL_NOHEX))
636 flags |= CONV_ESCAPEHEX;
637 if (!(vol->v_flags & AFPVOL_USEDOTS))
638 flags |= CONV_ESCAPEDOTS;
640 if ((vol->v_casefold & AFPVOL_MTOUUPPER))
641 flags |= CONV_TOUPPER;
642 else if ((vol->v_casefold & AFPVOL_MTOULOWER))
643 flags |= CONV_TOLOWER;
645 if ((vol->v_flags & AFPVOL_EILSEQ)) {
646 flags |= CONV__EILSEQ;
649 m = demangle(vol, mpath, did);
660 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)) ) {
661 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
666 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
674 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
676 static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
678 u_int16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX;
682 outlen = strlen(upath);
684 if ((vol->v_casefold & AFPVOL_UTOMUPPER))
685 flags |= CONV_TOUPPER;
686 else if ((vol->v_casefold & AFPVOL_UTOMLOWER))
687 flags |= CONV_TOLOWER;
689 if ((vol->v_flags & AFPVOL_EILSEQ)) {
690 flags |= CONV__EILSEQ;
695 /* convert charsets */
696 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)) ) {
697 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
701 if (!(flags & CONV_REQMANGLE))
709 m = mangle(vol, mpath, outlen, upath, id, flags);
712 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
718 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
722 /* ------------------------- */
723 static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
729 struct adouble ad, *adp;
731 clen = (u_char)*ibuf++;
732 clen = min( clen, 199 );
734 upath = path->u_name;
735 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
736 return AFPERR_ACCESS;
739 isadir = path_isadir(path);
740 if (isadir || !(of = of_findname(path))) {
741 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
746 if (ad_open_metadata( upath , vol_noadouble(vol) | ( (isadir) ? ADFLAGS_DIR :0),O_CREAT, adp) < 0 ) {
747 return( AFPERR_ACCESS );
750 if (ad_getentryoff(adp, ADEID_COMMENT)) {
751 if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
752 if ( *path->m_name == '\0' ) {
753 name = curdir->d_m_name;
757 ad_setname(adp, name);
759 ad_setentrylen( adp, ADEID_COMMENT, clen );
760 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
763 ad_close_metadata( adp);
767 /* ----------------------------- */
768 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
770 char *ibuf, *rbuf _U_;
771 int ibuflen _U_, *rbuflen;
782 memcpy( &vid, ibuf, sizeof( vid ));
783 ibuf += sizeof( vid );
784 if (NULL == ( vol = getvolbyvid( vid )) ) {
785 return( AFPERR_PARAM );
788 memcpy( &did, ibuf, sizeof( did ));
789 ibuf += sizeof( did );
790 if (NULL == ( dir = dirlookup( vol, did )) ) {
794 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
795 return get_afp_errno(AFPERR_NOOBJ);
798 if ((u_long)ibuf & 1 ) {
802 return ad_addcomment(vol, path, ibuf);
805 /* -------------------- */
806 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, int *rbuflen)
808 struct adouble ad, *adp;
814 upath = path->u_name;
815 isadir = path_isadir(path);
816 if (isadir || !(of = of_findname(path))) {
817 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
822 if ( ad_metadata( upath,( isadir) ? ADFLAGS_DIR : 0, adp) < 0 ) {
823 return( AFPERR_NOITEM );
826 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
827 ad_close_metadata( adp );
828 return AFPERR_NOITEM;
831 * Make sure the AD file is not bogus.
833 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
834 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
835 ad_close_metadata( adp );
836 return( AFPERR_NOITEM );
839 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
841 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
843 ad_close_metadata( adp);
848 /* -------------------- */
849 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
852 int ibuflen _U_, *rbuflen;
863 memcpy( &vid, ibuf, sizeof( vid ));
864 ibuf += sizeof( vid );
865 if (NULL == ( vol = getvolbyvid( vid )) ) {
866 return( AFPERR_PARAM );
869 memcpy( &did, ibuf, sizeof( did ));
870 ibuf += sizeof( did );
871 if (NULL == ( dir = dirlookup( vol, did )) ) {
875 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
876 return get_afp_errno(AFPERR_NOOBJ);
879 return ad_getcomment(vol, s_path, rbuf, rbuflen);
882 /* ----------------------- */
883 static int ad_rmvcomment(struct vol *vol, struct path *path)
885 struct adouble ad, *adp;
890 upath = path->u_name;
891 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
892 return AFPERR_ACCESS;
895 isadir = path_isadir(path);
896 if (isadir || !(of = of_findname(path))) {
897 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
902 if ( ad_open_metadata( upath, (isadir) ? ADFLAGS_DIR : 0, 0, adp) < 0 ) {
905 return( AFPERR_NOITEM );
907 return( AFPERR_ACCESS );
909 return( AFPERR_PARAM );
913 if (ad_getentryoff(adp, ADEID_COMMENT)) {
914 ad_setentrylen( adp, ADEID_COMMENT, 0 );
917 ad_close_metadata( adp);
921 /* ----------------------- */
922 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
924 char *ibuf, *rbuf _U_;
925 int ibuflen _U_, *rbuflen;
936 memcpy( &vid, ibuf, sizeof( vid ));
937 ibuf += sizeof( vid );
938 if (NULL == ( vol = getvolbyvid( vid )) ) {
939 return( AFPERR_PARAM );
942 memcpy( &did, ibuf, sizeof( did ));
943 ibuf += sizeof( did );
944 if (NULL == ( dir = dirlookup( vol, did )) ) {
948 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
949 return get_afp_errno(AFPERR_NOOBJ);
952 return ad_rmvcomment(vol, s_path);