2 * $Id: desktop.c,v 1.26.2.4.2.18 2004-10-09 12:48:21 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, *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 )
67 int ibuflen, *rbuflen;
73 struct savedt si = { { 0, 0, 0, 0 }, -1, 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 )
84 char *dtf, *adt, *adts;
86 if ( si.sdt_fd != -1 ) {
87 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
88 si.sdt_vid == vol->v_vid ) {
95 dtf = icon_dtfile( vol, creator);
97 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
98 if ( errno == ENOENT && ( flags & O_CREAT )) {
99 if (( adts = strrchr( dtf, '/' )) == NULL ) {
103 if (( adt = strrchr( dtf, '/' )) == NULL ) {
107 (void) ad_mkdir( dtf, DIRBITS | 0777 );
109 (void) ad_mkdir( dtf, DIRBITS | 0777 );
112 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
113 LOG(log_error, logtype_afpd, "iconopen(%s): open: %s", dtf, strerror(errno) );
121 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
122 si.sdt_vid = vol->v_vid;
127 int afp_addicon(obj, ibuf, ibuflen, rbuf, rbuflen)
130 int ibuflen, *rbuflen;
134 struct iovec iov[ 2 ];
136 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
137 int itype, cc = AFP_OK, iovcnt = 0, buflen;
138 u_int32_t ftype, itag;
139 u_int16_t bsize, rsize, vid;
145 memcpy( &vid, ibuf, sizeof( vid ));
146 ibuf += sizeof( vid );
147 if (NULL == ( vol = getvolbyvid( vid )) ) {
152 memcpy( fcreator, ibuf, sizeof( fcreator ));
153 ibuf += sizeof( fcreator );
155 memcpy( &ftype, ibuf, sizeof( ftype ));
156 ibuf += sizeof( ftype );
158 itype = (unsigned char) *ibuf;
161 memcpy( &itag, ibuf, sizeof( itag ));
162 ibuf += sizeof( itag );
164 memcpy( &bsize, ibuf, sizeof( bsize ));
165 bsize = ntohs( bsize );
167 if ( si.sdt_fd != -1 ) {
168 (void)close( si.sdt_fd );
172 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
177 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
180 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
186 * Read icon elements until we find a match to replace, or
187 * we get to the end to insert.
190 memcpy( p, &itag, sizeof( itag ));
192 memcpy( p, &ftype, sizeof( ftype ));
193 p += sizeof( ftype );
196 bsize = htons( bsize );
197 memcpy( p, &bsize, sizeof( bsize ));
198 bsize = ntohs( bsize );
199 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
200 memcpy( &rsize, irh + 10, sizeof( rsize ));
201 rsize = ntohs( rsize );
203 * Is this our set of headers?
205 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
207 * Is the size correct?
209 if ( bsize != rsize )
214 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
215 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator),strerror(errno) );
221 * Some error occurred, return.
225 if (obj->proto == AFPPROTO_DSI) {
226 dsi_writeinit(obj->handle, rbuf, buflen);
227 dsi_writeflush(obj->handle);
232 switch (obj->proto) {
236 if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
237 return( AFPERR_PARAM );
240 if (obj->options.flags & OPTION_DEBUG) {
241 printf("(write) len: %d\n", buflen);
242 bprint(rbuf, buflen);
247 * We're at the end of the file, add the headers, etc. */
249 iov[ 0 ].iov_base = (caddr_t)imh;
250 iov[ 0 ].iov_len = sizeof( imh );
251 iov[ 1 ].iov_base = rbuf;
252 iov[ 1 ].iov_len = bsize;
257 * We found an icon to replace.
260 iov[ 0 ].iov_base = rbuf;
261 iov[ 0 ].iov_len = bsize;
265 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
266 LOG(log_error, logtype_afpd, "afp_addicon(%s): writev: %s", icon_dtfile(vol, fcreator), strerror(errno) );
267 return( AFPERR_PARAM );
270 #endif /* no afp/asp */
273 DSI *dsi = obj->handle;
275 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
277 /* add headers at end of file */
278 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
279 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
284 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
285 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
290 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
292 if ( obj->options.flags & OPTION_DEBUG ) {
293 printf("(write) command cont'd: %d\n", iovcnt);
294 bprint(rbuf, iovcnt);
297 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
298 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
312 static u_char utag[] = { 0, 0, 0, 0 };
313 static u_char ucreator[] = { 0, 0, 0, 0 };/* { 'U', 'N', 'I', 'X' };*/
314 static u_char utype[] = { 0, 0, 0, 0 };/* { 'T', 'E', 'X', 'T' };*/
315 static short usize = 256;
316 static u_char uicon[] = {
317 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
318 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
319 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
320 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
321 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
322 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
323 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
324 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
325 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
326 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
327 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
328 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
329 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
330 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
331 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
332 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
333 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
334 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
335 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
336 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
337 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
338 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
339 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
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,
351 int afp_geticoninfo(obj, ibuf, ibuflen, rbuf, rbuflen )
354 int ibuflen, *rbuflen;
357 u_char fcreator[ 4 ], ih[ 12 ];
358 u_int16_t vid, iindex, bsize;
363 memcpy( &vid, ibuf, sizeof( vid ));
364 ibuf += sizeof( vid );
365 if (NULL == ( vol = getvolbyvid( vid )) ) {
366 return( AFPERR_PARAM );
369 memcpy( fcreator, ibuf, sizeof( fcreator ));
370 ibuf += sizeof( fcreator );
371 memcpy( &iindex, ibuf, sizeof( iindex ));
372 iindex = ntohs( iindex );
374 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
376 return( AFPERR_NOITEM );
378 memcpy( ih, utag, sizeof( utag ));
379 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
380 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
381 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
382 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
384 memcpy( rbuf, ih, sizeof( ih ));
385 *rbuflen = sizeof( ih );
389 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
390 return( AFPERR_NOITEM );
393 if ( iindex < si.sdt_index ) {
394 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
395 return( AFPERR_PARAM );
401 * Position to the correct spot.
404 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
407 return( AFPERR_NOITEM );
409 memcpy( &bsize, ih + 10, sizeof( bsize ));
410 bsize = ntohs(bsize);
411 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
412 LOG(log_error, logtype_afpd, "afp_iconinfo(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
413 return( AFPERR_PARAM );
415 if ( si.sdt_index == iindex ) {
416 memcpy( rbuf, ih, sizeof( ih ));
417 *rbuflen = sizeof( ih );
425 int afp_geticon(obj, ibuf, ibuflen, rbuf, rbuflen )
428 int ibuflen, *rbuflen;
433 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
434 u_int16_t vid, bsize, rsize;
440 memcpy( &vid, ibuf, sizeof( vid ));
441 ibuf += sizeof( vid );
442 if (NULL == ( vol = getvolbyvid( vid )) ) {
443 return( AFPERR_PARAM );
446 memcpy( fcreator, ibuf, sizeof( fcreator ));
447 ibuf += sizeof( fcreator );
448 memcpy( ftype, ibuf, sizeof( ftype ));
449 ibuf += sizeof( ftype );
450 itype = (unsigned char) *ibuf++;
452 memcpy( &bsize, ibuf, sizeof( bsize ));
453 bsize = ntohs( bsize );
455 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
456 memcmp( ftype, utype, sizeof( utype )) == 0 &&
459 memcpy( rbuf, uicon, bsize);
464 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
465 return( AFPERR_NOITEM );
468 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
471 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno));
472 return( AFPERR_PARAM );
477 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
479 offset += sizeof(ih);
480 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
481 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
484 memcpy( &rsize, ih + 10, sizeof( rsize ));
485 rsize = ntohs( rsize );
486 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
487 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
488 return( AFPERR_PARAM );
494 LOG(log_error, logtype_afpd, "afp_geticon(%s): read: %s", icon_dtfile(vol, fcreator), strerror(errno));
495 return( AFPERR_PARAM );
499 return( AFPERR_NOITEM );
502 memcpy( &rsize, ih + 10, sizeof( rsize ));
503 rsize = ntohs( rsize );
504 #define min(a,b) ((a)<(b)?(a):(b))
505 rc = min( bsize, rsize );
507 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
508 DSI *dsi = obj->handle;
512 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
513 if (size < rc + offset) {
517 if ((*rbuflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
520 /* do to the streaming nature, we have to exit if we encounter
521 * a problem. much confusion results otherwise. */
522 while (*rbuflen > 0) {
524 if (!obj->options.flags & OPTION_DEBUG) {
525 if (sys_sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0) {
528 case EINVAL: /* there's no guarantee that all fs support sendfile */
537 buflen = read(si.sdt_fd, rbuf, *rbuflen);
542 if (obj->options.flags & OPTION_DEBUG) {
543 printf( "(read) reply: %d, %d\n", buflen, dsi->clientID);
544 bprint(rbuf, buflen);
547 /* dsi_read() also returns buffer size of next allocation */
548 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
560 LOG(log_info, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno));
562 obj->exit(EXITERR_SYS);
566 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
567 return( AFPERR_PARAM );
574 /* ---------------------- */
575 static char hexdig[] = "0123456789abcdef";
576 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
578 static char path[ MAXPATHLEN + 1];
582 strcpy( path, vol->v_path );
583 strcat( path, "/.AppleDesktop/" );
584 for ( p = path; *p != '\0'; p++ )
587 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
588 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
589 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
596 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
597 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
598 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
599 *p++ = hexdig[ creator[ i ] & 0x0f ];
610 /* ---------------------------
611 * mpath is only a filename
612 * did filename parent directory ID.
614 static char upath[ MAXPATHLEN + 1];
615 static char mpath[ MAXPATHLEN + 1];
617 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
624 if ( *mpath == '\0' ) {
628 /* set conversion flags */
629 if (!(vol->v_flags & AFPVOL_NOHEX))
630 flags |= CONV_ESCAPEHEX;
631 if (!(vol->v_flags & AFPVOL_USEDOTS))
632 flags |= CONV_ESCAPEDOTS;
634 if ((vol->v_casefold & AFPVOL_MTOUUPPER))
635 flags |= CONV_TOUPPER;
636 else if ((vol->v_casefold & AFPVOL_MTOULOWER))
637 flags |= CONV_TOLOWER;
639 m = demangle(vol, mpath, did);
650 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)) ) {
651 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
657 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
665 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
668 u_int16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX;
672 outlen = strlen(upath);
674 if (vol->v_casefold & AFPVOL_UTOMUPPER)
675 flags |= CONV_TOUPPER;
676 else if (vol->v_casefold & AFPVOL_UTOMLOWER)
677 flags |= CONV_TOLOWER;
681 /* convert charsets */
682 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)) ) {
683 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
688 if (!(flags & CONV_REQMANGLE))
696 m = mangle(vol, mpath, outlen, upath, id, flags);
699 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
705 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
709 /* ------------------------- */
710 static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
716 struct adouble ad, *adp;
718 clen = (u_char)*ibuf++;
719 clen = min( clen, 199 );
721 upath = path->u_name;
722 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
723 return AFPERR_ACCESS;
726 isadir = path_isadir(path);
727 if (isadir || !(of = of_findname(path))) {
728 ad_init(&ad, vol->v_adouble);
733 if (ad_open( upath , vol_noadouble(vol) |
734 (( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
735 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
736 return( AFPERR_ACCESS );
739 if (ad_getentryoff(adp, ADEID_COMMENT)) {
740 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
741 if ( *path->m_name == '\0' ) {
742 name = curdir->d_m_name;
746 ad_setname(adp, name);
748 ad_setentrylen( adp, ADEID_COMMENT, clen );
749 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
750 ad_flush( adp, ADFLAGS_HF );
752 ad_close( adp, ADFLAGS_HF );
756 /* ----------------------------- */
757 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
760 int ibuflen, *rbuflen;
771 memcpy( &vid, ibuf, sizeof( vid ));
772 ibuf += sizeof( vid );
773 if (NULL == ( vol = getvolbyvid( vid )) ) {
774 return( AFPERR_PARAM );
777 memcpy( &did, ibuf, sizeof( did ));
778 ibuf += sizeof( did );
779 if (NULL == ( dir = dirlookup( vol, did )) ) {
783 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
784 return get_afp_errno(AFPERR_NOOBJ);
787 if ((u_long)ibuf & 1 ) {
791 return ad_addcomment(vol, path, ibuf);
794 /* -------------------- */
795 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, int *rbuflen)
797 struct adouble ad, *adp;
803 upath = path->u_name;
804 isadir = path_isadir(path);
805 if (isadir || !(of = of_findname(path))) {
806 ad_init(&ad, vol->v_adouble);
811 if ( ad_metadata( upath,( isadir) ? ADFLAGS_DIR : 0, adp) < 0 ) {
812 return( AFPERR_NOITEM );
815 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
816 return AFPERR_NOITEM;
819 * Make sure the AD file is not bogus.
821 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
822 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
823 ad_close( adp, ADFLAGS_HF );
824 return( AFPERR_NOITEM );
827 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
828 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
829 ad_getentrylen( adp, ADEID_COMMENT ));
830 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
831 ad_close( adp, ADFLAGS_HF );
836 /* -------------------- */
837 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
840 int ibuflen, *rbuflen;
851 memcpy( &vid, ibuf, sizeof( vid ));
852 ibuf += sizeof( vid );
853 if (NULL == ( vol = getvolbyvid( vid )) ) {
854 return( AFPERR_PARAM );
857 memcpy( &did, ibuf, sizeof( did ));
858 ibuf += sizeof( did );
859 if (NULL == ( dir = dirlookup( vol, did )) ) {
863 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
864 return get_afp_errno(AFPERR_NOOBJ);
867 return ad_getcomment(vol, s_path, rbuf, rbuflen);
870 /* ----------------------- */
871 static int ad_rmvcomment(struct vol *vol, struct path *path)
873 struct adouble ad, *adp;
878 upath = path->u_name;
879 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
880 return AFPERR_ACCESS;
883 isadir = path_isadir(path);
884 if (isadir || !(of = of_findname(path))) {
885 ad_init(&ad, vol->v_adouble);
891 (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
892 O_RDWR, 0, adp) < 0 ) {
895 return( AFPERR_NOITEM );
897 return( AFPERR_ACCESS );
899 return( AFPERR_PARAM );
903 if (ad_getentryoff(adp, ADEID_COMMENT)) {
904 ad_setentrylen( adp, ADEID_COMMENT, 0 );
905 ad_flush( adp, ADFLAGS_HF );
907 ad_close( adp, ADFLAGS_HF );
911 /* ----------------------- */
912 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
915 int ibuflen, *rbuflen;
926 memcpy( &vid, ibuf, sizeof( vid ));
927 ibuf += sizeof( vid );
928 if (NULL == ( vol = getvolbyvid( vid )) ) {
929 return( AFPERR_PARAM );
932 memcpy( &did, ibuf, sizeof( did ));
933 ibuf += sizeof( did );
934 if (NULL == ( dir = dirlookup( vol, did )) ) {
938 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
939 return get_afp_errno(AFPERR_NOOBJ);
942 return ad_rmvcomment(vol, s_path);