2 * $Id: desktop.c,v 1.26.2.4.2.12 2004-03-11 23:01:40 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, *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 int iconopen( vol, creator, flags, mode )
79 char *dtf, *adt, *adts;
81 if ( si.sdt_fd != -1 ) {
82 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
83 si.sdt_vid == vol->v_vid ) {
90 dtf = dtfile( vol, creator, ".icon" );
92 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
93 if ( errno == ENOENT && ( flags & O_CREAT )) {
94 if (( adts = strrchr( dtf, '/' )) == NULL ) {
98 if (( adt = strrchr( dtf, '/' )) == NULL ) {
102 (void) ad_mkdir( dtf, DIRBITS | 0777 );
104 (void) ad_mkdir( dtf, DIRBITS | 0777 );
107 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
108 LOG(log_error, logtype_afpd, "iconopen: open %s: %s", dtf, strerror(errno) );
116 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
117 si.sdt_vid = vol->v_vid;
122 int afp_addicon(obj, ibuf, ibuflen, rbuf, rbuflen)
125 int ibuflen, *rbuflen;
128 struct iovec iov[ 2 ];
129 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
130 int itype, cc = AFP_OK, iovcnt = 0, buflen;
131 u_int32_t ftype, itag;
132 u_int16_t bsize, rsize, vid;
138 memcpy( &vid, ibuf, sizeof( vid ));
139 ibuf += sizeof( vid );
140 if (NULL == ( vol = getvolbyvid( vid )) ) {
145 memcpy( fcreator, ibuf, sizeof( fcreator ));
146 ibuf += sizeof( fcreator );
148 memcpy( &ftype, ibuf, sizeof( ftype ));
149 ibuf += sizeof( ftype );
151 itype = (unsigned char) *ibuf;
154 memcpy( &itag, ibuf, sizeof( itag ));
155 ibuf += sizeof( itag );
157 memcpy( &bsize, ibuf, sizeof( bsize ));
158 bsize = ntohs( bsize );
160 if ( si.sdt_fd != -1 ) {
161 (void)close( si.sdt_fd );
165 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
170 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
173 LOG(log_error, logtype_afpd, "afp_addicon: lseek: %s", strerror(errno) );
179 * Read icon elements until we find a match to replace, or
180 * we get to the end to insert.
183 memcpy( p, &itag, sizeof( itag ));
185 memcpy( p, &ftype, sizeof( ftype ));
186 p += sizeof( ftype );
189 bsize = htons( bsize );
190 memcpy( p, &bsize, sizeof( bsize ));
191 bsize = ntohs( bsize );
192 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
193 memcpy( &rsize, irh + 10, sizeof( rsize ));
194 rsize = ntohs( rsize );
196 * Is this our set of headers?
198 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
200 * Is the size correct?
202 if ( bsize != rsize )
207 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
208 LOG(log_error, logtype_afpd, "afp_addicon: lseek: %s", strerror(errno) );
214 * Some error occurred, return.
218 LOG(log_error, logtype_afpd, "afp_addicon: %s", strerror(errno) );
219 if (obj->proto == AFPPROTO_DSI) {
220 dsi_writeinit(obj->handle, rbuf, buflen);
221 dsi_writeflush(obj->handle);
227 switch (obj->proto) {
231 if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
232 return( AFPERR_PARAM );
235 if (obj->options.flags & OPTION_DEBUG) {
236 printf("(write) len: %d\n", buflen);
237 bprint(rbuf, buflen);
242 * We're at the end of the file, add the headers, etc. */
244 iov[ 0 ].iov_base = (caddr_t)imh;
245 iov[ 0 ].iov_len = sizeof( imh );
246 iov[ 1 ].iov_base = rbuf;
247 iov[ 1 ].iov_len = bsize;
252 * We found an icon to replace.
255 iov[ 0 ].iov_base = rbuf;
256 iov[ 0 ].iov_len = bsize;
260 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
261 LOG(log_error, logtype_afpd, "afp_addicon: writev: %s", strerror(errno) );
262 return( AFPERR_PARAM );
265 #endif /* no afp/asp */
268 DSI *dsi = obj->handle;
270 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
272 /* add headers at end of file */
273 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
274 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
279 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
280 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
285 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
287 if ( obj->options.flags & OPTION_DEBUG ) {
288 printf("(write) command cont'd: %d\n", iovcnt);
289 bprint(rbuf, iovcnt);
292 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
293 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
307 u_char utag[] = { 0, 0, 0, 0 };
308 u_char ucreator[] = { 'U', 'N', 'I', 'X' };
309 u_char utype[] = { 'T', 'E', 'X', 'T' };
312 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
313 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
314 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
315 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
316 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
317 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
318 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
319 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
320 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
321 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
322 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
323 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
324 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
325 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
326 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
327 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
328 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
329 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
330 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
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,
335 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
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,
346 int afp_geticoninfo(obj, ibuf, ibuflen, rbuf, rbuflen )
349 int ibuflen, *rbuflen;
352 u_char fcreator[ 4 ], ih[ 12 ];
353 u_int16_t vid, iindex, bsize;
358 memcpy( &vid, ibuf, sizeof( vid ));
359 ibuf += sizeof( vid );
360 if (NULL == ( vol = getvolbyvid( vid )) ) {
361 return( AFPERR_PARAM );
364 memcpy( fcreator, ibuf, sizeof( fcreator ));
365 ibuf += sizeof( fcreator );
366 memcpy( &iindex, ibuf, sizeof( iindex ));
367 iindex = ntohs( iindex );
369 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
371 return( AFPERR_NOITEM );
373 memcpy( ih, utag, sizeof( utag ));
374 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
375 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
376 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
377 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
379 memcpy( rbuf, ih, sizeof( ih ));
380 *rbuflen = sizeof( ih );
384 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
385 return( AFPERR_NOITEM );
388 if ( iindex < si.sdt_index ) {
389 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
390 return( AFPERR_PARAM );
396 * Position to the correct spot.
399 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
402 return( AFPERR_NOITEM );
404 memcpy( &bsize, ih + 10, sizeof( bsize ));
405 bsize = ntohs(bsize);
406 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
407 LOG(log_error, logtype_afpd, "afp_iconinfo: lseek: %s", strerror(errno) );
408 return( AFPERR_PARAM );
410 if ( si.sdt_index == iindex ) {
411 memcpy( rbuf, ih, sizeof( ih ));
412 *rbuflen = sizeof( ih );
420 int afp_geticon(obj, ibuf, ibuflen, rbuf, rbuflen )
423 int ibuflen, *rbuflen;
428 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
429 u_int16_t vid, bsize, rsize;
435 memcpy( &vid, ibuf, sizeof( vid ));
436 ibuf += sizeof( vid );
437 if (NULL == ( vol = getvolbyvid( vid )) ) {
438 return( AFPERR_PARAM );
441 memcpy( fcreator, ibuf, sizeof( fcreator ));
442 ibuf += sizeof( fcreator );
443 memcpy( ftype, ibuf, sizeof( ftype ));
444 ibuf += sizeof( ftype );
445 itype = (unsigned char) *ibuf++;
447 memcpy( &bsize, ibuf, sizeof( bsize ));
448 bsize = ntohs( bsize );
450 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
451 memcmp( ftype, utype, sizeof( utype )) == 0 &&
454 memcpy( rbuf, uicon, bsize);
459 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
460 return( AFPERR_NOITEM );
463 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
466 LOG(log_error, logtype_afpd, "afp_geticon: lseek: %s", strerror(errno));
467 return( AFPERR_PARAM );
472 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
474 offset += sizeof(ih);
475 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
476 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
479 memcpy( &rsize, ih + 10, sizeof( rsize ));
480 rsize = ntohs( rsize );
481 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
482 LOG(log_error, logtype_afpd, "afp_geticon: lseek: %s", strerror(errno) );
483 return( AFPERR_PARAM );
489 LOG(log_error, logtype_afpd, "afp_geticon: read: %s", strerror(errno));
490 return( AFPERR_PARAM );
494 return( AFPERR_NOITEM );
497 memcpy( &rsize, ih + 10, sizeof( rsize ));
498 rsize = ntohs( rsize );
499 #define min(a,b) ((a)<(b)?(a):(b))
500 rc = min( bsize, rsize );
502 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
503 DSI *dsi = obj->handle;
507 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
508 if (size < rc + offset) {
512 if ((*rbuflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
515 /* do to the streaming nature, we have to exit if we encounter
516 * a problem. much confusion results otherwise. */
517 while (*rbuflen > 0) {
519 if (!obj->options.flags & OPTION_DEBUG) {
520 if (sys_sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0) {
523 case EINVAL: /* there's no guarantee that all fs support sendfile */
532 buflen = read(si.sdt_fd, rbuf, *rbuflen);
537 if (obj->options.flags & OPTION_DEBUG) {
538 printf( "(read) reply: %d, %d\n", buflen, dsi->clientID);
539 bprint(rbuf, buflen);
542 /* dsi_read() also returns buffer size of next allocation */
543 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
555 LOG(log_info, logtype_afpd, "afp_geticon: %s", strerror(errno));
561 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
562 return( AFPERR_PARAM );
569 /* ---------------------- */
570 static char hexdig[] = "0123456789abcdef";
571 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
573 static char path[ MAXPATHLEN + 1];
577 strcpy( path, vol->v_path );
578 strcat( path, "/.AppleDesktop/" );
579 for ( p = path; *p != '\0'; p++ )
582 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
583 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
584 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
591 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
592 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
593 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
594 *p++ = hexdig[ creator[ i ] & 0x0f ];
605 /* ---------------------------
606 * mpath is only a filename
607 * did filename parent directory ID.
609 static char upath[ MAXPATHLEN + 1];
610 static char mpath[ MAXPATHLEN + 1];
612 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
619 if ( *mpath == '\0' ) {
623 /* set conversion flags */
624 if (!(vol->v_flags & AFPVOL_NOHEX))
625 flags |= CONV_ESCAPEHEX;
626 if (!(vol->v_flags & AFPVOL_USEDOTS))
627 flags |= CONV_ESCAPEDOTS;
629 if ((vol->v_casefold & AFPVOL_MTOUUPPER))
630 flags |= CONV_TOUPPER;
631 else if ((vol->v_casefold & AFPVOL_MTOULOWER))
632 flags |= CONV_TOLOWER;
634 m = demangle(vol, mpath, did);
645 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)) ) {
646 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
652 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
660 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
663 u_int16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX;
667 outlen = strlen(upath);
669 if (vol->v_casefold & AFPVOL_UTOMUPPER)
670 flags |= CONV_TOUPPER;
671 else if (vol->v_casefold & AFPVOL_UTOMLOWER)
672 flags |= CONV_TOLOWER;
676 /* convert charsets */
677 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)) ) {
678 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
683 if (!(flags & CONV_REQMANGLE))
686 m = mangle(vol, mpath, upath, id, flags);
689 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
695 m = mangle(vol, u, upath, id, 1);
699 /* ------------------------- */
700 static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf)
706 struct adouble ad, *adp;
708 clen = (u_char)*ibuf++;
709 clen = min( clen, 199 );
711 upath = path->u_name;
712 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
713 return AFPERR_ACCESS;
716 isadir = path_isadir(path);
717 if (isadir || !(of = of_findname(path))) {
718 ad_init(&ad, vol->v_adouble);
723 if (ad_open( upath , vol_noadouble(vol) |
724 (( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
725 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
726 return( AFPERR_ACCESS );
729 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
730 /* not defined, save nothing but return success */
734 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
735 if ( *path->m_name == '\0' ) {
736 name = curdir->d_m_name;
740 ad_setname(adp, name);
743 ad_setentrylen( adp, ADEID_COMMENT, clen );
744 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
745 ad_flush( adp, ADFLAGS_HF );
746 ad_close( adp, ADFLAGS_HF );
750 /* ----------------------------- */
751 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
754 int ibuflen, *rbuflen;
765 memcpy( &vid, ibuf, sizeof( vid ));
766 ibuf += sizeof( vid );
767 if (NULL == ( vol = getvolbyvid( vid )) ) {
768 return( AFPERR_PARAM );
771 memcpy( &did, ibuf, sizeof( did ));
772 ibuf += sizeof( did );
773 if (NULL == ( dir = dirlookup( vol, did )) ) {
777 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
778 return get_afp_errno(AFPERR_NOOBJ);
781 if ((u_long)ibuf & 1 ) {
785 return ad_addcomment(vol, path, ibuf);
788 /* -------------------- */
789 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, int *rbuflen)
791 struct adouble ad, *adp;
797 upath = path->u_name;
798 isadir = path_isadir(path);
799 if (isadir || !(of = of_findname(path))) {
800 ad_init(&ad, vol->v_adouble);
806 ( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
807 O_RDONLY, 0666, adp) < 0 ) {
808 return( AFPERR_NOITEM );
811 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
812 return AFPERR_NOITEM;
815 * Make sure the AD file is not bogus.
817 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
818 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
819 ad_close( adp, ADFLAGS_HF );
820 return( AFPERR_NOITEM );
823 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
824 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
825 ad_getentrylen( adp, ADEID_COMMENT ));
826 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
827 ad_close( adp, ADFLAGS_HF );
832 /* -------------------- */
833 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
836 int ibuflen, *rbuflen;
847 memcpy( &vid, ibuf, sizeof( vid ));
848 ibuf += sizeof( vid );
849 if (NULL == ( vol = getvolbyvid( vid )) ) {
850 return( AFPERR_PARAM );
853 memcpy( &did, ibuf, sizeof( did ));
854 ibuf += sizeof( did );
855 if (NULL == ( dir = dirlookup( vol, did )) ) {
859 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
860 return get_afp_errno(AFPERR_NOOBJ);
863 return ad_getcomment(vol, s_path, rbuf, rbuflen);
866 /* ----------------------- */
867 static int ad_rmvcomment(struct vol *vol, struct path *path)
869 struct adouble ad, *adp;
874 upath = path->u_name;
875 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
876 return AFPERR_ACCESS;
879 isadir = path_isadir(path);
880 if (isadir || !(of = of_findname(path))) {
881 ad_init(&ad, vol->v_adouble);
887 (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
888 O_RDWR, 0, adp) < 0 ) {
891 return( AFPERR_NOITEM );
893 return( AFPERR_ACCESS );
895 return( AFPERR_PARAM );
899 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
903 ad_setentrylen( adp, ADEID_COMMENT, 0 );
904 ad_flush( adp, ADFLAGS_HF );
905 ad_close( adp, ADFLAGS_HF );
909 /* ----------------------- */
910 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
913 int ibuflen, *rbuflen;
924 memcpy( &vid, ibuf, sizeof( vid ));
925 ibuf += sizeof( vid );
926 if (NULL == ( vol = getvolbyvid( vid )) ) {
927 return( AFPERR_PARAM );
930 memcpy( &did, ibuf, sizeof( did ));
931 ibuf += sizeof( did );
932 if (NULL == ( dir = dirlookup( vol, did )) ) {
936 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
937 return get_afp_errno(AFPERR_NOOBJ);
940 return ad_rmvcomment(vol, s_path);