5 * afp_XXXcomment are (the only) functions able to open
6 * a ressource fork when there's no data fork, eg after
7 * it was removed with samba.
12 #endif /* HAVE_CONFIG_H */
20 #include <atalk/adouble.h>
22 #include <sys/param.h>
23 #include <sys/socket.h>
24 #include <arpa/inet.h>
26 #include <atalk/dsi.h>
27 #include <atalk/afp.h>
28 #include <atalk/util.h>
29 #include <atalk/logger.h>
30 #include <atalk/globals.h>
31 #include <atalk/netatalk_conf.h>
32 #include <atalk/unix.h>
33 #include <atalk/bstrlib.h>
36 #include "directory.h"
41 static void create_appledesktop_folder(const struct vol * vol)
43 bstring olddtpath = NULL, dtpath = NULL;
47 olddtpath = bfromcstr(vol->v_path);
48 bcatcstr(olddtpath, "/" APPLEDESKTOP);
50 dtpath = bfromcstr(vol->v_dbpath);
51 bcatcstr(dtpath, "/" APPLEDESKTOP);
53 if (lstat(bdata(dtpath), &st) != 0) {
57 if (lstat(bdata(olddtpath), &st) == 0) {
59 cmd_argv[1] = bdata(olddtpath);
60 cmd_argv[2] = bdata(dtpath);
62 if (run_cmd("mv", cmd_argv) != 0) {
63 LOG(log_error, logtype_afpd, "moving .AppleDesktop from \"%s\" to \"%s\" failed",
64 bdata(olddtpath), bdata(dtpath));
65 mkdir(bdata(dtpath), 0777);
68 mkdir(bdata(dtpath), 0777);
78 int afp_opendt(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
85 memcpy( &vid, ibuf, sizeof(vid));
86 if (NULL == ( vol = getvolbyvid( vid )) ) {
88 return( AFPERR_PARAM );
91 create_appledesktop_folder(vol);
93 memcpy( rbuf, &vid, sizeof(vid));
94 *rbuflen = sizeof(vid);
98 int afp_closedt(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
104 static struct savedt si = { { 0, 0, 0, 0 }, -1, 0, 0 };
106 static char *icon_dtfile(struct vol *vol, u_char creator[ 4 ])
108 return dtfile( vol, creator, ".icon" );
111 static int iconopen(struct vol *vol, u_char creator[ 4 ], int flags, int mode)
113 char *dtf, *adt, *adts;
115 if ( si.sdt_fd != -1 ) {
116 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
117 si.sdt_vid == vol->v_vid ) {
124 dtf = icon_dtfile( vol, creator);
126 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
127 if ( errno == ENOENT && ( flags & O_CREAT )) {
128 if (( adts = strrchr( dtf, '/' )) == NULL ) {
132 if (( adt = strrchr( dtf, '/' )) == NULL ) {
136 (void) ad_mkdir( dtf, DIRBITS | 0777 );
138 (void) ad_mkdir( dtf, DIRBITS | 0777 );
141 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
142 LOG(log_error, logtype_afpd, "iconopen(%s): open: %s", dtf, strerror(errno) );
150 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
151 si.sdt_vid = vol->v_vid;
156 int afp_addicon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
159 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
160 int itype, cc = AFP_OK, iovcnt = 0;
162 uint32_t ftype, itag;
163 uint16_t bsize, rsize, vid;
169 memcpy( &vid, ibuf, sizeof( vid ));
170 ibuf += sizeof( vid );
171 if (NULL == ( vol = getvolbyvid( vid )) ) {
176 memcpy( fcreator, ibuf, sizeof( fcreator ));
177 ibuf += sizeof( fcreator );
179 memcpy( &ftype, ibuf, sizeof( ftype ));
180 ibuf += sizeof( ftype );
182 itype = (unsigned char) *ibuf;
185 memcpy( &itag, ibuf, sizeof( itag ));
186 ibuf += sizeof( itag );
188 memcpy( &bsize, ibuf, sizeof( bsize ));
189 bsize = ntohs( bsize );
191 if ( si.sdt_fd != -1 ) {
192 (void)close( si.sdt_fd );
196 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
201 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
204 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
210 * Read icon elements until we find a match to replace, or
211 * we get to the end to insert.
214 memcpy( p, &itag, sizeof( itag ));
216 memcpy( p, &ftype, sizeof( ftype ));
217 p += sizeof( ftype );
220 bsize = htons( bsize );
221 memcpy( p, &bsize, sizeof( bsize ));
222 bsize = ntohs( bsize );
223 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
224 memcpy( &rsize, irh + 10, sizeof( rsize ));
225 rsize = ntohs( rsize );
227 * Is this our set of headers?
229 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
231 * Is the size correct?
233 if ( bsize != rsize )
238 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
239 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator),strerror(errno) );
245 * Some error occurred, return.
249 dsi_writeinit(obj->dsi, rbuf, buflen);
250 dsi_writeflush(obj->dsi);
256 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
258 /* add headers at end of file */
259 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
260 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
265 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
266 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
271 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
272 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
273 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
284 static const u_char utag[] = { 0, 0, 0, 0 };
285 static const u_char ucreator[] = { 0, 0, 0, 0 };/* { 'U', 'N', 'I', 'X' };*/
286 static const u_char utype[] = { 0, 0, 0, 0 };/* { 'T', 'E', 'X', 'T' };*/
287 static const short usize = 256;
290 static const u_char uicon[] = {
291 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
292 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
293 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
294 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
295 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
296 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
297 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
298 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
299 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
300 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
301 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
302 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
303 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
304 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
305 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
306 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
307 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
308 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
309 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
310 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
311 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
312 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
313 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
314 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
315 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
316 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
317 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
318 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
319 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
320 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
321 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
322 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
326 int afp_geticoninfo(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
329 unsigned char fcreator[ 4 ], ih[ 12 ];
330 uint16_t vid, iindex, bsize;
335 memcpy( &vid, ibuf, sizeof( vid ));
336 ibuf += sizeof( vid );
337 if (NULL == ( vol = getvolbyvid( vid )) ) {
338 return( AFPERR_PARAM );
341 memcpy( fcreator, ibuf, sizeof( fcreator ));
342 ibuf += sizeof( fcreator );
343 memcpy( &iindex, ibuf, sizeof( iindex ));
344 iindex = ntohs( iindex );
346 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
348 return( AFPERR_NOITEM );
350 memcpy( ih, utag, sizeof( utag ));
351 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
352 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
353 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
354 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
356 memcpy( rbuf, ih, sizeof( ih ));
357 *rbuflen = sizeof( ih );
361 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
362 return( AFPERR_NOITEM );
365 if ( iindex < si.sdt_index ) {
366 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
367 return( AFPERR_PARAM );
373 * Position to the correct spot.
376 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
379 return( AFPERR_NOITEM );
381 memcpy( &bsize, ih + 10, sizeof( bsize ));
382 bsize = ntohs(bsize);
383 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
384 LOG(log_error, logtype_afpd, "afp_iconinfo(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
385 return( AFPERR_PARAM );
387 if ( si.sdt_index == iindex ) {
388 memcpy( rbuf, ih, sizeof( ih ));
389 *rbuflen = sizeof( ih );
397 int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
402 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
403 uint16_t vid, bsize, rsize;
409 memcpy( &vid, ibuf, sizeof( vid ));
410 ibuf += sizeof( vid );
411 if (NULL == ( vol = getvolbyvid( vid )) ) {
412 return( AFPERR_PARAM );
415 memcpy( fcreator, ibuf, sizeof( fcreator ));
416 ibuf += sizeof( fcreator );
417 memcpy( ftype, ibuf, sizeof( ftype ));
418 ibuf += sizeof( ftype );
419 itype = (unsigned char) *ibuf++;
421 memcpy( &bsize, ibuf, sizeof( bsize ));
422 bsize = ntohs( bsize );
425 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
426 memcmp( ftype, utype, sizeof( utype )) == 0 &&
429 memcpy( rbuf, uicon, bsize);
435 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
436 return( AFPERR_NOITEM );
439 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
442 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno));
443 return( AFPERR_PARAM );
448 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
450 offset += sizeof(ih);
451 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
452 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
455 memcpy( &rsize, ih + 10, sizeof( rsize ));
456 rsize = ntohs( rsize );
457 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
458 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
459 return( AFPERR_PARAM );
465 LOG(log_error, logtype_afpd, "afp_geticon(%s): read: %s", icon_dtfile(vol, fcreator), strerror(errno));
466 return( AFPERR_PARAM );
470 return( AFPERR_NOITEM );
473 memcpy( &rsize, ih + 10, sizeof( rsize ));
474 rsize = ntohs( rsize );
475 #define min(a,b) ((a)<(b)?(a):(b))
476 rc = min( bsize, rsize );
483 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
484 if (size < rc + offset) {
488 #ifndef WITH_SENDFILE
489 if ((buflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
494 /* do to the streaming nature, we have to exit if we encounter
495 * a problem. much confusion results otherwise. */
496 while (*rbuflen > 0) {
498 if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize, AFP_OK) < 0) {
501 case EINVAL: /* there's no guarantee that all fs support sendfile */
512 buflen = read(si.sdt_fd, rbuf, *rbuflen);
516 /* dsi_read() also returns buffer size of next allocation */
517 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
528 LOG(log_error, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno));
530 obj->exit(EXITERR_SYS);
534 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
535 return( AFPERR_PARAM );
542 /* ---------------------- */
543 static const char hexdig[] = "0123456789abcdef";
544 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
546 static char path[ MAXPATHLEN + 1];
550 strcpy( path, vol->v_dbpath );
551 strcat( path, "/" APPLEDESKTOP "/" );
552 for ( p = path; *p != '\0'; p++ )
555 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
556 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
557 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
564 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
565 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
566 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
567 *p++ = hexdig[ creator[ i ] & 0x0f ];
578 /* ---------------------------
579 * mpath is only a filename
580 * did filename parent directory ID.
583 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
585 static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
591 if ( *mpath == '\0' ) {
596 /* set conversion flags */
597 flags = vol->v_mtou_flags;
599 m = demangle(vol, mpath, did);
610 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)) ) {
611 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
616 LOG(log_debug9, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
624 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
626 static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
632 outlen = strlen(upath);
634 flags = vol->v_utom_flags;
638 /* convert charsets */
639 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)) ) {
640 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
644 flags = !!(flags & CONV_REQMANGLE);
649 m = mangle(vol, mpath, outlen, upath, id, flags);
652 LOG(log_debug9, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
658 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
662 /* ------------------------- */
663 static int ad_addcomment(const AFPObj *obj, struct vol *vol, struct path *path, char *ibuf)
669 struct adouble ad, *adp;
671 clen = (u_char)*ibuf++;
672 clen = min( clen, 199 );
674 upath = path->u_name;
675 if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
676 return AFPERR_ACCESS;
679 isadir = path_isadir(path);
680 if (isadir || !(of = of_findname(path))) {
686 if (ad_open(adp, upath,
687 ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0) | ADFLAGS_CREATE | ADFLAGS_RDWR,
689 return( AFPERR_ACCESS );
692 if (ad_getentryoff(adp, ADEID_COMMENT)) {
693 if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
694 if ( *path->m_name == '\0' ) {
695 name = (char *)curdir->d_m_name->data;
699 ad_setname(adp, name);
701 ad_setentrylen( adp, ADEID_COMMENT, clen );
702 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
705 ad_close(adp, ADFLAGS_HF);
709 /* ----------------------------- */
710 int afp_addcomment(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
721 memcpy( &vid, ibuf, sizeof( vid ));
722 ibuf += sizeof( vid );
723 if (NULL == ( vol = getvolbyvid( vid )) ) {
724 return( AFPERR_PARAM );
727 memcpy( &did, ibuf, sizeof( did ));
728 ibuf += sizeof( did );
729 if (NULL == ( dir = dirlookup( vol, did )) ) {
733 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
734 return get_afp_errno(AFPERR_NOOBJ);
737 if ((u_long)ibuf & 1 ) {
741 return ad_addcomment(obj, vol, path, ibuf);
744 /* -------------------- */
745 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuflen)
747 struct adouble ad, *adp;
753 upath = path->u_name;
754 isadir = path_isadir(path);
755 if (isadir || !(of = of_findname(path))) {
761 if ( ad_metadata( upath, ((isadir) ? ADFLAGS_DIR : 0), adp) < 0 ) {
762 return( AFPERR_NOITEM );
765 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
766 ad_close(adp, ADFLAGS_HF);
767 return AFPERR_NOITEM;
770 * Make sure the AD file is not bogus.
772 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
773 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
774 ad_close(adp, ADFLAGS_HF);
775 return( AFPERR_NOITEM );
778 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
780 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
782 ad_close(adp, ADFLAGS_HF);
787 /* -------------------- */
788 int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
799 memcpy( &vid, ibuf, sizeof( vid ));
800 ibuf += sizeof( vid );
801 if (NULL == ( vol = getvolbyvid( vid )) ) {
802 return( AFPERR_PARAM );
805 memcpy( &did, ibuf, sizeof( did ));
806 ibuf += sizeof( did );
807 if (NULL == ( dir = dirlookup( vol, did )) ) {
811 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
812 return get_afp_errno(AFPERR_NOOBJ);
815 return ad_getcomment(vol, s_path, rbuf, rbuflen);
818 /* ----------------------- */
819 static int ad_rmvcomment(const AFPObj *obj, struct vol *vol, struct path *path)
821 struct adouble ad, *adp;
826 upath = path->u_name;
827 if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
828 return AFPERR_ACCESS;
831 isadir = path_isadir(path);
832 if (isadir || !(of = of_findname(path))) {
838 if ( ad_open(adp, upath, ADFLAGS_HF | ADFLAGS_RDWR | ((isadir) ? ADFLAGS_DIR : 0)) < 0 ) {
841 return( AFPERR_NOITEM );
843 return( AFPERR_ACCESS );
845 return( AFPERR_PARAM );
849 if (ad_getentryoff(adp, ADEID_COMMENT)) {
850 ad_setentrylen( adp, ADEID_COMMENT, 0 );
853 ad_close(adp, ADFLAGS_HF);
857 /* ----------------------- */
858 int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
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 return ad_rmvcomment(obj, vol, s_path);