2 * $Id: desktop.c,v 1.26.2.4.2.17 2004-10-06 19:48:40 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 /* not defined, save nothing but return success */
744 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
745 if ( *path->m_name == '\0' ) {
746 name = curdir->d_m_name;
750 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 );
756 ad_close( adp, ADFLAGS_HF );
760 /* ----------------------------- */
761 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
764 int ibuflen, *rbuflen;
775 memcpy( &vid, ibuf, sizeof( vid ));
776 ibuf += sizeof( vid );
777 if (NULL == ( vol = getvolbyvid( vid )) ) {
778 return( AFPERR_PARAM );
781 memcpy( &did, ibuf, sizeof( did ));
782 ibuf += sizeof( did );
783 if (NULL == ( dir = dirlookup( vol, did )) ) {
787 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
788 return get_afp_errno(AFPERR_NOOBJ);
791 if ((u_long)ibuf & 1 ) {
795 return ad_addcomment(vol, path, ibuf);
798 /* -------------------- */
799 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, int *rbuflen)
801 struct adouble ad, *adp;
807 upath = path->u_name;
808 isadir = path_isadir(path);
809 if (isadir || !(of = of_findname(path))) {
810 ad_init(&ad, vol->v_adouble);
815 if ( ad_metadata( upath,( isadir) ? ADFLAGS_DIR : 0, adp) < 0 ) {
816 return( AFPERR_NOITEM );
819 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
820 return AFPERR_NOITEM;
823 * Make sure the AD file is not bogus.
825 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
826 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
827 ad_close( adp, ADFLAGS_HF );
828 return( AFPERR_NOITEM );
831 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
832 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
833 ad_getentrylen( adp, ADEID_COMMENT ));
834 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
835 ad_close( adp, ADFLAGS_HF );
840 /* -------------------- */
841 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
844 int ibuflen, *rbuflen;
855 memcpy( &vid, ibuf, sizeof( vid ));
856 ibuf += sizeof( vid );
857 if (NULL == ( vol = getvolbyvid( vid )) ) {
858 return( AFPERR_PARAM );
861 memcpy( &did, ibuf, sizeof( did ));
862 ibuf += sizeof( did );
863 if (NULL == ( dir = dirlookup( vol, did )) ) {
867 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
868 return get_afp_errno(AFPERR_NOOBJ);
871 return ad_getcomment(vol, s_path, rbuf, rbuflen);
874 /* ----------------------- */
875 static int ad_rmvcomment(struct vol *vol, struct path *path)
877 struct adouble ad, *adp;
882 upath = path->u_name;
883 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
884 return AFPERR_ACCESS;
887 isadir = path_isadir(path);
888 if (isadir || !(of = of_findname(path))) {
889 ad_init(&ad, vol->v_adouble);
895 (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
896 O_RDWR, 0, adp) < 0 ) {
899 return( AFPERR_NOITEM );
901 return( AFPERR_ACCESS );
903 return( AFPERR_PARAM );
907 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
911 ad_setentrylen( adp, ADEID_COMMENT, 0 );
912 ad_flush( adp, ADFLAGS_HF );
913 ad_close( adp, ADFLAGS_HF );
917 /* ----------------------- */
918 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
921 int ibuflen, *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);