KIP, Powerprint Request software -samba
James Peach
jpeach at sgi.com
Sun Aug 15 23:59:43 GMT 2004
On Fri, Aug 13, 2004 at 10:19:20AM -0700, Jeremy Allison wrote:
> On Fri, Aug 13, 2004 at 11:43:10AM +0200, Martin Zielinski wrote:
> >
> > That's not the problem. Even the directory listing from Windows, using the
> > explorer is fast.
> > I'm not so deep in Windows API, but the slow-down effect using the Powerprint
> > application is caused by treating the request (samba calls it
> > "trans2findfirst") as a request using a wildcard.
> > Maybe the correct behaviour to get the file info would be a different call
> > from the Windows API - but I don't know.
> >
> > Samba creates a directory listing for each file request with
> > "dptr_create(...)" to find a match between the file and the directory
> > content.
> >
> > I think, the way to fix this behaviour ist to detect, that the file name is
> > NOT a wildcard but a valid file name. Checking, if we can get an excact match
> > on the pattern, and - if so - skip the directory listing could be the trick.
> >
> > But I'm not deep enaugh in Samba to be really shure about that or even able to
> > test it by hacking Samba :-(
>
> Ah - great ! That's wonderful debugging. This is an optimisation I've
> been thinking of for a while. Can you get me the ethereal capture
> trace of this and a debug level 10 log ? It should be easy to fix
> this particular case !
It just so happens that some of our customers have been seeing this
problem with the findfirst code. I spent a chunk of last week putting
together the attached patch (against 3.0.6rc2) which
1. Implements a lazy OpenDir for extremely large directory
listings.
2. Avoids walking the entire directory when there is an exact
filename match.
It's a little complicated, but I _really_ wanted to avoid disturbing the
logic in get_lanman2_dir_entry().
--
James Peach | jpeach at sgi.com | SGI Australian Software Group
I don't speak for SGI.
-------------- next part --------------
diff -r -u reference/source/smbd/dir.c samba-3.0.5rc1/source/smbd/dir.c
--- reference/source/smbd/dir.c Fri Jul 9 03:06:11 2004
+++ samba-3.0.5rc1/source/smbd/dir.c Fri Aug 6 14:42:44 2004
@@ -19,11 +19,43 @@
*/
#include "includes.h"
+#include <sys/pathname.h>
/*
This module implements directory related functions for Samba.
*/
+/* Directory abstraction. */
+typedef struct {
+ int pos;
+#define D_LAZY_READDIR 0x0001
+#define D_USE_VETO 0x0002
+#define D_CALLER_HIDES 0x0004
+ uint flags;
+ union {
+ /* A lazy directory hold the DIR* open and parcels entries out
+ * using readdir/seekdir/etc. The caller may choose to do name
+ * hiding itself by setting the D_CALLER_HIDES flag.
+ */
+ struct {
+ connection_struct *conn;
+ DIR *dp; /* open directory pointer */
+ char *origpath; /* full path to directory */
+ } lazy;
+ /* A fixed directory reads the entries once at creation time,
+ * hiding entries if necessary.
+ */
+ struct {
+ char *data; /* buffer of saved names */
+ char *current; /* current name */
+ int numentries;
+ } fixed;
+ } state;
+} Dir;
+
+#define IS_LAZY(d) ((d)->flags & D_LAZY_READDIR)
+
+/* Per client directory state wrapper. */
typedef struct _dptr_struct {
struct _dptr_struct *next, *prev;
int dnum;
@@ -30,12 +62,17 @@
uint16 spid;
connection_struct *conn;
void *ptr;
- BOOL expect_close;
+#define D_EXPECT_CLOSE 0x0100
+ uint flags;
char *wcard; /* Field only used for trans2_ searches */
uint16 attr; /* Field only used for trans2_ searches */
char *path;
} dptr_struct;
+#define EXPECT_CLOSE(d) ((d)->flags & D_EXPECT_CLOSE)
+
+static void *OpenSingletonDir(connection_struct *conn, const char *dname, const char * entry, BOOL use_veto);
+
static struct bitmap *dptr_bmap;
static dptr_struct *dirptrs;
@@ -121,8 +158,14 @@
if (dptrs_open >= MAX_OPEN_DIRECTORIES)
dptr_idleoldest();
DEBUG(4,("Reopening dptr key %d\n",key));
- if ((dptr->ptr = OpenDir(dptr->conn, dptr->path, True)))
+ dptr->ptr =
+ IS_LAZY(dptr) ? OpenDirLazy(dptr->conn, dptr->path, True)
+ : OpenDir(dptr->conn, dptr->path, True);
+
+ if (dptr->ptr) {
dptrs_open++;
+ }
+
}
DLIST_PROMOTE(dirptrs,dptr);
return dptr;
@@ -179,11 +222,38 @@
{
dptr_struct *dptr = dptr_get(key, False);
- if (dptr) {
- dptr->wcard = wcard;
- return True;
- }
- return False;
+ if (!dptr)
+ return False;
+
+ dptr->wcard = wcard;
+
+ if (IS_LAZY(dptr) && dptr->ptr && !ms_has_wild(wcard)) {
+ void * newdir;
+
+ /* This wild card isn't really wild, so all we have to
+ * worry about is case and suchlike. If we can create a
+ * singleton Dir for this case, there must be an exact
+ * match. If not, well no harm done .. we retain the
+ * existing directory.
+ */
+ if (newdir = OpenSingletonDir(dptr->conn, dptr->path, wcard, True)) {
+ DEBUG(4,("replaced directory (path=%s) with singleton (entry=%s)\n",
+ dptr->path, wcard));
+
+ /* If the connection_struct has a backpointer to the
+ * directory iterator we just replaced, we'd better
+ * update it.
+ */
+ if (dptr->conn->dirptr == dptr->ptr) {
+ dptr->conn->dirptr = newdir;
+ }
+
+ CloseDir(dptr->ptr);
+ dptr->ptr = newdir;
+ }
+ }
+
+ return True;
}
/****************************************************************************
@@ -327,7 +397,7 @@
Start a directory listing.
****************************************************************************/
-static BOOL start_dir(connection_struct *conn, pstring directory)
+static BOOL start_dir(connection_struct *conn, pstring directory, BOOL lazy)
{
const char *dir2;
@@ -342,7 +412,7 @@
if (! *dir2)
dir2 = ".";
- conn->dirptr = OpenDir(conn, directory, True);
+ conn->dirptr = lazy ? OpenDirLazy(conn, directory, True) : OpenDir(conn, directory, True);
if (conn->dirptr) {
dptrs_open++;
string_set(&conn->dirpath,directory);
@@ -380,7 +450,7 @@
*/
for(; dptr; dptr = dptr->prev) {
- if ((old && (dptr->dnum < 256) && !dptr->expect_close) ||
+ if ((old && (dptr->dnum < 256) && !EXPECT_CLOSE(dptr)) ||
(!old && (dptr->dnum > 255))) {
dptr_close_internal(dptr);
return;
@@ -397,11 +467,11 @@
me at Andrew's knee.... :-) :-). JRA.
****************************************************************************/
-int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid)
+static int dptr_create_common(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,BOOL lazy,uint16 spid)
{
dptr_struct *dptr;
- if (!start_dir(conn,path))
+ if (!start_dir(conn,path,lazy))
return(-2); /* Code to say use a unix error return code. */
if (dptrs_open >= MAX_OPEN_DIRECTORIES)
@@ -481,18 +551,33 @@
string_set(&dptr->path,path);
dptr->conn = conn;
dptr->spid = spid;
- dptr->expect_close = expect_close;
+ dptr->flags = 0;
dptr->wcard = NULL; /* Only used in lanman2 searches */
dptr->attr = 0; /* Only used in lanman2 searches */
+ if (expect_close)
+ dptr->flags |= D_EXPECT_CLOSE;
+ if (lazy)
+ dptr->flags |= D_LAZY_READDIR;
+
DLIST_ADD(dirptrs, dptr);
DEBUG(3,("creating new dirptr %d for path %s, expect_close = %d\n",
- dptr->dnum,path,expect_close));
+ dptr->dnum,path,EXPECT_CLOSE(dptr)));
return(dptr->dnum);
}
+int dptr_create(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid)
+{
+ return dptr_create_common(conn, path, old_handle, expect_close, False /* lazy */, spid);
+}
+
+int dptr_create_lazy(connection_struct *conn, pstring path, BOOL old_handle, BOOL expect_close,uint16 spid)
+{
+ return dptr_create_common(conn, path, old_handle, expect_close, True /* lazy */, spid);
+}
+
/****************************************************************************
Fill the 5 byte server reserved dptr field.
****************************************************************************/
@@ -667,14 +752,6 @@
return(found);
}
-typedef struct {
- int pos;
- int numentries;
- int mallocsize;
- char *data;
- char *current;
-} Dir;
-
/*******************************************************************
Check to see if a user can read a file. This is only approximate,
it is used as part of the "hide unreadable" option. Don't
@@ -807,9 +884,158 @@
}
/*******************************************************************
+ Should the given name be returned to the caller?
+********************************************************************/
+
+static BOOL user_can_see_file(connection_struct * conn,
+ const char * dirpath,
+ const char * fname,
+ BOOL use_veto,
+ BOOL must_stat)
+{
+ SMB_STRUCT_STAT st;
+ char * entry = NULL;
+
+ if (conn == NULL)
+ return True;
+
+ /* If it's a vetoed file, pretend it doesn't even exist */
+ if (use_veto && IS_VETO_PATH(conn, fname))
+ return False;
+
+ ZERO_STRUCT(st);
+
+ /* In the case of a singleton directory, we have to stat to make sure
+ * the filename isn't bogus.
+ */
+ if (must_stat) {
+ int ret = 0;
+ if (entry || asprintf(&entry, "%s/%s", dirpath, fname) > 0) {
+ ret = SMB_VFS_STAT(conn, entry, &st);
+ }
+ if (ret != 0) {
+ SAFE_FREE(entry);
+ return False;
+ }
+ }
+
+ /* Honour _hide unreadable_ option */
+ if (lp_hideunreadable(SNUM(conn))) {
+ int ret=0;
+
+ if (entry || asprintf(&entry, "%s/%s", dirpath, fname) > 0) {
+ ret = user_can_read_file(conn, entry, &st);
+ }
+ if (!ret) {
+ SAFE_FREE(entry);
+ return False;
+ }
+ }
+
+ /* Honour _hide unwriteable_ option */
+ if (lp_hideunwriteable_files(SNUM(conn))) {
+ int ret=0;
+
+ if (entry || asprintf(&entry, "%s/%s", dirpath, fname) > 0) {
+ ret = user_can_write_file(conn, entry, &st);
+ }
+ if (!ret) {
+ SAFE_FREE(entry);
+ return False;
+ }
+ }
+
+ /* Honour _hide_special_ option */
+ if (lp_hide_special_files(SNUM(conn))) {
+ int ret=0;
+
+ if (entry || asprintf(&entry, "%s/%s", dirpath, fname) > 0) {
+ ret = file_is_special(conn, entry, &st);
+ }
+ if (ret) {
+ SAFE_FREE(entry);
+ return False;
+ }
+ }
+
+ SAFE_FREE(entry);
+ return True;
+}
+
+/*******************************************************************
Open a directory.
********************************************************************/
+void *OpenDirLazy(connection_struct * conn, const char * name, BOOL use_veto)
+{
+ Dir * dirp;
+ DIR * dp;
+ char * path = NULL;
+
+ if (!(dp = SMB_VFS_OPENDIR(conn, name)))
+ return(NULL);
+
+ asprintf(&path, "%s/%s", conn->origpath, name);
+ dirp = calloc(sizeof(Dir), 1);
+ if (!dirp || !path) {
+ SAFE_FREE(dirp);
+ SAFE_FREE(path);
+ DEBUG(0, ("Out of memory in OpenDirLazy\n"));
+ SMB_VFS_CLOSEDIR(conn,dp);
+ return(NULL);
+ }
+
+ dirp->flags = (D_LAZY_READDIR | D_CALLER_HIDES);
+ dirp->state.lazy.conn = conn;
+ dirp->state.lazy.origpath = path;
+ dirp->state.lazy.dp = dp;
+
+ if (use_veto)
+ dirp->flags |= D_USE_VETO;
+
+ return(dirp);
+}
+
+/* This function fakes up a fixed Dir structure. This is an optimisation for
+ * the case where a client does a FindFirst without a wildcard. In this case it
+ * might be possible to just hand out the requested file without reading all the
+ * directory entries. This is a big help when deleting large directories.
+ */
+static void *OpenSingletonDir(connection_struct *conn, const char *dirpath, const char *entry, BOOL use_veto)
+{
+ Dir * dirp;
+ size_t e_len; /* entry length */
+
+ if (!user_can_see_file(conn, dirpath, entry, use_veto, True /* must_stat */)) {
+ return(NULL);
+ }
+
+ dirp = (Dir *)calloc(sizeof(Dir), 1);
+ if (!dirp) {
+ DEBUG(0,("Out of memory in OpenSingletonDir\n"));
+ return(NULL);
+ }
+
+ e_len = strlen(entry);
+#define S_DOTDOT_SZ (sizeof(".\0.."))
+
+ dirp->state.fixed.data = malloc(S_DOTDOT_SZ + e_len + 1);
+ if (!dirp->state.fixed.data) {
+ SAFE_FREE(dirp);
+ DEBUG(0,("Out of memory in OpenSingletonDir\n"));
+ return(NULL);
+ }
+
+ memcpy(dirp->state.fixed.data, ".\0..", S_DOTDOT_SZ);
+ memcpy(dirp->state.fixed.data + S_DOTDOT_SZ, entry, e_len + 1);
+
+ dirp->state.fixed.numentries = 3;
+ dirp->state.fixed.current = dirp->state.fixed.data;
+ return(dirp);
+
+#undef S_DOTDOT_SZ
+}
+
void *OpenDir(connection_struct *conn, const char *name, BOOL use_veto)
{
Dir *dirp;
@@ -816,23 +1042,29 @@
const char *n;
DIR *p = SMB_VFS_OPENDIR(conn,name);
int used=0;
+ char *dirpath=NULL;
+ size_t mallocsize = 0;
if (!p)
return(NULL);
- dirp = (Dir *)malloc(sizeof(Dir));
- if (!dirp) {
+
+ dirp = (Dir *)calloc(sizeof(Dir), 1);
+ asprintf(&dirpath, "%s/%s", conn->origpath, name);
+
+ if (!dirp || !dirpath) {
+ SAFE_FREE(dirp);
+ SAFE_FREE(dirpath);
DEBUG(0,("Out of memory in OpenDir\n"));
SMB_VFS_CLOSEDIR(conn,p);
return(NULL);
}
- dirp->pos = dirp->numentries = dirp->mallocsize = 0;
- dirp->data = dirp->current = NULL;
+ if (use_veto)
+ dirp->flags |= D_USE_VETO;
+
while (True) {
int l;
BOOL normal_entry = True;
- SMB_STRUCT_STAT st;
- char *entry = NULL;
if (used == 0) {
n = ".";
@@ -849,72 +1081,31 @@
normal_entry = True;
}
- ZERO_STRUCT(st);
- l = strlen(n)+1;
-
- /* If it's a vetoed file, pretend it doesn't even exist */
- if (normal_entry && use_veto && conn && IS_VETO_PATH(conn, n))
- continue;
-
- /* Honour _hide unreadable_ option */
- if (normal_entry && conn && lp_hideunreadable(SNUM(conn))) {
- int ret=0;
-
- if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
- ret = user_can_read_file(conn, entry, &st);
- }
- if (!ret) {
- SAFE_FREE(entry);
- continue;
- }
- }
-
- /* Honour _hide unwriteable_ option */
- if (normal_entry && conn && lp_hideunwriteable_files(SNUM(conn))) {
- int ret=0;
-
- if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
- ret = user_can_write_file(conn, entry, &st);
- }
- if (!ret) {
- SAFE_FREE(entry);
- continue;
- }
- }
-
- /* Honour _hide_special_ option */
- if (normal_entry && conn && lp_hide_special_files(SNUM(conn))) {
- int ret=0;
-
- if (entry || asprintf(&entry, "%s/%s/%s", conn->origpath, name, n) > 0) {
- ret = file_is_special(conn, entry, &st);
- }
- if (ret) {
- SAFE_FREE(entry);
- continue;
- }
- }
-
- SAFE_FREE(entry);
+ if (normal_entry && !user_can_see_file(conn, dirpath, n,
+ dirp->flags & D_USE_VETO, False /* must_stat */)) {
+ continue;
+ }
- if (used + l > dirp->mallocsize) {
+ l = strlen(n)+1;
+ if (used + l > mallocsize) {
int s = MAX(used+l,used+2000);
char *r;
- r = (char *)Realloc(dirp->data,s);
+ r = (char *)Realloc(dirp->state.fixed.data,s);
if (!r) {
DEBUG(0,("Out of memory in OpenDir\n"));
break;
}
- dirp->data = r;
- dirp->mallocsize = s;
- dirp->current = dirp->data;
+ dirp->state.fixed.data = r;
+ mallocsize = s;
+ dirp->state.fixed.current = dirp->state.fixed.data;
}
- safe_strcpy_base(dirp->data+used,n, dirp->data, dirp->mallocsize);
+ safe_strcpy_base(dirp->state.fixed.data+used,n, dirp->state.fixed.data, mallocsize);
used += l;
- dirp->numentries++;
+ dirp->state.fixed.numentries++;
}
+ SAFE_FREE(dirpath);
SMB_VFS_CLOSEDIR(conn,p);
return((void *)dirp);
}
@@ -926,9 +1117,17 @@
void CloseDir(void *p)
{
+ Dir *dirp = (Dir *)p;
if (!p)
return;
- SAFE_FREE(((Dir *)p)->data);
+
+ if (IS_LAZY(dirp)) {
+ SMB_VFS_CLOSEDIR(dirp->state.lazy.conn, dirp->state.lazy.dp);
+ SAFE_FREE(dirp->state.lazy.origpath);
+ } else {
+ SAFE_FREE(dirp->state.fixed.data);
+ }
+
SAFE_FREE(p);
}
@@ -941,16 +1140,50 @@
char *ret;
Dir *dirp = (Dir *)p;
- if (!dirp || !dirp->current || dirp->pos >= dirp->numentries)
- return(NULL);
+ if (!dirp || !dirp->state.fixed.current)
+ return(NULL);
- ret = dirp->current;
- dirp->current = skip_string(dirp->current,1);
- dirp->pos++;
+ if (IS_LAZY(dirp)) {
+ while (ret = vfs_readdirname(dirp->state.lazy.conn, dirp->state.lazy.dp)) {
+ dirp->pos++;
+
+ /* Skip checks for . and .. or if caller is doing them. */
+ if ((dirp->flags & D_CALLER_HIDES) || ISDOT(ret) || ISDOTDOT(ret)) {
+ break;
+ }
+
+ if (user_can_see_file(dirp->state.lazy.conn, dirp->state.lazy.origpath,
+ ret, dirp->flags & D_USE_VETO, False /* must_stat */)) {
+ break;
+ }
+ }
+ /* Don't update pos because telldir does an lseek, which is a
+ * syscall we just don't need.
+ */
+ } else {
+ if (dirp->pos >= dirp->state.fixed.numentries)
+ return(NULL);
+
+ ret = dirp->state.fixed.current;
+ dirp->state.fixed.current = skip_string(dirp->state.fixed.current,1);
+ dirp->pos++;
+ }
return(ret);
}
+BOOL HideDirEntry(void * p, const char * name)
+{
+ Dir *dirp = (Dir *)p;
+
+ if (dirp->flags & D_CALLER_HIDES) {
+ return !user_can_see_file(dirp->state.lazy.conn, dirp->state.lazy.origpath,
+ name, dirp->flags & D_USE_VETO, False /* must_stat */);
+ } else {
+ return False;
+ }
+}
+
/*******************************************************************
Seek a dir.
********************************************************************/
@@ -959,16 +1192,21 @@
{
Dir *dirp = (Dir *)p;
- if (!dirp)
+ if (!dirp || pos < 0)
return(False);
- if (pos < dirp->pos) {
- dirp->current = dirp->data;
- dirp->pos = 0;
- }
+ if (pos < dirp->pos) {
+ if (IS_LAZY(dirp)) {
+ rewinddir(dirp->state.lazy.dp);
+ dirp->pos = 0;
+ } else {
+ dirp->state.fixed.current = dirp->state.fixed.data;
+ dirp->pos = 0;
+ }
+ }
- while (dirp->pos < pos && ReadDirName(p))
- ;
+ while (dirp->pos < pos && ReadDirName(p))
+ ;
return (dirp->pos == pos);
}
diff -r -u reference/source/smbd/notify_hash.c samba-3.0.5rc1/source/smbd/notify_hash.c
--- reference/source/smbd/notify_hash.c Thu Aug 5 15:25:54 2004
+++ samba-3.0.5rc1/source/smbd/notify_hash.c Tue Aug 3 16:34:16 2004
@@ -90,7 +90,7 @@
* larger than the max time_t value).
*/
- dp = OpenDir(conn, path, True);
+ dp = OpenDirLazy(conn, path, True);
if (dp == NULL)
return False;
diff -r -u reference/source/smbd/reply.c samba-3.0.5rc1/source/smbd/reply.c
--- reference/source/smbd/reply.c Fri Jul 9 03:06:10 2004
+++ samba-3.0.5rc1/source/smbd/reply.c Thu Aug 5 15:35:49 2004
@@ -1600,7 +1600,7 @@
const char *dname;
if (check_name(directory,conn))
- dirptr = OpenDir(conn, directory, True);
+ dirptr = OpenDirLazy(conn, directory, True);
/* XXXX the CIFS spec says that if bit0 of the flags2 field is set then
the pattern matches against the long name, otherwise the short name
@@ -1631,7 +1631,10 @@
if(!mask_match(fname, mask, conn->case_sensitive))
continue;
-
+
+ if (HideDirEntry(dirptr, dname))
+ continue;
+
if (sys_direntry) {
error = NT_STATUS_OBJECT_NAME_INVALID;
DEBUG(3,("unlink_internals: system directory delete denied [%s] mask [%s]\n",
@@ -3887,7 +3890,7 @@
pstring destname;
if (check_name(directory,conn))
- dirptr = OpenDir(conn, directory, True);
+ dirptr = OpenDirLazy(conn, directory, True);
if (dirptr) {
error = NT_STATUS_NO_SUCH_FILE;
@@ -3915,7 +3918,10 @@
if(!mask_match(fname, mask, conn->case_sensitive))
continue;
-
+
+ if (HideDirEntry(dirptr, dname))
+ continue;
+
if (sysdir_entry) {
error = NT_STATUS_OBJECT_NAME_INVALID;
break;
@@ -4240,7 +4246,7 @@
pstring destname;
if (check_name(directory,conn))
- dirptr = OpenDir(conn, directory, True);
+ dirptr = OpenDirLazy(conn, directory, True);
if (dirptr) {
error = ERRbadfile;
@@ -4254,6 +4260,9 @@
if(!mask_match(fname, mask, conn->case_sensitive))
continue;
+
+ if (HideDirEntry(dirptr, dname))
+ continue;
error = ERRnoaccess;
slprintf(fname,sizeof(fname)-1, "%s/%s",directory,dname);
diff -r -u reference/source/smbd/trans2.c samba-3.0.5rc1/source/smbd/trans2.c
--- reference/source/smbd/trans2.c Fri Jul 9 03:06:11 2004
+++ samba-3.0.5rc1/source/smbd/trans2.c Fri Aug 6 14:47:53 2004
@@ -882,8 +882,8 @@
reskey = 0;
- DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset %d\n",
- (long)conn->dirptr,TellDir(conn->dirptr)));
+ DEBUG(8,("get_lanman2_dir_entry:readdir on dirptr 0x%lx now at offset=%d entry=\n",
+ (long)conn->dirptr,TellDir(conn->dirptr), dname));
if (!dname)
return(False);
@@ -893,6 +893,13 @@
if(!(got_match = *got_exact_match = exact_match(fname, mask, conn->case_sensitive)))
got_match = mask_match(fname, mask, conn->case_sensitive);
+ /* If we have a lazy directory iterator, we might need to
+ * exclude (potentially matching) this entry.
+ */
+ if (got_match && HideDirEntry(conn->dirptr, dname)) {
+ got_match = False;
+ }
+
if(!got_match && !mangle_is_8_3(fname, False)) {
/*
@@ -1422,7 +1429,8 @@
return ERROR_DOS(ERRDOS,ERRnomem);
*pparams = params;
- dptr_num = dptr_create(conn,directory, False, True ,SVAL(inbuf,smb_pid));
+ dptr_num = dptr_create_lazy(conn,directory, False, True, SVAL(inbuf,smb_pid));
+
if (dptr_num < 0)
return(UNIXERROR(ERRDOS,ERRbadfile));
@@ -1707,7 +1715,7 @@
if(current_pos < 0) {
DEBUG(7,("call_trans2findnext: notfound: seeking to pos %d\n", start_pos));
SeekDir(dirptr, start_pos);
- for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; SeekDir(dirptr,++current_pos)) {
+ for(current_pos = start_pos; (dname = ReadDirName(dirptr)) != NULL; ++current_pos) {
/*
* Remember, mangle_map is called by
More information about the samba-technical
mailing list