2 * $Id: desktop.c,v 1.26.2.4.2.13 2004-05-04 15:38:24 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 u_char utag[] = { 0, 0, 0, 0 };
313 u_char ucreator[] = { 'U', 'N', 'I', 'X' };
314 u_char utype[] = { 'T', 'E', 'X', 'T' };
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))
691 m = mangle(vol, mpath, upath, id, flags);
694 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
700 m = mangle(vol, u, upath, id, 1);
704 /* ------------------------- */
705 static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
711 struct adouble ad, *adp;
713 clen = (u_char)*ibuf++;
714 clen = min( clen, 199 );
716 upath = path->u_name;
717 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
718 return AFPERR_ACCESS;
721 isadir = path_isadir(path);
722 if (isadir || !(of = of_findname(path))) {
723 ad_init(&ad, vol->v_adouble);
728 if (ad_open( upath , vol_noadouble(vol) |
729 (( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
730 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
731 return( AFPERR_ACCESS );
734 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
735 /* not defined, save nothing but return success */
739 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
740 if ( *path->m_name == '\0' ) {
741 name = curdir->d_m_name;
745 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 );
751 ad_close( adp, ADFLAGS_HF );
755 /* ----------------------------- */
756 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
759 int ibuflen, *rbuflen;
770 memcpy( &vid, ibuf, sizeof( vid ));
771 ibuf += sizeof( vid );
772 if (NULL == ( vol = getvolbyvid( vid )) ) {
773 return( AFPERR_PARAM );
776 memcpy( &did, ibuf, sizeof( did ));
777 ibuf += sizeof( did );
778 if (NULL == ( dir = dirlookup( vol, did )) ) {
782 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
783 return get_afp_errno(AFPERR_NOOBJ);
786 if ((u_long)ibuf & 1 ) {
790 return ad_addcomment(vol, path, ibuf);
793 /* -------------------- */
794 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, int *rbuflen)
796 struct adouble ad, *adp;
802 upath = path->u_name;
803 isadir = path_isadir(path);
804 if (isadir || !(of = of_findname(path))) {
805 ad_init(&ad, vol->v_adouble);
811 ( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
812 O_RDONLY, 0666, adp) < 0 ) {
813 return( AFPERR_NOITEM );
816 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
817 return AFPERR_NOITEM;
820 * Make sure the AD file is not bogus.
822 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
823 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
824 ad_close( adp, ADFLAGS_HF );
825 return( AFPERR_NOITEM );
828 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
829 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
830 ad_getentrylen( adp, ADEID_COMMENT ));
831 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
832 ad_close( adp, ADFLAGS_HF );
837 /* -------------------- */
838 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
841 int ibuflen, *rbuflen;
852 memcpy( &vid, ibuf, sizeof( vid ));
853 ibuf += sizeof( vid );
854 if (NULL == ( vol = getvolbyvid( vid )) ) {
855 return( AFPERR_PARAM );
858 memcpy( &did, ibuf, sizeof( did ));
859 ibuf += sizeof( did );
860 if (NULL == ( dir = dirlookup( vol, did )) ) {
864 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
865 return get_afp_errno(AFPERR_NOOBJ);
868 return ad_getcomment(vol, s_path, rbuf, rbuflen);
871 /* ----------------------- */
872 static int ad_rmvcomment(struct vol *vol, struct path *path)
874 struct adouble ad, *adp;
879 upath = path->u_name;
880 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
881 return AFPERR_ACCESS;
884 isadir = path_isadir(path);
885 if (isadir || !(of = of_findname(path))) {
886 ad_init(&ad, vol->v_adouble);
892 (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
893 O_RDWR, 0, adp) < 0 ) {
896 return( AFPERR_NOITEM );
898 return( AFPERR_ACCESS );
900 return( AFPERR_PARAM );
904 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
908 ad_setentrylen( adp, ADEID_COMMENT, 0 );
909 ad_flush( adp, ADFLAGS_HF );
910 ad_close( adp, ADFLAGS_HF );
914 /* ----------------------- */
915 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
918 int ibuflen, *rbuflen;
929 memcpy( &vid, ibuf, sizeof( vid ));
930 ibuf += sizeof( vid );
931 if (NULL == ( vol = getvolbyvid( vid )) ) {
932 return( AFPERR_PARAM );
935 memcpy( &did, ibuf, sizeof( did ));
936 ibuf += sizeof( did );
937 if (NULL == ( dir = dirlookup( vol, did )) ) {
941 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
942 return get_afp_errno(AFPERR_NOOBJ);
945 return ad_rmvcomment(vol, s_path);