2 * $Id: desktop.c,v 1.26.2.4.2.18.2.7 2006-09-19 00:08:00 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.
621 static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
622 static char mpath[ MAXPATHLEN + 2];/* for convert_charset dest_len parameter +2 */
624 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
631 if ( *mpath == '\0' ) {
635 /* set conversion flags */
636 if (!(vol->v_flags & AFPVOL_NOHEX))
637 flags |= CONV_ESCAPEHEX;
638 if (!(vol->v_flags & AFPVOL_USEDOTS))
639 flags |= CONV_ESCAPEDOTS;
641 if ((vol->v_casefold & AFPVOL_MTOUUPPER))
642 flags |= CONV_TOUPPER;
643 else if ((vol->v_casefold & AFPVOL_MTOULOWER))
644 flags |= CONV_TOLOWER;
646 m = demangle(vol, mpath, did);
657 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)) ) {
658 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
663 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
671 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
674 u_int16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX;
678 outlen = strlen(upath);
680 if (vol->v_casefold & AFPVOL_UTOMUPPER)
681 flags |= CONV_TOUPPER;
682 else if (vol->v_casefold & AFPVOL_UTOMLOWER)
683 flags |= CONV_TOLOWER;
687 /* convert charsets */
688 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)) ) {
689 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
693 if (!(flags & CONV_REQMANGLE))
701 m = mangle(vol, mpath, outlen, upath, id, flags);
704 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
710 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
714 /* ------------------------- */
715 static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
721 struct adouble ad, *adp;
723 clen = (u_char)*ibuf++;
724 clen = min( clen, 199 );
726 upath = path->u_name;
727 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
728 return AFPERR_ACCESS;
731 isadir = path_isadir(path);
732 if (isadir || !(of = of_findname(path))) {
733 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
738 if (ad_open( upath , vol_noadouble(vol) |
739 (( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
740 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
741 return( AFPERR_ACCESS );
744 if (ad_getentryoff(adp, ADEID_COMMENT)) {
745 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
746 if ( *path->m_name == '\0' ) {
747 name = curdir->d_m_name;
751 ad_setname(adp, name);
753 ad_setentrylen( adp, ADEID_COMMENT, clen );
754 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
755 ad_flush( adp, ADFLAGS_HF );
757 ad_close( adp, ADFLAGS_HF );
761 /* ----------------------------- */
762 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
764 char *ibuf, *rbuf _U_;
765 int ibuflen _U_, *rbuflen;
776 memcpy( &vid, ibuf, sizeof( vid ));
777 ibuf += sizeof( vid );
778 if (NULL == ( vol = getvolbyvid( vid )) ) {
779 return( AFPERR_PARAM );
782 memcpy( &did, ibuf, sizeof( did ));
783 ibuf += sizeof( did );
784 if (NULL == ( dir = dirlookup( vol, did )) ) {
788 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
789 return get_afp_errno(AFPERR_NOOBJ);
792 if ((u_long)ibuf & 1 ) {
796 return ad_addcomment(vol, path, ibuf);
799 /* -------------------- */
800 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, int *rbuflen)
802 struct adouble ad, *adp;
808 upath = path->u_name;
809 isadir = path_isadir(path);
810 if (isadir || !(of = of_findname(path))) {
811 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
816 if ( ad_metadata( upath,( isadir) ? ADFLAGS_DIR : 0, adp) < 0 ) {
817 return( AFPERR_NOITEM );
820 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
821 ad_close( adp, ADFLAGS_HF );
822 return AFPERR_NOITEM;
825 * Make sure the AD file is not bogus.
827 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
828 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
829 ad_close( adp, ADFLAGS_HF );
830 return( AFPERR_NOITEM );
833 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
835 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
837 ad_close( adp, ADFLAGS_HF );
842 /* -------------------- */
843 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
846 int ibuflen _U_, *rbuflen;
857 memcpy( &vid, ibuf, sizeof( vid ));
858 ibuf += sizeof( vid );
859 if (NULL == ( vol = getvolbyvid( vid )) ) {
860 return( AFPERR_PARAM );
863 memcpy( &did, ibuf, sizeof( did ));
864 ibuf += sizeof( did );
865 if (NULL == ( dir = dirlookup( vol, did )) ) {
869 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
870 return get_afp_errno(AFPERR_NOOBJ);
873 return ad_getcomment(vol, s_path, rbuf, rbuflen);
876 /* ----------------------- */
877 static int ad_rmvcomment(struct vol *vol, struct path *path)
879 struct adouble ad, *adp;
884 upath = path->u_name;
885 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
886 return AFPERR_ACCESS;
889 isadir = path_isadir(path);
890 if (isadir || !(of = of_findname(path))) {
891 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
897 (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
898 O_RDWR, 0, adp) < 0 ) {
901 return( AFPERR_NOITEM );
903 return( AFPERR_ACCESS );
905 return( AFPERR_PARAM );
909 if (ad_getentryoff(adp, ADEID_COMMENT)) {
910 ad_setentrylen( adp, ADEID_COMMENT, 0 );
911 ad_flush( adp, ADFLAGS_HF );
913 ad_close( adp, ADFLAGS_HF );
917 /* ----------------------- */
918 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
920 char *ibuf, *rbuf _U_;
921 int ibuflen _U_, *rbuflen;
932 memcpy( &vid, ibuf, sizeof( vid ));
933 ibuf += sizeof( vid );
934 if (NULL == ( vol = getvolbyvid( vid )) ) {
935 return( AFPERR_PARAM );
938 memcpy( &did, ibuf, sizeof( did ));
939 ibuf += sizeof( did );
940 if (NULL == ( dir = dirlookup( vol, did )) ) {
944 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
945 return get_afp_errno(AFPERR_NOOBJ);
948 return ad_rmvcomment(vol, s_path);