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)) {
98 if ( chmod_acl( modbuf, (DIRBITS | mode)) < 0 && errno != EPERM ) {
99 LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
101 } else if ( chmod_acl( modbuf, mode & ~EXEC_MODE ) < 0 && errno != EPERM ) {
102 LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) );
107 /* XXX: need to preserve special modes */
108 if ( chmod_acl( deskp->d_name, (DIRBITS | mode)) < 0 && errno != EPERM ) {
109 LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(deskp->d_name), strerror(errno) );
113 if ( chdir( wd ) < 0 ) {
114 LOG(log_error, logtype_afpd, "setdeskmode: chdir %s: %s", wd, strerror(errno) );
117 /* XXX: need to preserve special modes */
118 if ( chmod_acl(bdata(dtpath), (DIRBITS | mode)) < 0 && errno != EPERM ) {
119 LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s", bdata(dtpath), strerror(errno));
127 int setdeskowner(const struct vol *vol, uid_t uid, gid_t gid)
130 char wd[ MAXPATHLEN + 1];
131 char modbuf[12 + 1], *m;
132 struct dirent *deskp, *subp;
135 if ( getcwd( wd, MAXPATHLEN ) == NULL ) {
139 bstring dtpath = bfromcstr(vol->v_dbpath);
140 bcatcstr(dtpath, "/" APPLEDESKTOP);
142 EC_NEG1( chdir(cfrombstr(dtpath)) );
144 if (( desk = opendir( "." )) == NULL ) {
145 if ( chdir( wd ) < 0 ) {
146 LOG(log_error, logtype_afpd, "setdeskowner: chdir %s: %s", wd, strerror(errno) );
150 for ( deskp = readdir( desk ); deskp != NULL; deskp = readdir( desk )) {
151 if ( strcmp( deskp->d_name, "." ) == 0 ||
152 strcmp( deskp->d_name, ".." ) == 0 ||
153 strlen( deskp->d_name ) > 2 ) {
156 strcpy( modbuf, deskp->d_name );
157 strcat( modbuf, "/" );
158 m = strchr( modbuf, '\0' );
159 if (( sub = opendir( deskp->d_name )) == NULL ) {
162 for ( subp = readdir( sub ); subp != NULL; subp = readdir( sub )) {
163 if ( strcmp( subp->d_name, "." ) == 0 ||
164 strcmp( subp->d_name, ".." ) == 0 ) {
168 strcat( modbuf, subp->d_name );
169 /* XXX: add special any uid, ignore group bits */
170 if ( chown( modbuf, uid, gid ) < 0 && errno != EPERM ) {
171 LOG(log_error, logtype_afpd, "setdeskown: chown %s: %s", fullpathname(modbuf), strerror(errno) );
175 /* XXX: add special any uid, ignore group bits */
176 if ( chown( deskp->d_name, uid, gid ) < 0 && errno != EPERM ) {
177 LOG(log_error, logtype_afpd, "setdeskowner: chown %s: %s",
178 deskp->d_name, strerror(errno) );
182 if ( chdir( wd ) < 0 ) {
183 LOG(log_error, logtype_afpd, "setdeskowner: chdir %s: %s", wd, strerror(errno) );
186 if (chown(cfrombstr(dtpath), uid, gid ) < 0 && errno != EPERM ) {
187 LOG(log_error, logtype_afpd, "setdeskowner: chown %s: %s", fullpathname(".AppleDouble"), strerror(errno) );
195 static void create_appledesktop_folder(const struct vol * vol)
197 bstring olddtpath = NULL, dtpath = NULL;
201 olddtpath = bfromcstr(vol->v_path);
202 bcatcstr(olddtpath, "/" APPLEDESKTOP);
204 dtpath = bfromcstr(vol->v_dbpath);
205 bcatcstr(dtpath, "/" APPLEDESKTOP);
207 if (lstat(cfrombstr(dtpath), &st) != 0) {
211 if (lstat(cfrombstr(olddtpath), &st) == 0) {
213 cmd_argv[1] = bdata(olddtpath);
214 cmd_argv[2] = bdata(dtpath);
216 if (run_cmd("mv", cmd_argv) != 0) {
217 LOG(log_error, logtype_afpd, "moving .AppleDesktop from \"%s\" to \"%s\" failed",
218 bdata(olddtpath), bdata(dtpath));
219 mkdir(cfrombstr(dtpath), 0777);
222 mkdir(cfrombstr(dtpath), 0777);
232 int afp_opendt(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
239 memcpy( &vid, ibuf, sizeof(vid));
240 if (NULL == ( vol = getvolbyvid( vid )) ) {
242 return( AFPERR_PARAM );
245 create_appledesktop_folder(vol);
247 memcpy( rbuf, &vid, sizeof(vid));
248 *rbuflen = sizeof(vid);
252 int afp_closedt(AFPObj *obj _U_, char *ibuf _U_, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
258 static struct savedt si = { { 0, 0, 0, 0 }, -1, 0, 0 };
260 static char *icon_dtfile(struct vol *vol, u_char creator[ 4 ])
262 return dtfile( vol, creator, ".icon" );
265 static int iconopen(struct vol *vol, u_char creator[ 4 ], int flags, int mode)
267 char *dtf, *adt, *adts;
269 if ( si.sdt_fd != -1 ) {
270 if ( memcmp( si.sdt_creator, creator, sizeof( CreatorType )) == 0 &&
271 si.sdt_vid == vol->v_vid ) {
278 dtf = icon_dtfile( vol, creator);
280 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
281 if ( errno == ENOENT && ( flags & O_CREAT )) {
282 if (( adts = strrchr( dtf, '/' )) == NULL ) {
286 if (( adt = strrchr( dtf, '/' )) == NULL ) {
290 (void) ad_mkdir( dtf, DIRBITS | 0777 );
292 (void) ad_mkdir( dtf, DIRBITS | 0777 );
295 if (( si.sdt_fd = open( dtf, flags, ad_mode( dtf, mode ))) < 0 ) {
296 LOG(log_error, logtype_afpd, "iconopen(%s): open: %s", dtf, strerror(errno) );
304 memcpy( si.sdt_creator, creator, sizeof( CreatorType ));
305 si.sdt_vid = vol->v_vid;
310 int afp_addicon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
313 u_char fcreator[ 4 ], imh[ 12 ], irh[ 12 ], *p;
314 int itype, cc = AFP_OK, iovcnt = 0;
316 uint32_t ftype, itag;
317 uint16_t bsize, rsize, vid;
323 memcpy( &vid, ibuf, sizeof( vid ));
324 ibuf += sizeof( vid );
325 if (NULL == ( vol = getvolbyvid( vid )) ) {
330 memcpy( fcreator, ibuf, sizeof( fcreator ));
331 ibuf += sizeof( fcreator );
333 memcpy( &ftype, ibuf, sizeof( ftype ));
334 ibuf += sizeof( ftype );
336 itype = (unsigned char) *ibuf;
339 memcpy( &itag, ibuf, sizeof( itag ));
340 ibuf += sizeof( itag );
342 memcpy( &bsize, ibuf, sizeof( bsize ));
343 bsize = ntohs( bsize );
345 if ( si.sdt_fd != -1 ) {
346 (void)close( si.sdt_fd );
350 if (iconopen( vol, fcreator, O_RDWR|O_CREAT, 0666 ) < 0) {
355 if (lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0) {
358 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
364 * Read icon elements until we find a match to replace, or
365 * we get to the end to insert.
368 memcpy( p, &itag, sizeof( itag ));
370 memcpy( p, &ftype, sizeof( ftype ));
371 p += sizeof( ftype );
374 bsize = htons( bsize );
375 memcpy( p, &bsize, sizeof( bsize ));
376 bsize = ntohs( bsize );
377 while (( cc = read( si.sdt_fd, irh, sizeof( irh ))) > 0 ) {
378 memcpy( &rsize, irh + 10, sizeof( rsize ));
379 rsize = ntohs( rsize );
381 * Is this our set of headers?
383 if ( memcmp( irh, imh, sizeof( irh ) - sizeof( u_short )) == 0 ) {
385 * Is the size correct?
387 if ( bsize != rsize )
392 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
393 LOG(log_error, logtype_afpd, "afp_addicon(%s): lseek: %s", icon_dtfile(vol, fcreator),strerror(errno) );
399 * Some error occurred, return.
403 dsi_writeinit(obj->dsi, rbuf, buflen);
404 dsi_writeflush(obj->dsi);
410 iovcnt = dsi_writeinit(dsi, rbuf, buflen);
412 /* add headers at end of file */
413 if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) {
414 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
419 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
420 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
425 while ((iovcnt = dsi_write(dsi, rbuf, buflen))) {
426 if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) {
427 LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno));
438 static const u_char utag[] = { 0, 0, 0, 0 };
439 static const u_char ucreator[] = { 0, 0, 0, 0 };/* { 'U', 'N', 'I', 'X' };*/
440 static const u_char utype[] = { 0, 0, 0, 0 };/* { 'T', 'E', 'X', 'T' };*/
441 static const short usize = 256;
444 static const u_char uicon[] = {
445 0x1F, 0xFF, 0xFC, 0x00, 0x10, 0x00, 0x06, 0x00,
446 0x10, 0x00, 0x05, 0x00, 0x10, 0x00, 0x04, 0x80,
447 0x10, 0x00, 0x04, 0x40, 0x10, 0x00, 0x04, 0x20,
448 0x10, 0x00, 0x07, 0xF0, 0x10, 0x00, 0x00, 0x10,
449 0x10, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10,
450 0x10, 0x00, 0x00, 0x10, 0x10, 0x80, 0x02, 0x10,
451 0x11, 0x80, 0x03, 0x10, 0x12, 0x80, 0x02, 0x90,
452 0x12, 0x80, 0x02, 0x90, 0x14, 0x80, 0x02, 0x50,
453 0x14, 0x87, 0xC2, 0x50, 0x14, 0x58, 0x34, 0x50,
454 0x14, 0x20, 0x08, 0x50, 0x12, 0x16, 0xD0, 0x90,
455 0x11, 0x01, 0x01, 0x10, 0x12, 0x80, 0x02, 0x90,
456 0x12, 0x9C, 0x72, 0x90, 0x14, 0x22, 0x88, 0x50,
457 0x14, 0x41, 0x04, 0x50, 0x14, 0x49, 0x24, 0x50,
458 0x14, 0x55, 0x54, 0x50, 0x14, 0x5D, 0x74, 0x50,
459 0x14, 0x5D, 0x74, 0x50, 0x12, 0x49, 0x24, 0x90,
460 0x12, 0x22, 0x88, 0x90, 0x1F, 0xFF, 0xFF, 0xF0,
461 0x1F, 0xFF, 0xFC, 0x00, 0x1F, 0xFF, 0xFE, 0x00,
462 0x1F, 0xFF, 0xFF, 0x00, 0x1F, 0xFF, 0xFF, 0x80,
463 0x1F, 0xFF, 0xFF, 0xC0, 0x1F, 0xFF, 0xFF, 0xE0,
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,
476 0x1F, 0xFF, 0xFF, 0xF0, 0x1F, 0xFF, 0xFF, 0xF0,
480 int afp_geticoninfo(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
483 unsigned char fcreator[ 4 ], ih[ 12 ];
484 uint16_t vid, iindex, bsize;
489 memcpy( &vid, ibuf, sizeof( vid ));
490 ibuf += sizeof( vid );
491 if (NULL == ( vol = getvolbyvid( vid )) ) {
492 return( AFPERR_PARAM );
495 memcpy( fcreator, ibuf, sizeof( fcreator ));
496 ibuf += sizeof( fcreator );
497 memcpy( &iindex, ibuf, sizeof( iindex ));
498 iindex = ntohs( iindex );
500 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 ) {
502 return( AFPERR_NOITEM );
504 memcpy( ih, utag, sizeof( utag ));
505 memcpy( ih + sizeof( utag ), utype, sizeof( utype ));
506 *( ih + sizeof( utag ) + sizeof( utype )) = 1;
507 *( ih + sizeof( utag ) + sizeof( utype ) + 1 ) = 0;
508 memcpy( ih + sizeof( utag ) + sizeof( utype ) + 2, &usize,
510 memcpy( rbuf, ih, sizeof( ih ));
511 *rbuflen = sizeof( ih );
515 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
516 return( AFPERR_NOITEM );
519 if ( iindex < si.sdt_index ) {
520 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
521 return( AFPERR_PARAM );
527 * Position to the correct spot.
530 if ( read( si.sdt_fd, ih, sizeof( ih )) != sizeof( ih )) {
533 return( AFPERR_NOITEM );
535 memcpy( &bsize, ih + 10, sizeof( bsize ));
536 bsize = ntohs(bsize);
537 if ( lseek( si.sdt_fd, (off_t) bsize, SEEK_CUR ) < 0 ) {
538 LOG(log_error, logtype_afpd, "afp_iconinfo(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
539 return( AFPERR_PARAM );
541 if ( si.sdt_index == iindex ) {
542 memcpy( rbuf, ih, sizeof( ih ));
543 *rbuflen = sizeof( ih );
551 int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
556 u_char fcreator[ 4 ], ftype[ 4 ], itype, ih[ 12 ];
557 uint16_t vid, bsize, rsize;
563 memcpy( &vid, ibuf, sizeof( vid ));
564 ibuf += sizeof( vid );
565 if (NULL == ( vol = getvolbyvid( vid )) ) {
566 return( AFPERR_PARAM );
569 memcpy( fcreator, ibuf, sizeof( fcreator ));
570 ibuf += sizeof( fcreator );
571 memcpy( ftype, ibuf, sizeof( ftype ));
572 ibuf += sizeof( ftype );
573 itype = (unsigned char) *ibuf++;
575 memcpy( &bsize, ibuf, sizeof( bsize ));
576 bsize = ntohs( bsize );
579 if ( memcmp( fcreator, ucreator, sizeof( ucreator )) == 0 &&
580 memcmp( ftype, utype, sizeof( utype )) == 0 &&
583 memcpy( rbuf, uicon, bsize);
589 if ( iconopen( vol, fcreator, O_RDONLY, 0 ) < 0) {
590 return( AFPERR_NOITEM );
593 if ( lseek( si.sdt_fd, (off_t) 0L, SEEK_SET ) < 0 ) {
596 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno));
597 return( AFPERR_PARAM );
602 while (( rc = read( si.sdt_fd, ih, sizeof( ih ))) > 0 ) {
604 offset += sizeof(ih);
605 if ( memcmp( ih + sizeof( int ), ftype, sizeof( ftype )) == 0 &&
606 *(ih + sizeof( int ) + sizeof( ftype )) == itype ) {
609 memcpy( &rsize, ih + 10, sizeof( rsize ));
610 rsize = ntohs( rsize );
611 if ( lseek( si.sdt_fd, (off_t) rsize, SEEK_CUR ) < 0 ) {
612 LOG(log_error, logtype_afpd, "afp_geticon(%s): lseek: %s", icon_dtfile(vol, fcreator), strerror(errno) );
613 return( AFPERR_PARAM );
619 LOG(log_error, logtype_afpd, "afp_geticon(%s): read: %s", icon_dtfile(vol, fcreator), strerror(errno));
620 return( AFPERR_PARAM );
624 return( AFPERR_NOITEM );
627 memcpy( &rsize, ih + 10, sizeof( rsize ));
628 rsize = ntohs( rsize );
629 #define min(a,b) ((a)<(b)?(a):(b))
630 rc = min( bsize, rsize );
637 size = (fstat(si.sdt_fd, &st) < 0) ? 0 : st.st_size;
638 if (size < rc + offset) {
642 #ifndef WITH_SENDFILE
643 if ((buflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0)
648 /* do to the streaming nature, we have to exit if we encounter
649 * a problem. much confusion results otherwise. */
650 while (*rbuflen > 0) {
652 if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize, AFP_OK) < 0) {
655 case EINVAL: /* there's no guarantee that all fs support sendfile */
666 buflen = read(si.sdt_fd, rbuf, *rbuflen);
670 /* dsi_read() also returns buffer size of next allocation */
671 buflen = dsi_read(dsi, rbuf, buflen); /* send it off */
682 LOG(log_error, logtype_afpd, "afp_geticon(%s): %s", icon_dtfile(vol, fcreator), strerror(errno));
684 obj->exit(EXITERR_SYS);
688 if ( read( si.sdt_fd, rbuf, rc ) < rc ) {
689 return( AFPERR_PARAM );
696 /* ---------------------- */
697 static const char hexdig[] = "0123456789abcdef";
698 char *dtfile(const struct vol *vol, u_char creator[], char *ext )
700 static char path[ MAXPATHLEN + 1];
704 strcpy( path, vol->v_dbpath );
705 strcat( path, "/" APPLEDESKTOP "/" );
706 for ( p = path; *p != '\0'; p++ )
709 if ( !isprint( creator[ 0 ] ) || creator[ 0 ] == '/' ) {
710 *p++ = hexdig[ ( creator[ 0 ] & 0xf0 ) >> 4 ];
711 *p++ = hexdig[ creator[ 0 ] & 0x0f ];
718 for ( i = 0; i < sizeof( CreatorType ); i++ ) {
719 if ( !isprint( creator[ i ] ) || creator[ i ] == '/' ) {
720 *p++ = hexdig[ ( creator[ i ] & 0xf0 ) >> 4 ];
721 *p++ = hexdig[ creator[ i ] & 0x0f ];
732 /* ---------------------------
733 * mpath is only a filename
734 * did filename parent directory ID.
737 char *mtoupath(const struct vol *vol, char *mpath, cnid_t did, int utf8)
739 static char upath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
745 if ( *mpath == '\0' ) {
750 /* set conversion flags */
751 flags = vol->v_mtou_flags;
753 m = demangle(vol, mpath, did);
764 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)) ) {
765 LOG(log_error, logtype_afpd, "conversion from %s to %s for %s failed.", (utf8)?"UTF8-MAC":vol->v_maccodepage, vol->v_volcodepage, mpath);
770 LOG(log_debug9, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
778 char *utompath(const struct vol *vol, char *upath, cnid_t id, int utf8)
780 static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */
786 outlen = strlen(upath);
788 flags = vol->v_utom_flags;
792 /* convert charsets */
793 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)) ) {
794 LOG(log_error, logtype_afpd, "Conversion from %s to %s for %s (%u) failed.", vol->v_volcodepage, vol->v_maccodepage, u, ntohl(id));
798 flags = !!(flags & CONV_REQMANGLE);
803 m = mangle(vol, mpath, outlen, upath, id, flags);
806 LOG(log_debug9, logtype_afpd, "utompath: '%s':'%s':'%2.2X'", upath, m, ntohl(id));
812 m = mangle(vol, u, strlen(u), upath, id, (utf8)?3:1);
816 /* ------------------------- */
817 static int ad_addcomment(const AFPObj *obj, struct vol *vol, struct path *path, char *ibuf)
823 struct adouble ad, *adp;
825 clen = (u_char)*ibuf++;
826 clen = min( clen, 199 );
828 upath = path->u_name;
829 if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
830 return AFPERR_ACCESS;
833 isadir = path_isadir(path);
834 if (isadir || !(of = of_findname(vol, path))) {
840 if (ad_open(adp, upath,
841 ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0) | ADFLAGS_CREATE | ADFLAGS_RDWR,
843 return( AFPERR_ACCESS );
846 if (ad_getentryoff(adp, ADEID_COMMENT)) {
847 if ( (ad_get_MD_flags( adp ) & O_CREAT) ) {
848 if ( *path->m_name == '\0' ) {
849 name = (char *)curdir->d_m_name->data;
853 ad_setname(adp, name);
855 ad_setentrylen( adp, ADEID_COMMENT, clen );
856 memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen );
859 ad_close(adp, ADFLAGS_HF);
863 /* ----------------------------- */
864 int afp_addcomment(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
875 memcpy( &vid, ibuf, sizeof( vid ));
876 ibuf += sizeof( vid );
877 if (NULL == ( vol = getvolbyvid( vid )) ) {
878 return( AFPERR_PARAM );
881 memcpy( &did, ibuf, sizeof( did ));
882 ibuf += sizeof( did );
883 if (NULL == ( dir = dirlookup( vol, did )) ) {
887 if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
888 return get_afp_errno(AFPERR_NOOBJ);
891 if ((u_long)ibuf & 1 ) {
895 return ad_addcomment(obj, vol, path, ibuf);
898 /* -------------------- */
899 static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuflen)
901 struct adouble ad, *adp;
907 upath = path->u_name;
908 isadir = path_isadir(path);
909 if (isadir || !(of = of_findname(vol, path))) {
915 if ( ad_metadata( upath, ((isadir) ? ADFLAGS_DIR : 0), adp) < 0 ) {
916 return( AFPERR_NOITEM );
919 if (!ad_getentryoff(adp, ADEID_COMMENT)) {
920 ad_close(adp, ADFLAGS_HF);
921 return AFPERR_NOITEM;
924 * Make sure the AD file is not bogus.
926 if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 ||
927 ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) {
928 ad_close(adp, ADFLAGS_HF);
929 return( AFPERR_NOITEM );
932 clen = min( ad_getentrylen( adp, ADEID_COMMENT ), 128 ); /* OSX only use 128, greater kill Adobe CS2 */
934 memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen);
936 ad_close(adp, ADFLAGS_HF);
941 /* -------------------- */
942 int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
953 memcpy( &vid, ibuf, sizeof( vid ));
954 ibuf += sizeof( vid );
955 if (NULL == ( vol = getvolbyvid( vid )) ) {
956 return( AFPERR_PARAM );
959 memcpy( &did, ibuf, sizeof( did ));
960 ibuf += sizeof( did );
961 if (NULL == ( dir = dirlookup( vol, did )) ) {
965 if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
966 return get_afp_errno(AFPERR_NOOBJ);
969 return ad_getcomment(vol, s_path, rbuf, rbuflen);
972 /* ----------------------- */
973 static int ad_rmvcomment(const AFPObj *obj, struct vol *vol, struct path *path)
975 struct adouble ad, *adp;
980 upath = path->u_name;
981 if (check_access(obj, vol, upath, OPENACC_WR ) < 0) {
982 return AFPERR_ACCESS;
985 isadir = path_isadir(path);
986 if (isadir || !(of = of_findname(vol, path))) {
992 if ( ad_open(adp, upath, ADFLAGS_HF | ADFLAGS_RDWR | ((isadir) ? ADFLAGS_DIR : 0)) < 0 ) {
995 return( AFPERR_NOITEM );
997 return( AFPERR_ACCESS );
999 return( AFPERR_PARAM );
1003 if (ad_getentryoff(adp, ADEID_COMMENT)) {
1004 ad_setentrylen( adp, ADEID_COMMENT, 0 );
1007 ad_close(adp, ADFLAGS_HF);
1011 /* ----------------------- */
1012 int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
1016 struct path *s_path;
1023 memcpy( &vid, ibuf, sizeof( vid ));
1024 ibuf += sizeof( vid );
1025 if (NULL == ( vol = getvolbyvid( vid )) ) {
1026 return( AFPERR_PARAM );
1029 memcpy( &did, ibuf, sizeof( did ));
1030 ibuf += sizeof( did );
1031 if (NULL == ( dir = dirlookup( vol, did )) ) {
1035 if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
1036 return get_afp_errno(AFPERR_NOOBJ);
1039 return ad_rmvcomment(obj, vol, s_path);