summaryrefslogtreecommitdiff
path: root/source4/ntvfs/posix/pvfs_dirlist.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2004-09-18 08:16:14 +0000
committerGerald (Jerry) Carter <jerry@samba.org>2007-10-10 12:58:48 -0500
commit03cb4367d67ba9cdedf22df743d25d81093941d7 (patch)
tree0d6d97adec85cf9d4d67c34d8fc4e55b0b0eb019 /source4/ntvfs/posix/pvfs_dirlist.c
parent046380c56c35177ccf49d0a40e3771242b134277 (diff)
downloadsamba-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.c126
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;
+}
+