2 * $Id: desktop.c,v 1.26.2.4.2.7 2004-01-10 06:40:58 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 */
21 #endif /* HAVE_UNISTD_H */
24 #endif /* HAVE_FCNTL_H */
27 #include <sys/types.h>
30 #include <sys/param.h>
32 #include <sys/socket.h>
33 #include <netatalk/at.h>
34 #include <netatalk/endian.h>
35 #include <atalk/dsi.h>
36 #include <atalk/atp.h>
37 #include <atalk/asp.h>
38 #include <atalk/afp.h>
39 #include <atalk/adouble.h>
40 #include <atalk/util.h>
41 #include <atalk/logger.h>
43 #include "directory.h"
50 int afp_opendt(obj, ibuf, ibuflen, rbuf, rbuflen )
53 int ibuflen, *rbuflen;
60 memcpy( &vid, ibuf, sizeof(vid));
61 if (NULL == ( vol = getvolbyvid( vid )) ) {
63 return( AFPERR_PARAM );
66 memcpy( rbuf, &vid, sizeof(vid));
67 *rbuflen = sizeof(vid);
71 int afp_closedt(obj, ibuf, ibuflen, rbuf, rbuflen )
74 int ibuflen, *rbuflen;
80 struct savedt si = { { 0, 0, 0, 0 }, -1, 0 };
82 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 = dtfile( vol, creator, ".icon" );
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: open %s: %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, *rbuflen;
135 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: lseek: %s", 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: lseek: %s", strerror(errno) );
221 * Some error occurred, return.
225 LOG(log_error, logtype_afpd, "afp_addicon: %s", strerror(errno) );
226 if (obj->proto == AFPPROTO_DSI) {
227 dsi_writeinit(obj->handle, rbuf, buflen);
228 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: writev: %s", 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: write: %s", strerror(errno));
286 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
287 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", 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: write: %s", strerror(errno));
314 u_char utag[] = { 0, 0, 0, 0 };
315 u_char ucreator[] = { 'U', 'N', 'I', 'X' };
316 u_char utype[] = { 'T', 'E', 'X', 'T' };
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, *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: lseek: %s", 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, *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: lseek: %s", 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: lseek: %s", strerror(errno) );
490 return( AFPERR_PARAM );
496 LOG(log_error, logtype_afpd, "afp_geticon: read: %s", 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", strerror(errno));
568 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
569 return( AFPERR_PARAM );
576 /* ---------------------- */
577 static 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.
616 static char upath[ MAXPATHLEN + 1];
617 static char mpath[ MAXPATHLEN + 1];
619 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
626 if ( *mpath == '\0' ) {
630 /* set conversion flags */
631 if (!(vol->v_flags & AFPVOL_NOHEX))
632 flags |= CONV_ESCAPEHEX;
633 if (!(vol->v_flags & AFPVOL_USEDOTS))
634 flags |= CONV_ESCAPEDOTS;
636 if ((vol->v_casefold & AFPVOL_MTOUUPPER))
637 flags |= CONV_TOUPPER;
638 else if ((vol->v_casefold & AFPVOL_MTOULOWER))
639 flags |= CONV_TOLOWER;
641 m = demangle(vol, mpath, did);
652 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)) ) {
653 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
659 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
667 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
670 u_int16_t flags = CONV_IGNORE | CONV_UNESCAPEHEX;
674 outlen = strlen(upath);
676 if (vol->v_casefold & AFPVOL_UTOMUPPER)
677 flags |= CONV_TOUPPER;
678 else if (vol->v_casefold & AFPVOL_UTOMLOWER)
679 flags |= CONV_TOLOWER;
683 /* convert charsets */
684 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)) ) {
685 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
690 if (!(flags & CONV_REQMANGLE))
693 m = mangle(vol, mpath, upath, id, flags);
696 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
702 m = mangle(vol, u, upath, id, 1);
706 /* ----------------------------- */
707 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
710 int ibuflen, *rbuflen;
712 struct adouble ad, *adp;
726 memcpy( &vid, ibuf, sizeof( vid ));
727 ibuf += sizeof( vid );
728 if (NULL == ( vol = getvolbyvid( vid )) ) {
729 return( AFPERR_PARAM );
732 memcpy( &did, ibuf, sizeof( did ));
733 ibuf += sizeof( did );
734 if (NULL == ( dir = dirlookup( vol, did )) ) {
738 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
739 return get_afp_errno(AFPERR_NOOBJ);
742 if ((u_long)ibuf & 1 ) {
746 clen = (u_char)*ibuf++;
747 clen = min( clen, 199 );
749 upath = path->u_name;
750 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
751 return AFPERR_ACCESS;
754 isadir = path_isadir(path);
755 if (isadir || !(of = of_findname(path))) {
756 ad_init(&ad, vol->v_adouble);
761 if (ad_open( upath , vol_noadouble(vol) |
762 (( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
763 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
764 return( AFPERR_ACCESS );
767 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
768 if ( *path->m_name == '\0' ) {
769 name = curdir->d_m_name;
773 ad_setentrylen( adp, ADEID_NAME, strlen( name ));
774 memcpy( ad_entry( adp, ADEID_NAME ), name,
775 ad_getentrylen( adp, ADEID_NAME ));
778 ad_setentrylen( adp, ADEID_COMMENT, clen );
779 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
780 ad_flush( adp, ADFLAGS_HF );
781 ad_close( adp, ADFLAGS_HF );
785 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
788 int ibuflen, *rbuflen;
790 struct adouble ad, *adp;
803 memcpy( &vid, ibuf, sizeof( vid ));
804 ibuf += sizeof( vid );
805 if (NULL == ( vol = getvolbyvid( vid )) ) {
806 return( AFPERR_PARAM );
809 memcpy( &did, ibuf, sizeof( did ));
810 ibuf += sizeof( did );
811 if (NULL == ( dir = dirlookup( vol, did )) ) {
815 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
816 return get_afp_errno(AFPERR_NOOBJ);
819 upath = s_path->u_name;
820 isadir = path_isadir(s_path);
821 if (isadir || !(of = of_findname(s_path))) {
822 ad_init(&ad, vol->v_adouble);
827 ( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
828 O_RDONLY, 0666, adp) < 0 ) {
829 return( AFPERR_NOITEM );
833 * Make sure the AD file is not bogus.
835 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
836 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
837 ad_close( adp, ADFLAGS_HF );
838 return( AFPERR_NOITEM );
841 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
842 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
843 ad_getentrylen( adp, ADEID_COMMENT ));
844 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
845 ad_close( adp, ADFLAGS_HF );
847 /* return AFPERR_NOITEM if len == 0 ? */
851 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
854 int ibuflen, *rbuflen;
856 struct adouble ad, *adp;
869 memcpy( &vid, ibuf, sizeof( vid ));
870 ibuf += sizeof( vid );
871 if (NULL == ( vol = getvolbyvid( vid )) ) {
872 return( AFPERR_PARAM );
875 memcpy( &did, ibuf, sizeof( did ));
876 ibuf += sizeof( did );
877 if (NULL == ( dir = dirlookup( vol, did )) ) {
881 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
882 return get_afp_errno(AFPERR_NOOBJ);
885 upath = s_path->u_name;
886 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
887 return AFPERR_ACCESS;
890 isadir = path_isadir(s_path);
891 if (isadir || !(of = of_findname(s_path))) {
892 ad_init(&ad, vol->v_adouble);
898 (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
899 O_RDWR, 0, adp) < 0 ) {
902 return( AFPERR_NOITEM );
904 return( AFPERR_ACCESS );
906 return( AFPERR_PARAM );
910 ad_setentrylen( adp, ADEID_COMMENT, 0 );
911 ad_flush( adp, ADFLAGS_HF );
912 ad_close( adp, ADFLAGS_HF );