summaryrefslogtreecommitdiff
path: root/source4/ntvfs/posix
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
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')
-rw-r--r--source4/ntvfs/posix/pvfs_dirlist.c126
-rw-r--r--source4/ntvfs/posix/pvfs_fileinfo.c128
-rw-r--r--source4/ntvfs/posix/pvfs_resolve.c303
-rw-r--r--source4/ntvfs/posix/pvfs_search.c250
-rw-r--r--source4/ntvfs/posix/pvfs_shortname.c34
-rw-r--r--source4/ntvfs/posix/pvfs_unlink.c111
-rw-r--r--source4/ntvfs/posix/pvfs_util.c56
-rw-r--r--source4/ntvfs/posix/vfs_posix.c81
-rw-r--r--source4/ntvfs/posix/vfs_posix.h85
9 files changed, 1137 insertions, 37 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;
+}
+
diff --git a/source4/ntvfs/posix/pvfs_fileinfo.c b/source4/ntvfs/posix/pvfs_fileinfo.c
new file mode 100644
index 0000000000..83a577d092
--- /dev/null
+++ b/source4/ntvfs/posix/pvfs_fileinfo.c
@@ -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
index 0000000000..66e7a5d103
--- /dev/null
+++ b/source4/ntvfs/posix/pvfs_resolve.c
@@ -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
index 0000000000..da47bba75a
--- /dev/null
+++ b/source4/ntvfs/posix/pvfs_search.c
@@ -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
index 0000000000..b68f60d5e7
--- /dev/null
+++ b/source4/ntvfs/posix/pvfs_shortname.c
@@ -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
index 0000000000..d93c15f19e
--- /dev/null
+++ b/source4/ntvfs/posix/pvfs_unlink.c
@@ -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
index 0000000000..2524261245
--- /dev/null
+++ b/source4/ntvfs/posix/pvfs_util.c
@@ -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;
+}
diff --git a/source4/ntvfs/posix/vfs_posix.c b/source4/ntvfs/posix/vfs_posix.c
index ee70e79835..86179debc5 100644
--- a/source4/ntvfs/posix/vfs_posix.c
+++ b/source4/ntvfs/posix/vfs_posix.c
@@ -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;
}
@@ -72,20 +79,11 @@ static NTSTATUS pvfs_disconnect(struct smbsrv_tcon *tcon)
}
/*
- 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)
{
diff --git a/source4/ntvfs/posix/vfs_posix.h b/source4/ntvfs/posix/vfs_posix.h
index 6b05240f43..1e6d763fc1 100644
--- a/source4/ntvfs/posix/vfs_posix.h
+++ b/source4/ntvfs/posix/vfs_posix.h
@@ -1,7 +1,7 @@
/*
Unix SMB/CIFS implementation.
- POSIX NTVFS backend - header
+ POSIX NTVFS backend - structure definitions
Copyright (C) Andrew Tridgell 2004
@@ -20,8 +20,91 @@
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_ */