2 * $Id: desktop.c,v 1.29 2003-06-05 09:17:10 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 (NULL == ( vol = getvolbyvid( vid )) ) {
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 if ((vol->v_casefold & (AFPVOL_MTOUUPPER| AFPVOL_MTOULOWER))) {
635 while ( *m != '\0' ) {
636 /* handle case conversion first */
637 if (vol->v_casefold & AFPVOL_MTOUUPPER)
638 *m = diatoupper( *m );
639 else if (vol->v_casefold & AFPVOL_MTOULOWER)
640 *m = diatolower( *m );
642 /* we have a code page. we only use the ascii range
643 * if we have map ascii specified. */
644 if (vol->v_mtoupage && ((*m & 0x80) ||
645 vol->v_flags & AFPVOL_MAPASCII)) {
646 *u = vol->v_mtoupage->map[(unsigned char) *m].value;
649 /* if conversion failed, encode in hex
650 * to prevent silly truncation
651 * H.P. Jansen <hpj@urpla.net> */
653 LOG(log_debug, logtype_afpd, "mtoupath: hex encode: 0x%x", (unsigned char) *m);
656 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
657 *u = hexdig[ *m & 0x0f ];
660 #if AD_VERSION == AD_VERSION1
661 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
662 (!isascii(*m) || *m == '/')) ||
663 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
664 ( i == 0 && (*m == '.' )))) {
666 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
667 (!isprint(*m) || *m == '/')) ||
668 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
669 ( i == 0 && (*m == '.' )))) {
671 /* do hex conversion. */
673 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
674 *u = hexdig[ *m & 0x0f ];
686 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
689 return( (changed)?upath:mpath );
692 /* ---------------------------- */
693 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
694 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
696 static char *old_utompath(const struct vol *vol, char *upath)
702 /* do the hex conversion */
705 if ((vol->v_casefold & (AFPVOL_MTOUUPPER| AFPVOL_MTOULOWER))) {
708 while ( *u != '\0' ) {
709 /* we have a code page */
710 if (vol->v_utompage && ((*u & 0x80) ||
711 (vol->v_flags & AFPVOL_MAPASCII))) {
712 *m = vol->v_utompage->map[(unsigned char) *u].value;
715 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
716 *(u+2) != '\0' && islxdigit( *(u+2))) {
718 h = hextoint( *u ) << 4;
726 /* handle case conversion */
727 if (vol->v_casefold & AFPVOL_UTOMLOWER)
728 *m = diatolower( *m );
729 else if (vol->v_casefold & AFPVOL_UTOMUPPER)
730 *m = diatoupper( *m );
739 m = mangle(vol, mpath, upath, 0);
743 #endif /* FILE_MANGLING */
746 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s'", upath, mpath);
749 return((changed)? m:upath );
752 /* --------------- */
753 extern unsigned int do_precomposition(unsigned int base, unsigned int comb);
755 static char comp[MAXPATHLEN +1];
757 static char *precompose(u_int16_t *name, size_t inplen, size_t *outlen)
760 u_int16_t base, comb;
764 if (!inplen || (inplen & 1) || inplen > sizeof(comp)/sizeof(u_int16_t))
768 out = (u_int16_t *)comp;
781 if (comb >= 0x300 && (result = do_precomposition(base, comb))) {
800 /* --------------- */
801 extern unsigned int do_decomposition(unsigned int base);
803 static char *decompose(u_int16_t *name, size_t inplen, size_t *outlen)
810 if (!inplen || (inplen & 1))
814 out = (u_int16_t *)comp;
818 if (*outlen >= sizeof(comp)/sizeof(u_int16_t) +2) {
822 if ((result = do_decomposition(base))) {
826 *out = result & 0xffff;
841 /* --------------------------- */
842 char *mtoupath(const struct vol *vol, char *mpath, int utf8)
849 if ( *mpath == '\0' ) {
854 m = demangle(vol, mpath);
858 #endif /* FILE_MANGLING */
861 return old_mtoupath(vol, mpath);
865 while ( *m != '\0' ) {
866 if ( (!(vol->v_flags & AFPVOL_NOHEX) && *m == '/') ||
867 (!(vol->v_flags & AFPVOL_USEDOTS) && i == 0 && *m == '.') ||
868 (!utf8 && (unsigned char)*m == 0xf0) /* Apple logo */
870 /* do hex conversion. */
872 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
873 *u = hexdig[ *m & 0x0f ];
887 if ((size_t)(-1) == iconv(vol->v_mactoutf8, 0,0,0,0) )
889 /* assume precompose */
890 if ((size_t)(-1) == iconv(vol->v_mactoutf8, &u, &inplen, &r, &outlen))
895 if ((size_t)(-1) == iconv(vol->v_utf8toucs2, 0,0,0,0) )
898 if ((size_t)(-1) == iconv(vol->v_utf8toucs2, &u, &inplen, &r, &outlen))
901 u = precompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen);
903 if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, 0,0,0,0))
908 if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, &u, &inplen, &r, &outlen))
912 u[MAXPATHLEN -outlen] = 0;
915 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
920 /* --------------- */
921 char *utompath(const struct vol *vol, char *upath, int utf8)
930 return old_utompath(vol, upath);
931 /* do the hex conversion */
934 while ( *u != '\0' ) {
935 if ( *u == ':' && islxdigit( *(u+1)) && islxdigit( *(u+2))) {
937 h = hextoint( *u ) << 4;
949 if ((size_t)(-1) == iconv(vol->v_utf8toucs2, 0,0,0,0) )
951 inplen = strlen(mpath);
954 if ((size_t)(-1) == iconv(vol->v_utf8toucs2, &m, &inplen, &r, &outlen))
958 if ( NULL == (m = decompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen)))
961 if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, 0,0,0,0))
966 if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, &m, &inplen, &r, &outlen))
970 m = precompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen);
972 if ((size_t)(-1) == iconv(vol->v_ucs2tomac, 0,0,0,0))
977 if ((size_t)(-1) == iconv(vol->v_ucs2tomac, &m, &inplen, &r, &outlen)) {
980 if (outlen != MAXPATHLEN) {
988 mpath[MAXPATHLEN -outlen] = 0;
991 m = mangle(vol, mpath, upath, mangleflag);
996 #endif /* FILE_MANGLING */
1001 /* ----------------------------- */
1002 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
1005 int ibuflen, *rbuflen;
1007 struct adouble ad, *adp;
1021 memcpy( &vid, ibuf, sizeof( vid ));
1022 ibuf += sizeof( vid );
1023 if (NULL == ( vol = getvolbyvid( vid )) ) {
1024 return( AFPERR_PARAM );
1027 memcpy( &did, ibuf, sizeof( did ));
1028 ibuf += sizeof( did );
1029 if (NULL == ( dir = dirlookup( vol, did )) ) {
1033 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
1034 return get_afp_errno(AFPERR_NOOBJ);
1037 if ((u_long)ibuf & 1 ) {
1041 clen = (u_char)*ibuf++;
1042 clen = min( clen, 199 );
1044 upath = path->u_name;
1045 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
1046 return AFPERR_ACCESS;
1049 isadir = path_isadir(path);
1050 if (isadir || !(of = of_findname(path))) {
1051 memset(&ad, 0, sizeof(ad));
1056 if (ad_open( upath , vol_noadouble(vol) |
1057 (( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
1058 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
1059 return( AFPERR_ACCESS );
1062 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
1063 if ( *path->m_name == '\0' ) {
1064 name = curdir->d_m_name;
1066 name = path->m_name;
1068 ad_setentrylen( adp, ADEID_NAME, strlen( name ));
1069 memcpy( ad_entry( adp, ADEID_NAME ), name,
1070 ad_getentrylen( adp, ADEID_NAME ));
1073 ad_setentrylen( adp, ADEID_COMMENT, clen );
1074 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
1075 ad_flush( adp, ADFLAGS_HF );
1076 ad_close( adp, ADFLAGS_HF );
1080 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
1083 int ibuflen, *rbuflen;
1085 struct adouble ad, *adp;
1089 struct path *s_path;
1098 memcpy( &vid, ibuf, sizeof( vid ));
1099 ibuf += sizeof( vid );
1100 if (NULL == ( vol = getvolbyvid( vid )) ) {
1101 return( AFPERR_PARAM );
1104 memcpy( &did, ibuf, sizeof( did ));
1105 ibuf += sizeof( did );
1106 if (NULL == ( dir = dirlookup( vol, did )) ) {
1110 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
1111 return get_afp_errno(AFPERR_NOOBJ);
1114 upath = s_path->u_name;
1115 isadir = path_isadir(s_path);
1116 if (isadir || !(of = of_findname(s_path))) {
1117 memset(&ad, 0, sizeof(ad));
1121 if ( ad_open( upath,
1122 ( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
1123 O_RDONLY, 0666, adp) < 0 ) {
1124 return( AFPERR_NOITEM );
1128 * Make sure the AD file is not bogus.
1130 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
1131 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
1132 ad_close( adp, ADFLAGS_HF );
1133 return( AFPERR_NOITEM );
1136 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
1137 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
1138 ad_getentrylen( adp, ADEID_COMMENT ));
1139 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
1140 ad_close( adp, ADFLAGS_HF );
1142 /* return AFPERR_NOITEM if len == 0 ? */
1146 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
1149 int ibuflen, *rbuflen;
1151 struct adouble ad, *adp;
1155 struct path *s_path;
1164 memcpy( &vid, ibuf, sizeof( vid ));
1165 ibuf += sizeof( vid );
1166 if (NULL == ( vol = getvolbyvid( vid )) ) {
1167 return( AFPERR_PARAM );
1170 memcpy( &did, ibuf, sizeof( did ));
1171 ibuf += sizeof( did );
1172 if (NULL == ( dir = dirlookup( vol, did )) ) {
1176 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
1177 return get_afp_errno(AFPERR_NOOBJ);
1180 upath = s_path->u_name;
1181 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
1182 return AFPERR_ACCESS;
1185 isadir = path_isadir(s_path);
1186 if (isadir || !(of = of_findname(s_path))) {
1187 memset(&ad, 0, sizeof(ad));
1192 if ( ad_open( upath,
1193 (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
1194 O_RDWR, 0, adp) < 0 ) {
1197 return( AFPERR_NOITEM );
1199 return( AFPERR_ACCESS );
1201 return( AFPERR_PARAM );
1205 ad_setentrylen( adp, ADEID_COMMENT, 0 );
1206 ad_flush( adp, ADFLAGS_HF );
1207 ad_close( adp, ADFLAGS_HF );