2 * $Id: desktop.c,v 1.43 2009-10-25 09:47:03 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, 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 (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize) < 0) {
512 case EINVAL: /* there's no guarantee that all fs support sendfile */
524 buflen = read(si.sdt_fd, rbuf, *rbuflen);
528 /* dsi_read() also returns buffer size of next allocation */
529 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
540 LOG(log_info, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno));
542 obj->exit(EXITERR_SYS);
546 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
547 return( AFPERR_PARAM );
554 /* ---------------------- */
555 static const char hexdig[] = "0123456789abcdef";
556 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
558 static char path[ MAXPATHLEN + 1];
562 strcpy( path, vol->v_path );
563 strcat( path, "/.AppleDesktop/" );
564 for ( p = path; *p != '\0'; p++ )
567 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
568 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
569 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
576 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
577 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
578 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
579 *p++ = hexdig[ creator[ i ] & 0x0f ];
590 /* ---------------------------
591 * mpath is only a filename
592 * did filename parent directory ID.
595 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
597 static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
603 if ( *mpath == '\0' ) {
607 /* set conversion flags */
608 if (!(vol->v_flags & AFPVOL_NOHEX))
609 flags |= CONV_ESCAPEHEX;
610 if (!(vol->v_flags & AFPVOL_USEDOTS))
611 flags |= CONV_ESCAPEDOTS;
613 if ((vol->v_casefold & AFPVOL_MTOUUPPER))
614 flags |= CONV_TOUPPER;
615 else if ((vol->v_casefold & AFPVOL_MTOULOWER))
616 flags |= CONV_TOLOWER;
618 if ((vol->v_flags & AFPVOL_EILSEQ)) {
619 flags |= CONV__EILSEQ;
622 m = demangle(vol, mpath, did);
633 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)) ) {
634 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
639 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
647 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
649 static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
651 u_int16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX;
655 outlen = strlen(upath);
657 if ((vol->v_casefold & AFPVOL_UTOMUPPER))
658 flags |= CONV_TOUPPER;
659 else if ((vol->v_casefold & AFPVOL_UTOMLOWER))
660 flags |= CONV_TOLOWER;
662 if ((vol->v_flags & AFPVOL_EILSEQ)) {
663 flags |= CONV__EILSEQ;
668 /* convert charsets */
669 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)) ) {
670 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
674 if (!(flags & CONV_REQMANGLE))
682 m = mangle(vol, mpath, outlen, upath, id, flags);
685 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
691 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
695 /* ------------------------- */
696 static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
702 struct adouble ad, *adp;
704 clen = (u_char)*ibuf++;
705 clen = min( clen, 199 );
707 upath = path->u_name;
708 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
709 return AFPERR_ACCESS;
712 isadir = path_isadir(path);
713 if (isadir || !(of = of_findname(path))) {
714 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
719 if (ad_open_metadata( upath , vol_noadouble(vol) | ( (isadir) ? ADFLAGS_DIR :0),O_CREAT, adp) < 0 ) {
720 return( AFPERR_ACCESS );
723 if (ad_getentryoff(adp, ADEID_COMMENT)) {
724 if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
725 if ( *path->m_name == '\0' ) {
726 name = curdir->d_m_name;
730 ad_setname(adp, name);
732 ad_setentrylen( adp, ADEID_COMMENT, clen );
733 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
736 ad_close_metadata( adp);
740 /* ----------------------------- */
741 int afp_addcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
752 memcpy( &vid, ibuf, sizeof( vid ));
753 ibuf += sizeof( vid );
754 if (NULL == ( vol = getvolbyvid( vid )) ) {
755 return( AFPERR_PARAM );
758 memcpy( &did, ibuf, sizeof( did ));
759 ibuf += sizeof( did );
760 if (NULL == ( dir = dirlookup( vol, did )) ) {
764 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
765 return get_afp_errno(AFPERR_NOOBJ);
768 if ((u_long)ibuf & 1 ) {
772 return ad_addcomment(vol, path, ibuf);
775 /* -------------------- */
776 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuflen)
778 struct adouble ad, *adp;
784 upath = path->u_name;
785 isadir = path_isadir(path);
786 if (isadir || !(of = of_findname(path))) {
787 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
792 if ( ad_metadata( upath,( isadir) ? ADFLAGS_DIR : 0, adp) < 0 ) {
793 return( AFPERR_NOITEM );
796 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
797 ad_close_metadata( adp );
798 return AFPERR_NOITEM;
801 * Make sure the AD file is not bogus.
803 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
804 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
805 ad_close_metadata( adp );
806 return( AFPERR_NOITEM );
809 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
811 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
813 ad_close_metadata( adp);
818 /* -------------------- */
819 int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
830 memcpy( &vid, ibuf, sizeof( vid ));
831 ibuf += sizeof( vid );
832 if (NULL == ( vol = getvolbyvid( vid )) ) {
833 return( AFPERR_PARAM );
836 memcpy( &did, ibuf, sizeof( did ));
837 ibuf += sizeof( did );
838 if (NULL == ( dir = dirlookup( vol, did )) ) {
842 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
843 return get_afp_errno(AFPERR_NOOBJ);
846 return ad_getcomment(vol, s_path, rbuf, rbuflen);
849 /* ----------------------- */
850 static int ad_rmvcomment(struct vol *vol, struct path *path)
852 struct adouble ad, *adp;
857 upath = path->u_name;
858 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
859 return AFPERR_ACCESS;
862 isadir = path_isadir(path);
863 if (isadir || !(of = of_findname(path))) {
864 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
869 if ( ad_open_metadata( upath, (isadir) ? ADFLAGS_DIR : 0, 0, adp) < 0 ) {
872 return( AFPERR_NOITEM );
874 return( AFPERR_ACCESS );
876 return( AFPERR_PARAM );
880 if (ad_getentryoff(adp, ADEID_COMMENT)) {
881 ad_setentrylen( adp, ADEID_COMMENT, 0 );
884 ad_close_metadata( adp);
888 /* ----------------------- */
889 int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
900 memcpy( &vid, ibuf, sizeof( vid ));
901 ibuf += sizeof( vid );
902 if (NULL == ( vol = getvolbyvid( vid )) ) {
903 return( AFPERR_PARAM );
906 memcpy( &did, ibuf, sizeof( did ));
907 ibuf += sizeof( did );
908 if (NULL == ( dir = dirlookup( vol, did )) ) {
912 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
913 return get_afp_errno(AFPERR_NOOBJ);
916 return ad_rmvcomment(vol, s_path);