2 * $Id: desktop.c,v 1.41 2009-10-22 05:09:56 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 (sys_sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0) {
512 case EINVAL: /* there's no guarantee that all fs support sendfile */
521 buflen = read(si.sdt_fd, rbuf, *rbuflen);
525 /* dsi_read() also returns buffer size of next allocation */
526 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
538 LOG(log_info, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno));
540 obj->exit(EXITERR_SYS);
544 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
545 return( AFPERR_PARAM );
552 /* ---------------------- */
553 static const char hexdig[] = "0123456789abcdef";
554 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
556 static char path[ MAXPATHLEN + 1];
560 strcpy( path, vol->v_path );
561 strcat( path, "/.AppleDesktop/" );
562 for ( p = path; *p != '\0'; p++ )
565 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
566 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
567 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
574 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
575 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
576 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
577 *p++ = hexdig[ creator[ i ] & 0x0f ];
588 /* ---------------------------
589 * mpath is only a filename
590 * did filename parent directory ID.
593 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
595 static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
601 if ( *mpath == '\0' ) {
605 /* set conversion flags */
606 if (!(vol->v_flags & AFPVOL_NOHEX))
607 flags |= CONV_ESCAPEHEX;
608 if (!(vol->v_flags & AFPVOL_USEDOTS))
609 flags |= CONV_ESCAPEDOTS;
611 if ((vol->v_casefold & AFPVOL_MTOUUPPER))
612 flags |= CONV_TOUPPER;
613 else if ((vol->v_casefold & AFPVOL_MTOULOWER))
614 flags |= CONV_TOLOWER;
616 if ((vol->v_flags & AFPVOL_EILSEQ)) {
617 flags |= CONV__EILSEQ;
620 m = demangle(vol, mpath, did);
631 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)) ) {
632 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
637 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
645 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
647 static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
649 u_int16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX;
653 outlen = strlen(upath);
655 if ((vol->v_casefold & AFPVOL_UTOMUPPER))
656 flags |= CONV_TOUPPER;
657 else if ((vol->v_casefold & AFPVOL_UTOMLOWER))
658 flags |= CONV_TOLOWER;
660 if ((vol->v_flags & AFPVOL_EILSEQ)) {
661 flags |= CONV__EILSEQ;
666 /* convert charsets */
667 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)) ) {
668 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
672 if (!(flags & CONV_REQMANGLE))
680 m = mangle(vol, mpath, outlen, upath, id, flags);
683 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
689 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
693 /* ------------------------- */
694 static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
700 struct adouble ad, *adp;
702 clen = (u_char)*ibuf++;
703 clen = min( clen, 199 );
705 upath = path->u_name;
706 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
707 return AFPERR_ACCESS;
710 isadir = path_isadir(path);
711 if (isadir || !(of = of_findname(path))) {
712 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
717 if (ad_open_metadata( upath , vol_noadouble(vol) | ( (isadir) ? ADFLAGS_DIR :0),O_CREAT, adp) < 0 ) {
718 return( AFPERR_ACCESS );
721 if (ad_getentryoff(adp, ADEID_COMMENT)) {
722 if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
723 if ( *path->m_name == '\0' ) {
724 name = curdir->d_m_name;
728 ad_setname(adp, name);
730 ad_setentrylen( adp, ADEID_COMMENT, clen );
731 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
734 ad_close_metadata( adp);
738 /* ----------------------------- */
739 int afp_addcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
750 memcpy( &vid, ibuf, sizeof( vid ));
751 ibuf += sizeof( vid );
752 if (NULL == ( vol = getvolbyvid( vid )) ) {
753 return( AFPERR_PARAM );
756 memcpy( &did, ibuf, sizeof( did ));
757 ibuf += sizeof( did );
758 if (NULL == ( dir = dirlookup( vol, did )) ) {
762 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
763 return get_afp_errno(AFPERR_NOOBJ);
766 if ((u_long)ibuf & 1 ) {
770 return ad_addcomment(vol, path, ibuf);
773 /* -------------------- */
774 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuflen)
776 struct adouble ad, *adp;
782 upath = path->u_name;
783 isadir = path_isadir(path);
784 if (isadir || !(of = of_findname(path))) {
785 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
790 if ( ad_metadata( upath,( isadir) ? ADFLAGS_DIR : 0, adp) < 0 ) {
791 return( AFPERR_NOITEM );
794 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
795 ad_close_metadata( adp );
796 return AFPERR_NOITEM;
799 * Make sure the AD file is not bogus.
801 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
802 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
803 ad_close_metadata( adp );
804 return( AFPERR_NOITEM );
807 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
809 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
811 ad_close_metadata( adp);
816 /* -------------------- */
817 int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
828 memcpy( &vid, ibuf, sizeof( vid ));
829 ibuf += sizeof( vid );
830 if (NULL == ( vol = getvolbyvid( vid )) ) {
831 return( AFPERR_PARAM );
834 memcpy( &did, ibuf, sizeof( did ));
835 ibuf += sizeof( did );
836 if (NULL == ( dir = dirlookup( vol, did )) ) {
840 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
841 return get_afp_errno(AFPERR_NOOBJ);
844 return ad_getcomment(vol, s_path, rbuf, rbuflen);
847 /* ----------------------- */
848 static int ad_rmvcomment(struct vol *vol, struct path *path)
850 struct adouble ad, *adp;
855 upath = path->u_name;
856 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
857 return AFPERR_ACCESS;
860 isadir = path_isadir(path);
861 if (isadir || !(of = of_findname(path))) {
862 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
867 if ( ad_open_metadata( upath, (isadir) ? ADFLAGS_DIR : 0, 0, adp) < 0 ) {
870 return( AFPERR_NOITEM );
872 return( AFPERR_ACCESS );
874 return( AFPERR_PARAM );
878 if (ad_getentryoff(adp, ADEID_COMMENT)) {
879 ad_setentrylen( adp, ADEID_COMMENT, 0 );
882 ad_close_metadata( adp);
886 /* ----------------------- */
887 int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
898 memcpy( &vid, ibuf, sizeof( vid ));
899 ibuf += sizeof( vid );
900 if (NULL == ( vol = getvolbyvid( vid )) ) {
901 return( AFPERR_PARAM );
904 memcpy( &did, ibuf, sizeof( did ));
905 ibuf += sizeof( did );
906 if (NULL == ( dir = dirlookup( vol, did )) ) {
910 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
911 return get_afp_errno(AFPERR_NOOBJ);
914 return ad_rmvcomment(vol, s_path);