From 4d7d2d86f6b63289c3d73df13d2f219b8eaa429b Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Wed, 20 May 2026 10:45:44 +0200 Subject: [PATCH] connect revers path changes --- src/connect.c | 215 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 206 insertions(+), 9 deletions(-) diff --git a/src/connect.c b/src/connect.c index 1dc0eb9..f2a7582 100644 --- a/src/connect.c +++ b/src/connect.c @@ -144,6 +144,166 @@ static char *build_unix_name(NW_PATH *nwpath, int modus) return(unixname); } +static int resolve_dos_component_in_dir(const char *dir_unix, + const uint8 *dos_component, + uint8 *resolved_name, + int resolved_name_size, + int options) +{ + DIR *d; + struct dirent *dirbuff; + + d = opendir(dir_unix); + if (!d) { + if (seteuid(0)) {} + d = opendir(dir_unix); + reseteuid(); + } + if (!d) { + XDPRINTF((2, 0, + "OPEN RESOLVE opendir failed dir='%s' component='%s'", + dir_unix ? dir_unix : "(null)", + dos_component ? (char *)dos_component : "(null)")); + return 0; + } + + while ((dirbuff = readdir(d)) != NULL) { + uint8 dosname[DOS83_NAME_MAX + 1]; + + if (!dirbuff->d_ino) + continue; + if (!strcmp(dirbuff->d_name, ".") || !strcmp(dirbuff->d_name, "..")) + continue; + + if (dos83_match_name_in_dir(dir_unix, + (uint8 *)dirbuff->d_name, + dos_component, + options, + dosname, + sizeof(dosname))) { + strncpy((char *)resolved_name, dirbuff->d_name, resolved_name_size - 1); + resolved_name[resolved_name_size - 1] = '\0'; + XDPRINTF((2, 0, + "OPEN RESOLVE MATCH dir='%s' component='%s' unix='%s' alias='%s'", + dir_unix ? dir_unix : "(null)", + dos_component ? (char *)dos_component : "(null)", + dirbuff->d_name, + dosname)); + closedir(d); + return 1; + } + } + + XDPRINTF((2, 0, + "OPEN RESOLVE MISS dir='%s' component='%s'", + dir_unix ? dir_unix : "(null)", + dos_component ? (char *)dos_component : "(null)")); + closedir(d); + return 0; +} + +static int resolve_dos_nwpath_in_place(NW_VOL *v, uint8 *nw_path, uint8 *nw_fn) +{ + char dir_unix[1024]; + uint8 resolved_path[256]; + uint8 component[256]; + uint8 resolved_name[256]; + uint8 fncopy[256]; + uint8 *src; + uint8 *dst; + int had_leading_slash = (nw_path && nw_path[0] == '/'); + + if (!v || !nw_path || !nw_fn) + return -0x9c; + + strncpy(dir_unix, (const char *)v->unixname, sizeof(dir_unix) - 1); + dir_unix[sizeof(dir_unix) - 1] = '\0'; + + resolved_path[0] = '\0'; + dst = resolved_path; + + if (had_leading_slash) + *dst++ = '/'; + + src = nw_path; + if (*src == '/') + src++; + + while (*src) { + uint8 *c = component; + + while (*src == '/') + src++; + + if (!*src) + break; + + while (*src && *src != '/') + *c++ = *src++; + *c = '\0'; + + if (!resolve_dos_component_in_dir(dir_unix, + component, + resolved_name, + sizeof(resolved_name), + v->options)) { + XDPRINTF((2, 0, + "OPEN RESOLVE PATH FAIL dir='%s' component='%s'", + dir_unix, + component)); + return -0x9c; + } + + if (strlen(dir_unix) + 1 + strlen((char *)resolved_name) < sizeof(dir_unix) - 1) { + if (dir_unix[strlen(dir_unix) - 1] != '/') + strcat(dir_unix, "/"); + strcat(dir_unix, (char *)resolved_name); + } else + return -0x9c; + + strncpy((char *)dst, (const char *)resolved_name, + sizeof(resolved_path) - (int)(dst - resolved_path) - 2); + dst += strlen((char *)dst); + *dst++ = '/'; + *dst = '\0'; + } + + if (resolved_path[0]) { + unix2doscharset(resolved_path); + strmaxcpy(nw_path, (char *)resolved_path, 255); + } else + nw_path[0] = '\0'; + + strmaxcpy(fncopy, (char *)nw_fn, sizeof(fncopy) - 1); + if (fncopy[0]) { + if (!resolve_dos_component_in_dir(dir_unix, + fncopy, + resolved_name, + sizeof(resolved_name), + v->options)) { + XDPRINTF((2, 0, + "OPEN RESOLVE FN FAIL dir='%s' fn='%s'", + dir_unix, + fncopy)); + return -0x9c; + } + + unix2doscharset(resolved_name); + strmaxcpy(nw_fn, (char *)resolved_name, 255); + + XDPRINTF((2, 0, + "OPEN RESOLVE FINAL path='%s' fn='%s'", + nw_path, + nw_fn)); + } else { + XDPRINTF((2, 0, + "OPEN RESOLVE FINAL path='%s' fn=''", + nw_path)); + } + + return 0; +} + static int new_dir_handle(struct stat *stb, NW_PATH *nwpath) /* @@ -1085,23 +1245,60 @@ static int build_dir_name(NW_PATH *nwpath, /* gets complete path */ if (v->options & VOL_OPTION_IGNCASE) { uint8 unixname[1024]; /* should be enough */ uint8 *pp=unixname+v->unixnamlen; - int offset = ppp - nwpath->path; int pathlen = strlen(nwpath->path); int fnlen = strlen(nwpath->fn); + int resolve_result; + memcpy(unixname, v->unixname, v->unixnamlen); strmaxcpy(pp, nwpath->path, sizeof(unixname) - v->unixnamlen-1); if (fnlen) strmaxcpy(pp+pathlen, nwpath->fn, sizeof(unixname) - v->unixnamlen - pathlen-1 ); dos2unixcharset(pp); - pp += offset; - pathlen -= offset; - mangle_dos_name(v, unixname, pp); - unix2doscharset(pp); - XDPRINTF((5, 0, "Mangled DOS/unixname=%s", unixname)); - memcpy(ppp, pp, pathlen); - if (fnlen) - memcpy(nwpath->fn, pp+pathlen, fnlen); + + XDPRINTF((2, 0, + "OPEN RESOLVE START volume=%d path='%s' fn='%s' unix='%s'", + nwpath->volume, + nwpath->path, + nwpath->fn, + unixname)); + + resolve_result = resolve_dos_nwpath_in_place(v, nwpath->path, nwpath->fn); + + if (resolve_result) { + XDPRINTF((2, 0, + "OPEN RESOLVE FALLBACK result=0x%x path='%s' fn='%s'", + resolve_result, + nwpath->path, + nwpath->fn)); + + /* Keep the old path mangling as fallback for comparison/debugging. */ + { + int offset = ppp - nwpath->path; + uint8 *pp_old = unixname + v->unixnamlen; + int pathlen_old = strlen(nwpath->path); + int fnlen_old = strlen(nwpath->fn); + + strmaxcpy(pp_old, nwpath->path, sizeof(unixname) - v->unixnamlen-1); + if (fnlen_old) + strmaxcpy(pp_old+pathlen_old, nwpath->fn, + sizeof(unixname) - v->unixnamlen - pathlen_old-1 ); + dos2unixcharset(pp_old); + pp_old += offset; + pathlen_old -= offset; + mangle_dos_name(v, unixname, pp_old); + unix2doscharset(pp_old); + XDPRINTF((2, 0, "OPEN RESOLVE FALLBACK MANGLED unix='%s'", unixname)); + memcpy(ppp, pp_old, pathlen_old); + if (fnlen_old) + memcpy(nwpath->fn, pp_old+pathlen_old, fnlen_old); + } + } else { + XDPRINTF((2, 0, + "OPEN RESOLVE APPLIED path='%s' fn='%s'", + nwpath->path, + nwpath->fn)); + } } } else return(-0x98); /* wrong volume */ completition = nw_path_directory_is_ok(nwpath, stbuff);