2 * $Id: desktop.c,v 1.26.2.4.2.9 2004-03-04 23:57:14 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 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
703 int ibuflen, *rbuflen;
705 struct adouble ad, *adp;
719 memcpy( &vid, ibuf, sizeof( vid ));
720 ibuf += sizeof( vid );
721 if (NULL == ( vol = getvolbyvid( vid )) ) {
722 return( AFPERR_PARAM );
725 memcpy( &did, ibuf, sizeof( did ));
726 ibuf += sizeof( did );
727 if (NULL == ( dir = dirlookup( vol, did )) ) {
731 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
732 return get_afp_errno(AFPERR_NOOBJ);
735 if ((u_long)ibuf & 1 ) {
739 clen = (u_char)*ibuf++;
740 clen = min( clen, 199 );
742 upath = path->u_name;
743 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
744 return AFPERR_ACCESS;
747 isadir = path_isadir(path);
748 if (isadir || !(of = of_findname(path))) {
749 ad_init(&ad, vol->v_adouble);
754 if (ad_open( upath , vol_noadouble(vol) |
755 (( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
756 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
757 return( AFPERR_ACCESS );
760 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
761 if ( *path->m_name == '\0' ) {
762 name = curdir->d_m_name;
766 ad_setentrylen( adp, ADEID_NAME, strlen( name ));
767 memcpy( ad_entry( adp, ADEID_NAME ), name,
768 ad_getentrylen( adp, ADEID_NAME ));
771 ad_setentrylen( adp, ADEID_COMMENT, clen );
772 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
773 ad_flush( adp, ADFLAGS_HF );
774 ad_close( adp, ADFLAGS_HF );
778 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
781 int ibuflen, *rbuflen;
783 struct adouble ad, *adp;
796 memcpy( &vid, ibuf, sizeof( vid ));
797 ibuf += sizeof( vid );
798 if (NULL == ( vol = getvolbyvid( vid )) ) {
799 return( AFPERR_PARAM );
802 memcpy( &did, ibuf, sizeof( did ));
803 ibuf += sizeof( did );
804 if (NULL == ( dir = dirlookup( vol, did )) ) {
808 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
809 return get_afp_errno(AFPERR_NOOBJ);
812 upath = s_path->u_name;
813 isadir = path_isadir(s_path);
814 if (isadir || !(of = of_findname(s_path))) {
815 ad_init(&ad, vol->v_adouble);
820 ( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
821 O_RDONLY, 0666, adp) < 0 ) {
822 return( AFPERR_NOITEM );
826 * Make sure the AD file is not bogus.
828 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
829 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
830 ad_close( adp, ADFLAGS_HF );
831 return( AFPERR_NOITEM );
834 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
835 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
836 ad_getentrylen( adp, ADEID_COMMENT ));
837 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
838 ad_close( adp, ADFLAGS_HF );
840 /* return AFPERR_NOITEM if len == 0 ? */
844 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
847 int ibuflen, *rbuflen;
849 struct adouble ad, *adp;
862 memcpy( &vid, ibuf, sizeof( vid ));
863 ibuf += sizeof( vid );
864 if (NULL == ( vol = getvolbyvid( vid )) ) {
865 return( AFPERR_PARAM );
868 memcpy( &did, ibuf, sizeof( did ));
869 ibuf += sizeof( did );
870 if (NULL == ( dir = dirlookup( vol, did )) ) {
874 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
875 return get_afp_errno(AFPERR_NOOBJ);
878 upath = s_path->u_name;
879 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
880 return AFPERR_ACCESS;
883 isadir = path_isadir(s_path);
884 if (isadir || !(of = of_findname(s_path))) {
885 ad_init(&ad, vol->v_adouble);
891 (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
892 O_RDWR, 0, adp) < 0 ) {
895 return( AFPERR_NOITEM );
897 return( AFPERR_ACCESS );
899 return( AFPERR_PARAM );
903 ad_setentrylen( adp, ADEID_COMMENT, 0 );
904 ad_flush( adp, ADFLAGS_HF );
905 ad_close( adp, ADFLAGS_HF );