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 if ((buflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
492 /* do to the streaming nature, we have to exit if we encounter
493 * a problem. much confusion results otherwise. */
494 while (*rbuflen > 0) {
496 if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize) < 0) {
499 case EINVAL: /* there's no guarantee that all fs support sendfile */
510 buflen = read(si.sdt_fd, rbuf, *rbuflen);
514 /* dsi_read() also returns buffer size of next allocation */
515 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
526 LOG(log_error, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno));
528 obj->exit(EXITERR_SYS);
532 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
533 return( AFPERR_PARAM );
540 /* ---------------------- */
541 static const char hexdig[] = "0123456789abcdef";
542 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
544 static char path[ MAXPATHLEN + 1];
548 strcpy( path, vol->v_dbpath );
549 strcat( path, "/" APPLEDESKTOP "/" );
550 for ( p = path; *p != '\0'; p++ )
553 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
554 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
555 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
562 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
563 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
564 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
565 *p++ = hexdig[ creator[ i ] & 0x0f ];
576 /* ---------------------------
577 * mpath is only a filename
578 * did filename parent directory ID.
581 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
583 static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
589 if ( *mpath == '\0' ) {
594 /* set conversion flags */
595 flags = vol->v_mtou_flags;
597 m = demangle(vol, mpath, did);
608 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)) ) {
609 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
614 LOG(log_debug9, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
622 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
624 static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
630 outlen = strlen(upath);
632 flags = vol->v_utom_flags;
636 /* convert charsets */
637 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)) ) {
638 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
642 flags = !!(flags & CONV_REQMANGLE);
647 m = mangle(vol, mpath, outlen, upath, id, flags);
650 LOG(log_debug9, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
656 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
660 /* ------------------------- */
661 static int ad_addcomment(const AFPObj *obj, struct vol *vol, struct path *path, char *ibuf)
667 struct adouble ad, *adp;
669 clen = (u_char)*ibuf++;
670 clen = min( clen, 199 );
672 upath = path->u_name;
673 if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
674 return AFPERR_ACCESS;
677 isadir = path_isadir(path);
678 if (isadir || !(of = of_findname(path))) {
684 if (ad_open(adp, upath,
685 ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0) | ADFLAGS_CREATE | ADFLAGS_RDWR,
687 return( AFPERR_ACCESS );
690 if (ad_getentryoff(adp, ADEID_COMMENT)) {
691 if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
692 if ( *path->m_name == '\0' ) {
693 name = (char *)curdir->d_m_name->data;
697 ad_setname(adp, name);
699 ad_setentrylen( adp, ADEID_COMMENT, clen );
700 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
703 ad_close(adp, ADFLAGS_HF);
707 /* ----------------------------- */
708 int afp_addcomment(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
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 return ad_addcomment(obj, vol, path, ibuf);
742 /* -------------------- */
743 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuflen)
745 struct adouble ad, *adp;
751 upath = path->u_name;
752 isadir = path_isadir(path);
753 if (isadir || !(of = of_findname(path))) {
759 if ( ad_metadata( upath, ((isadir) ? ADFLAGS_DIR : 0), adp) < 0 ) {
760 return( AFPERR_NOITEM );
763 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
764 ad_close(adp, ADFLAGS_HF);
765 return AFPERR_NOITEM;
768 * Make sure the AD file is not bogus.
770 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
771 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
772 ad_close(adp, ADFLAGS_HF);
773 return( AFPERR_NOITEM );
776 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
778 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
780 ad_close(adp, ADFLAGS_HF);
785 /* -------------------- */
786 int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
797 memcpy( &vid, ibuf, sizeof( vid ));
798 ibuf += sizeof( vid );
799 if (NULL == ( vol = getvolbyvid( vid )) ) {
800 return( AFPERR_PARAM );
803 memcpy( &did, ibuf, sizeof( did ));
804 ibuf += sizeof( did );
805 if (NULL == ( dir = dirlookup( vol, did )) ) {
809 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
810 return get_afp_errno(AFPERR_NOOBJ);
813 return ad_getcomment(vol, s_path, rbuf, rbuflen);
816 /* ----------------------- */
817 static int ad_rmvcomment(const AFPObj *obj, struct vol *vol, struct path *path)
819 struct adouble ad, *adp;
824 upath = path->u_name;
825 if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
826 return AFPERR_ACCESS;
829 isadir = path_isadir(path);
830 if (isadir || !(of = of_findname(path))) {
836 if ( ad_open(adp, upath, ADFLAGS_HF | ADFLAGS_RDWR | ((isadir) ? ADFLAGS_DIR : 0)) < 0 ) {
839 return( AFPERR_NOITEM );
841 return( AFPERR_ACCESS );
843 return( AFPERR_PARAM );
847 if (ad_getentryoff(adp, ADEID_COMMENT)) {
848 ad_setentrylen( adp, ADEID_COMMENT, 0 );
851 ad_close(adp, ADFLAGS_HF);
855 /* ----------------------- */
856 int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
867 memcpy( &vid, ibuf, sizeof( vid ));
868 ibuf += sizeof( vid );
869 if (NULL == ( vol = getvolbyvid( vid )) ) {
870 return( AFPERR_PARAM );
873 memcpy( &did, ibuf, sizeof( did ));
874 ibuf += sizeof( did );
875 if (NULL == ( dir = dirlookup( vol, did )) ) {
879 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
880 return get_afp_errno(AFPERR_NOOBJ);
883 return ad_rmvcomment(obj, vol, s_path);