/*
- * $Id: desktop.c,v 1.21 2003-01-12 14:39:58 didg Exp $
+ * $Id: desktop.c,v 1.30 2003-06-09 14:42:38 srittau Exp $
*
* See COPYRIGHT.
*
#include "fork.h"
#include "globals.h"
#include "desktop.h"
+
#ifdef FILE_MANGLING
#include "mangle.h"
#endif /* CNID_DB */
+#ifdef AFP3x
+#include <iconv.h>
+#endif
+
int afp_opendt(obj, ibuf, ibuflen, rbuf, rbuflen )
AFPObj *obj;
char *ibuf, *rbuf;
memcpy( &vid, ibuf, sizeof( vid ));
ibuf += sizeof( vid );
- if (( vol = getvolbyvid( vid )) == NULL ) {
+ if (NULL == ( vol = getvolbyvid( vid )) ) {
cc = AFPERR_PARAM;
goto addicon_err;
}
memcpy( &vid, ibuf, sizeof( vid ));
ibuf += sizeof( vid );
- if (( vol = getvolbyvid( vid )) == NULL ) {
+ if (NULL == ( vol = getvolbyvid( vid )) ) {
return( AFPERR_PARAM );
}
memcpy( &vid, ibuf, sizeof( vid ));
ibuf += sizeof( vid );
- if (( vol = getvolbyvid( vid )) == NULL ) {
+ if (NULL == ( vol = getvolbyvid( vid )) ) {
return( AFPERR_PARAM );
}
return( path );
}
-/*
+/* ---------------------------
* mpath is only a filename
*/
-char *mtoupath(const struct vol *vol, char *mpath)
+static char upath[ MAXPATHLEN + 1];
+static char mpath[ MAXPATHLEN + 1];
+#ifdef AFP3x
+static char ucs2[ MAXPATHLEN + 1];
+#endif
+
+static char *old_mtoupath(const struct vol *vol, char *mpath)
{
- static char upath[ MAXPATHLEN + 1];
char *m, *u;
int i = 0;
int changed = 0;
- if ( *mpath == '\0' ) {
- return( "." );
- }
-
-#ifdef FILE_MANGLING
- m = demangle(vol, mpath);
- if (m != mpath) {
- changed = 1;
- mpath = m;
- }
-#endif /* FILE_MANGLING */
m = mpath;
u = upath;
+ if ((vol->v_casefold & (AFPVOL_MTOUUPPER| AFPVOL_MTOULOWER))) {
+ changed = 1;
+ }
while ( *m != '\0' ) {
/* handle case conversion first */
if (vol->v_casefold & AFPVOL_MTOUUPPER)
* H.P. Jansen <hpj@urpla.net> */
#ifdef DEBUG
LOG(log_debug, logtype_afpd, "mtoupath: hex encode: 0x%x", (unsigned char) *m);
-#endif /* DEBUG */
+#endif
*u++ = ':';
*u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
*u = hexdig[ *m & 0x0f ];
(!isascii(*m) || *m == '/')) ||
(((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
( i == 0 && (*m == '.' )))) {
-#else /* AD_VERSION == AD_VERSION1 */
+#else
if ((((vol->v_flags & AFPVOL_NOHEX) == 0) &&
(!isprint(*m) || *m == '/')) ||
(((vol->v_flags & AFPVOL_USEDOTS) == 0) &&
( i == 0 && (*m == '.' )))) {
-#endif /* AD_VERSION == AD_VERSION1 */
+#endif
/* do hex conversion. */
*u++ = ':';
*u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
return( (changed)?upath:mpath );
}
+/* ---------------------------- */
#define hextoint( c ) ( isdigit( c ) ? c - '0' : c + 10 - 'a' )
#define islxdigit(x) (!isupper(x)&&isxdigit(x))
-char *utompath(const struct vol *vol, char *upath)
+static char *old_utompath(const struct vol *vol, char *upath)
{
- static char mpath[ MAXPATHLEN + 1];
char *m, *u;
int h;
int changed = 0;
/* do the hex conversion */
u = upath;
m = mpath;
+ if ((vol->v_casefold & (AFPVOL_MTOUUPPER| AFPVOL_MTOULOWER))) {
+ changed = 1;
+ }
while ( *u != '\0' ) {
/* we have a code page */
-#if 1
if (vol->v_utompage && ((*u & 0x80) ||
(vol->v_flags & AFPVOL_MAPASCII))) {
*m = vol->v_utompage->map[(unsigned char) *u].value;
changed = 1;
} else
-#endif /* 1 */
if ( *u == ':' && *(u+1) != '\0' && islxdigit( *(u+1)) &&
*(u+2) != '\0' && islxdigit( *(u+2))) {
++u;
m = mpath;
#ifdef FILE_MANGLING
- m = mangle(vol, mpath);
+ m = mangle(vol, mpath, upath, 0);
if (m != mpath) {
changed = 1;
}
return((changed)? m:upath );
}
+/* --------------- */
+#ifdef AFP3x
+extern unsigned int do_precomposition(unsigned int base, unsigned int comb);
+
+static char comp[MAXPATHLEN +1];
+
+static char *precompose(u_int16_t *name, size_t inplen, size_t *outlen)
+{
+size_t i;
+u_int16_t base, comb;
+u_int16_t *in, *out;
+u_int16_t result;
+
+ if (!inplen || (inplen & 1) || inplen > sizeof(comp)/sizeof(u_int16_t))
+ return NULL;
+ i = 0;
+ in = name;
+ out = (u_int16_t *)comp;
+ *outlen = 0;
+
+ base = *in;
+ while (1) {
+ i += 2;
+ in++;
+ if (i == inplen) {
+ *out = base;
+ *outlen += 2;
+ return comp;
+ }
+ comb = *in;
+ if (comb >= 0x300 && (result = do_precomposition(base, comb))) {
+ *out = result;
+ out++;
+ *outlen += 2;
+ i += 2;
+ in++;
+ if (i == inplen)
+ return comp;
+ base = *in;
+ }
+ else {
+ *out = base;
+ out++;
+ *outlen += 2;
+ base = comb;
+ }
+ }
+}
+
+/* --------------- */
+extern unsigned int do_decomposition(unsigned int base);
+
+static char *decompose(u_int16_t *name, size_t inplen, size_t *outlen)
+{
+size_t i;
+u_int16_t base;
+u_int16_t *in, *out;
+unsigned int result;
+
+ if (!inplen || (inplen & 1))
+ return NULL;
+ i = 0;
+ in = name;
+ out = (u_int16_t *)comp;
+ *outlen = 0;
+
+ while (i < inplen) {
+ if (*outlen >= sizeof(comp)/sizeof(u_int16_t) +2) {
+ return NULL;
+ }
+ base = *in;
+ if ((result = do_decomposition(base))) {
+ *out = result >> 16;
+ out++;
+ *outlen += 2;
+ *out = result & 0xffff;
+ out++;
+ *outlen += 2;
+ }
+ else {
+ *out = base;
+ out++;
+ *outlen += 2;
+ }
+ i += 2;
+ in++;
+ }
+ return comp;
+}
+#endif
+
+/* --------------------------- */
+char *mtoupath(const struct vol *vol, char *mpath, int utf8)
+{
+ int i = 0;
+ char *m, *u;
+#ifdef AFP3x
+ char *r;
+ size_t inplen;
+ size_t outlen;
+#endif
+
+ if ( *mpath == '\0' ) {
+ return( "." );
+ }
+
+#ifdef FILE_MANGLING
+ m = demangle(vol, mpath);
+ if (m != mpath) {
+ return m;
+ }
+#endif /* FILE_MANGLING */
+
+ if (!vol_utf8(vol))
+ return old_mtoupath(vol, mpath);
+
+ m = mpath;
+ u = upath;
+ while ( *m != '\0' ) {
+ if ( (!(vol->v_flags & AFPVOL_NOHEX) && *m == '/') ||
+ (!(vol->v_flags & AFPVOL_USEDOTS) && i == 0 && *m == '.') ||
+ (!utf8 && (unsigned char)*m == 0xf0) /* Apple logo */
+ ) {
+ /* do hex conversion. */
+ *u++ = ':';
+ *u++ = hexdig[ ( *m & 0xf0 ) >> 4 ];
+ *u = hexdig[ *m & 0x0f ];
+ } else
+ *u = *m;
+ u++;
+ i++;
+ m++;
+ }
+ *u = '\0';
+ u = upath;
+#ifdef AFP3x
+ inplen = strlen(u);
+ outlen = MAXPATHLEN;
+ r = ucs2;
+ if (!utf8) {
+ if ((size_t)(-1) == iconv(vol->v_mactoutf8, 0,0,0,0) )
+ return NULL;
+ /* assume precompose */
+ if ((size_t)(-1) == iconv(vol->v_mactoutf8, &u, &inplen, &r, &outlen))
+ return NULL;
+ u = ucs2;
+ }
+ else {
+ if ((size_t)(-1) == iconv(vol->v_utf8toucs2, 0,0,0,0) )
+ return NULL;
+
+ if ((size_t)(-1) == iconv(vol->v_utf8toucs2, &u, &inplen, &r, &outlen))
+ return NULL;
+
+ u = precompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen);
+
+ if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, 0,0,0,0))
+ return NULL;
+
+ outlen = MAXPATHLEN;
+ r = upath;
+ if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, &u, &inplen, &r, &outlen))
+ return NULL;
+ u = upath;
+ }
+ u[MAXPATHLEN -outlen] = 0;
+#endif
+#ifdef DEBUG
+ LOG(log_debug, logtype_afpd, "mtoupath: '%s':'%s'", mpath, upath);
+#endif /* DEBUG */
+ return( u );
+}
+
+/* --------------- */
+char *utompath(const struct vol *vol, char *upath, int utf8)
+{
+ int h;
+ int mangleflag = 0;
+ char *m, *u;
+#ifdef AFP3x
+ char *r;
+ size_t inplen;
+ size_t outlen;
+#endif
+
+ if (!vol_utf8(vol))
+ return old_utompath(vol, upath);
+ /* do the hex conversion */
+ u = upath;
+ m = mpath;
+ while ( *u != '\0' ) {
+ if ( *u == ':' && islxdigit( *(u+1)) && islxdigit( *(u+2))) {
+ ++u;
+ h = hextoint( *u ) << 4;
+ ++u;
+ h |= hextoint( *u );
+ *m = h;
+ } else
+ *m = *u;
+ u++;
+ m++;
+ }
+ *m = '\0';
+ m = mpath;
+#ifdef AFP3x
+ if ((size_t)(-1) == iconv(vol->v_utf8toucs2, 0,0,0,0) )
+ return NULL;
+ inplen = strlen(mpath);
+ outlen = MAXPATHLEN;
+ r = ucs2;
+ if ((size_t)(-1) == iconv(vol->v_utf8toucs2, &m, &inplen, &r, &outlen))
+ return NULL;
+
+ if (utf8) {
+ if ( NULL == (m = decompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen)))
+ return NULL;
+
+ if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, 0,0,0,0))
+ return NULL;
+
+ outlen = MAXPATHLEN;
+ r = mpath;
+ if ((size_t)(-1) == iconv(vol->v_ucs2toutf8, &m, &inplen, &r, &outlen))
+ return NULL;
+ }
+ else {
+ m = precompose((u_int16_t *)ucs2, MAXPATHLEN -outlen, &inplen);
+
+ if ((size_t)(-1) == iconv(vol->v_ucs2tomac, 0,0,0,0))
+ return NULL;
+
+ outlen = MAXPATHLEN;
+ r = mpath;
+ if ((size_t)(-1) == iconv(vol->v_ucs2tomac, &m, &inplen, &r, &outlen)) {
+ switch (errno) {
+ case EILSEQ:
+ if (outlen != MAXPATHLEN) {
+ mangleflag = 1;
+ }
+ default:
+ return NULL;
+ }
+ }
+ }
+ mpath[MAXPATHLEN -outlen] = 0;
+#endif
+#ifdef FILE_MANGLING
+ m = mangle(vol, mpath, upath, mangleflag);
+#else
+ if (mangleflag)
+ return NULL;
+ m = mpath;
+#endif /* FILE_MANGLING */
+
+ return(m);
+}
+
+/* ----------------------------- */
int afp_addcomment(obj, ibuf, ibuflen, rbuf, rbuflen )
AFPObj *obj;
char *ibuf, *rbuf;
int clen;
u_int32_t did;
u_int16_t vid;
+ int isadir;
*rbuflen = 0;
ibuf += 2;
}
if (NULL == ( path = cname( vol, dir, &ibuf )) ) {
- return afp_errno;
+ return get_afp_errno(AFPERR_NOOBJ);
}
if ((u_long)ibuf & 1 ) {
clen = min( clen, 199 );
upath = path->u_name;
- if (check_access(upath, OPENACC_WR ) < 0) {
+ if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
return AFPERR_ACCESS;
}
- if (*path->m_name == '\0' || !(of = of_findname(path))) {
+ isadir = path_isadir(path);
+ if (isadir || !(of = of_findname(path))) {
memset(&ad, 0, sizeof(ad));
adp = &ad;
} else
adp = of->of_ad;
if (ad_open( upath , vol_noadouble(vol) |
- (( *path->m_name == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
+ (( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
O_RDWR|O_CREAT, 0666, adp) < 0 ) {
return( AFPERR_ACCESS );
}
struct dir *dir;
struct ofork *of;
struct path *s_path;
- char *path, *upath;
+ char *upath;
u_int32_t did;
u_int16_t vid;
-
+ int isadir;
+
*rbuflen = 0;
ibuf += 2;
}
if (NULL == ( s_path = cname( vol, dir, &ibuf )) ) {
- return afp_errno;
+ return get_afp_errno(AFPERR_NOOBJ);
}
upath = s_path->u_name;
- path = s_path->m_name;
-
- if (*path == '\0' || !(of = of_findname(s_path))) {
+ isadir = path_isadir(s_path);
+ if (isadir || !(of = of_findname(s_path))) {
memset(&ad, 0, sizeof(ad));
adp = &ad;
} else
adp = of->of_ad;
if ( ad_open( upath,
- (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
+ ( isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
O_RDONLY, 0666, adp) < 0 ) {
return( AFPERR_NOITEM );
}
struct dir *dir;
struct ofork *of;
struct path *s_path;
- char *path, *upath;
+ char *upath;
u_int32_t did;
u_int16_t vid;
+ int isadir;
*rbuflen = 0;
ibuf += 2;
}
if (NULL == ( s_path = cname( vol, dir, &ibuf ))) {
- return afp_errno;
+ return get_afp_errno(AFPERR_NOOBJ);
}
upath = s_path->u_name;
- path = s_path->m_name;
- if (check_access(upath, OPENACC_WR ) < 0) {
+ if (!vol_unix_priv(vol) && check_access(upath, OPENACC_WR ) < 0) {
return AFPERR_ACCESS;
}
- if (path == '\0' || !(of = of_findname(s_path))) {
+ isadir = path_isadir(s_path);
+ if (isadir || !(of = of_findname(s_path))) {
memset(&ad, 0, sizeof(ad));
adp = &ad;
} else
adp = of->of_ad;
if ( ad_open( upath,
- (( *path == '\0' ) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF),
+ (isadir) ? ADFLAGS_HF|ADFLAGS_DIR : ADFLAGS_HF,
O_RDWR, 0, adp) < 0 ) {
switch ( errno ) {
case ENOENT :