2 * $Id: desktop.c,v 1.31 2005-04-28 20:49:41 bfernhomberg 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 _U_, *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 )
66 char *ibuf _U_, *rbuf _U_;
67 int ibuflen _U_, *rbuflen;
73 struct savedt si = { { 0, 0, 0, 0 }, -1, 0, 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 )
86 char *dtf, *adt, *adts;
88 if ( si.sdt_fd != -1 ) {
89 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
90 si.sdt_vid == vol->v_vid ) {
97 dtf = icon_dtfile( vol, creator);
99 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
100 if ( errno == ENOENT && ( flags & O_CREAT )) {
101 if (( adts = strrchr( dtf, '/' )) == NULL ) {
105 if (( adt = strrchr( dtf, '/' )) == NULL ) {
109 (void) ad_mkdir( dtf, DIRBITS | 0777 );
111 (void) ad_mkdir( dtf, DIRBITS | 0777 );
114 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
115 LOG(log_error, logtype_afpd, "iconopen(%s): open: %s", dtf, strerror(errno) );
123 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
124 si.sdt_vid = vol->v_vid;
129 int afp_addicon(obj, ibuf, ibuflen, rbuf, rbuflen)
132 int ibuflen _U_, *rbuflen;
136 struct iovec iov[ 2 ];
138 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
139 int itype, cc = AFP_OK, iovcnt = 0, buflen;
140 u_int32_t ftype, itag;
141 u_int16_t bsize, rsize, vid;
147 memcpy( &vid, ibuf, sizeof( vid ));
148 ibuf += sizeof( vid );
149 if (NULL == ( vol = getvolbyvid( vid )) ) {
154 memcpy( fcreator, ibuf, sizeof( fcreator ));
155 ibuf += sizeof( fcreator );
157 memcpy( &ftype, ibuf, sizeof( ftype ));
158 ibuf += sizeof( ftype );
160 itype = (unsigned char) *ibuf;
163 memcpy( &itag, ibuf, sizeof( itag ));
164 ibuf += sizeof( itag );
166 memcpy( &bsize, ibuf, sizeof( bsize ));
167 bsize = ntohs( bsize );
169 if ( si.sdt_fd != -1 ) {
170 (void)close( si.sdt_fd );
174 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
179 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
182 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
188 * Read icon elements until we find a match to replace, or
189 * we get to the end to insert.
192 memcpy( p, &itag, sizeof( itag ));
194 memcpy( p, &ftype, sizeof( ftype ));
195 p += sizeof( ftype );
198 bsize = htons( bsize );
199 memcpy( p, &bsize, sizeof( bsize ));
200 bsize = ntohs( bsize );
201 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
202 memcpy( &rsize, irh + 10, sizeof( rsize ));
203 rsize = ntohs( rsize );
205 * Is this our set of headers?
207 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
209 * Is the size correct?
211 if ( bsize != rsize )
216 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
217 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator),strerror(errno) );
223 * Some error occurred, return.
227 if (obj->proto == AFPPROTO_DSI) {
228 dsi_writeinit(obj->handle, rbuf, buflen);
229 dsi_writeflush(obj->handle);
234 switch (obj->proto) {
238 if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
239 return( AFPERR_PARAM );
242 if (obj->options.flags & OPTION_DEBUG) {
243 printf("(write) len: %d\n", buflen);
244 bprint(rbuf, buflen);
249 * We're at the end of the file, add the headers, etc. */
251 iov[ 0 ].iov_base = (caddr_t)imh;
252 iov[ 0 ].iov_len = sizeof( imh );
253 iov[ 1 ].iov_base = rbuf;
254 iov[ 1 ].iov_len = bsize;
259 * We found an icon to replace.
262 iov[ 0 ].iov_base = rbuf;
263 iov[ 0 ].iov_len = bsize;
267 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
268 LOG(log_error, logtype_afpd, "afp_addicon(%s): writev: %s", icon_dtfile(vol, fcreator), strerror(errno) );
269 return( AFPERR_PARAM );
272 #endif /* no afp/asp */
275 DSI *dsi = obj->handle;
277 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
279 /* add headers at end of file */
280 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
281 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
286 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
287 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
292 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
294 if ( obj->options.flags & OPTION_DEBUG ) {
295 printf("(write) command cont'd: %d\n", iovcnt);
296 bprint(rbuf, iovcnt);
299 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
300 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
314 static const u_char utag[] = { 0, 0, 0, 0 };
315 static const u_char ucreator[] = { 0, 0, 0, 0 };/* { 'U', 'N', 'I', 'X' };*/
316 static const u_char utype[] = { 0, 0, 0, 0 };/* { 'T', 'E', 'X', 'T' };*/
317 static const short usize = 256;
318 static const u_char uicon[] = {
319 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
320 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
321 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
322 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
323 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
324 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
325 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
326 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
327 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
328 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
329 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
330 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
331 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
332 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
333 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
334 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
335 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
336 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
337 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
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,
349 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
350 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
353 int afp_geticoninfo(obj, ibuf, ibuflen, rbuf, rbuflen )
356 int ibuflen _U_, *rbuflen;
359 u_char fcreator[ 4 ], ih[ 12 ];
360 u_int16_t vid, iindex, bsize;
365 memcpy( &vid, ibuf, sizeof( vid ));
366 ibuf += sizeof( vid );
367 if (NULL == ( vol = getvolbyvid( vid )) ) {
368 return( AFPERR_PARAM );
371 memcpy( fcreator, ibuf, sizeof( fcreator ));
372 ibuf += sizeof( fcreator );
373 memcpy( &iindex, ibuf, sizeof( iindex ));
374 iindex = ntohs( iindex );
376 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
378 return( AFPERR_NOITEM );
380 memcpy( ih, utag, sizeof( utag ));
381 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
382 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
383 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
384 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
386 memcpy( rbuf, ih, sizeof( ih ));
387 *rbuflen = sizeof( ih );
391 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
392 return( AFPERR_NOITEM );
395 if ( iindex < si.sdt_index ) {
396 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
397 return( AFPERR_PARAM );
403 * Position to the correct spot.
406 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
409 return( AFPERR_NOITEM );
411 memcpy( &bsize, ih + 10, sizeof( bsize ));
412 bsize = ntohs(bsize);
413 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
414 LOG(log_error, logtype_afpd, "afp_iconinfo(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
415 return( AFPERR_PARAM );
417 if ( si.sdt_index == iindex ) {
418 memcpy( rbuf, ih, sizeof( ih ));
419 *rbuflen = sizeof( ih );
427 int afp_geticon(obj, ibuf, ibuflen, rbuf, rbuflen )
430 int ibuflen _U_, *rbuflen;
435 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
436 u_int16_t vid, bsize, rsize;
442 memcpy( &vid, ibuf, sizeof( vid ));
443 ibuf += sizeof( vid );
444 if (NULL == ( vol = getvolbyvid( vid )) ) {
445 return( AFPERR_PARAM );
448 memcpy( fcreator, ibuf, sizeof( fcreator ));
449 ibuf += sizeof( fcreator );
450 memcpy( ftype, ibuf, sizeof( ftype ));
451 ibuf += sizeof( ftype );
452 itype = (unsigned char) *ibuf++;
454 memcpy( &bsize, ibuf, sizeof( bsize ));
455 bsize = ntohs( bsize );
457 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
458 memcmp( ftype, utype, sizeof( utype )) == 0 &&
461 memcpy( rbuf, uicon, bsize);
466 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
467 return( AFPERR_NOITEM );
470 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
473 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno));
474 return( AFPERR_PARAM );
479 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
481 offset += sizeof(ih);
482 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
483 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
486 memcpy( &rsize, ih + 10, sizeof( rsize ));
487 rsize = ntohs( rsize );
488 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
489 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
490 return( AFPERR_PARAM );
496 LOG(log_error, logtype_afpd, "afp_geticon(%s): read: %s", icon_dtfile(vol, fcreator), strerror(errno));
497 return( AFPERR_PARAM );
501 return( AFPERR_NOITEM );
504 memcpy( &rsize, ih + 10, sizeof( rsize ));
505 rsize = ntohs( rsize );
506 #define min(a,b) ((a)<(b)?(a):(b))
507 rc = min( bsize, rsize );
509 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
510 DSI *dsi = obj->handle;
514 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
515 if (size < rc + offset) {
519 if ((*rbuflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
522 /* do to the streaming nature, we have to exit if we encounter
523 * a problem. much confusion results otherwise. */
524 while (*rbuflen > 0) {
526 if (!obj->options.flags & OPTION_DEBUG) {
527 if (sys_sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0) {
530 case EINVAL: /* there's no guarantee that all fs support sendfile */
539 buflen = read(si.sdt_fd, rbuf, *rbuflen);
544 if (obj->options.flags & OPTION_DEBUG) {
545 printf( "(read) reply: %d, %d\n", buflen, dsi->clientID);
546 bprint(rbuf, buflen);
549 /* dsi_read() also returns buffer size of next allocation */
550 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
562 LOG(log_info, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno));
564 obj->exit(EXITERR_SYS);
568 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
569 return( AFPERR_PARAM );
576 /* ---------------------- */
577 static const char hexdig[] = "0123456789abcdef";
578 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
580 static char path[ MAXPATHLEN + 1];
584 strcpy( path, vol->v_path );
585 strcat( path, "/.AppleDesktop/" );
586 for ( p = path; *p != '\0'; p++ )
589 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
590 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
591 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
598 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
599 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
600 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
601 *p++ = hexdig[ creator[ i ] & 0x0f ];
612 /* ---------------------------
613 * mpath is only a filename
614 * did filename parent directory ID.
617 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
619 static char upath[ MAXPATHLEN + 1];
625 if ( *mpath == '\0' ) {
629 /* set conversion flags */
630 if (!(vol->v_flags & AFPVOL_NOHEX))
631 flags |= CONV_ESCAPEHEX;
632 if (!(vol->v_flags & AFPVOL_USEDOTS))
633 flags |= CONV_ESCAPEDOTS;
635 if ((vol->v_casefold & AFPVOL_MTOUUPPER))
636 flags |= CONV_TOUPPER;
637 else if ((vol->v_casefold & AFPVOL_MTOULOWER))
638 flags |= CONV_TOLOWER;
640 if ((vol->v_flags & AFPVOL_EILSEQ)) {
641 flags |= CONV__EILSEQ;
644 m = demangle(vol, mpath, did);
655 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)) ) {
656 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
662 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
670 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
672 static char mpath[ MAXPATHLEN + 1];
674 u_int16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX;
678 outlen = strlen(upath);
680 if ((vol->v_casefold & AFPVOL_UTOMUPPER))
681 flags |= CONV_TOUPPER;
682 else if ((vol->v_casefold & AFPVOL_UTOMLOWER))
683 flags |= CONV_TOLOWER;
685 if ((vol->v_flags & AFPVOL_EILSEQ)) {
686 flags |= CONV__EILSEQ;
691 /* convert charsets */
692 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)) ) {
693 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
698 if (!(flags & CONV_REQMANGLE))
706 m = mangle(vol, mpath, outlen, upath, id, flags);
709 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
715 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
719 /* ------------------------- */
720 static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
726 struct adouble ad, *adp;
728 clen = (u_char)*ibuf++;
729 clen = min( clen, 199 );
731 upath = path->u_name;
732 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
733 return AFPERR_ACCESS;
736 isadir = path_isadir(path);
737 if (isadir || !(of = of_findname(path))) {
738 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
743 if (ad_open( upath , vol_noadouble(vol) |
744 (( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
745 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
746 return( AFPERR_ACCESS );
749 if (ad_getentryoff(adp, ADEID_COMMENT)) {
750 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
751 if ( *path->m_name == '\0' ) {
752 name = curdir->d_m_name;
756 ad_setname(adp, name);
758 ad_setentrylen( adp, ADEID_COMMENT, clen );
759 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
760 ad_flush( adp, ADFLAGS_HF );
762 ad_close( adp, ADFLAGS_HF );
766 /* ----------------------------- */
767 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
769 char *ibuf, *rbuf _U_;
770 int ibuflen _U_, *rbuflen;
781 memcpy( &vid, ibuf, sizeof( vid ));
782 ibuf += sizeof( vid );
783 if (NULL == ( vol = getvolbyvid( vid )) ) {
784 return( AFPERR_PARAM );
787 memcpy( &did, ibuf, sizeof( did ));
788 ibuf += sizeof( did );
789 if (NULL == ( dir = dirlookup( vol, did )) ) {
793 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
794 return get_afp_errno(AFPERR_NOOBJ);
797 if ((u_long)ibuf & 1 ) {
801 return ad_addcomment(vol, path, ibuf);
804 /* -------------------- */
805 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, int *rbuflen)
807 struct adouble ad, *adp;
813 upath = path->u_name;
814 isadir = path_isadir(path);
815 if (isadir || !(of = of_findname(path))) {
816 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
821 if ( ad_metadata( upath,( isadir) ? ADFLAGS_DIR : 0, adp) < 0 ) {
822 return( AFPERR_NOITEM );
825 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
826 return AFPERR_NOITEM;
829 * Make sure the AD file is not bogus.
831 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
832 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
833 ad_close( adp, ADFLAGS_HF );
834 return( AFPERR_NOITEM );
837 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
838 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
839 ad_getentrylen( adp, ADEID_COMMENT ));
840 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
841 ad_close( adp, ADFLAGS_HF );
846 /* -------------------- */
847 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
850 int ibuflen _U_, *rbuflen;
861 memcpy( &vid, ibuf, sizeof( vid ));
862 ibuf += sizeof( vid );
863 if (NULL == ( vol = getvolbyvid( vid )) ) {
864 return( AFPERR_PARAM );
867 memcpy( &did, ibuf, sizeof( did ));
868 ibuf += sizeof( did );
869 if (NULL == ( dir = dirlookup( vol, did )) ) {
873 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
874 return get_afp_errno(AFPERR_NOOBJ);
877 return ad_getcomment(vol, s_path, rbuf, rbuflen);
880 /* ----------------------- */
881 static int ad_rmvcomment(struct vol *vol, struct path *path)
883 struct adouble ad, *adp;
888 upath = path->u_name;
889 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
890 return AFPERR_ACCESS;
893 isadir = path_isadir(path);
894 if (isadir || !(of = of_findname(path))) {
895 ad_init(&ad, vol->v_adouble, vol->v_ad_options);
901 (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
902 O_RDWR, 0, adp) < 0 ) {
905 return( AFPERR_NOITEM );
907 return( AFPERR_ACCESS );
909 return( AFPERR_PARAM );
913 if (ad_getentryoff(adp, ADEID_COMMENT)) {
914 ad_setentrylen( adp, ADEID_COMMENT, 0 );
915 ad_flush( adp, ADFLAGS_HF );
917 ad_close( adp, ADFLAGS_HF );
921 /* ----------------------- */
922 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
924 char *ibuf, *rbuf _U_;
925 int ibuflen _U_, *rbuflen;
936 memcpy( &vid, ibuf, sizeof( vid ));
937 ibuf += sizeof( vid );
938 if (NULL == ( vol = getvolbyvid( vid )) ) {
939 return( AFPERR_PARAM );
942 memcpy( &did, ibuf, sizeof( did ));
943 ibuf += sizeof( did );
944 if (NULL == ( dir = dirlookup( vol, did )) ) {
948 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
949 return get_afp_errno(AFPERR_NOOBJ);
952 return ad_rmvcomment(vol, s_path);