diff options
author | Andrew Tridgell <tridge@samba.org> | 2004-09-18 08:16:14 +0000 |
---|---|---|
committer | Gerald (Jerry) Carter <jerry@samba.org> | 2007-10-10 12:58:48 -0500 |
commit | 03cb4367d67ba9cdedf22df743d25d81093941d7 (patch) | |
tree | 0d6d97adec85cf9d4d67c34d8fc4e55b0b0eb019 /source4/ntvfs/posix/pvfs_dirlist.c | |
parent | 046380c56c35177ccf49d0a40e3771242b134277 (diff) | |
download | samba-03cb4367d67ba9cdedf22df743d25d81093941d7.tar.gz samba-03cb4367d67ba9cdedf22df743d25d81093941d7.tar.bz2 samba-03cb4367d67ba9cdedf22df743d25d81093941d7.zip |
r2404: the first large lump of posix vfs stuff.
this is still very much a skeleton (with many limbs missing too!). I
am committing this early to get some feedback on the approach taken.
(This used to be commit 40d5cae5ebbfe328e193eadb685df6a370730299)
Diffstat (limited to 'source4/ntvfs/posix/pvfs_dirlist.c')
-rw-r--r-- | source4/ntvfs/posix/pvfs_dirlist.c | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/source4/ntvfs/posix/pvfs_dirlist.c b/source4/ntvfs/posix/pvfs_dirlist.c new file mode 100644 index 0000000000..1b4d01c197 --- /dev/null +++ b/source4/ntvfs/posix/pvfs_dirlist.c @@ -0,0 +1,126 @@ +/* + Unix SMB/CIFS implementation. + + Copyright (C) Andrew Tridgell 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ +/* + directory listing functions for posix backend +*/ + +#include "includes.h" +#include "vfs_posix.h" + +/* + a special directory listing case where the pattern has no wildcard. We can just do a single stat() + thus avoiding the more expensive directory scan +*/ +static NTSTATUS pvfs_list_no_wildcard(struct pvfs_state *pvfs, struct pvfs_filename *name, + const char *pattern, struct pvfs_dir *dir) +{ + if (!name->exists) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + dir->count = 0; + dir->unix_path = name->full_name; + + dir->names = talloc_array_p(dir, const char *, 1); + if (!dir->names) { + return NT_STATUS_NO_MEMORY; + } + + dir->names[0] = talloc_strdup(dir, pattern); + if (!dir->names[0]) { + return NT_STATUS_NO_MEMORY; + } + + dir->count = 1; + + return NT_STATUS_OK; +} + +/* + read a directory and find all matching file names, returning them in + the structure *dir. The returned names are relative to the directory + + if the pattern matches no files then we return NT_STATUS_OK, with dir->count = 0 +*/ +NTSTATUS pvfs_list(struct pvfs_state *pvfs, struct pvfs_filename *name, struct pvfs_dir *dir) +{ + DIR *odir; + struct dirent *dent; + uint_t allocated = 0; + char *pattern; + + /* split the unix path into a directory + pattern */ + pattern = strrchr(name->full_name, '/'); + if (!pattern) { + /* this should not happen, as pvfs_unix_path is supposed to + return an absolute path */ + return NT_STATUS_UNSUCCESSFUL; + } + + *pattern++ = 0; + + if (!name->has_wildcard) { + return pvfs_list_no_wildcard(pvfs, name, pattern, dir); + } + + dir->count = 0; + dir->unix_path = name->full_name; + dir->names = talloc(dir, 0); + if (!dir->names) { + return NT_STATUS_NO_MEMORY; + } + + odir = opendir(name->full_name); + if (!odir) { + return pvfs_map_errno(pvfs, errno); + } + + while ((dent = readdir(odir))) { + uint_t i = dir->count; + const char *dname = dent->d_name; + + /* check it matches the wildcard pattern */ + if (ms_fnmatch(pattern, dname, PROTOCOL_NT1) != 0) { + continue; + } + + if (dir->count >= allocated) { + allocated = (allocated + 100) * 1.2; + dir->names = talloc_realloc_p(dir->names, const char *, allocated); + if (!dir->names) { + closedir(odir); + return NT_STATUS_NO_MEMORY; + } + } + + dir->names[i] = talloc_strdup(dir, dname); + if (!dir->names[i]) { + closedir(odir); + return NT_STATUS_NO_MEMORY; + } + + dir->count++; + } + + closedir(odir); + + return NT_STATUS_OK; +} + |