2 * $Id: desktop.c,v 1.35 2006-09-18 09:22:25 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 + 1];
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);
667 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
675 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
677 static char mpath[ MAXPATHLEN + 1];
679 u_int16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX;
683 outlen = strlen(upath);
685 if ((vol->v_casefold & AFPVOL_UTOMUPPER))
686 flags |= CONV_TOUPPER;
687 else if ((vol->v_casefold & AFPVOL_UTOMLOWER))
688 flags |= CONV_TOLOWER;
690 if ((vol->v_flags & AFPVOL_EILSEQ)) {
691 flags |= CONV__EILSEQ;
696 /* convert charsets */
697 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)) ) {
698 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
703 if (!(flags & CONV_REQMANGLE))
711 m = mangle(vol, mpath, outlen, upath, id, flags);
714 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
720 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
724 /* ------------------------- */
725 static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
731 struct adouble ad, *adp;
733 clen = (u_char)*ibuf++;
734 clen = min( clen, 199 );
736 upath = path->u_name;
737 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
738 return AFPERR_ACCESS;
741 isadir = path_isadir(path);
742 if (isadir || !(of = of_findname(path))) {
743 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
748 if (ad_open_metadata( upath , vol_noadouble(vol) | ( (isadir) ? ADFLAGS_DIR :0),O_CREAT, adp) < 0 ) {
749 return( AFPERR_ACCESS );
752 if (ad_getentryoff(adp, ADEID_COMMENT)) {
753 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
754 if ( *path->m_name == '\0' ) {
755 name = curdir->d_m_name;
759 ad_setname(adp, name);
761 ad_setentrylen( adp, ADEID_COMMENT, clen );
762 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
763 ad_flush_metadata( adp );
765 ad_close_metadata( adp);
769 /* ----------------------------- */
770 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
772 char *ibuf, *rbuf _U_;
773 int ibuflen _U_, *rbuflen;
784 memcpy( &vid, ibuf, sizeof( vid ));
785 ibuf += sizeof( vid );
786 if (NULL == ( vol = getvolbyvid( vid )) ) {
787 return( AFPERR_PARAM );
790 memcpy( &did, ibuf, sizeof( did ));
791 ibuf += sizeof( did );
792 if (NULL == ( dir = dirlookup( vol, did )) ) {
796 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
797 return get_afp_errno(AFPERR_NOOBJ);
800 if ((u_long)ibuf & 1 ) {
804 return ad_addcomment(vol, path, ibuf);
807 /* -------------------- */
808 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, int *rbuflen)
810 struct adouble ad, *adp;
816 upath = path->u_name;
817 isadir = path_isadir(path);
818 if (isadir || !(of = of_findname(path))) {
819 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
824 if ( ad_metadata( upath,( isadir) ? ADFLAGS_DIR : 0, adp) < 0 ) {
825 return( AFPERR_NOITEM );
828 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
829 ad_close_metadata( adp );
830 return AFPERR_NOITEM;
833 * Make sure the AD file is not bogus.
835 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
836 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
837 ad_close_metadata( adp );
838 return( AFPERR_NOITEM );
841 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
843 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
845 ad_close_metadata( adp);
850 /* -------------------- */
851 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
854 int ibuflen _U_, *rbuflen;
865 memcpy( &vid, ibuf, sizeof( vid ));
866 ibuf += sizeof( vid );
867 if (NULL == ( vol = getvolbyvid( vid )) ) {
868 return( AFPERR_PARAM );
871 memcpy( &did, ibuf, sizeof( did ));
872 ibuf += sizeof( did );
873 if (NULL == ( dir = dirlookup( vol, did )) ) {
877 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
878 return get_afp_errno(AFPERR_NOOBJ);
881 return ad_getcomment(vol, s_path, rbuf, rbuflen);
884 /* ----------------------- */
885 static int ad_rmvcomment(struct vol *vol, struct path *path)
887 struct adouble ad, *adp;
892 upath = path->u_name;
893 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
894 return AFPERR_ACCESS;
897 isadir = path_isadir(path);
898 if (isadir || !(of = of_findname(path))) {
899 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
904 if ( ad_open_metadata( upath, (isadir) ? ADFLAGS_DIR : 0, 0, adp) < 0 ) {
907 return( AFPERR_NOITEM );
909 return( AFPERR_ACCESS );
911 return( AFPERR_PARAM );
915 if (ad_getentryoff(adp, ADEID_COMMENT)) {
916 ad_setentrylen( adp, ADEID_COMMENT, 0 );
917 ad_flush_metadata( adp );
919 ad_close_metadata( adp);
923 /* ----------------------- */
924 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
926 char *ibuf, *rbuf _U_;
927 int ibuflen _U_, *rbuflen;
938 memcpy( &vid, ibuf, sizeof( vid ));
939 ibuf += sizeof( vid );
940 if (NULL == ( vol = getvolbyvid( vid )) ) {
941 return( AFPERR_PARAM );
944 memcpy( &did, ibuf, sizeof( did ));
945 ibuf += sizeof( did );
946 if (NULL == ( dir = dirlookup( vol, did )) ) {
950 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
951 return get_afp_errno(AFPERR_NOOBJ);
954 return ad_rmvcomment(vol, s_path);