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>
33 #include <atalk/bstrlib.h>
34 #include <atalk/bstradd.h>
35 #include <atalk/errchk.h>
38 #include "directory.h"
43 #define EXEC_MODE (S_IXGRP | S_IXUSR | S_IXOTH)
45 int setdeskmode(const struct vol *vol, const mode_t mode)
48 char wd[ MAXPATHLEN + 1];
50 char modbuf[ 12 + 1], *m;
51 struct dirent *deskp, *subp;
54 if (!dir_rx_set(mode)) {
55 /* want to remove read and search access to owner it will screw the volume */
58 if ( getcwd( wd , MAXPATHLEN) == NULL ) {
62 bstring dtpath = bfromcstr(vol->v_dbpath);
63 bcatcstr(dtpath, "/" APPLEDESKTOP);
65 EC_NEG1( chdir(cfrombstr(dtpath)) );
67 if (( desk = opendir( "." )) == NULL ) {
68 if ( chdir( wd ) < 0 ) {
69 LOG(log_error, logtype_afpd, "setdeskmode: chdir %s: %s", wd, strerror(errno) );
73 for ( deskp = readdir( desk ); deskp != NULL; deskp = readdir( desk )) {
74 if ( strcmp( deskp->d_name, "." ) == 0 ||
75 strcmp( deskp->d_name, ".." ) == 0 || strlen( deskp->d_name ) > 2 ) {
78 strcpy( modbuf, deskp->d_name );
79 strcat( modbuf, "/" );
80 m = strchr( modbuf, '\0' );
81 if (( sub = opendir( deskp->d_name )) == NULL ) {
84 for ( subp = readdir( sub ); subp != NULL; subp = readdir( sub )) {
85 if ( strcmp( subp->d_name, "." ) == 0 ||
86 strcmp( subp->d_name, ".." ) == 0 ) {
90 strcat( modbuf, subp->d_name );
91 /* XXX: need to preserve special modes */
92 if (lstat(modbuf, &st) < 0) {
93 LOG(log_error, logtype_afpd, "setdeskmode: stat %s: %s",fullpathname(modbuf), strerror(errno) );
97 if (S_ISDIR(st.st_mode)) {
101 vol_syml_opt(vol) | vol_chmod_opt(vol)
102 ) < 0 && errno != EPERM) {
103 LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
105 } else if (ochmod(modbuf,
108 vol_syml_opt(vol) | vol_chmod_opt(vol)
109 ) < 0 && errno != EPERM) {
110 LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
115 /* XXX: need to preserve special modes */
116 if (ochmod(deskp->d_name,
119 vol_syml_opt(vol) | vol_chmod_opt(vol)
120 ) < 0 && errno != EPERM) {
121 LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(deskp->d_name), strerror(errno) );
125 if ( chdir( wd ) < 0 ) {
126 LOG(log_error, logtype_afpd, "setdeskmode: chdir %s: %s", wd, strerror(errno) );
129 /* XXX: need to preserve special modes */
130 if (ochmod(bdata(dtpath),
133 vol_syml_opt(vol) | vol_chmod_opt(vol)
134 ) < 0 && errno != EPERM) {
135 LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s", bdata(dtpath), strerror(errno));
143 int setdeskowner(const struct vol *vol, uid_t uid, gid_t gid)
146 char wd[ MAXPATHLEN + 1];
147 char modbuf[12 + 1], *m;
148 struct dirent *deskp, *subp;
151 if ( getcwd( wd, MAXPATHLEN ) == NULL ) {
155 bstring dtpath = bfromcstr(vol->v_dbpath);
156 bcatcstr(dtpath, "/" APPLEDESKTOP);
158 EC_NEG1( chdir(cfrombstr(dtpath)) );
160 if (( desk = opendir( "." )) == NULL ) {
161 if ( chdir( wd ) < 0 ) {
162 LOG(log_error, logtype_afpd, "setdeskowner: chdir %s: %s", wd, strerror(errno) );
166 for ( deskp = readdir( desk ); deskp != NULL; deskp = readdir( desk )) {
167 if ( strcmp( deskp->d_name, "." ) == 0 ||
168 strcmp( deskp->d_name, ".." ) == 0 ||
169 strlen( deskp->d_name ) > 2 ) {
172 strcpy( modbuf, deskp->d_name );
173 strcat( modbuf, "/" );
174 m = strchr( modbuf, '\0' );
175 if (( sub = opendir( deskp->d_name )) == NULL ) {
178 for ( subp = readdir( sub ); subp != NULL; subp = readdir( sub )) {
179 if ( strcmp( subp->d_name, "." ) == 0 ||
180 strcmp( subp->d_name, ".." ) == 0 ) {
184 strcat( modbuf, subp->d_name );
185 /* XXX: add special any uid, ignore group bits */
186 if ( chown( modbuf, uid, gid ) < 0 && errno != EPERM ) {
187 LOG(log_error, logtype_afpd, "setdeskown: chown %s: %s", fullpathname(modbuf), strerror(errno) );
191 /* XXX: add special any uid, ignore group bits */
192 if ( chown( deskp->d_name, uid, gid ) < 0 && errno != EPERM ) {
193 LOG(log_error, logtype_afpd, "setdeskowner: chown %s: %s",
194 deskp->d_name, strerror(errno) );
198 if ( chdir( wd ) < 0 ) {
199 LOG(log_error, logtype_afpd, "setdeskowner: chdir %s: %s", wd, strerror(errno) );
202 if (chown(cfrombstr(dtpath), uid, gid ) < 0 && errno != EPERM ) {
203 LOG(log_error, logtype_afpd, "setdeskowner: chown %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
211 static void create_appledesktop_folder(const struct vol * vol)
213 bstring olddtpath = NULL, dtpath = NULL;
217 olddtpath = bfromcstr(vol->v_path);
218 bcatcstr(olddtpath, "/" APPLEDESKTOP);
220 dtpath = bfromcstr(vol->v_dbpath);
221 bcatcstr(dtpath, "/" APPLEDESKTOP);
223 if (lstat(cfrombstr(dtpath), &st) != 0) {
227 if (lstat(cfrombstr(olddtpath), &st) == 0) {
229 cmd_argv[1] = bdata(olddtpath);
230 cmd_argv[2] = bdata(dtpath);
232 if (run_cmd("mv", cmd_argv) != 0) {
233 LOG(log_error, logtype_afpd, "moving .AppleDesktop from \"%s\" to \"%s\" failed",
234 bdata(olddtpath), bdata(dtpath));
235 mkdir(cfrombstr(dtpath), 0777);
238 mkdir(cfrombstr(dtpath), 0777);
248 int afp_opendt(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
255 memcpy( &vid, ibuf, sizeof(vid));
256 if (NULL == ( vol = getvolbyvid( vid )) ) {
258 return( AFPERR_PARAM );
261 create_appledesktop_folder(vol);
263 memcpy( rbuf, &vid, sizeof(vid));
264 *rbuflen = sizeof(vid);
268 int afp_closedt(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
274 static struct savedt si = { { 0, 0, 0, 0 }, -1, 0, 0 };
276 static char *icon_dtfile(struct vol *vol, u_char creator[ 4 ])
278 return dtfile( vol, creator, ".icon" );
281 static int iconopen(struct vol *vol, u_char creator[ 4 ], int flags, int mode)
283 char *dtf, *adt, *adts;
285 if ( si.sdt_fd != -1 ) {
286 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
287 si.sdt_vid == vol->v_vid ) {
294 dtf = icon_dtfile( vol, creator);
296 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
297 if ( errno == ENOENT && ( flags & O_CREAT )) {
298 if (( adts = strrchr( dtf, '/' )) == NULL ) {
302 if (( adt = strrchr( dtf, '/' )) == NULL ) {
306 (void) ad_mkdir( dtf, DIRBITS | 0777 );
308 (void) ad_mkdir( dtf, DIRBITS | 0777 );
311 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
312 LOG(log_error, logtype_afpd, "iconopen(%s): open: %s", dtf, strerror(errno) );
320 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
321 si.sdt_vid = vol->v_vid;
326 int afp_addicon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
329 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
330 int itype, cc = AFP_OK, iovcnt = 0;
332 uint32_t ftype, itag;
333 uint16_t bsize, rsize, vid;
339 memcpy( &vid, ibuf, sizeof( vid ));
340 ibuf += sizeof( vid );
341 if (NULL == ( vol = getvolbyvid( vid )) ) {
346 memcpy( fcreator, ibuf, sizeof( fcreator ));
347 ibuf += sizeof( fcreator );
349 memcpy( &ftype, ibuf, sizeof( ftype ));
350 ibuf += sizeof( ftype );
352 itype = (unsigned char) *ibuf;
355 memcpy( &itag, ibuf, sizeof( itag ));
356 ibuf += sizeof( itag );
358 memcpy( &bsize, ibuf, sizeof( bsize ));
359 bsize = ntohs( bsize );
361 if ( si.sdt_fd != -1 ) {
362 (void)close( si.sdt_fd );
366 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
371 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
374 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
380 * Read icon elements until we find a match to replace, or
381 * we get to the end to insert.
384 memcpy( p, &itag, sizeof( itag ));
386 memcpy( p, &ftype, sizeof( ftype ));
387 p += sizeof( ftype );
390 bsize = htons( bsize );
391 memcpy( p, &bsize, sizeof( bsize ));
392 bsize = ntohs( bsize );
393 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
394 memcpy( &rsize, irh + 10, sizeof( rsize ));
395 rsize = ntohs( rsize );
397 * Is this our set of headers?
399 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
401 * Is the size correct?
403 if ( bsize != rsize )
408 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
409 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator),strerror(errno) );
415 * Some error occurred, return.
419 dsi_writeinit(obj->dsi, rbuf, buflen);
420 dsi_writeflush(obj->dsi);
426 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
428 /* add headers at end of file */
429 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
430 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
435 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
436 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
441 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
442 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
443 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
454 static const u_char utag[] = { 0, 0, 0, 0 };
455 static const u_char ucreator[] = { 0, 0, 0, 0 };/* { 'U', 'N', 'I', 'X' };*/
456 static const u_char utype[] = { 0, 0, 0, 0 };/* { 'T', 'E', 'X', 'T' };*/
457 static const short usize = 256;
460 static const u_char uicon[] = {
461 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
462 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
463 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
464 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
465 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
466 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
467 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
468 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
469 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
470 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
471 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
472 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
473 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
474 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
475 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
476 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
477 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
478 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
479 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
480 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
481 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
482 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
483 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
484 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
485 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
486 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
487 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
488 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
489 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
490 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
491 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
492 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
496 int afp_geticoninfo(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
499 unsigned char fcreator[ 4 ], ih[ 12 ];
500 uint16_t vid, iindex, bsize;
505 memcpy( &vid, ibuf, sizeof( vid ));
506 ibuf += sizeof( vid );
507 if (NULL == ( vol = getvolbyvid( vid )) ) {
508 return( AFPERR_PARAM );
511 memcpy( fcreator, ibuf, sizeof( fcreator ));
512 ibuf += sizeof( fcreator );
513 memcpy( &iindex, ibuf, sizeof( iindex ));
514 iindex = ntohs( iindex );
516 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
518 return( AFPERR_NOITEM );
520 memcpy( ih, utag, sizeof( utag ));
521 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
522 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
523 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
524 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
526 memcpy( rbuf, ih, sizeof( ih ));
527 *rbuflen = sizeof( ih );
531 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
532 return( AFPERR_NOITEM );
535 if ( iindex < si.sdt_index ) {
536 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
537 return( AFPERR_PARAM );
543 * Position to the correct spot.
546 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
549 return( AFPERR_NOITEM );
551 memcpy( &bsize, ih + 10, sizeof( bsize ));
552 bsize = ntohs(bsize);
553 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
554 LOG(log_error, logtype_afpd, "afp_iconinfo(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
555 return( AFPERR_PARAM );
557 if ( si.sdt_index == iindex ) {
558 memcpy( rbuf, ih, sizeof( ih ));
559 *rbuflen = sizeof( ih );
567 int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
572 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
573 uint16_t vid, bsize, rsize;
579 memcpy( &vid, ibuf, sizeof( vid ));
580 ibuf += sizeof( vid );
581 if (NULL == ( vol = getvolbyvid( vid )) ) {
582 return( AFPERR_PARAM );
585 memcpy( fcreator, ibuf, sizeof( fcreator ));
586 ibuf += sizeof( fcreator );
587 memcpy( ftype, ibuf, sizeof( ftype ));
588 ibuf += sizeof( ftype );
589 itype = (unsigned char) *ibuf++;
591 memcpy( &bsize, ibuf, sizeof( bsize ));
592 bsize = ntohs( bsize );
595 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
596 memcmp( ftype, utype, sizeof( utype )) == 0 &&
599 memcpy( rbuf, uicon, bsize);
605 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
606 return( AFPERR_NOITEM );
609 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
612 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno));
613 return( AFPERR_PARAM );
618 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
620 offset += sizeof(ih);
621 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
622 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
625 memcpy( &rsize, ih + 10, sizeof( rsize ));
626 rsize = ntohs( rsize );
627 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
628 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
629 return( AFPERR_PARAM );
635 LOG(log_error, logtype_afpd, "afp_geticon(%s): read: %s", icon_dtfile(vol, fcreator), strerror(errno));
636 return( AFPERR_PARAM );
640 return( AFPERR_NOITEM );
643 memcpy( &rsize, ih + 10, sizeof( rsize ));
644 rsize = ntohs( rsize );
645 #define min(a,b) ((a)<(b)?(a):(b))
646 rc = min( bsize, rsize );
653 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
654 if (size < rc + offset) {
658 #ifndef WITH_SENDFILE
659 if ((buflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
664 /* do to the streaming nature, we have to exit if we encounter
665 * a problem. much confusion results otherwise. */
666 while (*rbuflen > 0) {
668 if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize, AFP_OK) < 0) {
671 case EINVAL: /* there's no guarantee that all fs support sendfile */
682 buflen = read(si.sdt_fd, rbuf, *rbuflen);
686 /* dsi_read() also returns buffer size of next allocation */
687 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
698 LOG(log_error, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno));
700 obj->exit(EXITERR_SYS);
704 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
705 return( AFPERR_PARAM );
712 /* ---------------------- */
713 static const char hexdig[] = "0123456789abcdef";
714 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
716 static char path[ MAXPATHLEN + 1];
720 strcpy( path, vol->v_dbpath );
721 strcat( path, "/" APPLEDESKTOP "/" );
722 for ( p = path; *p != '\0'; p++ )
725 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
726 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
727 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
734 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
735 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
736 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
737 *p++ = hexdig[ creator[ i ] & 0x0f ];
748 /* ---------------------------
749 * mpath is only a filename
750 * did filename parent directory ID.
753 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
755 static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
761 if ( *mpath == '\0' ) {
766 /* set conversion flags */
767 flags = vol->v_mtou_flags;
769 m = demangle(vol, mpath, did);
780 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)) ) {
781 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
786 LOG(log_debug9, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
794 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
796 static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
802 outlen = strlen(upath);
804 flags = vol->v_utom_flags;
808 /* convert charsets */
809 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)) ) {
810 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
814 flags = !!(flags & CONV_REQMANGLE);
819 m = mangle(vol, mpath, outlen, upath, id, flags);
822 LOG(log_debug9, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
828 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
832 /* ------------------------- */
833 static int ad_addcomment(const AFPObj *obj, struct vol *vol, struct path *path, char *ibuf)
839 struct adouble ad, *adp;
841 clen = (u_char)*ibuf++;
842 clen = min( clen, 199 );
844 upath = path->u_name;
845 if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
846 return AFPERR_ACCESS;
849 isadir = path_isadir(path);
850 if (isadir || !(of = of_findname(vol, path))) {
856 if (ad_open(adp, upath,
857 ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0) | ADFLAGS_CREATE | ADFLAGS_RDWR,
859 return( AFPERR_ACCESS );
862 if (ad_getentryoff(adp, ADEID_COMMENT)) {
863 if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
864 if ( *path->m_name == '\0' ) {
865 name = (char *)curdir->d_m_name->data;
869 ad_setname(adp, name);
871 ad_setentrylen( adp, ADEID_COMMENT, clen );
872 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
875 ad_close(adp, ADFLAGS_HF);
879 /* ----------------------------- */
880 int afp_addcomment(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
891 memcpy( &vid, ibuf, sizeof( vid ));
892 ibuf += sizeof( vid );
893 if (NULL == ( vol = getvolbyvid( vid )) ) {
894 return( AFPERR_PARAM );
897 memcpy( &did, ibuf, sizeof( did ));
898 ibuf += sizeof( did );
899 if (NULL == ( dir = dirlookup( vol, did )) ) {
903 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
904 return get_afp_errno(AFPERR_NOOBJ);
907 if ((u_long)ibuf & 1 ) {
911 return ad_addcomment(obj, vol, path, ibuf);
914 /* -------------------- */
915 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuflen)
917 struct adouble ad, *adp;
923 upath = path->u_name;
924 isadir = path_isadir(path);
925 if (isadir || !(of = of_findname(vol, path))) {
931 if ( ad_metadata( upath, ((isadir) ? ADFLAGS_DIR : 0), adp) < 0 ) {
932 return( AFPERR_NOITEM );
935 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
936 ad_close(adp, ADFLAGS_HF);
937 return AFPERR_NOITEM;
940 * Make sure the AD file is not bogus.
942 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
943 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
944 ad_close(adp, ADFLAGS_HF);
945 return( AFPERR_NOITEM );
948 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
950 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
952 ad_close(adp, ADFLAGS_HF);
957 /* -------------------- */
958 int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
969 memcpy( &vid, ibuf, sizeof( vid ));
970 ibuf += sizeof( vid );
971 if (NULL == ( vol = getvolbyvid( vid )) ) {
972 return( AFPERR_PARAM );
975 memcpy( &did, ibuf, sizeof( did ));
976 ibuf += sizeof( did );
977 if (NULL == ( dir = dirlookup( vol, did )) ) {
981 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
982 return get_afp_errno(AFPERR_NOOBJ);
985 return ad_getcomment(vol, s_path, rbuf, rbuflen);
988 /* ----------------------- */
989 static int ad_rmvcomment(const AFPObj *obj, struct vol *vol, struct path *path)
991 struct adouble ad, *adp;
996 upath = path->u_name;
997 if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
998 return AFPERR_ACCESS;
1001 isadir = path_isadir(path);
1002 if (isadir || !(of = of_findname(vol, path))) {
1008 if ( ad_open(adp, upath, ADFLAGS_HF | ADFLAGS_RDWR | ((isadir) ? ADFLAGS_DIR : 0)) < 0 ) {
1011 return( AFPERR_NOITEM );
1013 return( AFPERR_ACCESS );
1015 return( AFPERR_PARAM );
1019 if (ad_getentryoff(adp, ADEID_COMMENT)) {
1020 ad_setentrylen( adp, ADEID_COMMENT, 0 );
1023 ad_close(adp, ADFLAGS_HF);
1027 /* ----------------------- */
1028 int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
1032 struct path *s_path;
1039 memcpy( &vid, ibuf, sizeof( vid ));
1040 ibuf += sizeof( vid );
1041 if (NULL == ( vol = getvolbyvid( vid )) ) {
1042 return( AFPERR_PARAM );
1045 memcpy( &did, ibuf, sizeof( did ));
1046 ibuf += sizeof( did );
1047 if (NULL == ( dir = dirlookup( vol, did )) ) {
1051 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
1052 return get_afp_errno(AFPERR_NOOBJ);
1055 return ad_rmvcomment(obj, vol, s_path);