int get_real_filename(connection_struct *conn, const char *path, const char *name, TALLOC_CTX *mem_ctx, char **found_name) { struct smb_Dir *cur_dir; const char *dname; bool mangled; char *unmangled_name = NULL; long curpos; /* open the directory */ if (!(cur_dir = OpenDir(talloc_tos(), conn, path, NULL, 0))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); TALLOC_FREE(unmangled_name); return -1; } /* now scan for matching names */ curpos = 0; while ((dname = ReadDirName(cur_dir, &curpos, NULL))) { /* Is it dot or dot dot. */ if (ISDOT(dname) || ISDOTDOT(dname)) { continue; } /* * At this point dname is the unmangled name. * name is either mangled or not, depending on the state * of the "mangled" variable. JRA. */ /* * Check mangled name against mangled name, or unmangled name * against unmangled name. */ if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ *found_name = talloc_strdup(mem_ctx, dname); TALLOC_FREE(unmangled_name); TALLOC_FREE(cur_dir); if (!*found_name) { errno = ENOMEM; return -1; } return 0; } } TALLOC_FREE(unmangled_name); TALLOC_FREE(cur_dir); errno = ENOENT; return -1; }
static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *orig_path, struct smb_filename *smb_fname) { NTSTATUS status; unsigned int i, num_streams = 0; struct stream_struct *streams = NULL; if (SMB_VFS_STAT(conn, smb_fname) == 0) { DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname))); return NT_STATUS_OK; } if (errno != ENOENT) { DEBUG(10, ("vfs_stat failed: %s\n", strerror(errno))); status = map_nt_error_from_unix(errno); goto fail; } /* Fall back to a case-insensitive scan of all streams on the file. */ status = vfs_streaminfo(conn, NULL, smb_fname->base_name, mem_ctx, &num_streams, &streams); if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { SET_STAT_INVALID(smb_fname->st); return NT_STATUS_OK; } if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status))); goto fail; } for (i=0; i<num_streams; i++) { DEBUG(10, ("comparing [%s] and [%s]: ", smb_fname->stream_name, streams[i].name)); if (fname_equal(smb_fname->stream_name, streams[i].name, conn->case_sensitive)) { DEBUGADD(10, ("equal\n")); break; } DEBUGADD(10, ("not equal\n")); } /* Couldn't find the stream. */ if (i == num_streams) { SET_STAT_INVALID(smb_fname->st); TALLOC_FREE(streams); return NT_STATUS_OK; } DEBUG(10, ("case insensitive stream. requested: %s, actual: %s\n", smb_fname->stream_name, streams[i].name)); TALLOC_FREE(smb_fname->stream_name); smb_fname->stream_name = talloc_strdup(smb_fname, streams[i].name); if (smb_fname->stream_name == NULL) { status = NT_STATUS_NO_MEMORY; goto fail; } SET_STAT_INVALID(smb_fname->st); if (SMB_VFS_STAT(conn, smb_fname) == 0) { DEBUG(10, ("'%s' exists\n", smb_fname_str_dbg(smb_fname))); } status = NT_STATUS_OK; fail: TALLOC_FREE(streams); return status; }
static int get_real_filename_full_scan(connection_struct *conn, const char *path, const char *name, bool mangled, TALLOC_CTX *mem_ctx, char **found_name) { struct smb_Dir *cur_dir; const char *dname = NULL; char *talloced = NULL; char *unmangled_name = NULL; long curpos; /* handle null paths */ if ((path == NULL) || (*path == 0)) { path = "."; } /* If we have a case-sensitive filesystem, it doesn't do us any * good to search for a name. If a case variation of the name was * there, then the original stat(2) would have found it. */ if (!mangled && !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) { errno = ENOENT; return -1; } /* * The incoming name can be mangled, and if we de-mangle it * here it will not compare correctly against the filename (name2) * read from the directory and then mangled by the name_to_8_3() * call. We need to mangle both names or neither. * (JRA). * * Fix for bug found by Dina Fine. If in case sensitive mode then * the mangle cache is no good (3 letter extension could be wrong * case - so don't demangle in this case - leave as mangled and * allow the mangling of the directory entry read (which is done * case insensitively) to match instead. This will lead to more * false positive matches but we fail completely without it. JRA. */ if (mangled && !conn->case_sensitive) { mangled = !mangle_lookup_name_from_8_3(talloc_tos(), name, &unmangled_name, conn->params); if (!mangled) { /* Name is now unmangled. */ name = unmangled_name; } } /* open the directory */ if (!(cur_dir = OpenDir(talloc_tos(), conn, path, NULL, 0))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); TALLOC_FREE(unmangled_name); return -1; } /* now scan for matching names */ curpos = 0; while ((dname = ReadDirName(cur_dir, &curpos, NULL, &talloced))) { /* Is it dot or dot dot. */ if (ISDOT(dname) || ISDOTDOT(dname)) { TALLOC_FREE(talloced); continue; } /* * At this point dname is the unmangled name. * name is either mangled or not, depending on the state * of the "mangled" variable. JRA. */ /* * Check mangled name against mangled name, or unmangled name * against unmangled name. */ if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ *found_name = talloc_strdup(mem_ctx, dname); TALLOC_FREE(unmangled_name); TALLOC_FREE(cur_dir); if (!*found_name) { errno = ENOMEM; TALLOC_FREE(talloced); return -1; } TALLOC_FREE(talloced); return 0; } TALLOC_FREE(talloced); } TALLOC_FREE(unmangled_name); TALLOC_FREE(cur_dir); errno = ENOENT; return -1; }
static BOOL scan_directory(connection_struct *conn, const char *path, char *name, size_t maxlength) { struct smb_Dir *cur_dir; const char *dname; BOOL mangled; long curpos; mangled = mangle_is_mangled(name, conn->params); /* handle null paths */ if (*path == 0) path = "."; /* If we have a case-sensitive filesystem, it doesn't do us any * good to search for a name. If a case variation of the name was * there, then the original stat(2) would have found it. */ if (!(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) { errno = ENOENT; return False; } /* * The incoming name can be mangled, and if we de-mangle it * here it will not compare correctly against the filename (name2) * read from the directory and then mangled by the mangle_map() * call. We need to mangle both names or neither. * (JRA). * * Fix for bug found by Dina Fine. If in case sensitive mode then * the mangle cache is no good (3 letter extension could be wrong * case - so don't demangle in this case - leave as mangled and * allow the mangling of the directory entry read (which is done * case insensitively) to match instead. This will lead to more * false positive matches but we fail completely without it. JRA. */ if (mangled && !conn->case_sensitive) { mangled = !mangle_check_cache( name, maxlength, conn->params); } /* open the directory */ if (!(cur_dir = OpenDir(conn, path, NULL, 0))) { DEBUG(3,("scan dir didn't open dir [%s]\n",path)); return(False); } /* now scan for matching names */ curpos = 0; while ((dname = ReadDirName(cur_dir, &curpos))) { /* Is it dot or dot dot. */ if ((dname[0] == '.') && (!dname[1] || (dname[1] == '.' && !dname[2]))) { continue; } /* * At this point dname is the unmangled name. * name is either mangled or not, depending on the state of the "mangled" * variable. JRA. */ /* * Check mangled name against mangled name, or unmangled name * against unmangled name. */ if ((mangled && mangled_equal(name,dname,conn->params)) || fname_equal(name, dname, conn->case_sensitive)) { /* we've found the file, change it's name and return */ safe_strcpy(name, dname, maxlength); CloseDir(cur_dir); return(True); } } CloseDir(cur_dir); errno = ENOENT; return(False); }
static NTSTATUS build_stream_path(TALLOC_CTX *mem_ctx, connection_struct *conn, const char *orig_path, const char *basepath, const char *streamname, SMB_STRUCT_STAT *pst, char **path) { SMB_STRUCT_STAT st; char *result = NULL; NTSTATUS status; unsigned int i, num_streams; struct stream_struct *streams = NULL; result = talloc_asprintf(mem_ctx, "%s%s", basepath, streamname); if (result == NULL) { return NT_STATUS_NO_MEMORY; } if (SMB_VFS_STAT(conn, result, &st) == 0) { *pst = st; *path = result; return NT_STATUS_OK; } if (errno != ENOENT) { status = map_nt_error_from_unix(errno); DEBUG(10, ("vfs_stat failed: %s\n", nt_errstr(status))); goto fail; } status = SMB_VFS_STREAMINFO(conn, NULL, basepath, mem_ctx, &num_streams, &streams); if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { SET_STAT_INVALID(*pst); *path = result; return NT_STATUS_OK; } if (!NT_STATUS_IS_OK(status)) { DEBUG(10, ("vfs_streaminfo failed: %s\n", nt_errstr(status))); goto fail; } for (i=0; i<num_streams; i++) { DEBUG(10, ("comparing [%s] and [%s]: ", streamname, streams[i].name)); if (fname_equal(streamname, streams[i].name, conn->case_sensitive)) { DEBUGADD(10, ("equal\n")); break; } DEBUGADD(10, ("not equal\n")); } if (i == num_streams) { SET_STAT_INVALID(*pst); *path = result; TALLOC_FREE(streams); return NT_STATUS_OK; } TALLOC_FREE(result); result = talloc_asprintf(mem_ctx, "%s%s", basepath, streams[i].name); if (result == NULL) { status = NT_STATUS_NO_MEMORY; goto fail; } SET_STAT_INVALID(*pst); if (SMB_VFS_STAT(conn, result, pst) == 0) { stat_cache_add(orig_path, result, conn->case_sensitive); } *path = result; TALLOC_FREE(streams); return NT_STATUS_OK; fail: TALLOC_FREE(result); TALLOC_FREE(streams); return status; }