2 * $Id: desktop.c,v 1.30 2003-06-09 14:42:38 srittau 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];
623 static char ucs2[ MAXPATHLEN + 1];
626 static char *old_mtoupath(const struct vol *vol, char *mpath)
634 if ((vol->v_casefold & (AFPVOL_MTOUUPPER| AFPVOL_MTOULOWER))) {
637 while ( *m != '\0' ) {
638 /* handle case conversion first */
639 if (vol->v_casefold & AFPVOL_MTOUUPPER)
640 *m = diatoupper( *m );
641 else if (vol->v_casefold & AFPVOL_MTOULOWER)
642 *m = diatolower( *m );
644 /* we have a code page. we only use the ascii range
645 * if we have map ascii specified. */
646 if (vol->v_mtoupage && ((*m & 0x80) ||
647 vol->v_flags & AFPVOL_MAPASCII)) {
648 *u = vol->v_mtoupage->map[(unsigned char) *m].value;
651 /* if conversion failed, encode in hex
652 * to prevent silly truncation
653 * H.P. Jansen <hpj@urpla.net> */
655 LOG(log_debug, logtype_afpd, "mtoupath: hex encode: 0x%x", (unsigned char) *m);
658 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
659 *u = hexdig[ *m & 0x0f ];
662 #if AD_VERSION == AD_VERSION1
663 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
664 (!isascii(*m) || *m == '/')) ||
665 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
666 ( i == 0 && (*m == '.' )))) {
668 if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
669 (!isprint(*m) || *m == '/')) ||
670 (((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
671 ( i == 0 && (*m == '.' )))) {
673 /* do hex conversion. */
675 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
676 *u = hexdig[ *m & 0x0f ];
688 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
691 return( (changed)?upath:mpath );
694 /* ---------------------------- */
695 #define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
696 #define islxdigit(x) (!isupper(x)&&isxdigit(x))
698 static char *old_utompath(const struct vol *vol, char *upath)
704 /* do the hex conversion */
707 if ((vol->v_casefold & (AFPVOL_MTOUUPPER| AFPVOL_MTOULOWER))) {
710 while ( *u != '\0' ) {
711 /* we have a code page */
712 if (vol->v_utompage && ((*u & 0x80) ||
713 (vol->v_flags & AFPVOL_MAPASCII))) {
714 *m = vol->v_utompage->map[(unsigned char) *u].value;
717 if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
718 *(u+2) != '\0' && islxdigit( *(u+2))) {
720 h = hextoint( *u ) << 4;
728 /* handle case conversion */
729 if (vol->v_casefold & AFPVOL_UTOMLOWER)
730 *m = diatolower( *m );
731 else if (vol->v_casefold & AFPVOL_UTOMUPPER)
732 *m = diatoupper( *m );
741 m = mangle(vol, mpath, upath, 0);
745 #endif /* FILE_MANGLING */
748 LOG(log_debug, logtype_afpd, "utompath: '%s':'%s'", upath, mpath);
751 return((changed)? m:upath );
754 /* --------------- */
756 extern unsigned int do_precomposition(unsigned int base, unsigned int comb);
758 static char comp[MAXPATHLEN +1];
760 static char *precompose(u_int16_t *name, size_t inplen, size_t *outlen)
763 u_int16_t base, comb;
767 if (!inplen || (inplen & 1) || inplen > sizeof(comp)/sizeof(u_int16_t))
771 out = (u_int16_t *)comp;
784 if (comb >= 0x300 && (result = do_precomposition(base, comb))) {
803 /* --------------- */
804 extern unsigned int do_decomposition(unsigned int base);
806 static char *decompose(u_int16_t *name, size_t inplen, size_t *outlen)
813 if (!inplen || (inplen & 1))
817 out = (u_int16_t *)comp;
821 if (*outlen >= sizeof(comp)/sizeof(u_int16_t) +2) {
825 if ((result = do_decomposition(base))) {
829 *out = result & 0xffff;
845 /* --------------------------- */
846 char *mtoupath(const struct vol *vol, char *mpath, int utf8)
856 if ( *mpath == '\0' ) {
861 m = demangle(vol, mpath);
865 #endif /* FILE_MANGLING */
868 return old_mtoupath(vol, mpath);
872 while ( *m != '\0' ) {
873 if ( (!(vol->v_flags & AFPVOL_NOHEX) && *m == '/') ||
874 (!(vol->v_flags & AFPVOL_USEDOTS) && i == 0 && *m == '.') ||
875 (!utf8 && (unsigned char)*m == 0xf0) /* Apple logo */
877 /* do hex conversion. */
879 *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
880 *u = hexdig[ *m & 0x0f ];
894 if ((size_t)(-1) == iconv(vol->v_mactoutf8, 0,0,0,0) )
896 /* assume precompose */
897 if ((size_t)(-1) == iconv(vol->v_mactoutf8, &u, &inplen, &r, &outlen))
902 if ((size_t)(-1) == iconv(vol->v_utf8toucs2, 0,0,0,0) )
905 if ((size_t)(-1) == iconv(vol->v_utf8toucs2, &u, &inplen, &r, &outlen))
908 u = precompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen);
910 if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, 0,0,0,0))
915 if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, &u, &inplen, &r, &outlen))
919 u[MAXPATHLEN -outlen] = 0;
922 LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
927 /* --------------- */
928 char *utompath(const struct vol *vol, char *upath, int utf8)
940 return old_utompath(vol, upath);
941 /* do the hex conversion */
944 while ( *u != '\0' ) {
945 if ( *u == ':' && islxdigit( *(u+1)) && islxdigit( *(u+2))) {
947 h = hextoint( *u ) << 4;
959 if ((size_t)(-1) == iconv(vol->v_utf8toucs2, 0,0,0,0) )
961 inplen = strlen(mpath);
964 if ((size_t)(-1) == iconv(vol->v_utf8toucs2, &m, &inplen, &r, &outlen))
968 if ( NULL == (m = decompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen)))
971 if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, 0,0,0,0))
976 if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, &m, &inplen, &r, &outlen))
980 m = precompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen);
982 if ((size_t)(-1) == iconv(vol->v_ucs2tomac, 0,0,0,0))
987 if ((size_t)(-1) == iconv(vol->v_ucs2tomac, &m, &inplen, &r, &outlen)) {
990 if (outlen != MAXPATHLEN) {
998 mpath[MAXPATHLEN -outlen] = 0;
1000 #ifdef FILE_MANGLING
1001 m = mangle(vol, mpath, upath, mangleflag);
1006 #endif /* FILE_MANGLING */
1011 /* ----------------------------- */
1012 int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
1015 int ibuflen, *rbuflen;
1017 struct adouble ad, *adp;
1031 memcpy( &vid, ibuf, sizeof( vid ));
1032 ibuf += sizeof( vid );
1033 if (NULL == ( vol = getvolbyvid( vid )) ) {
1034 return( AFPERR_PARAM );
1037 memcpy( &did, ibuf, sizeof( did ));
1038 ibuf += sizeof( did );
1039 if (NULL == ( dir = dirlookup( vol, did )) ) {
1043 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
1044 return get_afp_errno(AFPERR_NOOBJ);
1047 if ((u_long)ibuf & 1 ) {
1051 clen = (u_char)*ibuf++;
1052 clen = min( clen, 199 );
1054 upath = path->u_name;
1055 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
1056 return AFPERR_ACCESS;
1059 isadir = path_isadir(path);
1060 if (isadir || !(of = of_findname(path))) {
1061 memset(&ad, 0, sizeof(ad));
1066 if (ad_open( upath , vol_noadouble(vol) |
1067 (( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
1068 O_RDWR|O_CREAT, 0666, adp) < 0 ) {
1069 return( AFPERR_ACCESS );
1072 if ( (ad_getoflags( adp, ADFLAGS_HF ) & O_CREAT) ) {
1073 if ( *path->m_name == '\0' ) {
1074 name = curdir->d_m_name;
1076 name = path->m_name;
1078 ad_setentrylen( adp, ADEID_NAME, strlen( name ));
1079 memcpy( ad_entry( adp, ADEID_NAME ), name,
1080 ad_getentrylen( adp, ADEID_NAME ));
1083 ad_setentrylen( adp, ADEID_COMMENT, clen );
1084 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
1085 ad_flush( adp, ADFLAGS_HF );
1086 ad_close( adp, ADFLAGS_HF );
1090 int afp_getcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
1093 int ibuflen, *rbuflen;
1095 struct adouble ad, *adp;
1099 struct path *s_path;
1108 memcpy( &vid, ibuf, sizeof( vid ));
1109 ibuf += sizeof( vid );
1110 if (NULL == ( vol = getvolbyvid( vid )) ) {
1111 return( AFPERR_PARAM );
1114 memcpy( &did, ibuf, sizeof( did ));
1115 ibuf += sizeof( did );
1116 if (NULL == ( dir = dirlookup( vol, did )) ) {
1120 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
1121 return get_afp_errno(AFPERR_NOOBJ);
1124 upath = s_path->u_name;
1125 isadir = path_isadir(s_path);
1126 if (isadir || !(of = of_findname(s_path))) {
1127 memset(&ad, 0, sizeof(ad));
1131 if ( ad_open( upath,
1132 ( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
1133 O_RDONLY, 0666, adp) < 0 ) {
1134 return( AFPERR_NOITEM );
1138 * Make sure the AD file is not bogus.
1140 if ( ad_getentrylen( adp, ADEID_COMMENT ) < 0 ||
1141 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
1142 ad_close( adp, ADFLAGS_HF );
1143 return( AFPERR_NOITEM );
1146 *rbuf++ = ad_getentrylen( adp, ADEID_COMMENT );
1147 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ),
1148 ad_getentrylen( adp, ADEID_COMMENT ));
1149 *rbuflen = ad_getentrylen( adp, ADEID_COMMENT ) + 1;
1150 ad_close( adp, ADFLAGS_HF );
1152 /* return AFPERR_NOITEM if len == 0 ? */
1156 int afp_rmvcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
1159 int ibuflen, *rbuflen;
1161 struct adouble ad, *adp;
1165 struct path *s_path;
1174 memcpy( &vid, ibuf, sizeof( vid ));
1175 ibuf += sizeof( vid );
1176 if (NULL == ( vol = getvolbyvid( vid )) ) {
1177 return( AFPERR_PARAM );
1180 memcpy( &did, ibuf, sizeof( did ));
1181 ibuf += sizeof( did );
1182 if (NULL == ( dir = dirlookup( vol, did )) ) {
1186 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
1187 return get_afp_errno(AFPERR_NOOBJ);
1190 upath = s_path->u_name;
1191 if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
1192 return AFPERR_ACCESS;
1195 isadir = path_isadir(s_path);
1196 if (isadir || !(of = of_findname(s_path))) {
1197 memset(&ad, 0, sizeof(ad));
1202 if ( ad_open( upath,
1203 (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
1204 O_RDWR, 0, adp) < 0 ) {
1207 return( AFPERR_NOITEM );
1209 return( AFPERR_ACCESS );
1211 return( AFPERR_PARAM );
1215 ad_setentrylen( adp, ADEID_COMMENT, 0 );
1216 ad_flush( adp, ADFLAGS_HF );
1217 ad_close( adp, ADFLAGS_HF );