2 * $Id: desktop.c,v 1.25 2003-03-15 01:34:35 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"
57 int afp_opendt(obj, ibuf, ibuflen, rbuf, rbuflen )
60 int ibuflen, *rbuflen;
67 memcpy( &vid, ibuf, sizeof(vid));
68 if (NULL == ( vol = getvolbyvid( vid )) ) {
70 return( AFPERR_PARAM );
73 memcpy( rbuf, &vid, sizeof(vid));
74 *rbuflen = sizeof(vid);
78 int afp_closedt(obj, ibuf, ibuflen, rbuf, rbuflen )
81 int ibuflen, *rbuflen;
87 struct savedt si = { { 0, 0, 0, 0 }, -1, 0 };
89 static int iconopen( vol, creator, flags, mode )
93 char *dtf, *adt, *adts;
95 if ( si.sdt_fd != -1 ) {
96 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
97 si.sdt_vid == vol->v_vid ) {
104 dtf = dtfile( vol, creator, ".icon" );
106 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
107 if ( errno == ENOENT && ( flags & O_CREAT )) {
108 if (( adts = strrchr( dtf, '/' )) == NULL ) {
112 if (( adt = strrchr( dtf, '/' )) == NULL ) {
116 (void) ad_mkdir( dtf, DIRBITS | 0777 );
118 (void) ad_mkdir( dtf, DIRBITS | 0777 );
121 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
122 LOG(log_error, logtype_afpd, "iconopen: open %s: %s", dtf, strerror(errno) );
130 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
131 si.sdt_vid = vol->v_vid;
136 int afp_addicon(obj, ibuf, ibuflen, rbuf, rbuflen)
139 int ibuflen, *rbuflen;
142 struct iovec iov[ 2 ];
143 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
144 int itype, cc = AFP_OK, iovcnt = 0, buflen;
145 u_int32_t ftype, itag;
146 u_int16_t bsize, rsize, vid;
152 memcpy( &vid, ibuf, sizeof( vid ));
153 ibuf += sizeof( vid );
154 if (( vol = getvolbyvid( vid )) == NULL ) {
159 memcpy( fcreator, ibuf, sizeof( fcreator ));
160 ibuf += sizeof( fcreator );
162 memcpy( &ftype, ibuf, sizeof( ftype ));
163 ibuf += sizeof( ftype );
165 itype = (unsigned char) *ibuf;
168 memcpy( &itag, ibuf, sizeof( itag ));
169 ibuf += sizeof( itag );
171 memcpy( &bsize, ibuf, sizeof( bsize ));
172 bsize = ntohs( bsize );
174 if ( si.sdt_fd != -1 ) {
175 (void)close( si.sdt_fd );
179 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
184 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
187 LOG(log_error, logtype_afpd, "afp_addicon: lseek: %s", strerror(errno) );
193 * Read icon elements until we find a match to replace, or
194 * we get to the end to insert.
197 memcpy( p, &itag, sizeof( itag ));
199 memcpy( p, &ftype, sizeof( ftype ));
200 p += sizeof( ftype );
203 bsize = htons( bsize );
204 memcpy( p, &bsize, sizeof( bsize ));
205 bsize = ntohs( bsize );
206 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
207 memcpy( &rsize, irh + 10, sizeof( rsize ));
208 rsize = ntohs( rsize );
210 * Is this our set of headers?
212 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
214 * Is the size correct?
216 if ( bsize != rsize )
221 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
222 LOG(log_error, logtype_afpd, "afp_addicon: lseek: %s", strerror(errno) );
228 * Some error occurred, return.
232 LOG(log_error, logtype_afpd, "afp_addicon: %s", strerror(errno) );
233 if (obj->proto == AFPPROTO_DSI) {
234 dsi_writeinit(obj->handle, rbuf, buflen);
235 dsi_writeflush(obj->handle);
241 switch (obj->proto) {
245 if ((asp_wrtcont(obj->handle, rbuf, &buflen) < 0) || buflen != bsize)
246 return( AFPERR_PARAM );
248 if (obj->options.flags & OPTION_DEBUG) {
249 printf("(write) len: %d\n", buflen);
250 bprint(rbuf, buflen);
254 * We're at the end of the file, add the headers, etc. */
256 iov[ 0 ].iov_base = (caddr_t)imh;
257 iov[ 0 ].iov_len = sizeof( imh );
258 iov[ 1 ].iov_base = rbuf;
259 iov[ 1 ].iov_len = bsize;
264 * We found an icon to replace.
267 iov[ 0 ].iov_base = rbuf;
268 iov[ 0 ].iov_len = bsize;
272 if ( writev( si.sdt_fd, iov, iovcnt ) < 0 ) {
273 LOG(log_error, logtype_afpd, "afp_addicon: writev: %s", strerror(errno) );
274 return( AFPERR_PARAM );
277 #endif /* no afp/asp */
280 DSI *dsi = obj->handle;
282 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
284 /* add headers at end of file */
285 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
286 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
291 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
292 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
297 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
298 if ( obj->options.flags & OPTION_DEBUG ) {
299 printf("(write) command cont'd: %d\n", iovcnt);
300 bprint(rbuf, iovcnt);
303 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
304 LOG(log_error, logtype_afpd, "afp_addicon: write: %s", strerror(errno));
318 u_char utag[] = { 0, 0, 0, 0 };
319 u_char ucreator[] = { 'U', 'N', 'I', 'X' };
320 u_char utype[] = { 'T', 'E', 'X', 'T' };
323 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
324 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
325 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
326 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
327 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
328 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
329 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
330 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
331 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
332 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
333 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
334 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
335 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
336 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
337 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
338 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
339 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
340 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
341 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
342 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
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,
357 int afp_geticoninfo(obj, ibuf, ibuflen, rbuf, rbuflen )
360 int ibuflen, *rbuflen;
363 u_char fcreator[ 4 ], ih[ 12 ];
364 u_int16_t vid, iindex, bsize;
369 memcpy( &vid, ibuf, sizeof( vid ));
370 ibuf += sizeof( vid );
371 if (NULL == ( vol = getvolbyvid( vid )) ) {
372 return( AFPERR_PARAM );
375 memcpy( fcreator, ibuf, sizeof( fcreator ));
376 ibuf += sizeof( fcreator );
377 memcpy( &iindex, ibuf, sizeof( iindex ));
378 iindex = ntohs( iindex );
380 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
382 return( AFPERR_NOITEM );
384 memcpy( ih, utag, sizeof( utag ));
385 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
386 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
387 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
388 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
390 memcpy( rbuf, ih, sizeof( ih ));
391 *rbuflen = sizeof( ih );
395 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
396 return( AFPERR_NOITEM );
399 if ( iindex < si.sdt_index ) {
400 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
401 return( AFPERR_PARAM );
407 * Position to the correct spot.
410 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
413 return( AFPERR_NOITEM );
415 memcpy( &bsize, ih + 10, sizeof( bsize ));
416 bsize = ntohs(bsize);
417 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
418 LOG(log_error, logtype_afpd, "afp_iconinfo: lseek: %s", strerror(errno) );
419 return( AFPERR_PARAM );
421 if ( si.sdt_index == iindex ) {
422 memcpy( rbuf, ih, sizeof( ih ));
423 *rbuflen = sizeof( ih );
431 int afp_geticon(obj, ibuf, ibuflen, rbuf, rbuflen )
434 int ibuflen, *rbuflen;
439 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
440 u_int16_t vid, bsize, rsize;
446 memcpy( &vid, ibuf, sizeof( vid ));
447 ibuf += sizeof( vid );
448 if (NULL == ( vol = getvolbyvid( vid )) ) {
449 return( AFPERR_PARAM );
452 memcpy( fcreator, ibuf, sizeof( fcreator ));
453 ibuf += sizeof( fcreator );
454 memcpy( ftype, ibuf, sizeof( ftype ));
455 ibuf += sizeof( ftype );
456 itype = (unsigned char) *ibuf++;
458 memcpy( &bsize, ibuf, sizeof( bsize ));
459 bsize = ntohs( bsize );
461 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
462 memcmp( ftype, utype, sizeof( utype )) == 0 &&
465 memcpy( rbuf, uicon, bsize);
470 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
471 return( AFPERR_NOITEM );
474 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
477 LOG(log_error, logtype_afpd, "afp_geticon: lseek: %s", strerror(errno));
478 return( AFPERR_PARAM );
483 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
485 offset += sizeof(ih);
486 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
487 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
490 memcpy( &rsize, ih + 10, sizeof( rsize ));
491 rsize = ntohs( rsize );
492 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
493 LOG(log_error, logtype_afpd, "afp_geticon: lseek: %s", strerror(errno) );
494 return( AFPERR_PARAM );
500 LOG(log_error, logtype_afpd, "afp_geticon: read: %s", strerror(errno));
501 return( AFPERR_PARAM );
505 return( AFPERR_NOITEM );
508 memcpy( &rsize, ih + 10, sizeof( rsize ));
509 rsize = ntohs( rsize );
510 #define min(a,b) ((a)<(b)?(a):(b))
511 rc = min( bsize, rsize );
513 if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) {
514 DSI *dsi = obj->handle;
518 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
519 if (size < rc + offset) {
523 if ((*rbuflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
526 /* do to the streaming nature, we have to exit if we encounter
527 * a problem. much confusion results otherwise. */
528 while (*rbuflen > 0) {
529 #if defined(SENDFILE_FLAVOR_LINUX) || defined(SENDFILE_FLAVOR_BSD)
530 if (!obj->options.flags & OPTION_DEBUG) {
531 #ifdef SENDFILE_FLAVOR_LINUX
532 if (sendfile(dsi->socket, si.sdt_fd, &offset, dsi->datasize) < 0)
534 #endif /* SENDFILE_FLAVOR_LINUX */
536 #ifdef SENDFILE_FLAVOR_BSD
537 if (sendfile(si.sdt_fd, dsi->socket, offset, rc, NULL, NULL, 0) < 0)
539 #endif /* SENDFILE_FLAVOR_BSD */
543 #endif /* SENDFILE_FLAVOR_LINUX || SENDFILE_FLAVOR_BSD */
545 buflen = read(si.sdt_fd, rbuf, *rbuflen);
549 if (obj->options.flags & OPTION_DEBUG) {
550 printf( "(read) reply: %d, %d\n", buflen, dsi->clientID);
551 bprint(rbuf, buflen);
554 /* dsi_read() also returns buffer size of next allocation */
555 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
567 LOG(log_info, logtype_afpd, "afp_geticon: %s", strerror(errno));
573 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
574 return( AFPERR_PARAM );
582 static char hexdig[] = "0123456789abcdef";
583 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
585 static char path[ MAXPATHLEN + 1];
589 strcpy( path, vol->v_path );
590 strcat( path, "/.AppleDesktop/" );
591 for ( p = path; *p != '\0'; p++ )
594 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
595 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
596 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
603 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
604 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
605 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
606 *p++ = hexdig[ creator[ i ] & 0x0f ];
617 /* ---------------------------
618 * mpath is only a filename
620 static char upath[ MAXPATHLEN + 1];
621 static char mpath[ MAXPATHLEN + 1];
622 static char ucs2[ MAXPATHLEN + 1];
624 static char *old_mtoupath(const struct vol *vol, char *mpath)
632 while ( *m != '\0' ) {
633 /* handle case conversion first */
634 if (vol->v_casefold & AFPVOL_MTOUUPPER)
635 *m = diatoupper( *m );
636 else if (vol->v_casefold & AFPVOL_MTOULOWER)
637 *m = diatolower( *m );
639 /* we have a code page. we only use the ascii range
640 * if we have map ascii specified. */
641 if (vol->v_mtoupage && ((*m & 0x80) ||
642 vol->v_flags & AFPVOL_MAPASCII)) {
643 *u = vol->v_mtoupage->map[(unsigned char) *m].value;
646 /* if conversion failed, encode in hex
647 * to prevent silly truncation
648 * H.P. Jansen <hpj@urpla.net> */
650 LOG(log_debug, logtype_afpd, "mtoupath: hex encode: 0x%x", (unsigned char) *m);
653 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
654 *u = hexdig[ *m & 0x0f ];
657 #if AD_VERSION == AD_VERSION1
658 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
659 (!isascii(*m) || *m == '/')) ||
660 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
661 ( i == 0 && (*m == '.' )))) {
663 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
664 (!isprint(*m) || *m == '/')) ||
665 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
666 ( i == 0 && (*m == '.' )))) {
668 /* do hex conversion. */
670 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
671 *u = hexdig[ *m & 0x0f ];
683 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
686 return( (changed)?upath:mpath );
689 /* ---------------------------- */
690 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
691 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
693 static char *old_utompath(const struct vol *vol, char *upath)
699 /* do the hex conversion */
702 while ( *u != '\0' ) {
703 /* we have a code page */
704 if (vol->v_utompage && ((*u & 0x80) ||
705 (vol->v_flags & AFPVOL_MAPASCII))) {
706 *m = vol->v_utompage->map[(unsigned char) *u].value;
709 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
710 *(u+2) != '\0' && islxdigit( *(u+2))) {
712 h = hextoint( *u ) << 4;
720 /* handle case conversion */
721 if (vol->v_casefold & AFPVOL_UTOMLOWER)
722 *m = diatolower( *m );
723 else if (vol->v_casefold & AFPVOL_UTOMUPPER)
724 *m = diatoupper( *m );
733 m = mangle(vol, mpath, upath, 0);
737 #endif /* FILE_MANGLING */
740 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s'", upath, mpath);
743 return((changed)? m:upath );
746 /* --------------- */
747 extern unsigned int do_precomposition(unsigned int base, unsigned int comb);
749 static char comp[MAXPATHLEN +1];
751 static char *precompose(u_int16_t *name, size_t inplen, size_t *outlen)
754 u_int16_t base, comb;
758 if (!inplen || (inplen & 1) || inplen > sizeof(comp)/sizeof(u_int16_t))
762 out = (u_int16_t *)comp;
775 if (comb >= 0x300 && (result = do_precomposition(base, comb))) {
794 /* --------------- */
795 extern unsigned int do_decomposition(unsigned int base);
797 static char *decompose(u_int16_t *name, size_t inplen, size_t *outlen)
804 if (!inplen || (inplen & 1))
808 out = (u_int16_t *)comp;
812 if (*outlen >= sizeof(comp)/sizeof(u_int16_t) +2) {
816 if ((result = do_decomposition(base))) {
820 *out = result & 0xffff;
835 /* --------------------------- */
836 char *mtoupath(const struct vol *vol, char *mpath, int utf8)
843 if ( *mpath == '\0' ) {
848 m = demangle(vol, mpath);
852 #endif /* FILE_MANGLING */
855 return old_mtoupath(vol, mpath);
859 while ( *m != '\0' ) {
860 if ( (!(vol->v_flags & AFPVOL_NOHEX) && *m == '/') ||
861 (!(vol->v_flags & AFPVOL_USEDOTS) && i == 0 && *m == '.') ||
862 (!utf8 && (unsigned char)*m == 0xf0) /* Apple logo */
864 /* do hex conversion. */
866 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
867 *u = hexdig[ *m & 0x0f ];
881 if ((size_t)(-1) == iconv(vol->v_mactoutf8, 0,0,0,0) )
883 /* assume precompose */
884 if ((size_t)(-1) == iconv(vol->v_mactoutf8, &u, &inplen, &r, &outlen))
889 if ((size_t)(-1) == iconv(vol->v_utf8toucs2, 0,0,0,0) )
892 if ((size_t)(-1) == iconv(vol->v_utf8toucs2, &u, &inplen, &r, &outlen))
895 u = precompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen);
897 if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, 0,0,0,0))
902 if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, &u, &inplen, &r, &outlen))
906 u[MAXPATHLEN -outlen] = 0;
909 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
914 /* --------------- */
915 char *utompath(const struct vol *vol, char *upath, int utf8)
924 return old_utompath(vol, upath);
925 /* do the hex conversion */
928 while ( *u != '\0' ) {
929 if ( *u == ':' && islxdigit( *(u+1)) && islxdigit( *(u+2))) {
931 h = hextoint( *u ) << 4;
943 if ((size_t)(-1) == iconv(vol->v_utf8toucs2, 0,0,0,0) )
945 inplen = strlen(mpath);
948 if ((size_t)(-1) == iconv(vol->v_utf8toucs2, &m, &inplen, &r, &outlen))
952 if ( NULL == (m = decompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen)))
955 if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, 0,0,0,0))
960 if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, &m, &inplen, &r, &outlen))
964 m = precompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen);
966 if ((size_t)(-1) == iconv(vol->v_ucs2tomac, 0,0,0,0))
971 if ((size_t)(-1) == iconv(vol->v_ucs2tomac, &m, &inplen, &r, &outlen)) {
974 if (outlen != MAXPATHLEN) {
982 mpath[MAXPATHLEN -outlen] = 0;
985 m = mangle(vol, mpath, upath, mangleflag);
986 #endif /* FILE_MANGLING */
991 /* ----------------------------- */
992 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
995 int ibuflen, *rbuflen;
997 struct adouble ad, *adp;
1011 memcpy( &vid, ibuf, sizeof( vid ));
1012 ibuf += sizeof( vid );
1013 if (NULL == ( vol = getvolbyvid( vid )) ) {
1014 return( AFPERR_PARAM );
1017 memcpy( &did, ibuf, sizeof( did ));
1018 ibuf += sizeof( did );
1019 if (NULL == ( dir = dirlookup( vol, did )) ) {
1023 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
1024 return get_afp_errno(AFPERR_NOOBJ);
1027 if ((u_long)ibuf & 1 ) {
1031 clen = (u_char)*ibuf++;
1032 clen = min( clen, 199 );
1034 upath = path->u_name;
1035 if (check_access(upath, OPENACC_WR ) < 0) {
1036 return AFPERR_ACCESS;
1039 isadir = path_isadir(path);
1040 if (isadir || !(of = of_findname(path))) {
1041 memset(&ad, 0, sizeof(ad));
1046 if (ad_open( upath , vol_noadouble(vol) |
1047 (( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
1048 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
1049 return( AFPERR_ACCESS );
1052 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
1053 if ( *path->m_name == '\0' ) {
1054 name = curdir->d_m_name;
1056 name = path->m_name;
1058 ad_setentrylen( adp, ADEID_NAME, strlen( name ));
1059 memcpy( ad_entry( adp, ADEID_NAME ), name,
1060 ad_getentrylen( adp, ADEID_NAME ));
1063 ad_setentrylen( adp, ADEID_COMMENT, clen );
1064 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
1065 ad_flush( adp, ADFLAGS_HF );
1066 ad_close( adp, ADFLAGS_HF );
1070 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
1073 int ibuflen, *rbuflen;
1075 struct adouble ad, *adp;
1079 struct path *s_path;
1088 memcpy( &vid, ibuf, sizeof( vid ));
1089 ibuf += sizeof( vid );
1090 if (NULL == ( vol = getvolbyvid( vid )) ) {
1091 return( AFPERR_PARAM );
1094 memcpy( &did, ibuf, sizeof( did ));
1095 ibuf += sizeof( did );
1096 if (NULL == ( dir = dirlookup( vol, did )) ) {
1100 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
1101 return get_afp_errno(AFPERR_NOOBJ);
1104 upath = s_path->u_name;
1105 isadir = path_isadir(s_path);
1106 if (isadir || !(of = of_findname(s_path))) {
1107 memset(&ad, 0, sizeof(ad));
1111 if ( ad_open( upath,
1112 ( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
1113 O_RDONLY, 0666, adp) < 0 ) {
1114 return( AFPERR_NOITEM );
1118 * Make sure the AD file is not bogus.
1120 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
1121 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
1122 ad_close( adp, ADFLAGS_HF );
1123 return( AFPERR_NOITEM );
1126 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
1127 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
1128 ad_getentrylen( adp, ADEID_COMMENT ));
1129 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
1130 ad_close( adp, ADFLAGS_HF );
1132 /* return AFPERR_NOITEM if len == 0 ? */
1136 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
1139 int ibuflen, *rbuflen;
1141 struct adouble ad, *adp;
1145 struct path *s_path;
1154 memcpy( &vid, ibuf, sizeof( vid ));
1155 ibuf += sizeof( vid );
1156 if (NULL == ( vol = getvolbyvid( vid )) ) {
1157 return( AFPERR_PARAM );
1160 memcpy( &did, ibuf, sizeof( did ));
1161 ibuf += sizeof( did );
1162 if (NULL == ( dir = dirlookup( vol, did )) ) {
1166 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
1167 return get_afp_errno(AFPERR_NOOBJ);
1170 upath = s_path->u_name;
1171 if (check_access(upath, OPENACC_WR ) < 0) {
1172 return AFPERR_ACCESS;
1175 isadir = path_isadir(s_path);
1176 if (isadir || !(of = of_findname(s_path))) {
1177 memset(&ad, 0, sizeof(ad));
1182 if ( ad_open( upath,
1183 (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
1184 O_RDWR, 0, adp) < 0 ) {
1187 return( AFPERR_NOITEM );
1189 return( AFPERR_ACCESS );
1191 return( AFPERR_PARAM );
1195 ad_setentrylen( adp, ADEID_COMMENT, 0 );
1196 ad_flush( adp, ADFLAGS_HF );
1197 ad_close( adp, ADFLAGS_HF );