diff options
author | Jeremy Allison <jra@samba.org> | 2005-06-10 23:13:25 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 10:57:10 -0500 |
commit | c3fedee2a67966e4640b26dd084e75125e58f55c (patch) | |
tree | 0c1919f5331aa020555287ab21cdbe5dbf315d2e /source3/smbd | |
parent | 46c94b2659fa1f9d7ce2b6fd798e3abb3c7760d8 (diff) | |
download | samba-c3fedee2a67966e4640b26dd084e75125e58f55c.tar.gz samba-c3fedee2a67966e4640b26dd084e75125e58f55c.tar.bz2 samba-c3fedee2a67966e4640b26dd084e75125e58f55c.zip |
r7474: A *foul* and *disgusting* hack to ensure that, at the very lowest
level, . and .. are the first two entries returned when reading a
directory. This also means we can't seek to these offsets, but we
will never be doing that anyway (as far as I can think). The reason
we have to do this is that the NT4 explorer will happily display a
folder marked ".." as a clickable folder (and probably would display
"." as a clickable folder too) if these are not in positions zero
and one of the returned file list. W2K seems to have fixed this but
there are too many older systems out there... Never mind, more for
the "Undocumented CIFS talk", coming to a CIFS2005 conference near
you soon.... :-).
Jeremy.
(This used to be commit 7b6e907922b7d98abe4430ea73712a9c6419ea08)
Diffstat (limited to 'source3/smbd')
-rw-r--r-- | source3/smbd/dir.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/source3/smbd/dir.c b/source3/smbd/dir.c index f335c60897..b9c6cf8797 100644 --- a/source3/smbd/dir.c +++ b/source3/smbd/dir.c @@ -42,6 +42,7 @@ struct smb_Dir { char *dir_path; struct name_cache_entry *name_cache; unsigned int name_cache_index; + unsigned int file_number; }; struct dptr_struct { @@ -1074,15 +1075,35 @@ const char *ReadDirName(struct smb_Dir *dirp, long *poffset) const char *n; connection_struct *conn = dirp->conn; - SeekDir(dirp, *poffset); + /* Cheat to allow . and .. to be the first entries returned. */ + if ((*poffset == 0) && (dirp->file_number < 2)) { + if (dirp->file_number == 0) { + n = "."; + } else { + n = ".."; + } + dirp->file_number++; + return n; + } else { + /* A real offset, seek to it. */ + SeekDir(dirp, *poffset); + } + while ((n = vfs_readdirname(conn, dirp->dir))) { struct name_cache_entry *e; + /* Ignore . and .. - we've already returned them. */ + if (*n == '.') { + if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) { + continue; + } + } dirp->offset = SMB_VFS_TELLDIR(conn, dirp->dir); dirp->name_cache_index = (dirp->name_cache_index+1) % NAME_CACHE_SIZE; e = &dirp->name_cache[dirp->name_cache_index]; SAFE_FREE(e->name); e->name = SMB_STRDUP(n); *poffset = e->offset= dirp->offset; + dirp->file_number++; return e->name; } dirp->offset = -1; @@ -1141,6 +1162,7 @@ BOOL SearchDir(struct smb_Dir *dirp, const char *name, long *poffset) /* Not found in the name cache. Rewind directory and start from scratch. */ SMB_VFS_REWINDDIR(conn, dirp->dir); + dirp->file_number = 0; *poffset = 0; while ((entry = ReadDirName(dirp, poffset))) { if (conn->case_sensitive ? (strcmp(entry, name) == 0) : strequal(entry, name)) { |