2 * $Id: desktop.c,v 1.26.2.4 2003-07-21 05:50:54 didg 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 */
16 #include <atalk/logger.h>
18 #include <sys/types.h>
21 #include <sys/param.h>
23 #include <sys/socket.h>
24 #include <netatalk/at.h>
25 #include <netatalk/endian.h>
26 #include <atalk/dsi.h>
27 #include <atalk/atp.h>
28 #include <atalk/asp.h>
29 #include <atalk/afp.h>
30 #include <atalk/adouble.h>
31 #include <atalk/util.h>
35 #endif /* HAVE_FCNTL_H */
41 #endif /* HAVE_FCNTL_H */
44 #include "directory.h"
55 #include <atalk/unicode.h>
58 int afp_opendt(obj, ibuf, ibuflen, rbuf, rbuflen )
61 int ibuflen, *rbuflen;
68 memcpy( &vid, ibuf, sizeof(vid));
69 if (NULL == ( vol = getvolbyvid( vid )) ) {
71 return( AFPERR_PARAM );
74 memcpy( rbuf, &vid, sizeof(vid));
75 *rbuflen = sizeof(vid);
79 int afp_closedt(obj, ibuf, ibuflen, rbuf, rbuflen )
82 int ibuflen, *rbuflen;
88 struct savedt si = { { 0, 0, 0, 0 }, -1, 0 };
90 static int iconopen( vol, creator, flags, mode )
94 char *dtf, *adt, *adts;
96 if ( si.sdt_fd != -1 ) {
97 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
98 si.sdt_vid == vol->v_vid ) {
105 dtf = dtfile( vol, creator, ".icon" );
107 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
108 if ( errno == ENOENT && ( flags & O_CREAT )) {
109 if (( adts = strrchr( dtf, '/' )) == NULL ) {
113 if (( adt = strrchr( dtf, '/' )) == NULL ) {
117 (void) ad_mkdir( dtf, DIRBITS | 0777 );
119 (void) ad_mkdir( dtf, DIRBITS | 0777 );
122 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
123 LOG(log_error, logtype_afpd, "iconopen: open %s: %s", dtf, strerror(errno) );
131 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
132 si.sdt_vid = vol->v_vid;
137 int afp_addicon(obj, ibuf, ibuflen, rbuf, rbuflen)
140 int ibuflen, *rbuflen;
143 struct iovec iov[ 2 ];
144 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
145 int itype, cc = AFP_OK, iovcnt = 0, buflen;
146 u_int32_t ftype, itag;
147 u_int16_t bsize, rsize, vid;
153 memcpy( &vid, ibuf, sizeof( vid ));
154 ibuf += sizeof( vid );
155 if (NULL == ( vol = getvolbyvid( vid )) ) {
160 memcpy( fcreator, ibuf, sizeof( fcreator ));
161 ibuf += sizeof( fcreator );
163 memcpy( &ftype, ibuf, sizeof( ftype ));
164 ibuf += sizeof( ftype );
166 itype = (unsigned char) *ibuf;
169 memcpy( &itag, ibuf, sizeof( itag ));
170 ibuf += sizeof( itag );
172 memcpy( &bsize, ibuf, sizeof( bsize ));
173 bsize = ntohs( bsize );
175 if ( si.sdt_fd != -1 ) {
176 (void)close( si.sdt_fd );
180 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
185 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
188 LOG(log_error, logtype_afpd, "afp_addicon: lseek: %s", strerror(errno) );
194 * Read icon elements until we find a match to replace, or
195 * we get to the end to insert.
198 memcpy( p, &itag, sizeof( itag ));
200 memcpy( p, &ftype, sizeof( ftype ));
201 p += sizeof( ftype );
204 bsize = htons( bsize );
205 memcpy( p, &bsize, sizeof( bsize ));
206 bsize = ntohs( bsize );
207 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
208 memcpy( &rsize, irh + 10, sizeof( rsize ));
209 rsize = ntohs( rsize );
211 * Is this our set of headers?
213 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
215 * Is the size correct?
217 if ( bsize != rsize )
222 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
223 LOG(log_error, logtype_afpd, "afp_addicon: lseek: %s", strerror(errno) );
229 * Some error occurred, return.
233 LOG(log_error, logtype_afpd, "afp_addicon: %s", strerror(errno) );
234 if (obj->proto == AFPPROTO_DSI) {
235 dsi_writeinit(obj->handle, rbuf, buflen);
236 dsi_writeflush(obj->handle);
242 switch (obj->proto) {
246 if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
247 return( AFPERR_PARAM );
249 if (obj->options.flags & OPTION_DEBUG) {
250 printf("(write) len: %d\n", buflen);
251 bprint(rbuf, buflen);
255 * We're at the end of the file, add the headers, etc. */
257 iov[ 0 ].iov_base = (caddr_t)imh;
258 iov[ 0 ].iov_len = sizeof( imh );
259 iov[ 1 ].iov_base = rbuf;
260 iov[ 1 ].iov_len = bsize;
265 * We found an icon to replace.
268 iov[ 0 ].iov_base = rbuf;
269 iov[ 0 ].iov_len = bsize;
273 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
274 LOG(log_error, logtype_afpd, "afp_addicon: writev: %s", strerror(errno) );
275 return( AFPERR_PARAM );
278 #endif /* no afp/asp */
281 DSI *dsi = obj->handle;
283 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
285 /* add headers at end of file */
286 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
287 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
292 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
293 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
298 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
299 if ( obj->options.flags & OPTION_DEBUG ) {
300 printf("(write) command cont'd: %d\n", iovcnt);
301 bprint(rbuf, iovcnt);
304 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
305 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
319 u_char utag[] = { 0, 0, 0, 0 };
320 u_char ucreator[] = { 'U', 'N', 'I', 'X' };
321 u_char utype[] = { 'T', 'E', 'X', 'T' };
324 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
325 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
326 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
327 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
328 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
329 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
330 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
331 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
332 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
333 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
334 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
335 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
336 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
337 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
338 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
339 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
340 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
341 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
342 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
343 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
344 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
345 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
346 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
347 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
348 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
349 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
350 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
351 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
352 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
353 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
354 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
355 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
358 int afp_geticoninfo(obj, ibuf, ibuflen, rbuf, rbuflen )
361 int ibuflen, *rbuflen;
364 u_char fcreator[ 4 ], ih[ 12 ];
365 u_int16_t vid, iindex, bsize;
370 memcpy( &vid, ibuf, sizeof( vid ));
371 ibuf += sizeof( vid );
372 if (NULL == ( vol = getvolbyvid( vid )) ) {
373 return( AFPERR_PARAM );
376 memcpy( fcreator, ibuf, sizeof( fcreator ));
377 ibuf += sizeof( fcreator );
378 memcpy( &iindex, ibuf, sizeof( iindex ));
379 iindex = ntohs( iindex );
381 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
383 return( AFPERR_NOITEM );
385 memcpy( ih, utag, sizeof( utag ));
386 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
387 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
388 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
389 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
391 memcpy( rbuf, ih, sizeof( ih ));
392 *rbuflen = sizeof( ih );
396 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
397 return( AFPERR_NOITEM );
400 if ( iindex < si.sdt_index ) {
401 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
402 return( AFPERR_PARAM );
408 * Position to the correct spot.
411 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
414 return( AFPERR_NOITEM );
416 memcpy( &bsize, ih + 10, sizeof( bsize ));
417 bsize = ntohs(bsize);
418 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
419 LOG(log_error, logtype_afpd, "afp_iconinfo: lseek: %s", strerror(errno) );
420 return( AFPERR_PARAM );
422 if ( si.sdt_index == iindex ) {
423 memcpy( rbuf, ih, sizeof( ih ));
424 *rbuflen = sizeof( ih );
432 int afp_geticon(obj, ibuf, ibuflen, rbuf, rbuflen )
435 int ibuflen, *rbuflen;
440 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
441 u_int16_t vid, bsize, rsize;
447 memcpy( &vid, ibuf, sizeof( vid ));
448 ibuf += sizeof( vid );
449 if (NULL == ( vol = getvolbyvid( vid )) ) {
450 return( AFPERR_PARAM );
453 memcpy( fcreator, ibuf, sizeof( fcreator ));
454 ibuf += sizeof( fcreator );
455 memcpy( ftype, ibuf, sizeof( ftype ));
456 ibuf += sizeof( ftype );
457 itype = (unsigned char) *ibuf++;
459 memcpy( &bsize, ibuf, sizeof( bsize ));
460 bsize = ntohs( bsize );
462 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
463 memcmp( ftype, utype, sizeof( utype )) == 0 &&
466 memcpy( rbuf, uicon, bsize);
471 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
472 return( AFPERR_NOITEM );
475 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
478 LOG(log_error, logtype_afpd, "afp_geticon: lseek: %s", strerror(errno));
479 return( AFPERR_PARAM );
484 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
486 offset += sizeof(ih);
487 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
488 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
491 memcpy( &rsize, ih + 10, sizeof( rsize ));
492 rsize = ntohs( rsize );
493 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
494 LOG(log_error, logtype_afpd, "afp_geticon: lseek: %s", strerror(errno) );
495 return( AFPERR_PARAM );
501 LOG(log_error, logtype_afpd, "afp_geticon: read: %s", strerror(errno));
502 return( AFPERR_PARAM );
506 return( AFPERR_NOITEM );
509 memcpy( &rsize, ih + 10, sizeof( rsize ));
510 rsize = ntohs( rsize );
511 #define min(a,b) ((a)<(b)?(a):(b))
512 rc = min( bsize, rsize );
514 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
515 DSI *dsi = obj->handle;
519 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
520 if (size < rc + offset) {
524 if ((*rbuflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
527 /* do to the streaming nature, we have to exit if we encounter
528 * a problem. much confusion results otherwise. */
529 while (*rbuflen > 0) {
530 #if defined(SENDFILE_FLAVOR_LINUX) || defined(SENDFILE_FLAVOR_BSD)
531 if (!obj->options.flags & OPTION_DEBUG) {
532 #ifdef SENDFILE_FLAVOR_LINUX
533 if (sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0)
535 #endif /* SENDFILE_FLAVOR_LINUX */
537 #ifdef SENDFILE_FLAVOR_BSD
538 if (sendfile(si.sdt_fd, dsi->socket, offset, rc, NULL, NULL, 0) < 0)
540 #endif /* SENDFILE_FLAVOR_BSD */
544 #endif /* SENDFILE_FLAVOR_LINUX || SENDFILE_FLAVOR_BSD */
546 buflen = read(si.sdt_fd, rbuf, *rbuflen);
550 if (obj->options.flags & OPTION_DEBUG) {
551 printf( "(read) reply: %d, %d\n", buflen, dsi->clientID);
552 bprint(rbuf, buflen);
555 /* dsi_read() also returns buffer size of next allocation */
556 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
568 LOG(log_info, logtype_afpd, "afp_geticon: %s", strerror(errno));
574 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
575 return( AFPERR_PARAM );
583 static char hexdig[] = "0123456789abcdef";
584 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
586 static char path[ MAXPATHLEN + 1];
590 strcpy( path, vol->v_path );
591 strcat( path, "/.AppleDesktop/" );
592 for ( p = path; *p != '\0'; p++ )
595 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
596 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
597 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
604 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
605 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
606 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
607 *p++ = hexdig[ creator[ i ] & 0x0f ];
618 /* ---------------------------
619 * mpath is only a filename
621 static char upath[ MAXPATHLEN + 1];
622 static char mpath[ MAXPATHLEN + 1];
623 static char ucs2[ MAXPATHLEN + 1];
625 static char *old_mtoupath(const struct vol *vol, char *mpath)
633 if ((vol->v_casefold & (AFPVOL_MTOUUPPER| AFPVOL_MTOULOWER))) {
636 while ( *m != '\0' ) {
637 /* handle case conversion first */
638 if (vol->v_casefold & AFPVOL_MTOUUPPER)
639 *m = diatoupper( *m );
640 else if (vol->v_casefold & AFPVOL_MTOULOWER)
641 *m = diatolower( *m );
643 /* we have a code page. we only use the ascii range
644 * if we have map ascii specified. */
645 if (vol->v_mtoupage && ((*m & 0x80) ||
646 vol->v_flags & AFPVOL_MAPASCII)) {
647 *u = vol->v_mtoupage->map[(unsigned char) *m].value;
650 /* if conversion failed, encode in hex
651 * to prevent silly truncation
652 * H.P. Jansen <hpj@urpla.net> */
654 LOG(log_debug, logtype_afpd, "mtoupath: hex encode: 0x%x", (unsigned char) *m);
657 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
658 *u = hexdig[ *m & 0x0f ];
661 #if AD_VERSION == AD_VERSION1
662 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
663 (!isascii(*m) || *m == '/')) ||
664 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
665 ( i == 0 && (*m == '.' )))) {
667 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
668 (!isprint(*m) || *m == '/')) ||
669 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
670 ( i == 0 && (*m == '.' )))) {
672 /* do hex conversion. */
674 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
675 *u = hexdig[ *m & 0x0f ];
687 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
690 return( (changed)?upath:mpath );
693 /* ---------------------------- */
694 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
695 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
697 static char *old_utompath(const struct vol *vol, char *upath)
703 /* do the hex conversion */
706 if ((vol->v_casefold & (AFPVOL_MTOUUPPER| AFPVOL_MTOULOWER))) {
709 while ( *u != '\0' ) {
710 /* we have a code page */
711 if (vol->v_utompage && ((*u & 0x80) ||
712 (vol->v_flags & AFPVOL_MAPASCII))) {
713 *m = vol->v_utompage->map[(unsigned char) *u].value;
716 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
717 *(u+2) != '\0' && islxdigit( *(u+2))) {
719 h = hextoint( *u ) << 4;
727 /* handle case conversion */
728 if (vol->v_casefold & AFPVOL_UTOMLOWER)
729 *m = diatolower( *m );
730 else if (vol->v_casefold & AFPVOL_UTOMUPPER)
731 *m = diatoupper( *m );
740 m = mangle(vol, mpath, upath, 0);
744 #endif /* FILE_MANGLING */
747 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s'", upath, mpath);
750 return((changed)? m:upath );
753 /* --------------------------- */
754 char *mtoupath(const struct vol *vol, char *mpath, int utf8)
761 if ( *mpath == '\0' ) {
766 m = demangle(vol, mpath);
770 #endif /* FILE_MANGLING */
773 return old_mtoupath(vol, mpath);
777 while ( *m != '\0' ) {
778 if ( (!(vol->v_flags & AFPVOL_NOHEX) && *m == '/') ||
779 (!(vol->v_flags & AFPVOL_USEDOTS) && i == 0 && *m == '.')
781 /* do hex conversion. */
783 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
784 *u = hexdig[ *m & 0x0f ];
798 /* assume precompose */
799 if ((size_t)(-1) == (outlen = convert_string ( vol->v_maccharset, CH_UTF8, u, inplen, r, outlen)) )
807 if ((size_t)(-1) == (outlen = utf8_precompose( u, inplen, r, outlen)) )
815 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
820 /* --------------- */
821 char *utompath(const struct vol *vol, char *upath, int utf8)
829 return old_utompath(vol, upath);
830 /* do the hex conversion */
833 while ( *u != '\0' ) {
834 if ( *u == ':' && islxdigit( *(u+1)) && islxdigit( *(u+2))) {
836 h = hextoint( *u ) << 4;
849 if ((size_t)(-1) == ( outlen = utf8_decompose ( mpath, strlen (mpath), mpath, MAXPATHLEN)) )
853 if ((size_t)(-1) == ( outlen = utf8_to_mac_charset ( vol->v_maccharset, mpath, strlen(mpath), mpath, MAXPATHLEN, &mangleflag)) )
860 m = mangle(vol, mpath, upath, mangleflag);
865 #endif /* FILE_MANGLING */
870 /* ----------------------------- */
871 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
874 int ibuflen, *rbuflen;
876 struct adouble ad, *adp;
890 memcpy( &vid, ibuf, sizeof( vid ));
891 ibuf += sizeof( vid );
892 if (NULL == ( vol = getvolbyvid( vid )) ) {
893 return( AFPERR_PARAM );
896 memcpy( &did, ibuf, sizeof( did ));
897 ibuf += sizeof( did );
898 if (NULL == ( dir = dirlookup( vol, did )) ) {
902 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
903 return get_afp_errno(AFPERR_NOOBJ);
906 if ((u_long)ibuf & 1 ) {
910 clen = (u_char)*ibuf++;
911 clen = min( clen, 199 );
913 upath = path->u_name;
914 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
915 return AFPERR_ACCESS;
918 isadir = path_isadir(path);
919 if (isadir || !(of = of_findname(path))) {
920 memset(&ad, 0, sizeof(ad));
925 if (ad_open( upath , vol_noadouble(vol) |
926 (( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
927 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
928 return( AFPERR_ACCESS );
931 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
932 if ( *path->m_name == '\0' ) {
933 name = curdir->d_m_name;
937 ad_setentrylen( adp, ADEID_NAME, strlen( name ));
938 memcpy( ad_entry( adp, ADEID_NAME ), name,
939 ad_getentrylen( adp, ADEID_NAME ));
942 ad_setentrylen( adp, ADEID_COMMENT, clen );
943 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
944 ad_flush( adp, ADFLAGS_HF );
945 ad_close( adp, ADFLAGS_HF );
949 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
952 int ibuflen, *rbuflen;
954 struct adouble ad, *adp;
967 memcpy( &vid, ibuf, sizeof( vid ));
968 ibuf += sizeof( vid );
969 if (NULL == ( vol = getvolbyvid( vid )) ) {
970 return( AFPERR_PARAM );
973 memcpy( &did, ibuf, sizeof( did ));
974 ibuf += sizeof( did );
975 if (NULL == ( dir = dirlookup( vol, did )) ) {
979 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
980 return get_afp_errno(AFPERR_NOOBJ);
983 upath = s_path->u_name;
984 isadir = path_isadir(s_path);
985 if (isadir || !(of = of_findname(s_path))) {
986 memset(&ad, 0, sizeof(ad));
991 ( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
992 O_RDONLY, 0666, adp) < 0 ) {
993 return( AFPERR_NOITEM );
997 * Make sure the AD file is not bogus.
999 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
1000 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
1001 ad_close( adp, ADFLAGS_HF );
1002 return( AFPERR_NOITEM );
1005 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
1006 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
1007 ad_getentrylen( adp, ADEID_COMMENT ));
1008 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
1009 ad_close( adp, ADFLAGS_HF );
1011 /* return AFPERR_NOITEM if len == 0 ? */
1015 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
1018 int ibuflen, *rbuflen;
1020 struct adouble ad, *adp;
1024 struct path *s_path;
1033 memcpy( &vid, ibuf, sizeof( vid ));
1034 ibuf += sizeof( vid );
1035 if (NULL == ( vol = getvolbyvid( vid )) ) {
1036 return( AFPERR_PARAM );
1039 memcpy( &did, ibuf, sizeof( did ));
1040 ibuf += sizeof( did );
1041 if (NULL == ( dir = dirlookup( vol, did )) ) {
1045 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
1046 return get_afp_errno(AFPERR_NOOBJ);
1049 upath = s_path->u_name;
1050 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
1051 return AFPERR_ACCESS;
1054 isadir = path_isadir(s_path);
1055 if (isadir || !(of = of_findname(s_path))) {
1056 memset(&ad, 0, sizeof(ad));
1061 if ( ad_open( upath,
1062 (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
1063 O_RDWR, 0, adp) < 0 ) {
1066 return( AFPERR_NOITEM );
1068 return( AFPERR_ACCESS );
1070 return( AFPERR_PARAM );
1074 ad_setentrylen( adp, ADEID_COMMENT, 0 );
1075 ad_flush( adp, ADFLAGS_HF );
1076 ad_close( adp, ADFLAGS_HF );