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/errchk.h>
37 #include "directory.h"
42 #define EXEC_MODE (S_IXGRP | S_IXUSR | S_IXOTH)
44 int setdeskmode(const struct vol *vol, const mode_t mode)
47 char wd[ MAXPATHLEN + 1];
49 char modbuf[ 12 + 1], *m;
50 struct dirent *deskp, *subp;
53 if (!dir_rx_set(mode)) {
54 /* want to remove read and search access to owner it will screw the volume */
57 if ( getcwd( wd , MAXPATHLEN) == NULL ) {
61 bstring dtpath = bfromcstr(vol->v_dbpath);
62 bcatcstr(dtpath, "/" APPLEDESKTOP);
64 EC_NEG1( chdir(bdata(dtpath)) );
66 if (( desk = opendir( "." )) == NULL ) {
67 if ( chdir( wd ) < 0 ) {
68 LOG(log_error, logtype_afpd, "setdeskmode: chdir %s: %s", wd, strerror(errno) );
72 for ( deskp = readdir( desk ); deskp != NULL; deskp = readdir( desk )) {
73 if ( strcmp( deskp->d_name, "." ) == 0 ||
74 strcmp( deskp->d_name, ".." ) == 0 || strlen( deskp->d_name ) > 2 ) {
77 strcpy( modbuf, deskp->d_name );
78 strcat( modbuf, "/" );
79 m = strchr( modbuf, '\0' );
80 if (( sub = opendir( deskp->d_name )) == NULL ) {
83 for ( subp = readdir( sub ); subp != NULL; subp = readdir( sub )) {
84 if ( strcmp( subp->d_name, "." ) == 0 ||
85 strcmp( subp->d_name, ".." ) == 0 ) {
89 strcat( modbuf, subp->d_name );
90 /* XXX: need to preserve special modes */
91 if (lstat(modbuf, &st) < 0) {
92 LOG(log_error, logtype_afpd, "setdeskmode: stat %s: %s",fullpathname(modbuf), strerror(errno) );
96 if (S_ISDIR(st.st_mode)) {
97 if ( chmod_acl( modbuf, (DIRBITS | mode)) < 0 && errno != EPERM ) {
98 LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
100 } else if ( chmod_acl( modbuf, mode & ~EXEC_MODE ) < 0 && errno != EPERM ) {
101 LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
106 /* XXX: need to preserve special modes */
107 if ( chmod_acl( deskp->d_name, (DIRBITS | mode)) < 0 && errno != EPERM ) {
108 LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(deskp->d_name), strerror(errno) );
112 if ( chdir( wd ) < 0 ) {
113 LOG(log_error, logtype_afpd, "setdeskmode: chdir %s: %s", wd, strerror(errno) );
116 /* XXX: need to preserve special modes */
117 if ( chmod_acl(bdata(dtpath), (DIRBITS | mode)) < 0 && errno != EPERM ) {
118 LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s", bdata(dtpath), strerror(errno));
126 int setdeskowner(const struct vol *vol, uid_t uid, gid_t gid)
129 char wd[ MAXPATHLEN + 1];
130 char modbuf[12 + 1], *m;
131 struct dirent *deskp, *subp;
134 if ( getcwd( wd, MAXPATHLEN ) == NULL ) {
138 bstring dtpath = bfromcstr(vol->v_dbpath);
139 bcatcstr(dtpath, "/" APPLEDESKTOP);
141 EC_NEG1( chdir(bdata(dtpath)) );
143 if (( desk = opendir( "." )) == NULL ) {
144 if ( chdir( wd ) < 0 ) {
145 LOG(log_error, logtype_afpd, "setdeskowner: chdir %s: %s", wd, strerror(errno) );
149 for ( deskp = readdir( desk ); deskp != NULL; deskp = readdir( desk )) {
150 if ( strcmp( deskp->d_name, "." ) == 0 ||
151 strcmp( deskp->d_name, ".." ) == 0 ||
152 strlen( deskp->d_name ) > 2 ) {
155 strcpy( modbuf, deskp->d_name );
156 strcat( modbuf, "/" );
157 m = strchr( modbuf, '\0' );
158 if (( sub = opendir( deskp->d_name )) == NULL ) {
161 for ( subp = readdir( sub ); subp != NULL; subp = readdir( sub )) {
162 if ( strcmp( subp->d_name, "." ) == 0 ||
163 strcmp( subp->d_name, ".." ) == 0 ) {
167 strcat( modbuf, subp->d_name );
168 /* XXX: add special any uid, ignore group bits */
169 if ( chown( modbuf, uid, gid ) < 0 && errno != EPERM ) {
170 LOG(log_error, logtype_afpd, "setdeskown: chown %s: %s", fullpathname(modbuf), strerror(errno) );
174 /* XXX: add special any uid, ignore group bits */
175 if ( chown( deskp->d_name, uid, gid ) < 0 && errno != EPERM ) {
176 LOG(log_error, logtype_afpd, "setdeskowner: chown %s: %s",
177 deskp->d_name, strerror(errno) );
181 if ( chdir( wd ) < 0 ) {
182 LOG(log_error, logtype_afpd, "setdeskowner: chdir %s: %s", wd, strerror(errno) );
185 if (chown(bdata(dtpath), uid, gid ) < 0 && errno != EPERM ) {
186 LOG(log_error, logtype_afpd, "setdeskowner: chown %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
194 static void create_appledesktop_folder(const struct vol * vol)
196 bstring olddtpath = NULL, dtpath = NULL;
200 olddtpath = bfromcstr(vol->v_path);
201 bcatcstr(olddtpath, "/" APPLEDESKTOP);
203 dtpath = bfromcstr(vol->v_dbpath);
204 bcatcstr(dtpath, "/" APPLEDESKTOP);
206 if (lstat(bdata(dtpath), &st) != 0) {
210 if (lstat(bdata(olddtpath), &st) == 0) {
212 cmd_argv[1] = bdata(olddtpath);
213 cmd_argv[2] = bdata(dtpath);
215 if (run_cmd("mv", cmd_argv) != 0) {
216 LOG(log_error, logtype_afpd, "moving .AppleDesktop from \"%s\" to \"%s\" failed",
217 bdata(olddtpath), bdata(dtpath));
218 mkdir(bdata(dtpath), 0777);
221 mkdir(bdata(dtpath), 0777);
231 int afp_opendt(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
238 memcpy( &vid, ibuf, sizeof(vid));
239 if (NULL == ( vol = getvolbyvid( vid )) ) {
241 return( AFPERR_PARAM );
244 create_appledesktop_folder(vol);
246 memcpy( rbuf, &vid, sizeof(vid));
247 *rbuflen = sizeof(vid);
251 int afp_closedt(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
257 static struct savedt si = { { 0, 0, 0, 0 }, -1, 0, 0 };
259 static char *icon_dtfile(struct vol *vol, u_char creator[ 4 ])
261 return dtfile( vol, creator, ".icon" );
264 static int iconopen(struct vol *vol, u_char creator[ 4 ], int flags, int mode)
266 char *dtf, *adt, *adts;
268 if ( si.sdt_fd != -1 ) {
269 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
270 si.sdt_vid == vol->v_vid ) {
277 dtf = icon_dtfile( vol, creator);
279 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
280 if ( errno == ENOENT && ( flags & O_CREAT )) {
281 if (( adts = strrchr( dtf, '/' )) == NULL ) {
285 if (( adt = strrchr( dtf, '/' )) == NULL ) {
289 (void) ad_mkdir( dtf, DIRBITS | 0777 );
291 (void) ad_mkdir( dtf, DIRBITS | 0777 );
294 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
295 LOG(log_error, logtype_afpd, "iconopen(%s): open: %s", dtf, strerror(errno) );
303 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
304 si.sdt_vid = vol->v_vid;
309 int afp_addicon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
312 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
313 int itype, cc = AFP_OK, iovcnt = 0;
315 uint32_t ftype, itag;
316 uint16_t bsize, rsize, vid;
322 memcpy( &vid, ibuf, sizeof( vid ));
323 ibuf += sizeof( vid );
324 if (NULL == ( vol = getvolbyvid( vid )) ) {
329 memcpy( fcreator, ibuf, sizeof( fcreator ));
330 ibuf += sizeof( fcreator );
332 memcpy( &ftype, ibuf, sizeof( ftype ));
333 ibuf += sizeof( ftype );
335 itype = (unsigned char) *ibuf;
338 memcpy( &itag, ibuf, sizeof( itag ));
339 ibuf += sizeof( itag );
341 memcpy( &bsize, ibuf, sizeof( bsize ));
342 bsize = ntohs( bsize );
344 if ( si.sdt_fd != -1 ) {
345 (void)close( si.sdt_fd );
349 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
354 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
357 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
363 * Read icon elements until we find a match to replace, or
364 * we get to the end to insert.
367 memcpy( p, &itag, sizeof( itag ));
369 memcpy( p, &ftype, sizeof( ftype ));
370 p += sizeof( ftype );
373 bsize = htons( bsize );
374 memcpy( p, &bsize, sizeof( bsize ));
375 bsize = ntohs( bsize );
376 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
377 memcpy( &rsize, irh + 10, sizeof( rsize ));
378 rsize = ntohs( rsize );
380 * Is this our set of headers?
382 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
384 * Is the size correct?
386 if ( bsize != rsize )
391 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
392 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator),strerror(errno) );
398 * Some error occurred, return.
402 dsi_writeinit(obj->dsi, rbuf, buflen);
403 dsi_writeflush(obj->dsi);
409 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
411 /* add headers at end of file */
412 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
413 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
418 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
419 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
424 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
425 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
426 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
437 static const u_char utag[] = { 0, 0, 0, 0 };
438 static const u_char ucreator[] = { 0, 0, 0, 0 };/* { 'U', 'N', 'I', 'X' };*/
439 static const u_char utype[] = { 0, 0, 0, 0 };/* { 'T', 'E', 'X', 'T' };*/
440 static const short usize = 256;
443 static const u_char uicon[] = {
444 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
445 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
446 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
447 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
448 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
449 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
450 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
451 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
452 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
453 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
454 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
455 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
456 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
457 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
458 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
459 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
460 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
461 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
462 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
463 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
464 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
465 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
466 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
467 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
468 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
469 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
470 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
471 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
472 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
473 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
474 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
475 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
479 int afp_geticoninfo(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
482 unsigned char fcreator[ 4 ], ih[ 12 ];
483 uint16_t vid, iindex, bsize;
488 memcpy( &vid, ibuf, sizeof( vid ));
489 ibuf += sizeof( vid );
490 if (NULL == ( vol = getvolbyvid( vid )) ) {
491 return( AFPERR_PARAM );
494 memcpy( fcreator, ibuf, sizeof( fcreator ));
495 ibuf += sizeof( fcreator );
496 memcpy( &iindex, ibuf, sizeof( iindex ));
497 iindex = ntohs( iindex );
499 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
501 return( AFPERR_NOITEM );
503 memcpy( ih, utag, sizeof( utag ));
504 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
505 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
506 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
507 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
509 memcpy( rbuf, ih, sizeof( ih ));
510 *rbuflen = sizeof( ih );
514 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
515 return( AFPERR_NOITEM );
518 if ( iindex < si.sdt_index ) {
519 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
520 return( AFPERR_PARAM );
526 * Position to the correct spot.
529 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
532 return( AFPERR_NOITEM );
534 memcpy( &bsize, ih + 10, sizeof( bsize ));
535 bsize = ntohs(bsize);
536 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
537 LOG(log_error, logtype_afpd, "afp_iconinfo(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
538 return( AFPERR_PARAM );
540 if ( si.sdt_index == iindex ) {
541 memcpy( rbuf, ih, sizeof( ih ));
542 *rbuflen = sizeof( ih );
550 int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
555 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
556 uint16_t vid, bsize, rsize;
562 memcpy( &vid, ibuf, sizeof( vid ));
563 ibuf += sizeof( vid );
564 if (NULL == ( vol = getvolbyvid( vid )) ) {
565 return( AFPERR_PARAM );
568 memcpy( fcreator, ibuf, sizeof( fcreator ));
569 ibuf += sizeof( fcreator );
570 memcpy( ftype, ibuf, sizeof( ftype ));
571 ibuf += sizeof( ftype );
572 itype = (unsigned char) *ibuf++;
574 memcpy( &bsize, ibuf, sizeof( bsize ));
575 bsize = ntohs( bsize );
578 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
579 memcmp( ftype, utype, sizeof( utype )) == 0 &&
582 memcpy( rbuf, uicon, bsize);
588 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
589 return( AFPERR_NOITEM );
592 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
595 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno));
596 return( AFPERR_PARAM );
601 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
603 offset += sizeof(ih);
604 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
605 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
608 memcpy( &rsize, ih + 10, sizeof( rsize ));
609 rsize = ntohs( rsize );
610 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
611 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
612 return( AFPERR_PARAM );
618 LOG(log_error, logtype_afpd, "afp_geticon(%s): read: %s", icon_dtfile(vol, fcreator), strerror(errno));
619 return( AFPERR_PARAM );
623 return( AFPERR_NOITEM );
626 memcpy( &rsize, ih + 10, sizeof( rsize ));
627 rsize = ntohs( rsize );
628 #define min(a,b) ((a)<(b)?(a):(b))
629 rc = min( bsize, rsize );
636 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
637 if (size < rc + offset) {
641 #ifndef WITH_SENDFILE
642 if ((buflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
647 /* do to the streaming nature, we have to exit if we encounter
648 * a problem. much confusion results otherwise. */
649 while (*rbuflen > 0) {
651 if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize, AFP_OK) < 0) {
654 case EINVAL: /* there's no guarantee that all fs support sendfile */
665 buflen = read(si.sdt_fd, rbuf, *rbuflen);
669 /* dsi_read() also returns buffer size of next allocation */
670 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
681 LOG(log_error, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno));
683 obj->exit(EXITERR_SYS);
687 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
688 return( AFPERR_PARAM );
695 /* ---------------------- */
696 static const char hexdig[] = "0123456789abcdef";
697 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
699 static char path[ MAXPATHLEN + 1];
703 strcpy( path, vol->v_dbpath );
704 strcat( path, "/" APPLEDESKTOP "/" );
705 for ( p = path; *p != '\0'; p++ )
708 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
709 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
710 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
717 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
718 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
719 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
720 *p++ = hexdig[ creator[ i ] & 0x0f ];
731 /* ---------------------------
732 * mpath is only a filename
733 * did filename parent directory ID.
736 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
738 static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
744 if ( *mpath == '\0' ) {
749 /* set conversion flags */
750 flags = vol->v_mtou_flags;
752 m = demangle(vol, mpath, did);
763 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)) ) {
764 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
769 LOG(log_debug9, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
777 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
779 static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
785 outlen = strlen(upath);
787 flags = vol->v_utom_flags;
791 /* convert charsets */
792 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)) ) {
793 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
797 flags = !!(flags & CONV_REQMANGLE);
802 m = mangle(vol, mpath, outlen, upath, id, flags);
805 LOG(log_debug9, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
811 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
815 /* ------------------------- */
816 static int ad_addcomment(const AFPObj *obj, struct vol *vol, struct path *path, char *ibuf)
822 struct adouble ad, *adp;
824 clen = (u_char)*ibuf++;
825 clen = min( clen, 199 );
827 upath = path->u_name;
828 if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
829 return AFPERR_ACCESS;
832 isadir = path_isadir(path);
833 if (isadir || !(of = of_findname(path))) {
839 if (ad_open(adp, upath,
840 ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0) | ADFLAGS_CREATE | ADFLAGS_RDWR,
842 return( AFPERR_ACCESS );
845 if (ad_getentryoff(adp, ADEID_COMMENT)) {
846 if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
847 if ( *path->m_name == '\0' ) {
848 name = (char *)curdir->d_m_name->data;
852 ad_setname(adp, name);
854 ad_setentrylen( adp, ADEID_COMMENT, clen );
855 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
858 ad_close(adp, ADFLAGS_HF);
862 /* ----------------------------- */
863 int afp_addcomment(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
874 memcpy( &vid, ibuf, sizeof( vid ));
875 ibuf += sizeof( vid );
876 if (NULL == ( vol = getvolbyvid( vid )) ) {
877 return( AFPERR_PARAM );
880 memcpy( &did, ibuf, sizeof( did ));
881 ibuf += sizeof( did );
882 if (NULL == ( dir = dirlookup( vol, did )) ) {
886 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
887 return get_afp_errno(AFPERR_NOOBJ);
890 if ((u_long)ibuf & 1 ) {
894 return ad_addcomment(obj, vol, path, ibuf);
897 /* -------------------- */
898 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuflen)
900 struct adouble ad, *adp;
906 upath = path->u_name;
907 isadir = path_isadir(path);
908 if (isadir || !(of = of_findname(path))) {
914 if ( ad_metadata( upath, ((isadir) ? ADFLAGS_DIR : 0), adp) < 0 ) {
915 return( AFPERR_NOITEM );
918 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
919 ad_close(adp, ADFLAGS_HF);
920 return AFPERR_NOITEM;
923 * Make sure the AD file is not bogus.
925 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
926 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
927 ad_close(adp, ADFLAGS_HF);
928 return( AFPERR_NOITEM );
931 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
933 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
935 ad_close(adp, ADFLAGS_HF);
940 /* -------------------- */
941 int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
952 memcpy( &vid, ibuf, sizeof( vid ));
953 ibuf += sizeof( vid );
954 if (NULL == ( vol = getvolbyvid( vid )) ) {
955 return( AFPERR_PARAM );
958 memcpy( &did, ibuf, sizeof( did ));
959 ibuf += sizeof( did );
960 if (NULL == ( dir = dirlookup( vol, did )) ) {
964 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
965 return get_afp_errno(AFPERR_NOOBJ);
968 return ad_getcomment(vol, s_path, rbuf, rbuflen);
971 /* ----------------------- */
972 static int ad_rmvcomment(const AFPObj *obj, struct vol *vol, struct path *path)
974 struct adouble ad, *adp;
979 upath = path->u_name;
980 if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
981 return AFPERR_ACCESS;
984 isadir = path_isadir(path);
985 if (isadir || !(of = of_findname(path))) {
991 if ( ad_open(adp, upath, ADFLAGS_HF | ADFLAGS_RDWR | ((isadir) ? ADFLAGS_DIR : 0)) < 0 ) {
994 return( AFPERR_NOITEM );
996 return( AFPERR_ACCESS );
998 return( AFPERR_PARAM );
1002 if (ad_getentryoff(adp, ADEID_COMMENT)) {
1003 ad_setentrylen( adp, ADEID_COMMENT, 0 );
1006 ad_close(adp, ADFLAGS_HF);
1010 /* ----------------------- */
1011 int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
1015 struct path *s_path;
1022 memcpy( &vid, ibuf, sizeof( vid ));
1023 ibuf += sizeof( vid );
1024 if (NULL == ( vol = getvolbyvid( vid )) ) {
1025 return( AFPERR_PARAM );
1028 memcpy( &did, ibuf, sizeof( did ));
1029 ibuf += sizeof( did );
1030 if (NULL == ( dir = dirlookup( vol, did )) ) {
1034 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
1035 return get_afp_errno(AFPERR_NOOBJ);
1038 return ad_rmvcomment(obj, vol, s_path);