r2404: the first large lump of posix vfs stuff.
authorAndrew Tridgell <tridge@samba.org>
Sat, 18 Sep 2004 08:16:14 +0000 (08:16 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 17:58:48 +0000 (12:58 -0500)
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)

source4/include/includes.h
source4/ntvfs/config.mk
source4/ntvfs/posix/pvfs_dirlist.c [new file with mode: 0644]
source4/ntvfs/posix/pvfs_fileinfo.c [new file with mode: 0644]
source4/ntvfs/posix/pvfs_resolve.c [new file with mode: 0644]
source4/ntvfs/posix/pvfs_search.c [new file with mode: 0644]
source4/ntvfs/posix/pvfs_shortname.c [new file with mode: 0644]
source4/ntvfs/posix/pvfs_unlink.c [new file with mode: 0644]
source4/ntvfs/posix/pvfs_util.c [new file with mode: 0644]
source4/ntvfs/posix/vfs_posix.c
source4/ntvfs/posix/vfs_posix.h

index b033d584f857c0fee6717c47298bbdfcf41bde79..bf566a01d60c1e370b17f82bc316b7e7781d0d4d 100644 (file)
@@ -676,6 +676,11 @@ extern int errno;
 #include "libnet/libnet.h"
 #include "utils/net/net.h"
 
+/* hmm, this really is getting ugly isn't it .... we probably need to
+   have some way to have subsystem includes without including it
+   globally */
+#include "ntvfs/posix/vfs_posix.h"
+
 #define malloc_p(type) (type *)malloc(sizeof(type))
 #define malloc_array_p(type, count) (type *)realloc_array(NULL, sizeof(type), count)
 #define realloc_p(p, type, count) (type *)realloc_array(p, sizeof(type), count)
index 25dd51b487d92947a0564f223ef399d40ca5f0a2..2298fcd554cce2c642bc8ec0038f76ea8860d369 100644 (file)
@@ -44,6 +44,14 @@ INIT_OBJ_FILES = \
 [MODULE::ntvfs_posix]
 INIT_OBJ_FILES = \
                ntvfs/posix/vfs_posix.o
+ADD_OBJ_FILES = \
+               ntvfs/posix/pvfs_util.o \
+               ntvfs/posix/pvfs_search.o \
+               ntvfs/posix/pvfs_dirlist.o \
+               ntvfs/posix/pvfs_fileinfo.o \
+               ntvfs/posix/pvfs_unlink.o \
+               ntvfs/posix/pvfs_resolve.o \
+               ntvfs/posix/pvfs_shortname.o
 # End MODULE ntvfs_posix
 ################################################
 
