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>
35 #include "directory.h"
40 typedef struct _special_folder {
47 static const _special_folder special_folders[] = {
48 {".AppleDesktop", 1, 0777, 0},
53 * this is only intended for folders in the volume root
54 * It will *not* work if the folder name contains extended characters
56 static int create_special_folder (const struct vol *vol, const struct _special_folder *folder)
65 p = (char *) malloc ( strlen(vol->v_path)+strlen(folder->name)+2);
67 LOG(log_error, logtype_afpd,"malloc failed");
71 q=strdup(folder->name);
73 LOG(log_error, logtype_afpd,"malloc failed");
77 strcpy(p, vol->v_path);
82 if ((vol->v_casefold & AFPVOL_MTOUUPPER))
84 else if ((vol->v_casefold & AFPVOL_MTOULOWER))
90 if ( (ret = stat( p, &st )) < 0 ) {
91 if (folder->precreate) {
92 if (ad_mkdir(p, folder->mode)) {
93 LOG(log_debug, logtype_afpd,"Creating '%s' failed in %s: %s", p, vol->v_path, strerror(errno));
102 if ( !ret && folder->hide) {
105 if (ad_open(&ad, p, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0) {
111 ad_setname(&ad, folder->name);
113 ad_getattr(&ad, &attr);
114 attr |= htons( ntohs( attr ) | ATTRBIT_INVISIBLE );
115 ad_setattr(&ad, attr);
117 /* do the same with the finder info */
118 if (ad_entry(&ad, ADEID_FINDERI)) {
119 memcpy(&attr, ad_entry(&ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, sizeof(attr));
120 attr |= htons(FINDERINFO_INVISIBLE);
121 memcpy(ad_entry(&ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF,&attr, sizeof(attr));
125 ad_close(&ad, ADFLAGS_HF);
132 static void create_appledesktop_folder(const struct vol * vol)
134 const _special_folder *p = &special_folders[0];
138 for (; p->name != NULL; p++) {
139 create_special_folder (vol, p);
145 int afp_opendt(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
152 memcpy( &vid, ibuf, sizeof(vid));
153 if (NULL == ( vol = getvolbyvid( vid )) ) {
155 return( AFPERR_PARAM );
158 create_appledesktop_folder(vol);
160 memcpy( rbuf, &vid, sizeof(vid));
161 *rbuflen = sizeof(vid);
165 int afp_closedt(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
171 static struct savedt si = { { 0, 0, 0, 0 }, -1, 0, 0 };
173 static char *icon_dtfile(struct vol *vol, u_char creator[ 4 ])
175 return dtfile( vol, creator, ".icon" );
178 static int iconopen(struct vol *vol, u_char creator[ 4 ], int flags, int mode)
180 char *dtf, *adt, *adts;
182 if ( si.sdt_fd != -1 ) {
183 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
184 si.sdt_vid == vol->v_vid ) {
191 dtf = icon_dtfile( vol, creator);
193 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
194 if ( errno == ENOENT && ( flags & O_CREAT )) {
195 if (( adts = strrchr( dtf, '/' )) == NULL ) {
199 if (( adt = strrchr( dtf, '/' )) == NULL ) {
203 (void) ad_mkdir( dtf, DIRBITS | 0777 );
205 (void) ad_mkdir( dtf, DIRBITS | 0777 );
208 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
209 LOG(log_error, logtype_afpd, "iconopen(%s): open: %s", dtf, strerror(errno) );
217 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
218 si.sdt_vid = vol->v_vid;
223 int afp_addicon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
226 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
227 int itype, cc = AFP_OK, iovcnt = 0;
229 uint32_t ftype, itag;
230 uint16_t bsize, rsize, vid;
236 memcpy( &vid, ibuf, sizeof( vid ));
237 ibuf += sizeof( vid );
238 if (NULL == ( vol = getvolbyvid( vid )) ) {
243 memcpy( fcreator, ibuf, sizeof( fcreator ));
244 ibuf += sizeof( fcreator );
246 memcpy( &ftype, ibuf, sizeof( ftype ));
247 ibuf += sizeof( ftype );
249 itype = (unsigned char) *ibuf;
252 memcpy( &itag, ibuf, sizeof( itag ));
253 ibuf += sizeof( itag );
255 memcpy( &bsize, ibuf, sizeof( bsize ));
256 bsize = ntohs( bsize );
258 if ( si.sdt_fd != -1 ) {
259 (void)close( si.sdt_fd );
263 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
268 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
271 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
277 * Read icon elements until we find a match to replace, or
278 * we get to the end to insert.
281 memcpy( p, &itag, sizeof( itag ));
283 memcpy( p, &ftype, sizeof( ftype ));
284 p += sizeof( ftype );
287 bsize = htons( bsize );
288 memcpy( p, &bsize, sizeof( bsize ));
289 bsize = ntohs( bsize );
290 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
291 memcpy( &rsize, irh + 10, sizeof( rsize ));
292 rsize = ntohs( rsize );
294 * Is this our set of headers?
296 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
298 * Is the size correct?
300 if ( bsize != rsize )
305 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
306 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator),strerror(errno) );
312 * Some error occurred, return.
316 dsi_writeinit(obj->dsi, rbuf, buflen);
317 dsi_writeflush(obj->dsi);
323 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
325 /* add headers at end of file */
326 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
327 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
332 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
333 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
338 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
339 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
340 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
351 static const u_char utag[] = { 0, 0, 0, 0 };
352 static const u_char ucreator[] = { 0, 0, 0, 0 };/* { 'U', 'N', 'I', 'X' };*/
353 static const u_char utype[] = { 0, 0, 0, 0 };/* { 'T', 'E', 'X', 'T' };*/
354 static const short usize = 256;
357 static const u_char uicon[] = {
358 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
359 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
360 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
361 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
362 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
363 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
364 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
365 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
366 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
367 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
368 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
369 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
370 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
371 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
372 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
373 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
374 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
375 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
376 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
377 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
378 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
379 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
380 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
381 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
382 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
383 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
384 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
385 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
386 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
387 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
388 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
389 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
393 int afp_geticoninfo(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
396 unsigned char fcreator[ 4 ], ih[ 12 ];
397 uint16_t vid, iindex, bsize;
402 memcpy( &vid, ibuf, sizeof( vid ));
403 ibuf += sizeof( vid );
404 if (NULL == ( vol = getvolbyvid( vid )) ) {
405 return( AFPERR_PARAM );
408 memcpy( fcreator, ibuf, sizeof( fcreator ));
409 ibuf += sizeof( fcreator );
410 memcpy( &iindex, ibuf, sizeof( iindex ));
411 iindex = ntohs( iindex );
413 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
415 return( AFPERR_NOITEM );
417 memcpy( ih, utag, sizeof( utag ));
418 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
419 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
420 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
421 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
423 memcpy( rbuf, ih, sizeof( ih ));
424 *rbuflen = sizeof( ih );
428 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
429 return( AFPERR_NOITEM );
432 if ( iindex < si.sdt_index ) {
433 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
434 return( AFPERR_PARAM );
440 * Position to the correct spot.
443 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
446 return( AFPERR_NOITEM );
448 memcpy( &bsize, ih + 10, sizeof( bsize ));
449 bsize = ntohs(bsize);
450 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
451 LOG(log_error, logtype_afpd, "afp_iconinfo(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
452 return( AFPERR_PARAM );
454 if ( si.sdt_index == iindex ) {
455 memcpy( rbuf, ih, sizeof( ih ));
456 *rbuflen = sizeof( ih );
464 int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
469 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
470 uint16_t vid, bsize, rsize;
476 memcpy( &vid, ibuf, sizeof( vid ));
477 ibuf += sizeof( vid );
478 if (NULL == ( vol = getvolbyvid( vid )) ) {
479 return( AFPERR_PARAM );
482 memcpy( fcreator, ibuf, sizeof( fcreator ));
483 ibuf += sizeof( fcreator );
484 memcpy( ftype, ibuf, sizeof( ftype ));
485 ibuf += sizeof( ftype );
486 itype = (unsigned char) *ibuf++;
488 memcpy( &bsize, ibuf, sizeof( bsize ));
489 bsize = ntohs( bsize );
492 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
493 memcmp( ftype, utype, sizeof( utype )) == 0 &&
496 memcpy( rbuf, uicon, bsize);
502 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
503 return( AFPERR_NOITEM );
506 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
509 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno));
510 return( AFPERR_PARAM );
515 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
517 offset += sizeof(ih);
518 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
519 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
522 memcpy( &rsize, ih + 10, sizeof( rsize ));
523 rsize = ntohs( rsize );
524 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
525 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
526 return( AFPERR_PARAM );
532 LOG(log_error, logtype_afpd, "afp_geticon(%s): read: %s", icon_dtfile(vol, fcreator), strerror(errno));
533 return( AFPERR_PARAM );
537 return( AFPERR_NOITEM );
540 memcpy( &rsize, ih + 10, sizeof( rsize ));
541 rsize = ntohs( rsize );
542 #define min(a,b) ((a)<(b)?(a):(b))
543 rc = min( bsize, rsize );
550 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
551 if (size < rc + offset) {
555 if ((buflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
559 /* do to the streaming nature, we have to exit if we encounter
560 * a problem. much confusion results otherwise. */
561 while (*rbuflen > 0) {
563 if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize) < 0) {
566 case EINVAL: /* there's no guarantee that all fs support sendfile */
577 buflen = read(si.sdt_fd, rbuf, *rbuflen);
581 /* dsi_read() also returns buffer size of next allocation */
582 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
593 LOG(log_error, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno));
595 obj->exit(EXITERR_SYS);
599 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
600 return( AFPERR_PARAM );
607 /* ---------------------- */
608 static const char hexdig[] = "0123456789abcdef";
609 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
611 static char path[ MAXPATHLEN + 1];
615 strcpy( path, vol->v_path );
616 strcat( path, "/.AppleDesktop/" );
617 for ( p = path; *p != '\0'; p++ )
620 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
621 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
622 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
629 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
630 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
631 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
632 *p++ = hexdig[ creator[ i ] & 0x0f ];
643 /* ---------------------------
644 * mpath is only a filename
645 * did filename parent directory ID.
648 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
650 static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
656 if ( *mpath == '\0' ) {
661 /* set conversion flags */
662 flags = vol->v_mtou_flags;
664 m = demangle(vol, mpath, did);
675 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)) ) {
676 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
681 LOG(log_debug9, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
689 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
691 static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
697 outlen = strlen(upath);
699 flags = vol->v_utom_flags;
703 /* convert charsets */
704 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)) ) {
705 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
709 flags = !!(flags & CONV_REQMANGLE);
714 m = mangle(vol, mpath, outlen, upath, id, flags);
717 LOG(log_debug9, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
723 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
727 /* ------------------------- */
728 static int ad_addcomment(const AFPObj *obj, struct vol *vol, struct path *path, char *ibuf)
734 struct adouble ad, *adp;
736 clen = (u_char)*ibuf++;
737 clen = min( clen, 199 );
739 upath = path->u_name;
740 if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
741 return AFPERR_ACCESS;
744 isadir = path_isadir(path);
745 if (isadir || !(of = of_findname(path))) {
751 if (ad_open(adp, upath,
752 ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0) | ADFLAGS_CREATE | ADFLAGS_RDWR,
754 return( AFPERR_ACCESS );
757 if (ad_getentryoff(adp, ADEID_COMMENT)) {
758 if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
759 if ( *path->m_name == '\0' ) {
760 name = (char *)curdir->d_m_name->data;
764 ad_setname(adp, name);
766 ad_setentrylen( adp, ADEID_COMMENT, clen );
767 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
770 ad_close(adp, ADFLAGS_HF);
774 /* ----------------------------- */
775 int afp_addcomment(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
786 memcpy( &vid, ibuf, sizeof( vid ));
787 ibuf += sizeof( vid );
788 if (NULL == ( vol = getvolbyvid( vid )) ) {
789 return( AFPERR_PARAM );
792 memcpy( &did, ibuf, sizeof( did ));
793 ibuf += sizeof( did );
794 if (NULL == ( dir = dirlookup( vol, did )) ) {
798 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
799 return get_afp_errno(AFPERR_NOOBJ);
802 if ((u_long)ibuf & 1 ) {
806 return ad_addcomment(obj, vol, path, ibuf);
809 /* -------------------- */
810 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuflen)
812 struct adouble ad, *adp;
818 upath = path->u_name;
819 isadir = path_isadir(path);
820 if (isadir || !(of = of_findname(path))) {
826 if ( ad_metadata( upath, ((isadir) ? ADFLAGS_DIR : 0), adp) < 0 ) {
827 return( AFPERR_NOITEM );
830 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
831 ad_close(adp, ADFLAGS_HF);
832 return AFPERR_NOITEM;
835 * Make sure the AD file is not bogus.
837 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
838 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
839 ad_close(adp, ADFLAGS_HF);
840 return( AFPERR_NOITEM );
843 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
845 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
847 ad_close(adp, ADFLAGS_HF);
852 /* -------------------- */
853 int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
864 memcpy( &vid, ibuf, sizeof( vid ));
865 ibuf += sizeof( vid );
866 if (NULL == ( vol = getvolbyvid( vid )) ) {
867 return( AFPERR_PARAM );
870 memcpy( &did, ibuf, sizeof( did ));
871 ibuf += sizeof( did );
872 if (NULL == ( dir = dirlookup( vol, did )) ) {
876 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
877 return get_afp_errno(AFPERR_NOOBJ);
880 return ad_getcomment(vol, s_path, rbuf, rbuflen);
883 /* ----------------------- */
884 static int ad_rmvcomment(const AFPObj *obj, struct vol *vol, struct path *path)
886 struct adouble ad, *adp;
891 upath = path->u_name;
892 if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
893 return AFPERR_ACCESS;
896 isadir = path_isadir(path);
897 if (isadir || !(of = of_findname(path))) {
903 if ( ad_open(adp, upath, ADFLAGS_HF | ADFLAGS_RDWR | ((isadir) ? ADFLAGS_DIR : 0)) < 0 ) {
906 return( AFPERR_NOITEM );
908 return( AFPERR_ACCESS );
910 return( AFPERR_PARAM );
914 if (ad_getentryoff(adp, ADEID_COMMENT)) {
915 ad_setentrylen( adp, ADEID_COMMENT, 0 );
918 ad_close(adp, ADFLAGS_HF);
922 /* ----------------------- */
923 int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
934 memcpy( &vid, ibuf, sizeof( vid ));
935 ibuf += sizeof( vid );
936 if (NULL == ( vol = getvolbyvid( vid )) ) {
937 return( AFPERR_PARAM );
940 memcpy( &did, ibuf, sizeof( did ));
941 ibuf += sizeof( did );
942 if (NULL == ( dir = dirlookup( vol, did )) ) {
946 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
947 return get_afp_errno(AFPERR_NOOBJ);
950 return ad_rmvcomment(obj, vol, s_path);