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 (!obj->options.flags & OPTION_DEBUG) {
564 if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize) < 0) {
567 case EINVAL: /* there's no guarantee that all fs support sendfile */
579 buflen = read(si.sdt_fd, rbuf, *rbuflen);
583 /* dsi_read() also returns buffer size of next allocation */
584 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
595 LOG(log_error, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno));
597 obj->exit(EXITERR_SYS);
601 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
602 return( AFPERR_PARAM );
609 /* ---------------------- */
610 static const char hexdig[] = "0123456789abcdef";
611 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
613 static char path[ MAXPATHLEN + 1];
617 strcpy( path, vol->v_path );
618 strcat( path, "/.AppleDesktop/" );
619 for ( p = path; *p != '\0'; p++ )
622 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
623 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
624 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
631 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
632 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
633 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
634 *p++ = hexdig[ creator[ i ] & 0x0f ];
645 /* ---------------------------
646 * mpath is only a filename
647 * did filename parent directory ID.
650 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
652 static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
658 if ( *mpath == '\0' ) {
663 /* set conversion flags */
664 flags = vol->v_mtou_flags;
666 m = demangle(vol, mpath, did);
677 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)) ) {
678 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
683 LOG(log_debug9, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
691 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
693 static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
699 outlen = strlen(upath);
701 flags = vol->v_utom_flags;
705 /* convert charsets */
706 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)) ) {
707 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
711 flags = !!(flags & CONV_REQMANGLE);
716 m = mangle(vol, mpath, outlen, upath, id, flags);
719 LOG(log_debug9, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
725 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
729 /* ------------------------- */
730 static int ad_addcomment(const AFPObj *obj, struct vol *vol, struct path *path, char *ibuf)
736 struct adouble ad, *adp;
738 clen = (u_char)*ibuf++;
739 clen = min( clen, 199 );
741 upath = path->u_name;
742 if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
743 return AFPERR_ACCESS;
746 isadir = path_isadir(path);
747 if (isadir || !(of = of_findname(path))) {
753 if (ad_open(adp, upath,
754 ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0) | ADFLAGS_CREATE | ADFLAGS_RDWR,
756 return( AFPERR_ACCESS );
759 if (ad_getentryoff(adp, ADEID_COMMENT)) {
760 if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
761 if ( *path->m_name == '\0' ) {
762 name = (char *)curdir->d_m_name->data;
766 ad_setname(adp, name);
768 ad_setentrylen( adp, ADEID_COMMENT, clen );
769 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
772 ad_close(adp, ADFLAGS_HF);
776 /* ----------------------------- */
777 int afp_addcomment(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
788 memcpy( &vid, ibuf, sizeof( vid ));
789 ibuf += sizeof( vid );
790 if (NULL == ( vol = getvolbyvid( vid )) ) {
791 return( AFPERR_PARAM );
794 memcpy( &did, ibuf, sizeof( did ));
795 ibuf += sizeof( did );
796 if (NULL == ( dir = dirlookup( vol, did )) ) {
800 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
801 return get_afp_errno(AFPERR_NOOBJ);
804 if ((u_long)ibuf & 1 ) {
808 return ad_addcomment(obj, vol, path, ibuf);
811 /* -------------------- */
812 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuflen)
814 struct adouble ad, *adp;
820 upath = path->u_name;
821 isadir = path_isadir(path);
822 if (isadir || !(of = of_findname(path))) {
828 if ( ad_metadata( upath, ((isadir) ? ADFLAGS_DIR : 0), adp) < 0 ) {
829 return( AFPERR_NOITEM );
832 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
833 ad_close(adp, ADFLAGS_HF);
834 return AFPERR_NOITEM;
837 * Make sure the AD file is not bogus.
839 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
840 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
841 ad_close(adp, ADFLAGS_HF);
842 return( AFPERR_NOITEM );
845 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
847 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
849 ad_close(adp, ADFLAGS_HF);
854 /* -------------------- */
855 int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
866 memcpy( &vid, ibuf, sizeof( vid ));
867 ibuf += sizeof( vid );
868 if (NULL == ( vol = getvolbyvid( vid )) ) {
869 return( AFPERR_PARAM );
872 memcpy( &did, ibuf, sizeof( did ));
873 ibuf += sizeof( did );
874 if (NULL == ( dir = dirlookup( vol, did )) ) {
878 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
879 return get_afp_errno(AFPERR_NOOBJ);
882 return ad_getcomment(vol, s_path, rbuf, rbuflen);
885 /* ----------------------- */
886 static int ad_rmvcomment(const AFPObj *obj, struct vol *vol, struct path *path)
888 struct adouble ad, *adp;
893 upath = path->u_name;
894 if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
895 return AFPERR_ACCESS;
898 isadir = path_isadir(path);
899 if (isadir || !(of = of_findname(path))) {
905 if ( ad_open(adp, upath, ADFLAGS_HF | ADFLAGS_RDWR | ((isadir) ? ADFLAGS_DIR : 0)) < 0 ) {
908 return( AFPERR_NOITEM );
910 return( AFPERR_ACCESS );
912 return( AFPERR_PARAM );
916 if (ad_getentryoff(adp, ADEID_COMMENT)) {
917 ad_setentrylen( adp, ADEID_COMMENT, 0 );
920 ad_close(adp, ADFLAGS_HF);
924 /* ----------------------- */
925 int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
936 memcpy( &vid, ibuf, sizeof( vid ));
937 ibuf += sizeof( vid );
938 if (NULL == ( vol = getvolbyvid( vid )) ) {
939 return( AFPERR_PARAM );
942 memcpy( &did, ibuf, sizeof( did ));
943 ibuf += sizeof( did );
944 if (NULL == ( dir = dirlookup( vol, did )) ) {
948 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
949 return get_afp_errno(AFPERR_NOOBJ);
952 return ad_rmvcomment(obj, vol, s_path);