diff --git a/source4/ntvfs/posix/pvfs_dirlist.c b/source4/ntvfs/posix/pvfs_dirlist.c
new file mode 100644 (file)
index 0000000..1b4d01c
--- /dev/null
@@ -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;
+}
+
diff --git a/source4/ntvfs/posix/pvfs_fileinfo.c b/source4/ntvfs/posix/pvfs_fileinfo.c
new file mode 100644 (file)
index 0000000..83a577d
--- /dev/null
@@ -0,0 +1,128 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   POSIX NTVFS backend - 
+
+   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.
+*/
+
+#include "include/includes.h"
+#include "vfs_posix.h"
+
+
+/* UNIX filetype mappings. */
+#define UNIX_TYPE_FILE 0
+#define UNIX_TYPE_DIR 1
+#define UNIX_TYPE_SYMLINK 2
+#define UNIX_TYPE_CHARDEV 3
+#define UNIX_TYPE_BLKDEV 4
+#define UNIX_TYPE_FIFO 5
+#define UNIX_TYPE_SOCKET 6
+#define UNIX_TYPE_UNKNOWN 0xFFFFFFFF
+
+
+/*
+ Return the major devicenumber for UNIX extensions.
+*/
+static uint32_t unix_dev_major(dev_t dev)
+{
+#if defined(HAVE_DEVICE_MAJOR_FN)
+       return (uint32)major(dev);
+#else
+       return (uint32)(dev >> 8);
+#endif
+}
+
+/*
+ Return the minor devicenumber for UNIX extensions.
+*/
+static uint32_t unix_dev_minor(dev_t dev)
+{
+#if defined(HAVE_DEVICE_MINOR_FN)
+       return (uint32)minor(dev);
+#else
+       return (uint32)(dev & 0xff);
+#endif
+}
+
+/*
+ Return the filetype for UNIX extensions
+*/
+static uint32_t unix_filetype(mode_t mode)
+{
+       if (S_ISREG(mode)) return UNIX_TYPE_FILE;
+       if (S_ISDIR(mode)) return UNIX_TYPE_DIR;
+#ifdef S_ISLNK
+       if (S_ISLNK(mode)) return UNIX_TYPE_SYMLINK;
+#endif
+#ifdef S_ISCHR
+       if (S_ISCHR(mode)) return UNIX_TYPE_CHARDEV;
+#endif
+#ifdef S_ISBLK
+       if (S_ISBLK(mode)) return UNIX_TYPE_BLKDEV;
+#endif
+#ifdef S_ISFIFO
+       if (S_ISFIFO(mode)) return UNIX_TYPE_FIFO;
+#endif
+#ifdef S_ISSOCK
+       if (S_ISSOCK(mode)) return UNIX_TYPE_SOCKET;
+#endif
+
+       DEBUG(0,("unix_filetype: unknown filetype %u", (unsigned)mode));
+       return UNIX_TYPE_UNKNOWN;
+}
+
+
+/*
+  return all basic information about a file. This call is case-sensitive (it assumes that the 
+  pathnames given have already had case conversion)
+*/
+NTSTATUS pvfs_relative_file_info_cs(struct pvfs_state *pvfs, const char *dir_path, 
+                                   const char *name, struct pvfs_file_info *finfo)
+{
+       char *full_name = NULL;
+       struct stat st;
+
+       asprintf(&full_name, "%s/%s", dir_path, name);
+       if (full_name == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (stat(full_name, &st) == -1) {
+               free(full_name);
+               return pvfs_map_errno(pvfs, errno);
+       }
+
+       unix_to_nt_time(&finfo->create_time, st.st_ctime);
+       unix_to_nt_time(&finfo->access_time, st.st_atime);
+       unix_to_nt_time(&finfo->write_time, st.st_mtime);
+       unix_to_nt_time(&finfo->change_time, st.st_mtime);
+       finfo->attrib      = 0;
+       finfo->alloc_size  = st.st_size;
+       finfo->size        = st.st_size;
+       finfo->nlink       = st.st_nlink;
+       finfo->ea_size     = 0;
+       finfo->file_id     = st.st_ino;
+       finfo->unix_uid    = st.st_uid;
+       finfo->unix_gid    = st.st_gid;
+       finfo->unix_file_type = unix_filetype(st.st_mode);
+       finfo->unix_dev_major = unix_dev_major(st.st_rdev);
+       finfo->unix_dev_minor = unix_dev_minor(st.st_rdev);
+       finfo->unix_permissions = unix_perms_to_wire(st.st_mode);
+
+       return NT_STATUS_OK;
+}
diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c
new file mode 100644 (file)
index 0000000..66e7a5d
--- /dev/null
@@ -0,0 +1,303 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   POSIX NTVFS backend - filename resolution
+
+   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.
+*/
+
+/*
+  this is the core code for converting a filename from the format as
+  given by a client to a posix filename, including any case-matching
+  required, and checks for legal characters
+*/
+
+
+#include "include/includes.h"
+#include "vfs_posix.h"
+
+/*
+  compare two filename components. This is where the name mangling hook will go
+*/
+static int component_compare(const char *c1, const char *c2)
+{
+       return StrCaseCmp(c1, c2);
+}
+
+/*
+  search for a filename in a case insensitive fashion
+
+  TODO: add a cache for previously resolved case-insensitive names
+  TODO: add mangled name support
+*/
+static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename *name)
+{
+       /* break into a series of components */
+       int num_components;
+       char **components;
+       char *p, *partial_name;
+       int i;
+
+       /* break up the full name info pathname components */
+       num_components=2;
+       p = name->full_name + strlen(pvfs->base_directory) + 1;
+
+       for (;*p;p++) {
+               if (*p == '/') {
+                       num_components++;
+               }
+       }
+
+       components = talloc_array_p(name, char *, num_components);
+       p = name->full_name + strlen(pvfs->base_directory);
+       *p++ = 0;
+
+       components[0] = name->full_name;
+
+       for (i=1;i<num_components;i++) {
+               components[i] = p;
+               p = strchr(p, '/');
+               if (p) *p++ = 0;
+       }
+
+       partial_name = talloc_strdup(name, components[0]);
+       if (!partial_name) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* for each component, check if it exists as-is, and if not then
+          do a directory scan */
+       for (i=1;i<num_components;i++) {
+               char *test_name;
+               DIR *dir;
+               struct dirent *de;
+
+               test_name = talloc_asprintf(name, "%s/%s", partial_name, components[i]);
+               if (!test_name) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               /* check if this component exists as-is */
+               if (stat(test_name, &name->st) == 0) {
+                       if (i<num_components-1 && !S_ISDIR(name->st.st_mode)) {
+                               return NT_STATUS_NOT_A_DIRECTORY;
+                       }
+                       talloc_free(partial_name);
+                       partial_name = test_name;
+                       if (i == num_components - 1) {
+                               name->exists = True;
+                       }
+                       continue;
+               }
+               
+               dir = opendir(partial_name);
+               if (!dir) {
+                       return pvfs_map_errno(pvfs, errno);
+               }
+
+               while ((de = readdir(dir))) {
+                       if (component_compare(components[i], de->d_name) == 0) {
+                               break;
+                       }
+               }
+
+               if (!de) {
+                       closedir(dir);
+                       return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+               }
+
+               components[i] = talloc_strdup(name, de->d_name);
+               test_name = talloc_asprintf(name, "%s/%s", partial_name, components[i]);
+               talloc_free(partial_name);
+               partial_name = test_name;
+
+               closedir(dir);
+       }
+
+       if (!name->exists) {
+               if (stat(partial_name, &name->st) == 0) {
+                       name->exists = True;
+               }
+       }
+
+       talloc_free(name->full_name);
+       name->full_name = partial_name;
+
+       return NT_STATUS_OK;
+}
+
+
+/*
+  convert a CIFS pathname to a unix pathname. Note that this does NOT
+  take into account case insensitivity, and in fact does not access
+  the filesystem at all. It is merely a reformatting and charset
+  checking routine.
+
+  errors are returned if the filename is illegal given the flags
+*/
+static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name,
+                              uint_t flags, struct pvfs_filename *name)
+{
+       char *ret, *p;
+
+       name->original_name = cifs_name;
+       name->stream_name = NULL;
+       name->has_wildcard = False;
+
+       if (*cifs_name == '\\') {
+               cifs_name++;
+       }
+
+       ret = talloc_asprintf(name, "%s/%s", pvfs->base_directory, cifs_name);
+       if (ret == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       p = ret + strlen(pvfs->base_directory) + 1;
+
+       /* now do an in-place conversion of '\' to '/', checking
+          for legal characters */
+       for (;*p;p++) {
+               switch (*p) {
+               case '\\':
+                       if (name->has_wildcard) {
+                               /* wildcards are only allowed in the last part
+                                  of a name */
+                               return NT_STATUS_ILLEGAL_CHARACTER;
+                       }
+                       *p = '/';
+                       break;
+               case ':':
+                       if (!(flags & PVFS_RESOLVE_STREAMS)) {
+                               return NT_STATUS_ILLEGAL_CHARACTER;
+                       }
+                       name->stream_name = talloc_strdup(name, p+1);
+                       if (name->stream_name == NULL) {
+                               return NT_STATUS_NO_MEMORY;
+                       }
+                       *p-- = 0;
+                       break;
+               case '*':
+               case '>':
+               case '<':
+               case '?':
+               case '"':
+                       if (flags & PVFS_RESOLVE_NO_WILDCARD) {
+                               return NT_STATUS_ILLEGAL_CHARACTER;
+                       }
+                       name->has_wildcard = True;
+                       break;
+               case '/':
+               case '|':
+                       return NT_STATUS_ILLEGAL_CHARACTER;
+               }
+       }
+
+       name->full_name = ret;
+
+       return NT_STATUS_OK;
+}
+
+
+/*
+  resolve a name from relative client format to a struct pvfs_filename
+  the memory for the filename is made as a talloc child of 'name'
+
+  flags include:
+     PVFS_RESOLVE_NO_WILDCARD = wildcards are considered illegal characters
+     PVFS_RESOLVE_STREAMS     = stream names are allowed
+
+     TODO: add reserved name checking (for things like LPT1)
+     TODO: ../ collapsing, and outside share checking
+*/
+NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
+                          const char *cifs_name,
+                          uint_t flags, struct pvfs_filename **name)
+{
+       NTSTATUS status;
+
+       *name = talloc_p(mem_ctx, struct pvfs_filename);
+       if (*name == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       (*name)->exists = False;
+
+       /* do the basic conversion to a unix formatted path,
+          also checking for allowable characters */
+       status = pvfs_unix_path(pvfs, cifs_name, flags, *name);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       /* if it has a wildcard then no point doing a stat() */
+       if ((*name)->has_wildcard) {
+               return NT_STATUS_OK;
+       }
+
+       /* if we can stat() the full name now then we are done */
+       if (stat((*name)->full_name, &(*name)->st) == 0) {
+               (*name)->exists = True;
+               return NT_STATUS_OK;
+       }
+
+       /* the filesystem might be case insensitive, in which
+          case a search is pointless */
+       if (pvfs->flags & PVFS_FLAG_CI_FILESYSTEM) {
+               return NT_STATUS_OK;
+       }
+
+       /* search for a matching filename */
+       status = pvfs_case_search(pvfs, *name);
+
+       return status;
+}
+
+
+/*
+  do a partial resolve, returning a pvfs_filename structure given a
+  base path and a relative component. It is an error if the file does
+  not exist. No case-insensitive matching is done.
+
+  this is used in places like directory searching where we need a pvfs_filename
+  to pass to a function, but already know the unix base directory and component
+*/
+NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
+                             const char *unix_dir, const char *fname,
+                             struct pvfs_filename **name)
+{
+       *name = talloc_p(mem_ctx, struct pvfs_filename);
+       if (*name == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       (*name)->full_name = talloc_asprintf(mem_ctx, "%s/%s", unix_dir, fname);
+       if ((*name)->full_name == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (stat((*name)->full_name, &(*name)->st) == -1) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       (*name)->exists = True;
+       (*name)->has_wildcard = False;
+       (*name)->original_name = fname;
+       (*name)->stream_name = NULL;
+
+       return NT_STATUS_OK;
+}
diff --git a/source4/ntvfs/posix/pvfs_search.c b/source4/ntvfs/posix/pvfs_search.c
new file mode 100644 (file)
index 0000000..da47bba
--- /dev/null
@@ -0,0 +1,250 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   POSIX NTVFS backend - directory search functions
+
+   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.
+*/
+
+#include "include/includes.h"
+#include "vfs_posix.h"
+
+/*
+  fill in a single search result for a given info level
+*/
+static NTSTATUS fill_search_info(struct pvfs_state *pvfs,
+                                enum smb_search_level level,
+                                const char *unix_path,
+                                const char *name, 
+                                uint16_t search_attrib,
+                                uint32_t dir_index,
+                                union smb_search_data *file)
+{
+       struct pvfs_file_info *finfo;
+       NTSTATUS status;
+
+       finfo = talloc_p((TALLOC_CTX *)file, struct pvfs_file_info);
+       if (!finfo) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       status = pvfs_relative_file_info_cs(pvfs, unix_path, name, finfo);
+       if (!NT_STATUS_IS_OK(status)) {
+               talloc_free(finfo);
+               return status;
+       }
+       
+       switch (level) {
+
+       case RAW_SEARCH_BOTH_DIRECTORY_INFO:
+               file->both_directory_info.file_index   = dir_index;
+               file->both_directory_info.create_time  = finfo->create_time;
+               file->both_directory_info.access_time  = finfo->access_time;
+               file->both_directory_info.write_time   = finfo->write_time;
+               file->both_directory_info.change_time  = finfo->change_time;
+               file->both_directory_info.size         = finfo->size;
+               file->both_directory_info.alloc_size   = finfo->alloc_size;
+               file->both_directory_info.attrib       = finfo->attrib;
+               file->both_directory_info.ea_size      = finfo->ea_size;
+               file->both_directory_info.short_name.s = pvfs_short_name(pvfs, (TALLOC_CTX *)file, 
+                                                                        unix_path, name);
+               file->both_directory_info.name.s       = name;
+               break;
+       }
+
+       talloc_free(finfo);
+
+       return NT_STATUS_OK;
+}
+
+/*
+  return the next available search handle
+*/
+static NTSTATUS pvfs_next_search_handle(struct pvfs_state *pvfs, uint16_t *handle)
+{
+       struct pvfs_search_state *search;
+
+       if (pvfs->search.num_active_searches >= 0x10000) {
+               return NT_STATUS_INSUFFICIENT_RESOURCES;
+       }
+
+       (*handle) = pvfs->search.next_search_handle;
+       for (search=pvfs->search.open_searches;search;search=search->next) {
+               if (*handle == search->handle) {
+                       *handle = ((*handle)+1) & 0xFFFF;
+                       continue;
+               } 
+       }
+       pvfs->search.next_search_handle = ((*handle)+1) & 0xFFFF;
+
+       return NT_STATUS_OK;
+}
+
+/* 
+   list files in a directory matching a wildcard pattern
+*/
+NTSTATUS pvfs_search_first(struct smbsrv_request *req, union smb_search_first *io, 
+                          void *search_private, 
+                          BOOL (*callback)(void *, union smb_search_data *))
+{
+       struct pvfs_dir *dir;
+       struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+       struct pvfs_search_state *search;
+       union smb_search_data *file;
+       uint16_t max_count, reply_count;
+       uint16_t search_attrib;
+       const char *pattern;
+       int i;
+       NTSTATUS status;
+       struct pvfs_filename *name;
+
+       switch (io->generic.level) {
+       case RAW_SEARCH_SEARCH:
+               max_count     = io->search_first.in.max_count;
+               search_attrib = io->search_first.in.search_attrib;
+               pattern       = io->search_first.in.pattern;
+               break;
+
+       case RAW_SEARCH_STANDARD:
+       case RAW_SEARCH_EA_SIZE:
+       case RAW_SEARCH_DIRECTORY_INFO:
+       case RAW_SEARCH_FULL_DIRECTORY_INFO:
+       case RAW_SEARCH_NAME_INFO:
+       case RAW_SEARCH_BOTH_DIRECTORY_INFO:
+       case RAW_SEARCH_ID_FULL_DIRECTORY_INFO:
+       case RAW_SEARCH_ID_BOTH_DIRECTORY_INFO:
+       case RAW_SEARCH_UNIX_INFO:
+               max_count     = io->t2ffirst.in.max_count;
+               search_attrib = io->t2ffirst.in.search_attrib;
+               pattern       = io->t2ffirst.in.pattern;
+               break;
+
+       case RAW_SEARCH_FCLOSE:
+       case RAW_SEARCH_GENERIC:
+               DEBUG(0,("WARNING: Invalid search class %d in pvfs_search_first\n", io->generic.level));
+               return NT_STATUS_INVALID_INFO_CLASS;
+       }
+
+       /* resolve the cifs name to a posix name */
+       status = pvfs_resolve_name(pvfs, req, pattern, 0, &name);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (!name->has_wildcard && !name->exists) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       /* we initially make search a child of the request, then if we
+          need to keep it long term we steal it for the private
+          structure */
+       search = talloc_p(req, struct pvfs_search_state);
+       if (!search) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       dir = talloc_p(search, struct pvfs_dir);
+       if (!dir) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* do the actual directory listing */
+       status = pvfs_list(pvfs, name, dir);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       /* we need to give a handle back to the client so it
+          can continue a search */
+       status = pvfs_next_search_handle(pvfs, &search->handle);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+       
+       search->dir = dir;
+       search->current_index = 0;
+       search->search_attrib = search_attrib;
+
+       if (dir->count < max_count) {
+               max_count = dir->count;
+       }
+
+       file = talloc_p(req, union smb_search_data);
+       if (!file) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* note that fill_search_info() can fail, if for example a
+          file disappears during a search or we don't have sufficient
+          permissions to stat() it, or the search_attrib does not
+          match the files attribute. In that case the name is ignored
+          and the search continues. */
+       for (i=reply_count=0; i < dir->count && reply_count < max_count;i++) {
+               status = fill_search_info(pvfs, io->generic.level, dir->unix_path, dir->names[i], 
+                                         search_attrib, i, file);
+               if (NT_STATUS_IS_OK(status)) {
+                       if (!callback(search_private, file)) {
+                               break;
+                       }
+                       reply_count++;
+               }
+       }
+
+       /* not matching any entries is an error */
+       if (reply_count == 0) {
+               return NT_STATUS_NO_MORE_ENTRIES;
+       }
+
+       search->current_index = i;
+
+       if (io->generic.level == RAW_SEARCH_SEARCH) {
+               io->search_first.out.count = reply_count;
+               DEBUG(0,("TODO: handle RAW_SEARCH_SEARCH continue\n"));
+       } else {
+               io->t2ffirst.out.count = reply_count;
+               io->t2ffirst.out.handle = search->handle;
+               io->t2ffirst.out.end_of_search = (i == dir->count) ? 1 : 0;
+               /* work out if we are going to keep the search state
+                  and allow for a search continue */
+               if ((io->t2ffirst.in.flags & FLAG_TRANS2_FIND_CLOSE) ||
+                   ((io->t2ffirst.in.flags & FLAG_TRANS2_FIND_CLOSE_IF_END) && (i == dir->count))) {
+                       talloc_free(search);
+               } else {
+                       pvfs->search.num_active_searches++;
+                       pvfs->search.next_search_handle++;
+                       talloc_steal(pvfs, search);
+                       DLIST_ADD(pvfs->search.open_searches, search);
+               }
+       }
+
+       return NT_STATUS_OK;
+}
+
+/* continue a search */
+NTSTATUS pvfs_search_next(struct smbsrv_request *req, union smb_search_next *io, 
+                         void *search_private, 
+                         BOOL (*callback)(void *, union smb_search_data *))
+{
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+/* close a search */
+NTSTATUS pvfs_search_close(struct smbsrv_request *req, union smb_search_close *io)
+{
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
diff --git a/source4/ntvfs/posix/pvfs_shortname.c b/source4/ntvfs/posix/pvfs_shortname.c
new file mode 100644 (file)
index 0000000..b68f60d
--- /dev/null
@@ -0,0 +1,34 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   POSIX NTVFS backend - 8.3 name routines
+
+   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.
+*/
+
+#include "include/includes.h"
+#include "vfs_posix.h"
+
+
+/*
+  return the short name for a given entry in a directory
+*/
+char *pvfs_short_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, 
+                     const char *unix_path, const char *name)
+{
+       return talloc_strndup(mem_ctx, name, 12);
+}
diff --git a/source4/ntvfs/posix/pvfs_unlink.c b/source4/ntvfs/posix/pvfs_unlink.c
new file mode 100644 (file)
index 0000000..d93c15f
--- /dev/null
@@ -0,0 +1,111 @@
+/* 
+   Unix SMB/CIFS implementation.
+
+   POSIX NTVFS backend - unlink
+
+   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.
+*/
+
+#include "include/includes.h"
+#include "vfs_posix.h"
+
+
+/*
+  unlink one file
+*/
+static NTSTATUS pvfs_unlink_one(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
+                               const char *unix_path, 
+                               const char *fname, uint32_t attrib)
+{
+       struct pvfs_filename *name;
+       NTSTATUS status;
+
+       /* get a pvfs_filename object */
+       status = pvfs_resolve_partial(pvfs, mem_ctx, 
+                                     unix_path, fname, &name);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       /* make sure its matches the given attributes */
+       if (!pvfs_match_attrib(pvfs, name, attrib)) {
+               talloc_free(name);
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       /* finally try the actual unlink */
+       if (unlink(name->full_name) == -1) {
+               status = pvfs_map_errno(pvfs, errno);
+       }
+
+       talloc_free(name);
+
+       return status;
+}
+
+/*
+  delete a file - the dirtype specifies the file types to include in the search. 
+  The name can contain CIFS wildcards, but rarely does (except with OS/2 clients)
+*/
+NTSTATUS pvfs_unlink(struct smbsrv_request *req, struct smb_unlink *unl)
+{
+       struct pvfs_dir *dir;
+       struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+       NTSTATUS status;
+       uint32_t i, total_deleted=0;
+       struct pvfs_filename *name;
+
+       /* resolve the cifs name to a posix name */
+       status = pvfs_resolve_name(pvfs, req, unl->in.pattern, 0, &name);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (!name->exists && !name->has_wildcard) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       dir = talloc_p(req, struct pvfs_dir);
+       if (dir == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* get list of matching files */
+       status = pvfs_list(pvfs, name, dir);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (dir->count == 0) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       for (i=0;i<dir->count;i++) {
+               status = pvfs_unlink_one(pvfs, req, dir->unix_path, dir->names[i], unl->in.attrib);
+               if (NT_STATUS_IS_OK(status)) {
+                       total_deleted++;
+               }
+       }
+
+       if (total_deleted == 0) {
+               return status;
+       }
+
+       return NT_STATUS_OK;
+}
+
+
diff --git a/source4/ntvfs/posix/pvfs_util.c b/source4/ntvfs/posix/pvfs_util.c
new file mode 100644 (file)
index 0000000..2524261
--- /dev/null
@@ -0,0 +1,56 @@
+/* 
+   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.
+*/
+/*
+  utility functions for posix backend
+*/
+
+#include "includes.h"
+#include "vfs_posix.h"
+
+/*
+  return True if a string contains one of the CIFS wildcard characters
+*/
+BOOL pvfs_has_wildcard(const char *str)
+{
+       if (strpbrk(str, "*?<>\"")) {
+               return True;
+       }
+       return False;
+}
+
+/*
+  map a unix errno to a NTSTATUS
+*/
+NTSTATUS pvfs_map_errno(struct pvfs_state *pvfs, int unix_errno)
+{
+       return map_nt_error_from_unix(unix_errno);
+}
+
+
+/*
+  check if a filename has an attribute matching the given attribute search value
+  this is used by calls like unlink and search which take an attribute
+  and only include special files if they match the given attribute
+*/
+BOOL pvfs_match_attrib(struct pvfs_state *pvfs, struct pvfs_filename *name, uint32_t attrib)
+{
+       /* TODO: add attribute conversion */
+       return True;
+}
index ee70e79835d74a3f90b0ff3cd919ab5e8d120e21..86179debc5cdd6ce5cddb0ff11e1354b900e4420 100644 (file)
@@ -39,6 +39,7 @@ static NTSTATUS pvfs_connect(struct smbsrv_request *req, const char *sharename)
        struct smbsrv_tcon *tcon = req->tcon;
        struct pvfs_state *pvfs;
        struct stat st;
+       char *base_directory;
 
        DEBUG(0,("WARNING: the posix vfs handler is incomplete - you probably want \"ntvfs handler = simple\"\n"));
 
@@ -46,8 +47,13 @@ static NTSTATUS pvfs_connect(struct smbsrv_request *req, const char *sharename)
        if (pvfs == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
+       ZERO_STRUCTP(pvfs);
 
-       pvfs->base_directory = talloc_strdup(pvfs, lp_pathname(tcon->service));
+       /* for simplicity of path construction, remove any trailing slash now */
+       base_directory = talloc_strdup(pvfs, lp_pathname(tcon->service));
+       trim_string(base_directory, NULL, "/");
+
+       pvfs->base_directory = base_directory;
 
        /* the directory must exist. Note that we deliberately don't
           check that it is readable */
@@ -59,6 +65,7 @@ static NTSTATUS pvfs_connect(struct smbsrv_request *req, const char *sharename)
 
        tcon->fs_type = talloc_strdup(tcon, "NTFS");
        tcon->dev_type = talloc_strdup(tcon, "A:");
+       tcon->ntvfs_private = pvfs;
 
        return NT_STATUS_OK;
 }
@@ -71,21 +78,12 @@ static NTSTATUS pvfs_disconnect(struct smbsrv_tcon *tcon)
        return NT_STATUS_OK;
 }
 
-/*
-  delete a file - the dirtype specifies the file types to include in the search. 
-  The name can contain CIFS wildcards, but rarely does (except with OS/2 clients)
-*/
-static NTSTATUS pvfs_unlink(struct smbsrv_request *req, struct smb_unlink *unl)
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-
 /*
   ioctl interface - we don't do any
 */
 static NTSTATUS pvfs_ioctl(struct smbsrv_request *req, union smb_ioctl *io)
 {
+       DEBUG(0,("pvfs_ioctl not implemented\n"));
        return NT_STATUS_INVALID_PARAMETER;
 }
 
@@ -94,7 +92,25 @@ static NTSTATUS pvfs_ioctl(struct smbsrv_request *req, union smb_ioctl *io)
 */
 static NTSTATUS pvfs_chkpath(struct smbsrv_request *req, struct smb_chkpath *cp)
 {
-       return NT_STATUS_NOT_IMPLEMENTED;
+       struct pvfs_state *pvfs = req->tcon->ntvfs_private;
+       struct pvfs_filename *name;
+       NTSTATUS status;
+
+       /* resolve the cifs name to a posix name */
+       status = pvfs_resolve_name(pvfs, req, cp->in.path, 0, &name);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (!name->exists) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       if (!S_ISDIR(name->st.st_mode)) {
+               return NT_STATUS_NOT_A_DIRECTORY;
+       }
+
+       return NT_STATUS_OK;
 }
 
 /*
@@ -102,6 +118,7 @@ static NTSTATUS pvfs_chkpath(struct smbsrv_request *req, struct smb_chkpath *cp)
 */
 static NTSTATUS pvfs_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *info)
 {
+       DEBUG(0,("pvfs_qpathinfo not implemented\n"));
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -110,6 +127,7 @@ static NTSTATUS pvfs_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *i
 */
 static NTSTATUS pvfs_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *info)
 {
+       DEBUG(0,("pvfs_qfileinfo not implemented\n"));
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -119,6 +137,7 @@ static NTSTATUS pvfs_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *i
 */
 static NTSTATUS pvfs_open(struct smbsrv_request *req, union smb_open *io)
 {
+       DEBUG(0,("pvfs_open not implemented\n"));
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -127,6 +146,7 @@ static NTSTATUS pvfs_open(struct smbsrv_request *req, union smb_open *io)
 */
 static NTSTATUS pvfs_mkdir(struct smbsrv_request *req, union smb_mkdir *md)
 {
+       DEBUG(0,("pvfs_mkdir not implemented\n"));
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -135,6 +155,7 @@ static NTSTATUS pvfs_mkdir(struct smbsrv_request *req, union smb_mkdir *md)
 */
 static NTSTATUS pvfs_rmdir(struct smbsrv_request *req, struct smb_rmdir *rd)
 {
+       DEBUG(0,("pvfs_rmdir not implemented\n"));
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -143,6 +164,7 @@ static NTSTATUS pvfs_rmdir(struct smbsrv_request *req, struct smb_rmdir *rd)
 */
 static NTSTATUS pvfs_rename(struct smbsrv_request *req, union smb_rename *ren)
 {
+       DEBUG(0,("pvfs_rename not implemented\n"));
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -151,6 +173,7 @@ static NTSTATUS pvfs_rename(struct smbsrv_request *req, union smb_rename *ren)
 */
 static NTSTATUS pvfs_copy(struct smbsrv_request *req, struct smb_copy *cp)
 {
+       DEBUG(0,("pvfs_copy not implemented\n"));
        return NT_STATUS_NOT_SUPPORTED;
 }
 
@@ -159,6 +182,7 @@ static NTSTATUS pvfs_copy(struct smbsrv_request *req, struct smb_copy *cp)
 */
 static NTSTATUS pvfs_read(struct smbsrv_request *req, union smb_read *rd)
 {
+       DEBUG(0,("pvfs_read not implemented\n"));
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -167,6 +191,7 @@ static NTSTATUS pvfs_read(struct smbsrv_request *req, union smb_read *rd)
 */
 static NTSTATUS pvfs_write(struct smbsrv_request *req, union smb_write *wr)
 {
+       DEBUG(0,("pvfs_write not implemented\n"));
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -175,6 +200,7 @@ static NTSTATUS pvfs_write(struct smbsrv_request *req, union smb_write *wr)
 */
 static NTSTATUS pvfs_seek(struct smbsrv_request *req, struct smb_seek *io)
 {
+       DEBUG(0,("pvfs_seek not implemented\n"));
        return NT_STATUS_NOT_SUPPORTED;
 }
 
@@ -183,6 +209,7 @@ static NTSTATUS pvfs_seek(struct smbsrv_request *req, struct smb_seek *io)
 */
 static NTSTATUS pvfs_flush(struct smbsrv_request *req, struct smb_flush *io)
 {
+       DEBUG(0,("pvfs_flush not implemented\n"));
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -191,6 +218,7 @@ static NTSTATUS pvfs_flush(struct smbsrv_request *req, struct smb_flush *io)
 */
 static NTSTATUS pvfs_close(struct smbsrv_request *req, union smb_close *io)
 {
+       DEBUG(0,("pvfs_close not implemented\n"));
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -199,6 +227,7 @@ static NTSTATUS pvfs_close(struct smbsrv_request *req, union smb_close *io)
 */
 static NTSTATUS pvfs_exit(struct smbsrv_request *req)
 {
+       DEBUG(0,("pvfs_exit not implemented\n"));
        return NT_STATUS_NOT_SUPPORTED;
 }
 
@@ -207,6 +236,7 @@ static NTSTATUS pvfs_exit(struct smbsrv_request *req)
 */
 static NTSTATUS pvfs_lock(struct smbsrv_request *req, union smb_lock *lck)
 {
+       DEBUG(0,("pvfs_lock not implemented\n"));
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -215,6 +245,7 @@ static NTSTATUS pvfs_lock(struct smbsrv_request *req, union smb_lock *lck)
 */
 static NTSTATUS pvfs_setpathinfo(struct smbsrv_request *req, union smb_setfileinfo *st)
 {
+       DEBUG(0,("pvfs_setpathinfo not implemented\n"));
        return NT_STATUS_NOT_SUPPORTED;
 }
 
@@ -224,6 +255,7 @@ static NTSTATUS pvfs_setpathinfo(struct smbsrv_request *req, union smb_setfilein
 static NTSTATUS pvfs_setfileinfo(struct smbsrv_request *req, 
                                 union smb_setfileinfo *info)
 {
+       DEBUG(0,("pvfs_setfileinfo not implemented\n"));
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -233,6 +265,7 @@ static NTSTATUS pvfs_setfileinfo(struct smbsrv_request *req,
 */
 static NTSTATUS pvfs_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs)
 {
+       DEBUG(0,("pvfs_fsinfo not implemented\n"));
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
@@ -244,30 +277,6 @@ static NTSTATUS pvfs_lpq(struct smbsrv_request *req, union smb_lpq *lpq)
        return NT_STATUS_NOT_SUPPORTED;
 }
 
-/* 
-   list files in a directory matching a wildcard pattern
-*/
-static NTSTATUS pvfs_search_first(struct smbsrv_request *req, union smb_search_first *io, 
-                                 void *search_private, 
-                                 BOOL (*callback)(void *, union smb_search_data *))
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-/* continue a search */
-static NTSTATUS pvfs_search_next(struct smbsrv_request *req, union smb_search_next *io, 
-                                void *search_private, 
-                                BOOL (*callback)(void *, union smb_search_data *))
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
-/* close a search */
-static NTSTATUS pvfs_search_close(struct smbsrv_request *req, union smb_search_close *io)
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
 /* SMBtrans - not used on file shares */
 static NTSTATUS pvfs_trans(struct smbsrv_request *req, struct smb_trans2 *trans2)
 {
index 6b05240f43b5dce6adae1d7ccce022cde4acf90d..1e6d763fc11b059f0dc012cca74f383d9f6f5994 100644 (file)
@@ -1,7 +1,7 @@
 /* 
    Unix SMB/CIFS implementation.
 
-   POSIX NTVFS backend - header
+   POSIX NTVFS backend - structure definitions
 
    Copyright (C) Andrew Tridgell 2004
 
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
+#ifndef _VFS_POSIX_H_
+#define _VFS_POSIX_H_
+
 /* this is the private structure for the posix vfs backend. It is used
    to hold per-connection (per tree connect) state information */
 struct pvfs_state {
        const char *base_directory;
+
+       uint_t flags;
+
+       struct {
+               /* a linked list of open searches */
+               struct pvfs_search_state *open_searches;
+
+               /* search handles are returned to the clients so they
+                  can continue searches */
+               uint16_t next_search_handle;
+
+               /* count of active searches */
+               uint_t num_active_searches;
+
+               /* during trans2 search continuations we need to use
+                  the initial search attributes */
+               uint16_t search_attrib;
+       } search;
+};
+
+/*
+  this is the structure returned by pvfs_resolve_name(). It holds the posix details of
+  a filename passed by the client to any function
+*/
+struct pvfs_filename {
+       const char *original_name;
+       char *full_name;
+       const char *stream_name;
+       BOOL has_wildcard;
+       BOOL exists;
+       struct stat st;
+};
+
+
+/* this holds a list of file names for a search. We deliberately do
+   not hold the file stat information here to minimise the memory
+   overhead of idle searches */
+struct pvfs_dir {
+       uint_t count;
+       const char *unix_path;
+       const char **names;
+};
+
+/* the state of a search started with pvfs_search_first() */
+struct pvfs_search_state {
+       struct pvfs_search_state *next, *prev;
+       uint16_t search_attrib;
+       uint16_t handle;
+       uint_t current_index;
+       struct pvfs_dir *dir;
+};
+
+
+/* this is the basic information needed about a file from the filesystem */
+struct pvfs_file_info {
+       NTTIME create_time;
+       NTTIME access_time;
+       NTTIME write_time;
+       NTTIME change_time;
+       uint32_t attrib;
+       uint64_t alloc_size;
+       uint64_t size;
+       uint32_t nlink;
+       uint32_t ea_size;
+       uint64_t file_id;
+       uint64_t unix_uid;
+       uint64_t unix_gid;
+       uint32_t unix_file_type;
+       uint64_t unix_dev_major;
+       uint64_t unix_dev_minor;
+       uint64_t unix_permissions;
 };
+
+/* flags to pvfs_resolve_name() */
+#define PVFS_RESOLVE_NO_WILDCARD (1<<0)
+#define PVFS_RESOLVE_STREAMS     (1<<1)
+
+/* flags in pvfs->flags */
+#define PVFS_FLAG_CI_FILESYSTEM (1<<0) /* the filesystem is case insensitive */
+
+#endif /* _VFS_POSIX_H_ */