From 03cb4367d67ba9cdedf22df743d25d81093941d7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 18 Sep 2004 08:16:14 +0000 Subject: 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) --- source4/ntvfs/posix/pvfs_resolve.c | 303 +++++++++++++++++++++++++++++++++++++ 1 file changed, 303 insertions(+) create mode 100644 source4/ntvfs/posix/pvfs_resolve.c (limited to 'source4/ntvfs/posix/pvfs_resolve.c') 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;ist) == 0) { + if (ist.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; +} -- cgit From 8a1c3ddd947039bf3b62efd94d3429359b593e15 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Sep 2004 07:28:43 +0000 Subject: r2436: the second big lump of posix vfs code. this is still just a skeleton, and many of the functions are just based on the simple vfs backend, they are there to allow me to run smbtorture tests against the real parts of the posix backend. (This used to be commit f2fa7fe565e89360dba3bb5434d3a6a36f398348) --- source4/ntvfs/posix/pvfs_resolve.c | 46 ++++++++++++++++++++++++++++++-------- 1 file changed, 37 insertions(+), 9 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 66e7a5d103..5c535c9880 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -116,11 +116,13 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * } if (!de) { - closedir(dir); - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + if (i < num_components-1) { + closedir(dir); + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + } else { + components[i] = talloc_strdup(name, de->d_name); } - - 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; @@ -137,6 +139,10 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * talloc_free(name->full_name); name->full_name = partial_name; + if (name->exists) { + return pvfs_fill_dos_info(pvfs, name); + } + return NT_STATUS_OK; } @@ -154,7 +160,7 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, { char *ret, *p; - name->original_name = cifs_name; + name->original_name = talloc_strdup(name, cifs_name); name->stream_name = NULL; name->has_wildcard = False; @@ -252,7 +258,7 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, /* 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; + return pvfs_fill_dos_info(pvfs, *name); } /* the filesystem might be case insensitive, in which @@ -280,12 +286,14 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, const char *unix_dir, const char *fname, struct pvfs_filename **name) { + NTSTATUS status; + *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); + (*name)->full_name = talloc_asprintf(*name, "%s/%s", unix_dir, fname); if ((*name)->full_name == NULL) { return NT_STATUS_NO_MEMORY; } @@ -296,8 +304,28 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, (*name)->exists = True; (*name)->has_wildcard = False; - (*name)->original_name = fname; + (*name)->original_name = talloc_strdup(*name, fname); (*name)->stream_name = NULL; - return NT_STATUS_OK; + status = pvfs_fill_dos_info(pvfs, *name); + + return status; +} + + +/* + fill in the pvfs_filename info for an open file, given the current + info for a (possibly) non-open file. This is used by places that need + to update the pvfs_filename stat information, and by pvfs_open() +*/ +NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, + struct pvfs_filename *name) +{ + if (fstat(fd, &name->st) == -1) { + return NT_STATUS_INVALID_HANDLE; + } + + name->exists = True; + + return pvfs_fill_dos_info(pvfs, name); } -- cgit From a3cec511bbef2cc7768906f3af947ce2f900bde6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 23 Sep 2004 07:44:42 +0000 Subject: r2561: completely redid the ntvfs module chaining code, You can now do something like: ntvfs handler = nbench posix and the nbench pass-thru module will be called before the posix module. The chaining logic is now much saner, and less racy, with each level in the chain getting its own private pointer rather than relying on save/restore logic in the pass-thru module. The only pass-thru module we have at the moment is the nbench one (which records all traffic in a nbench compatibe format), but I plan on soon writing a "unixuid" pass-thru module that will implement the setegid()/setgroups()/seteuid() logic for standard posix uid handling. This separation of the posix backend from the uid handling should simplify the code, and make development easier. I also modified the nbench module so it can do multiple chaining, so if you want to you can do: ntvfs module = nbench nbench posix and it will save 2 copies of the log file in /tmp. This is really only useful for testing at the moment until we have more than one pass-thru module. (This used to be commit f84c0af35cb54c8fdc4933afefc18fa4c062aae4) --- source4/ntvfs/posix/pvfs_resolve.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 5c535c9880..dfd6744eff 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -164,10 +164,18 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, name->stream_name = NULL; name->has_wildcard = False; - if (*cifs_name == '\\') { + while (*cifs_name == '\\') { cifs_name++; } + if (*cifs_name == 0) { + name->full_name = talloc_asprintf(name, "%s/.", pvfs->base_directory); + if (name->full_name == NULL) { + return NT_STATUS_NO_MEMORY; + } + return NT_STATUS_OK; + } + ret = talloc_asprintf(name, "%s/%s", pvfs->base_directory, cifs_name); if (ret == NULL) { return NT_STATUS_NO_MEMORY; @@ -175,6 +183,10 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, p = ret + strlen(pvfs->base_directory) + 1; + if (p[strlen(cifs_name)-1] == '\\') { + p[strlen(cifs_name)-1] = 0; + } + /* now do an in-place conversion of '\' to '/', checking for legal characters */ for (;*p;p++) { -- cgit From 84bbe948f3beff0fbdc51c9c63e2f674b70b5bbe Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 2 Oct 2004 12:25:02 +0000 Subject: r2786: - match on both long and short name for search posix backend - a final name component of . is illegal (This used to be commit 11c852170b83e5adbdb58407e1c7d3aeb4ab5bb8) --- source4/ntvfs/posix/pvfs_resolve.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index dfd6744eff..e846b7be77 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -159,6 +159,7 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, uint_t flags, struct pvfs_filename *name) { char *ret, *p; + size_t len; name->original_name = talloc_strdup(name, cifs_name); name->stream_name = NULL; @@ -183,8 +184,13 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, p = ret + strlen(pvfs->base_directory) + 1; - if (p[strlen(cifs_name)-1] == '\\') { - p[strlen(cifs_name)-1] = 0; + len = strlen(cifs_name); + if (len>0 && p[len-1] == '\\') { + p[len-1] = 0; + len--; + } + if (len>1 && p[len-1] == '.' && p[len-2] == '\\') { + return NT_STATUS_OBJECT_NAME_INVALID; } /* now do an in-place conversion of '\' to '/', checking -- cgit From 18dc1cd00f09d051497cf89e348f8ba794c63230 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 10 Oct 2004 05:29:59 +0000 Subject: r2893: added very primitive name mangling support to pvfs (This used to be commit 749fa73544201f521d9cd3fa972b89cae99bc2c0) --- source4/ntvfs/posix/pvfs_resolve.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index e846b7be77..5d6f270a42 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -33,9 +33,19 @@ /* compare two filename components. This is where the name mangling hook will go */ -static int component_compare(const char *c1, const char *c2) +static int component_compare(struct pvfs_state *pvfs, const char *comp, const char *name) { - return StrCaseCmp(c1, c2); + char *shortname; + int ret; + + if (StrCaseCmp(comp, name) == 0) return 0; + + shortname = pvfs_short_name_component(pvfs, name); + + ret = StrCaseCmp(comp, shortname); + + talloc_free(shortname); + return ret; } /* @@ -110,7 +120,7 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * } while ((de = readdir(dir))) { - if (component_compare(components[i], de->d_name) == 0) { + if (component_compare(pvfs, components[i], de->d_name) == 0) { break; } } -- cgit From 52f525c104ae2d17901f104cbf482395dc803cc1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Oct 2004 05:10:43 +0000 Subject: r2927: imported the hash2 name mangling code from Samba3 into Samba4, but heavily modified to suit the Samba4 architecture. Samba4 with posix backend now passes the BASE-MANGLE test (This used to be commit ed52d69e8a065b6a8df2fb73c89be67acfdbca65) --- source4/ntvfs/posix/pvfs_resolve.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 5d6f270a42..5b1a5680ae 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -35,16 +35,18 @@ */ static int component_compare(struct pvfs_state *pvfs, const char *comp, const char *name) { - char *shortname; int ret; - if (StrCaseCmp(comp, name) == 0) return 0; + ret = StrCaseCmp(comp, name); - shortname = pvfs_short_name_component(pvfs, name); - - ret = StrCaseCmp(comp, shortname); + if (ret != 0) { + char *shortname = pvfs_short_name_component(pvfs, name); + if (shortname) { + ret = StrCaseCmp(comp, shortname); + talloc_free(shortname); + } + } - talloc_free(shortname); return ret; } @@ -95,6 +97,13 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * char *test_name; DIR *dir; struct dirent *de; + char *long_component; + + /* possibly remap from the short name cache */ + long_component = pvfs_mangled_lookup(pvfs, name, components[i]); + if (long_component) { + components[i] = long_component; + } test_name = talloc_asprintf(name, "%s/%s", partial_name, components[i]); if (!test_name) { -- cgit From 4962d9d03efd91bf4e7209cff47877f20d7de25d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Oct 2004 05:33:05 +0000 Subject: r2928: - fixed the handling of reserved names (rejecting them with ACCESS_DENIED) - don't check for '.' specially in checking for legal names. Longhorn doesn't do this any more, and its a real pain. Longhorn allows for filenames ending in '.', and with as many '.' elements as you like. (This used to be commit 0a475175c53016bfa5b8246819676ddcd8b66feb) --- source4/ntvfs/posix/pvfs_resolve.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 5b1a5680ae..01f6b13ec2 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -84,6 +84,9 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * components[i] = p; p = strchr(p, '/'); if (p) *p++ = 0; + if (pvfs_is_reserved_name(pvfs, components[i])) { + return NT_STATUS_ACCESS_DENIED; + } } partial_name = talloc_strdup(name, components[0]); -- cgit From 2ec58445cac6152a652024372d367fc23d4770da Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Oct 2004 06:07:55 +0000 Subject: r2931: use next_codepoint() to ensure we properly handle multi-byte characters in pvfs_unix_path() (This used to be commit 0acf95d84c51d564f7215d34364c37ca74a2a150) --- source4/ntvfs/posix/pvfs_resolve.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 01f6b13ec2..205e1e283f 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -217,8 +217,10 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, /* now do an in-place conversion of '\' to '/', checking for legal characters */ - for (;*p;p++) { - switch (*p) { + while (*p) { + size_t c_size; + codepoint_t c = next_codepoint(p, &c_size); + switch (c) { case '\\': if (name->has_wildcard) { /* wildcards are only allowed in the last part @@ -251,6 +253,8 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, case '|': return NT_STATUS_ILLEGAL_CHARACTER; } + + p += c_size; } name->full_name = ret; -- cgit From 9d9b42b0591a82ef23bfa367941f711bc454cc26 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 15 Oct 2004 05:40:13 +0000 Subject: r2984: fixed the error code for a non-terminal component of a path name not existing (This used to be commit c6a922dbd844c69bbba83c259169655d17e9f87f) --- source4/ntvfs/posix/pvfs_resolve.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 205e1e283f..97068c3d03 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -140,7 +140,7 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * if (!de) { if (i < num_components-1) { closedir(dir); - return NT_STATUS_OBJECT_NAME_NOT_FOUND; + return NT_STATUS_OBJECT_PATH_NOT_FOUND; } } else { components[i] = talloc_strdup(name, de->d_name); @@ -271,7 +271,6 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, 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, -- cgit From f71e7ae1e34510081c393f5ae73a279e8c4d0641 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 22 Oct 2004 06:55:18 +0000 Subject: r3133: - more consistent error checking in rename and setfileinfo - add paranoid checking of device/inode change during open to detect race conditions (This used to be commit 043361fed487ed494fa497ffde1007b3f3bc0c29) --- source4/ntvfs/posix/pvfs_resolve.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 97068c3d03..5b86cd3a73 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -364,10 +364,29 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, struct pvfs_filename *name) { + dev_t device; + ino_t inode; + + if (name->exists) { + device = name->st.st_dev; + inode = name->st.st_ino; + } + if (fstat(fd, &name->st) == -1) { return NT_STATUS_INVALID_HANDLE; } + if (name->exists && + (device != name->st.st_dev || inode != name->st.st_ino)) { + /* the file we are looking at has changed! this could + be someone trying to exploit a race + condition. Certainly we don't want to continue + operating on this file */ + DEBUG(0,("pvfs: WARNING: file '%s' changed during resole - failing\n", + name->full_name)); + return NT_STATUS_UNEXPECTED_IO_ERROR; + } + name->exists = True; return pvfs_fill_dos_info(pvfs, name); -- cgit From 7780bec7b4169cb2a78ceda16e6dc9e00dcb0b0f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Oct 2004 06:23:28 +0000 Subject: r3198: check for too many .. components in filenames pvfs now passes RAW-MKDIR (This used to be commit 41adb385f123b8d4cd3fe2eb03d891b6bdcf2361) --- source4/ntvfs/posix/pvfs_resolve.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 5b86cd3a73..5d98274511 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -180,8 +180,9 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, uint_t flags, struct pvfs_filename *name) { - char *ret, *p; + char *ret, *p, *p_start; size_t len; + int num_components=0; name->original_name = talloc_strdup(name, cifs_name); name->stream_name = NULL; @@ -217,6 +218,7 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, /* now do an in-place conversion of '\' to '/', checking for legal characters */ + p_start = p; while (*p) { size_t c_size; codepoint_t c = next_codepoint(p, &c_size); @@ -228,6 +230,7 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, return NT_STATUS_ILLEGAL_CHARACTER; } *p = '/'; + num_components++; break; case ':': if (!(flags & PVFS_RESOLVE_STREAMS)) { @@ -252,6 +255,18 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, case '/': case '|': return NT_STATUS_ILLEGAL_CHARACTER; + case '.': + if (p[1] != '.' || + (p[2] != '\\' && p[2] != 0) || + (p != p_start && p[-1] != '/')) { + break; + } + /* its definately a .. component */ + num_components--; + if (num_components <= 0) { + return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; + } + break; } p += c_size; -- cgit From d5fd12648e004b47bbe5ed2623838866fedcbeb0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Oct 2004 00:59:06 +0000 Subject: r3227: added a per-share option "case insensitive filesystem", that tells the backend that the underlying filesystem is case insensitive, so it can bypass the directory search if the name is not found. (This used to be commit d84ade90ce7e03ec749d6ae8dcdcb41de85d836e) --- source4/ntvfs/posix/pvfs_resolve.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 5d98274511..271dbc2b9a 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -125,6 +125,18 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * } continue; } + + /* the filesystem might be case insensitive, in which + case a search is pointless unless the name is + mangled */ + if ((pvfs->flags & PVFS_FLAG_CI_FILESYSTEM) && + !pvfs_is_mangled_component(pvfs, components[i])) { + if (i < num_components-1) { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + partial_name = test_name; + continue; + } dir = opendir(partial_name); if (!dir) { @@ -319,12 +331,6 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, return pvfs_fill_dos_info(pvfs, *name); } - /* 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); -- cgit From e9820e1b6e62240c5a18fa85e38a99685beed2df Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Oct 2004 05:39:54 +0000 Subject: r3240: - update the rules for what error codes should be given on the different type of unlink an seach mismatches - wildcard directory listings that have attribute FILE_ATTRIBUTE_DIRECTORY and match "." or ".." should be failed. - don't set the write_time on SMBclose unless it is non-zero - added much better support for setfileinfo and setpathinfo in pvfs - better (and more efficient) handling of .. and . components in filenames (This used to be commit 9305b07af395a158cb9f0c1c9486f7122c79d357) --- source4/ntvfs/posix/pvfs_resolve.c | 116 ++++++++++++++++++++++++++++++++++--- 1 file changed, 107 insertions(+), 9 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 271dbc2b9a..a7a693b217 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -194,7 +194,6 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, { char *ret, *p, *p_start; size_t len; - int num_components=0; name->original_name = talloc_strdup(name, cifs_name); name->stream_name = NULL; @@ -242,7 +241,6 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, return NT_STATUS_ILLEGAL_CHARACTER; } *p = '/'; - num_components++; break; case ':': if (!(flags & PVFS_RESOLVE_STREAMS)) { @@ -268,14 +266,19 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, case '|': return NT_STATUS_ILLEGAL_CHARACTER; case '.': - if (p[1] != '.' || - (p[2] != '\\' && p[2] != 0) || - (p != p_start && p[-1] != '/')) { - break; + /* see if it is definately a .. or + . component. If it is then fail here, and + let the next layer up try again after + pvfs_reduce_name() if it wants to. This is + much more efficient on average than always + scanning for these separately */ + if (p[1] == '.' && + (p[2] == 0 || p[2] == '\\') && + (p == p_start || p[-1] == '/')) { + return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } - /* its definately a .. component */ - num_components--; - if (num_components <= 0) { + if ((p[1] == 0 || p[1] == '\\') && + (p == p_start || p[-1] == '/')) { return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } break; @@ -290,6 +293,92 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, } +/* + reduce a name that contains .. components or repeated \ separators + return NULL if it can't be reduced +*/ +const char *pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char *fname) +{ + codepoint_t c; + size_t c_size, len; + int i, num_components; + char **components; + char *p, *s, *ret; + + s = talloc_strdup(mem_ctx, fname); + if (s == NULL) return NULL; + + for (num_components=1, p=s; *p; p += c_size) { + c = next_codepoint(p, &c_size); + if (c == '\\') num_components++; + } + if (num_components < 2) { + talloc_free(s); + return NULL; + } + + components = talloc_array_p(s, char *, num_components+1); + if (components == NULL) { + talloc_free(s); + return NULL; + } + + components[0] = s; + for (i=0, p=s; *p; p += c_size) { + c = next_codepoint(p, &c_size); + if (c == '\\') { + *p = 0; + components[++i] = p+1; + } + } + components[i+1] = NULL; + + /* remove any null components */ + for (i=0;components[i];i++) { + if (strcmp(components[i], "") == 0 || + strcmp(components[i], ".") == 0) { + memmove(&components[i], &components[i+1], + sizeof(char *)*(num_components-i)); + i--; + } + if (strcmp(components[i], "..") == 0) { + if (i < 1) return NULL; + memmove(&components[i-1], &components[i+1], + sizeof(char *)*(num_components-(i+1))); + i -= 2; + } + } + + if (components[0] == NULL) { + talloc_free(s); + return talloc_strdup(mem_ctx, "\\"); + } + + for (len=i=0;components[i];i++) { + len += strlen(components[i]) + 1; + } + + /* rebuild the name */ + ret = talloc(mem_ctx, len+1); + if (ret == NULL) { + talloc_free(s); + return NULL; + } + + for (len=0,i=0;components[i];i++) { + size_t len1 = strlen(components[i]); + ret[len] = '\\'; + memcpy(ret+len+1, components[i], len1); + len += len1 + 1; + } + ret[len] = 0; + + talloc_free(s); + + return ret; +} + + /* 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' @@ -316,6 +405,15 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, /* 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_EQUAL(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) { + /* it might contain .. components which need to be reduced */ + cifs_name = pvfs_reduce_name(*name, cifs_name); + if (cifs_name) { + status = pvfs_unix_path(pvfs, cifs_name, flags, *name); + } + } + if (!NT_STATUS_IS_OK(status)) { return status; } -- cgit From 074da7ccf72bba1868d3f9e4ce206acbd56c8074 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 27 Oct 2004 08:36:51 +0000 Subject: r3288: - updated the path processing in pvfs to pass the RAW-CHKPATH test. This rather extensive test reveals some really bizarre error code handling in w2k3. - extended and simplified the RAW-CHKPATH test, making it easier to read (note that Samba3 fails the new tests - jra may wish to look) - marked RAW-CHKPATH as pass for pvfs (This used to be commit 32dccf91cfa5b57f84dd6307720b3f45faa10ae0) --- source4/ntvfs/posix/pvfs_resolve.c | 81 +++++++++++++++++++++++--------------- 1 file changed, 50 insertions(+), 31 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index a7a693b217..75fbeb39a5 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -116,7 +116,7 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * /* check if this component exists as-is */ if (stat(test_name, &name->st) == 0) { if (ist.st_mode)) { - return NT_STATUS_NOT_A_DIRECTORY; + return NT_STATUS_OBJECT_PATH_NOT_FOUND; } talloc_free(partial_name); partial_name = test_name; @@ -193,7 +193,6 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, uint_t flags, struct pvfs_filename *name) { char *ret, *p, *p_start; - size_t len; name->original_name = talloc_strdup(name, cifs_name); name->stream_name = NULL; @@ -218,18 +217,10 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, p = ret + strlen(pvfs->base_directory) + 1; - len = strlen(cifs_name); - if (len>0 && p[len-1] == '\\') { - p[len-1] = 0; - len--; - } - if (len>1 && p[len-1] == '.' && p[len-2] == '\\') { - return NT_STATUS_OBJECT_NAME_INVALID; - } - /* now do an in-place conversion of '\' to '/', checking for legal characters */ p_start = p; + while (*p) { size_t c_size; codepoint_t c = next_codepoint(p, &c_size); @@ -240,7 +231,11 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, of a name */ return NT_STATUS_ILLEGAL_CHARACTER; } - *p = '/'; + if (p > p_start && p[1] == 0) { + *p = 0; + } else { + *p = '/'; + } break; case ':': if (!(flags & PVFS_RESOLVE_STREAMS)) { @@ -258,7 +253,7 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, case '?': case '"': if (flags & PVFS_RESOLVE_NO_WILDCARD) { - return NT_STATUS_ILLEGAL_CHARACTER; + return NT_STATUS_OBJECT_NAME_INVALID; } name->has_wildcard = True; break; @@ -297,30 +292,26 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, reduce a name that contains .. components or repeated \ separators return NULL if it can't be reduced */ -const char *pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char *fname) +static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t flags) { codepoint_t c; size_t c_size, len; - int i, num_components; + int i, num_components, err_count; char **components; char *p, *s, *ret; - s = talloc_strdup(mem_ctx, fname); - if (s == NULL) return NULL; + s = talloc_strdup(mem_ctx, *fname); + if (s == NULL) return NT_STATUS_NO_MEMORY; for (num_components=1, p=s; *p; p += c_size) { c = next_codepoint(p, &c_size); if (c == '\\') num_components++; } - if (num_components < 2) { - talloc_free(s); - return NULL; - } components = talloc_array_p(s, char *, num_components+1); if (components == NULL) { talloc_free(s); - return NULL; + return NT_STATUS_NO_MEMORY; } components[0] = s; @@ -333,16 +324,40 @@ const char *pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char *fname) } components[i+1] = NULL; + /* + rather bizarre! + + '.' components are not allowed, but the rules for what error + code to give don't seem to make sense. This is a close + approximation. + */ + for (err_count=i=0;components[i];i++) { + if (strcmp(components[i], "") == 0) { + continue; + } + if (strcmp(components[i], ".") == 0 || err_count) { + err_count++; + } + } + if (err_count) { + if (!(flags & PVFS_RESOLVE_NO_WILDCARD)) err_count--; + + if (err_count==1) { + return NT_STATUS_OBJECT_NAME_INVALID; + } else { + return NT_STATUS_OBJECT_PATH_NOT_FOUND; + } + } + /* remove any null components */ for (i=0;components[i];i++) { - if (strcmp(components[i], "") == 0 || - strcmp(components[i], ".") == 0) { + if (strcmp(components[i], "") == 0) { memmove(&components[i], &components[i+1], sizeof(char *)*(num_components-i)); i--; } if (strcmp(components[i], "..") == 0) { - if (i < 1) return NULL; + if (i < 1) return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; memmove(&components[i-1], &components[i+1], sizeof(char *)*(num_components-(i+1))); i -= 2; @@ -351,7 +366,8 @@ const char *pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char *fname) if (components[0] == NULL) { talloc_free(s); - return talloc_strdup(mem_ctx, "\\"); + *fname = talloc_strdup(mem_ctx, "\\"); + return NT_STATUS_OK; } for (len=i=0;components[i];i++) { @@ -362,7 +378,7 @@ const char *pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char *fname) ret = talloc(mem_ctx, len+1); if (ret == NULL) { talloc_free(s); - return NULL; + return NT_STATUS_NO_MEMORY; } for (len=0,i=0;components[i];i++) { @@ -374,8 +390,10 @@ const char *pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char *fname) ret[len] = 0; talloc_free(s); + + *fname = ret; - return ret; + return NT_STATUS_OK; } @@ -408,10 +426,11 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) { /* it might contain .. components which need to be reduced */ - cifs_name = pvfs_reduce_name(*name, cifs_name); - if (cifs_name) { - status = pvfs_unix_path(pvfs, cifs_name, flags, *name); + status = pvfs_reduce_name(*name, &cifs_name, flags); + if (!NT_STATUS_IS_OK(status)) { + return status; } + status = pvfs_unix_path(pvfs, cifs_name, flags, *name); } if (!NT_STATUS_IS_OK(status)) { -- cgit From 78b85c96c946069cd16ad7399b0dd8cfb7e2590b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 29 Oct 2004 04:43:28 +0000 Subject: r3351: handle far more operations on open directory handles. pvfs was failing with a wxp client because of qfileinfo operations on directories failing with NT_STATUS_INVALID_HANDLE after the fstat() failed (as pvfs sets f->fd to -1 for directories) (This used to be commit 1993128cb1dbf49db6e3e0387996ecf2a14b8d76) --- source4/ntvfs/posix/pvfs_resolve.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 75fbeb39a5..be1662437e 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -510,8 +510,14 @@ NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, inode = name->st.st_ino; } - if (fstat(fd, &name->st) == -1) { - return NT_STATUS_INVALID_HANDLE; + if (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) { + if (stat(name->full_name, &name->st) == -1) { + return NT_STATUS_INVALID_HANDLE; + } + } else { + if (fstat(fd, &name->st) == -1) { + return NT_STATUS_INVALID_HANDLE; + } } if (name->exists && -- cgit From d1a732dd2d0828cb3f1f67e86acffcb053ca6851 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 29 Oct 2004 05:58:22 +0000 Subject: r3353: don't reference dos.attrib unless its initialised (This used to be commit 498799e4260b1c5e2bfc4fac4cba1080e8ec0a04) --- source4/ntvfs/posix/pvfs_resolve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index be1662437e..672d028dd5 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -510,7 +510,7 @@ NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, inode = name->st.st_ino; } - if (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) { + if (name->exists && (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) { if (stat(name->full_name, &name->st) == -1) { return NT_STATUS_INVALID_HANDLE; } -- cgit From ead3508ac81ff3ed2a48753f3b5e23537ba6ec73 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 00:24:21 +0000 Subject: r3447: more include/system/XXX.h include files (This used to be commit 264ce9181089922547e8f6f67116f2d7277a5105) --- source4/ntvfs/posix/pvfs_resolve.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 672d028dd5..551b05b248 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -29,6 +29,7 @@ #include "include/includes.h" #include "vfs_posix.h" +#include "system/dir.h" /* compare two filename components. This is where the name mangling hook will go -- cgit From 9fe5fa11d637252f1fbe79c7baf778e2d3cdade2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 5 Nov 2004 07:29:02 +0000 Subject: r3545: initial support for using extended attributes to hold extended dos attributes of files. I decided to use IDL/NDR to encode the attribute, as it gives us a simple way to describe and extend the saved attributes. The xattr code needs to hook into quite a few more places in the pvfs code, but this at least gets the basics done. I will start encoding alternate data streams streams, DOS EAs etc soon using the same basic mechanism. I'll probably stick to "version 1" for the xattr.idl for quite a while even though it will be changing, as I don't expect anyone to be deploying this in production just yet. Once we have production users we will need to keep compatibility by supporting all the old version numbers in xattr.idl. (This used to be commit c54253ed1b7dce1d14f43e747da61089aea87094) --- source4/ntvfs/posix/pvfs_resolve.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 551b05b248..30602b964a 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -27,7 +27,7 @@ */ -#include "include/includes.h" +#include "includes.h" #include "vfs_posix.h" #include "system/dir.h" @@ -175,7 +175,7 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * name->full_name = partial_name; if (name->exists) { - return pvfs_fill_dos_info(pvfs, name); + return pvfs_fill_dos_info(pvfs, name, -1); } return NT_STATUS_OK; @@ -446,7 +446,7 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, /* if we can stat() the full name now then we are done */ if (stat((*name)->full_name, &(*name)->st) == 0) { (*name)->exists = True; - return pvfs_fill_dos_info(pvfs, *name); + return pvfs_fill_dos_info(pvfs, *name, -1); } /* search for a matching filename */ @@ -489,7 +489,7 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, (*name)->original_name = talloc_strdup(*name, fname); (*name)->stream_name = NULL; - status = pvfs_fill_dos_info(pvfs, *name); + status = pvfs_fill_dos_info(pvfs, *name, -1); return status; } @@ -534,5 +534,5 @@ NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, name->exists = True; - return pvfs_fill_dos_info(pvfs, name); + return pvfs_fill_dos_info(pvfs, name, fd); } -- cgit From e7810eeab787bb93b36c95f8783d0b8f4c7cf7c0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 10 Nov 2004 12:40:33 +0000 Subject: r3658: use handle->fd == -1 as the primary indicator of a directory. This fixes a directory creation problem from WinXP (This used to be commit 4b3afc6c395b430e7e56d8ebe0ddf85c556a5df5) --- source4/ntvfs/posix/pvfs_resolve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 30602b964a..5c650440c3 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -511,7 +511,7 @@ NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, inode = name->st.st_ino; } - if (name->exists && (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) { + if (fd == -1) { if (stat(name->full_name, &name->st) == -1) { return NT_STATUS_INVALID_HANDLE; } -- cgit From 94c6fde541f2f8c5b93f8c779f0a1714a446e490 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 12 Nov 2004 02:45:52 +0000 Subject: r3694: added support for the RENAME_INFORMATION level of setfileinfo and setpathinfo. pvfs now passes the RAW-SFILEINFO test. (This used to be commit 31ac31398ba52dfc554e58edaa7ae257caf5fdc6) --- source4/ntvfs/posix/pvfs_resolve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 5c650440c3..354cdd4bb4 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -527,7 +527,7 @@ NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, be someone trying to exploit a race condition. Certainly we don't want to continue operating on this file */ - DEBUG(0,("pvfs: WARNING: file '%s' changed during resole - failing\n", + DEBUG(0,("pvfs: WARNING: file '%s' changed during resolve - failing\n", name->full_name)); return NT_STATUS_UNEXPECTED_IO_ERROR; } -- cgit From 187412f3da4fbc6feeca15bd0c2527534255964e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 15 Nov 2004 06:57:26 +0000 Subject: r3747: - added some of the infrastructure needed for streams support in pvfs (the IDL, and the load/save meta-data logic) - changed pvfs_resolve_name() to default to non-wildcard, needing PVFS_RESOLVE_WILDCARD to enable wildcards. Most callers don't want wildcards, so defaulting this way makes more sense. - fixed deletion of EAs (This used to be commit e7afd4403cc1b7e0928776929f8988aa6f15640b) --- source4/ntvfs/posix/pvfs_resolve.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 354cdd4bb4..576b0d9db4 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -253,7 +253,7 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, case '<': case '?': case '"': - if (flags & PVFS_RESOLVE_NO_WILDCARD) { + if (!(flags & PVFS_RESOLVE_WILDCARD)) { return NT_STATUS_OBJECT_NAME_INVALID; } name->has_wildcard = True; @@ -341,7 +341,7 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t } } if (err_count) { - if (!(flags & PVFS_RESOLVE_NO_WILDCARD)) err_count--; + if (flags & PVFS_RESOLVE_WILDCARD) err_count--; if (err_count==1) { return NT_STATUS_OBJECT_NAME_INVALID; -- cgit From ae7caf08c1f47f3ad08856cfea2a3e6e956b48ab Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 17 Nov 2004 05:58:04 +0000 Subject: r3798: added support for alternate data streams in xattrs into pvfs. The trickiest part about this was getting the sharing and locking rules right, as alternate streams are separate locking spaces from the main file for the purposes of byte range locking, and separate for most share violation rules. I suspect there are still problems with delete on close with alternate data streams. I'll look at that next. (This used to be commit b6452c4a2068cf7e837778559da002ae191b508a) --- source4/ntvfs/posix/pvfs_resolve.c | 45 +++++++++++++++++++++++++++++++++++--- 1 file changed, 42 insertions(+), 3 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 576b0d9db4..302ccdae60 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -181,6 +181,37 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * return NT_STATUS_OK; } +/* + parse a alternate data stream name +*/ +static NTSTATUS parse_stream_name(struct pvfs_filename *name, const char *s) +{ + char *p; + name->stream_name = talloc_strdup(name, s+1); + if (name->stream_name == NULL) { + return NT_STATUS_NO_MEMORY; + } + p = strchr_m(name->stream_name, ':'); + if (p == NULL) { + name->stream_id = pvfs_name_hash(name->stream_name, + strlen(name->stream_name)); + return NT_STATUS_OK; + } + if (StrCaseCmp(p, ":$DATA") != 0) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + *p = 0; + if (strcmp(name->stream_name, "") == 0) { + name->stream_name = NULL; + name->stream_id = 0; + } else { + name->stream_id = pvfs_name_hash(name->stream_name, + strlen(name->stream_name)); + } + + return NT_STATUS_OK; +} + /* convert a CIFS pathname to a unix pathname. Note that this does NOT @@ -194,9 +225,11 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, uint_t flags, struct pvfs_filename *name) { char *ret, *p, *p_start; + NTSTATUS status; name->original_name = talloc_strdup(name, cifs_name); name->stream_name = NULL; + name->stream_id = 0; name->has_wildcard = False; while (*cifs_name == '\\') { @@ -242,9 +275,12 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, 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; + if (name->has_wildcard) { + return NT_STATUS_ILLEGAL_CHARACTER; + } + status = parse_stream_name(name, p); + if (!NT_STATUS_IS_OK(status)) { + return status; } *p-- = 0; break; @@ -420,6 +456,7 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, } (*name)->exists = False; + (*name)->stream_exists = False; /* do the basic conversion to a unix formatted path, also checking for allowable characters */ @@ -485,9 +522,11 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, } (*name)->exists = True; + (*name)->stream_exists = True; (*name)->has_wildcard = False; (*name)->original_name = talloc_strdup(*name, fname); (*name)->stream_name = NULL; + (*name)->stream_id = 0; status = pvfs_fill_dos_info(pvfs, *name, -1); -- cgit From 5a34ef4df6152f5e970afbfb463d4665a823deb7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 17 Nov 2004 06:30:06 +0000 Subject: r3799: - added the bit for FS_ATTR_NAMED_STREAMS support into qfsinfo filesystem attribute reply - pvfs passes the RAW-STREAMS test (This used to be commit c1a48a7542a52df734b54031f405d574e4c891e3) --- source4/ntvfs/posix/pvfs_resolve.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 302ccdae60..7329968d6c 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -458,6 +458,10 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, (*name)->exists = False; (*name)->stream_exists = False; + if (!(pvfs->fs_attribs & FS_ATTR_NAMED_STREAMS)) { + flags &= ~PVFS_RESOLVE_STREAMS; + } + /* do the basic conversion to a unix formatted path, also checking for allowable characters */ status = pvfs_unix_path(pvfs, cifs_name, flags, *name); -- cgit From 4183b2ac3832cdc2055d7eb3ed7121a9ea91085c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 2 Dec 2004 04:51:56 +0000 Subject: r4037: fixed a bunch of "might be uninitialised" warnings after enabling -O1 in my compile (This used to be commit 0928b1f5b68c858922c3ea6c27ed03b5091c6221) --- source4/ntvfs/posix/pvfs_resolve.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 7329968d6c..7e7f49d0af 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -546,8 +546,8 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, struct pvfs_filename *name) { - dev_t device; - ino_t inode; + dev_t device = 0; + ino_t inode = 0; if (name->exists) { device = name->st.st_dev; -- cgit From abe22d0351955adb1ad7c304d45b9539d202aadb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 30 Dec 2004 02:25:20 +0000 Subject: r4403: - added ACL inheritance in the pvfs backend. ACLs are now inherited on file and directory creation via ntcreatex. pvfs now passes the inheritance test in RAW-ACLS - cleaned up the error handling a bit in pvfs_open() (This used to be commit f4dfb63d5395a365961a21388639809fcd3112d0) --- source4/ntvfs/posix/pvfs_resolve.c | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 7e7f49d0af..4ad3476795 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -579,3 +579,54 @@ NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, return pvfs_fill_dos_info(pvfs, name, fd); } + + +/* + resolve the parent of a given name +*/ +NTSTATUS pvfs_resolve_parent(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, + const struct pvfs_filename *child, + struct pvfs_filename **name) +{ + NTSTATUS status; + char *p; + + *name = talloc_p(mem_ctx, struct pvfs_filename); + if (*name == NULL) { + return NT_STATUS_NO_MEMORY; + } + + (*name)->full_name = talloc_strdup(*name, child->full_name); + if ((*name)->full_name == NULL) { + return NT_STATUS_NO_MEMORY; + } + + p = strrchr_m((*name)->full_name, '/'); + if (p == NULL) { + return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; + } + + /* this handles the root directory */ + if (p == (*name)->full_name) { + p[1] = 0; + } else { + p[0] = 0; + } + + if (stat((*name)->full_name, &(*name)->st) == -1) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + (*name)->exists = True; + (*name)->stream_exists = True; + (*name)->has_wildcard = False; + /* we can't get the correct 'original_name', but for the purposes + of this call this is close enough */ + (*name)->original_name = talloc_reference(*name, child->original_name); + (*name)->stream_name = NULL; + (*name)->stream_id = 0; + + status = pvfs_fill_dos_info(pvfs, *name, -1); + + return status; +} -- cgit From ddc10d4d37984246a6547e34a32d629c689c40d1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Jan 2005 03:06:58 +0000 Subject: r4549: got rid of a lot more uses of plain talloc(), instead using talloc_size() or talloc_array_p() where appropriate. also fixed a memory leak in pvfs_copy_file() (failed to free a memory context) (This used to be commit 89b74b53546e1570b11b3702f40bee58aed8c503) --- source4/ntvfs/posix/pvfs_resolve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 4ad3476795..fc1576b955 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -412,7 +412,7 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t } /* rebuild the name */ - ret = talloc(mem_ctx, len+1); + ret = talloc_size(mem_ctx, len+1); if (ret == NULL) { talloc_free(s); return NT_STATUS_NO_MEMORY; -- cgit From 759da3b915e2006d4c87b5ace47f399accd9ce91 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 27 Jan 2005 07:08:20 +0000 Subject: r5037: got rid of all of the TALLOC_DEPRECATED stuff. My apologies for the large commit. I thought this was worthwhile to get done for consistency. (This used to be commit ec32b22ed5ec224f6324f5e069d15e92e38e15c0) --- source4/ntvfs/posix/pvfs_resolve.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index fc1576b955..fc899c5fbc 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -75,7 +75,7 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * } } - components = talloc_array_p(name, char *, num_components); + components = talloc_array(name, char *, num_components); p = name->full_name + strlen(pvfs->base_directory); *p++ = 0; @@ -345,7 +345,7 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t if (c == '\\') num_components++; } - components = talloc_array_p(s, char *, num_components+1); + components = talloc_array(s, char *, num_components+1); if (components == NULL) { talloc_free(s); return NT_STATUS_NO_MEMORY; @@ -450,7 +450,7 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, { NTSTATUS status; - *name = talloc_p(mem_ctx, struct pvfs_filename); + *name = talloc(mem_ctx, struct pvfs_filename); if (*name == NULL) { return NT_STATUS_NO_MEMORY; } @@ -511,7 +511,7 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, { NTSTATUS status; - *name = talloc_p(mem_ctx, struct pvfs_filename); + *name = talloc(mem_ctx, struct pvfs_filename); if (*name == NULL) { return NT_STATUS_NO_MEMORY; } @@ -591,7 +591,7 @@ NTSTATUS pvfs_resolve_parent(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, NTSTATUS status; char *p; - *name = talloc_p(mem_ctx, struct pvfs_filename); + *name = talloc(mem_ctx, struct pvfs_filename); if (*name == NULL) { return NT_STATUS_NO_MEMORY; } -- cgit From 0f8d452ca020ece761872721e19e62ae0fc21582 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 10 Jun 2005 08:24:34 +0000 Subject: r7458: don't look at components[-1] :-) we now survive the RAW-UNLINK test without crashing metze (This used to be commit c2149963911bf95892e732b744f244fd76ff88c8) --- source4/ntvfs/posix/pvfs_resolve.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index fc899c5fbc..355e82c301 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -392,12 +392,14 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t memmove(&components[i], &components[i+1], sizeof(char *)*(num_components-i)); i--; + continue; } if (strcmp(components[i], "..") == 0) { if (i < 1) return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; memmove(&components[i-1], &components[i+1], sizeof(char *)*(num_components-(i+1))); i -= 2; + continue; } } -- cgit From b674411eb46c9e45f2740a1f9bac365e9a347e9c Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 30 Aug 2005 11:55:05 +0000 Subject: r9792: Rename StrCaseCmp -> strcasecmp_m. All these years I was thinking StrCaseCmp was sys_strcasecmp, while it is in fact strcasecmp_m! (This used to be commit 200a8f6652cb2de7a8037a7a4c2a204b50aee2b1) --- source4/ntvfs/posix/pvfs_resolve.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 355e82c301..b8e55c85bf 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -38,12 +38,12 @@ static int component_compare(struct pvfs_state *pvfs, const char *comp, const ch { int ret; - ret = StrCaseCmp(comp, name); + ret = strcasecmp_m(comp, name); if (ret != 0) { char *shortname = pvfs_short_name_component(pvfs, name); if (shortname) { - ret = StrCaseCmp(comp, shortname); + ret = strcasecmp_m(comp, shortname); talloc_free(shortname); } } @@ -197,7 +197,7 @@ static NTSTATUS parse_stream_name(struct pvfs_filename *name, const char *s) strlen(name->stream_name)); return NT_STATUS_OK; } - if (StrCaseCmp(p, ":$DATA") != 0) { + if (strcasecmp_m(p, ":$DATA") != 0) { return NT_STATUS_OBJECT_NAME_INVALID; } *p = 0; -- cgit From 6ab33938d5239e8688440f65e802f627622d301b Mon Sep 17 00:00:00 2001 From: James Peach Date: Mon, 24 Apr 2006 00:16:51 +0000 Subject: r15186: Introduce ISDOT and ISDOTDOT macros for testing whether a filename is "." for "..". These express the intention better that strcmp or strequal and improve searchability via cscope/ctags. (This used to be commit 7e4ad7e8e5ec266b969e3075c4ad7f021571f24e) --- source4/ntvfs/posix/pvfs_resolve.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index b8e55c85bf..70a1c0523a 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -372,7 +372,7 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t if (strcmp(components[i], "") == 0) { continue; } - if (strcmp(components[i], ".") == 0 || err_count) { + if (ISDOT(components[i]) || err_count) { err_count++; } } @@ -394,7 +394,7 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t i--; continue; } - if (strcmp(components[i], "..") == 0) { + if (ISDOTDOT(components[i])) { if (i < 1) return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; memmove(&components[i-1], &components[i+1], sizeof(char *)*(num_components-(i+1))); -- cgit From cf0f4ec073b694e43daeeddf9aab51cd3e51fd2b Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sun, 30 Apr 2006 13:54:03 +0000 Subject: r15358: Fix some compiler warnings / type safety. Found by tcc (This used to be commit 12ba42de5886f9f4f9b1698476557e0c217d06f3) --- source4/ntvfs/posix/pvfs_resolve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 70a1c0523a..3e5457f0cd 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -548,7 +548,7 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, struct pvfs_filename *name) { - dev_t device = 0; + dev_t device = (dev_t)0; ino_t inode = 0; if (name->exists) { -- cgit From 0479a2f1cbae51fcd8dbdc3c148c808421fb4d25 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 10 Jul 2007 02:07:03 +0000 Subject: r23792: convert Samba4 to GPLv3 There are still a few tidyups of old FSF addresses to come (in both s3 and s4). More commits soon. (This used to be commit fcf38a38ac691abd0fa51b89dc951a08e89fdafa) --- source4/ntvfs/posix/pvfs_resolve.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 3e5457f0cd..94fa0263ad 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -7,7 +7,7 @@ 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 + the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, @@ -16,8 +16,7 @@ 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. + along with this program. If not, see . */ /* -- cgit From 3b3bfed2c3964a6c5e8299d0a7871f412e03fa67 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 24 Aug 2007 03:40:40 +0000 Subject: r24646: fixed the handling of case insensitive paths with wildcards (This used to be commit 066bcd8420045f095130674e32bdee97cb1471be) --- source4/ntvfs/posix/pvfs_resolve.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 94fa0263ad..fae5ec432c 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -480,8 +480,40 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, return status; } - /* if it has a wildcard then no point doing a stat() */ + /* if it has a wildcard then no point doing a stat() of the + full name. Instead We need check if the directory exists + */ if ((*name)->has_wildcard) { + const char *p; + char *dir_name, *saved_name; + p = strrchr((*name)->full_name, '/'); + if (p == NULL) { + /* root directory wildcard is OK */ + return NT_STATUS_OK; + } + dir_name = talloc_strndup(*name, (*name)->full_name, (p-(*name)->full_name)); + if (stat(dir_name, &(*name)->st) == 0) { + talloc_free(dir_name); + return NT_STATUS_OK; + } + /* we need to search for a matching name */ + saved_name = (*name)->full_name; + (*name)->full_name = dir_name; + status = pvfs_case_search(pvfs, *name); + if (!NT_STATUS_IS_OK(status)) { + /* the directory doesn't exist */ + (*name)->full_name = saved_name; + return status; + } + /* it does exist, but might need a case change */ + if (dir_name != (*name)->full_name) { + (*name)->full_name = talloc_asprintf(*name, "%s%s", + (*name)->full_name, p); + NT_STATUS_HAVE_NO_MEMORY((*name)->full_name); + } else { + (*name)->full_name = saved_name; + talloc_free(dir_name); + } return NT_STATUS_OK; } -- cgit From 2151cde58014ea2e822c13d2f8a369b45dc19ca8 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Sat, 6 Oct 2007 22:28:14 +0000 Subject: r25554: Convert last instances of BOOL, True and False to the standard types. (This used to be commit 566aa14139510788548a874e9213d91317f83ca9) --- source4/ntvfs/posix/pvfs_resolve.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index fae5ec432c..8a7aa13351 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -121,7 +121,7 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * talloc_free(partial_name); partial_name = test_name; if (i == num_components - 1) { - name->exists = True; + name->exists = true; } continue; } @@ -166,7 +166,7 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * if (!name->exists) { if (stat(partial_name, &name->st) == 0) { - name->exists = True; + name->exists = true; } } @@ -229,7 +229,7 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, name->original_name = talloc_strdup(name, cifs_name); name->stream_name = NULL; name->stream_id = 0; - name->has_wildcard = False; + name->has_wildcard = false; while (*cifs_name == '\\') { cifs_name++; @@ -291,7 +291,7 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, if (!(flags & PVFS_RESOLVE_WILDCARD)) { return NT_STATUS_OBJECT_NAME_INVALID; } - name->has_wildcard = True; + name->has_wildcard = true; break; case '/': case '|': @@ -456,8 +456,8 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, return NT_STATUS_NO_MEMORY; } - (*name)->exists = False; - (*name)->stream_exists = False; + (*name)->exists = false; + (*name)->stream_exists = false; if (!(pvfs->fs_attribs & FS_ATTR_NAMED_STREAMS)) { flags &= ~PVFS_RESOLVE_STREAMS; @@ -519,7 +519,7 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, /* if we can stat() the full name now then we are done */ if (stat((*name)->full_name, &(*name)->st) == 0) { - (*name)->exists = True; + (*name)->exists = true; return pvfs_fill_dos_info(pvfs, *name, -1); } @@ -558,9 +558,9 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - (*name)->exists = True; - (*name)->stream_exists = True; - (*name)->has_wildcard = False; + (*name)->exists = true; + (*name)->stream_exists = true; + (*name)->has_wildcard = false; (*name)->original_name = talloc_strdup(*name, fname); (*name)->stream_name = NULL; (*name)->stream_id = 0; @@ -608,7 +608,7 @@ NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, return NT_STATUS_UNEXPECTED_IO_ERROR; } - name->exists = True; + name->exists = true; return pvfs_fill_dos_info(pvfs, name, fd); } @@ -650,9 +650,9 @@ NTSTATUS pvfs_resolve_parent(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - (*name)->exists = True; - (*name)->stream_exists = True; - (*name)->has_wildcard = False; + (*name)->exists = true; + (*name)->stream_exists = true; + (*name)->has_wildcard = false; /* we can't get the correct 'original_name', but for the purposes of this call this is close enough */ (*name)->original_name = talloc_reference(*name, child->original_name); -- cgit From 39ee38d9c1aabf4db065b433d067d0da053d7d61 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 6 Dec 2007 17:52:23 +0100 Subject: r26316: Use contexts for conversion functions. (This used to be commit f6420d933b5b011d428974f3a2a57edf19e6f482) --- source4/ntvfs/posix/pvfs_resolve.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 8a7aa13351..f1d701b343 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -256,7 +256,7 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, while (*p) { size_t c_size; - codepoint_t c = next_codepoint(p, &c_size); + codepoint_t c = next_codepoint(global_smb_iconv_convenience, p, &c_size); switch (c) { case '\\': if (name->has_wildcard) { @@ -340,7 +340,7 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t if (s == NULL) return NT_STATUS_NO_MEMORY; for (num_components=1, p=s; *p; p += c_size) { - c = next_codepoint(p, &c_size); + c = next_codepoint(global_smb_iconv_convenience, p, &c_size); if (c == '\\') num_components++; } @@ -352,7 +352,7 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t components[0] = s; for (i=0, p=s; *p; p += c_size) { - c = next_codepoint(p, &c_size); + c = next_codepoint(global_smb_iconv_convenience, p, &c_size); if (c == '\\') { *p = 0; components[++i] = p+1; -- cgit From d891c0c74a03d797aed1c5ac0329fd9d1d78da63 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 13 Dec 2007 22:46:09 +0100 Subject: r26429: Avoid use of global_smb_iconv_convenience. (This used to be commit d37136b7abfbba75ef2e5ab855eb3382b9648b8c) --- source4/ntvfs/posix/pvfs_resolve.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index f1d701b343..d9a60e3857 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -29,8 +29,9 @@ #include "includes.h" #include "vfs_posix.h" #include "system/dir.h" +#include "param/param.h" -/* +/** compare two filename components. This is where the name mangling hook will go */ static int component_compare(struct pvfs_state *pvfs, const char *comp, const char *name) @@ -256,7 +257,7 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, while (*p) { size_t c_size; - codepoint_t c = next_codepoint(global_smb_iconv_convenience, p, &c_size); + codepoint_t c = next_codepoint(lp_iconv_convenience(global_loadparm), p, &c_size); switch (c) { case '\\': if (name->has_wildcard) { @@ -340,7 +341,7 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t if (s == NULL) return NT_STATUS_NO_MEMORY; for (num_components=1, p=s; *p; p += c_size) { - c = next_codepoint(global_smb_iconv_convenience, p, &c_size); + c = next_codepoint(lp_iconv_convenience(global_loadparm), p, &c_size); if (c == '\\') num_components++; } @@ -352,7 +353,7 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t components[0] = s; for (i=0, p=s; *p; p += c_size) { - c = next_codepoint(global_smb_iconv_convenience, p, &c_size); + c = next_codepoint(lp_iconv_convenience(global_loadparm), p, &c_size); if (c == '\\') { *p = 0; components[++i] = p+1; -- cgit From 96a200511e884a88dcf48fa5b313b2cddb2df566 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Fri, 14 Dec 2007 00:27:31 +0100 Subject: r26443: Remove global_loadparm instances. (This used to be commit 8242c696235d1bfb402b5c276a57f36d93610545) --- source4/ntvfs/posix/pvfs_resolve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index d9a60e3857..949fa131a4 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -257,7 +257,7 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, while (*p) { size_t c_size; - codepoint_t c = next_codepoint(lp_iconv_convenience(global_loadparm), p, &c_size); + codepoint_t c = next_codepoint(lp_iconv_convenience(pvfs->ntvfs->ctx->lp_ctx), p, &c_size); switch (c) { case '\\': if (name->has_wildcard) { -- cgit From d9f8232c34a695df04a5240e270dd7ffc3101c0e Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 21 Feb 2008 15:21:45 +0100 Subject: Remove more uses of global_loadparm. (This used to be commit 230355d2e6e27918dff40823eb238904c7a1870e) --- source4/ntvfs/posix/pvfs_resolve.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 949fa131a4..cf74816391 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -336,12 +336,13 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t int i, num_components, err_count; char **components; char *p, *s, *ret; + struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(global_loadparm); s = talloc_strdup(mem_ctx, *fname); if (s == NULL) return NT_STATUS_NO_MEMORY; for (num_components=1, p=s; *p; p += c_size) { - c = next_codepoint(lp_iconv_convenience(global_loadparm), p, &c_size); + c = next_codepoint(iconv_convenience, p, &c_size); if (c == '\\') num_components++; } @@ -353,7 +354,7 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t components[0] = s; for (i=0, p=s; *p; p += c_size) { - c = next_codepoint(lp_iconv_convenience(global_loadparm), p, &c_size); + c = next_codepoint(iconv_convenience, p, &c_size); if (c == '\\') { *p = 0; components[++i] = p+1; -- cgit From c38c2765d1059b33f044a42c6555f3d10d339911 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 21 Feb 2008 17:17:37 +0100 Subject: Remove yet more uses of global_loadparm. (This used to be commit e01c1e87c0fe9709df7eb5b863f7ce85564174cd) --- source4/ntvfs/posix/pvfs_resolve.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index cf74816391..2bfc47beff 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -329,14 +329,15 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, reduce a name that contains .. components or repeated \ separators return NULL if it can't be reduced */ -static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, const char **fname, uint_t flags) +static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, + struct smb_iconv_convenience *iconv_convenience, + const char **fname, uint_t flags) { codepoint_t c; size_t c_size, len; int i, num_components, err_count; char **components; char *p, *s, *ret; - struct smb_iconv_convenience *iconv_convenience = lp_iconv_convenience(global_loadparm); s = talloc_strdup(mem_ctx, *fname); if (s == NULL) return NT_STATUS_NO_MEMORY; @@ -471,7 +472,7 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_SYNTAX_BAD)) { /* it might contain .. components which need to be reduced */ - status = pvfs_reduce_name(*name, &cifs_name, flags); + status = pvfs_reduce_name(*name, lp_iconv_convenience(pvfs->ntvfs->ctx->lp_ctx), &cifs_name, flags); if (!NT_STATUS_IS_OK(status)) { return status; } -- cgit From c5d961586e72b181b24fcbaf98c8da2fa27aa2d1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 29 Feb 2008 13:04:08 +0100 Subject: pvfs_resolve: fix endless loop with trailing ".." We also need to move the NULL termination. metze (This used to be commit 4fc41065a31cc8bd477ff5bf2d89f9f595002227) --- source4/ntvfs/posix/pvfs_resolve.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 2bfc47beff..c129038572 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -399,7 +399,7 @@ static NTSTATUS pvfs_reduce_name(TALLOC_CTX *mem_ctx, if (ISDOTDOT(components[i])) { if (i < 1) return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; memmove(&components[i-1], &components[i+1], - sizeof(char *)*(num_components-(i+1))); + sizeof(char *)*(num_components-i)); i -= 2; continue; } -- cgit From 5734a10c89b3ca90ee9463320a9be268fed38e8f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 29 Feb 2008 09:08:57 +0100 Subject: pvfs_resolve: "\\" and a trailing "\" need to be reduced metze (This used to be commit 356338b99a67bfaf09618f5ed7c8f5c4ff69fa06) --- source4/ntvfs/posix/pvfs_resolve.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index c129038572..37b182733c 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -265,8 +265,15 @@ static NTSTATUS pvfs_unix_path(struct pvfs_state *pvfs, const char *cifs_name, of a name */ return NT_STATUS_ILLEGAL_CHARACTER; } - if (p > p_start && p[1] == 0) { - *p = 0; + if (p > p_start && (p[1] == '\\' || p[1] == '\0')) { + /* see if it is definately a "\\" or + * a trailing "\". If it is then fail here, + * and let the next layer up try again after + * pvfs_reduce_name() if it wants to. This is + * much more efficient on average than always + * scanning for these separately + */ + return NT_STATUS_OBJECT_PATH_SYNTAX_BAD; } else { *p = '/'; } -- cgit From f9b2d29d32197095c993d57e00ffbc09ab27184c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 28 Feb 2008 12:14:17 +0100 Subject: pvfs_resolve: add pvfs_resolve_name_handle() metze (This used to be commit 714717253c035b31fc850df8456f8cf2b38bcb72) --- source4/ntvfs/posix/pvfs_resolve.c | 80 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 37b182733c..325bc74f8f 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -623,6 +623,86 @@ NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, return pvfs_fill_dos_info(pvfs, name, fd); } +/* + fill in the pvfs_filename info for an open file, given the current + info for a (possibly) non-open file. This is used by places that need + to update the pvfs_filename stat information, and the path + after a possible rename on a different handle. +*/ +NTSTATUS pvfs_resolve_name_handle(struct pvfs_state *pvfs, + struct pvfs_file_handle *h) +{ + NTSTATUS status; + + if (h->have_opendb_entry) { + struct odb_lock *lck; + const char *name = NULL; + + lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key); + if (lck == NULL) { + DEBUG(0,("%s: failed to lock file '%s' in opendb\n", + __FUNCTION__, h->name->full_name)); + /* we were supposed to do a blocking lock, so something + is badly wrong! */ + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + status = odb_get_path(lck, &name); + if (NT_STATUS_IS_OK(status)) { + /* + * This relies an the fact that + * renames of open files are only + * allowed by setpathinfo() and setfileinfo() + * and there're only renames within the same + * directory supported + */ + if (strcmp(h->name->full_name, name) != 0) { + const char *orig_dir; + const char *new_file; + const char *new_orig; + char *delim; + + delim = strrchr(name, '/'); + if (!delim) { + talloc_free(lck); + return NT_STATUS_INTERNAL_ERROR; + } + + new_file = delim + 1; + delim = strrchr(h->name->original_name, '\\'); + if (delim) { + delim[0] = '\0'; + orig_dir = h->name->original_name; + new_orig = talloc_asprintf(h->name, "%s\\%s", + orig_dir, new_file); + if (!new_orig) { + talloc_free(lck); + return NT_STATUS_NO_MEMORY; + } + } else { + new_orig = talloc_strdup(h->name, new_file); + if (!new_orig) { + talloc_free(lck); + return NT_STATUS_NO_MEMORY; + } + } + + talloc_free(h->name->original_name); + talloc_free(h->name->full_name); + h->name->full_name = talloc_steal(h->name, name); + h->name->original_name = new_orig; + } + } + + talloc_free(lck); + } + + status = pvfs_resolve_name_fd(pvfs, h->fd, h->name); + NT_STATUS_NOT_OK_RETURN(status); + + return NT_STATUS_OK; +} + /* resolve the parent of a given name -- cgit From 391b746430ad3d0b371930933e0a77e6a70a9ac0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2008 09:46:50 +0200 Subject: pvfs_resolve: stream_name = "" is only the same as NULL for files metze (This used to be commit 47756129fdf01075bac06cdd24107d7dc8ba34af) --- source4/ntvfs/posix/pvfs_resolve.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 325bc74f8f..2e97925c49 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -202,7 +202,13 @@ static NTSTATUS parse_stream_name(struct pvfs_filename *name, const char *s) } *p = 0; if (strcmp(name->stream_name, "") == 0) { - name->stream_name = NULL; + /* + * we don't set stream_name to NULL, here + * as this would be wrong for directories + * + * pvfs_fill_dos_info() will set it to NULL + * if it's not a directory. + */ name->stream_id = 0; } else { name->stream_id = pvfs_name_hash(name->stream_name, -- cgit From c43591c2168577a790051fc27840ab5cef7866c4 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 5 May 2008 12:18:47 +0200 Subject: pvfs: add PVFS_RESOLVE_NO_OPENDB flag and get the write time from the opendb By default get the current write time from the opendb, but allow callers to pass PVFS_RESOLVE_NO_OPENDB for performance reasons, if they don't need to the write time. metze (This used to be commit def52cc0988c26a815e74b3391e5857512408d90) --- source4/ntvfs/posix/pvfs_resolve.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 2e97925c49..969a50239f 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -57,7 +57,9 @@ static int component_compare(struct pvfs_state *pvfs, const char *comp, const ch 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) +static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, + struct pvfs_filename *name, + uint_t flags) { /* break into a series of components */ int num_components; @@ -175,7 +177,7 @@ static NTSTATUS pvfs_case_search(struct pvfs_state *pvfs, struct pvfs_filename * name->full_name = partial_name; if (name->exists) { - return pvfs_fill_dos_info(pvfs, name, -1); + return pvfs_fill_dos_info(pvfs, name, flags, -1); } return NT_STATUS_OK; @@ -515,7 +517,7 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, /* we need to search for a matching name */ saved_name = (*name)->full_name; (*name)->full_name = dir_name; - status = pvfs_case_search(pvfs, *name); + status = pvfs_case_search(pvfs, *name, flags); if (!NT_STATUS_IS_OK(status)) { /* the directory doesn't exist */ (*name)->full_name = saved_name; @@ -536,11 +538,11 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, /* if we can stat() the full name now then we are done */ if (stat((*name)->full_name, &(*name)->st) == 0) { (*name)->exists = true; - return pvfs_fill_dos_info(pvfs, *name, -1); + return pvfs_fill_dos_info(pvfs, *name, flags, -1); } /* search for a matching filename */ - status = pvfs_case_search(pvfs, *name); + status = pvfs_case_search(pvfs, *name, flags); return status; } @@ -556,7 +558,7 @@ NTSTATUS pvfs_resolve_name(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, */ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, const char *unix_dir, const char *fname, - struct pvfs_filename **name) + uint_t flags, struct pvfs_filename **name) { NTSTATUS status; @@ -581,7 +583,7 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, (*name)->stream_name = NULL; (*name)->stream_id = 0; - status = pvfs_fill_dos_info(pvfs, *name, -1); + status = pvfs_fill_dos_info(pvfs, *name, flags, -1); return status; } @@ -593,7 +595,7 @@ NTSTATUS pvfs_resolve_partial(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, to update the pvfs_filename stat information, and by pvfs_open() */ NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, - struct pvfs_filename *name) + struct pvfs_filename *name, uint_t flags) { dev_t device = (dev_t)0; ino_t inode = 0; @@ -626,7 +628,7 @@ NTSTATUS pvfs_resolve_name_fd(struct pvfs_state *pvfs, int fd, name->exists = true; - return pvfs_fill_dos_info(pvfs, name, fd); + return pvfs_fill_dos_info(pvfs, name, flags, fd); } /* @@ -703,7 +705,11 @@ NTSTATUS pvfs_resolve_name_handle(struct pvfs_state *pvfs, talloc_free(lck); } - status = pvfs_resolve_name_fd(pvfs, h->fd, h->name); + /* + * TODO: pass PVFS_RESOLVE_NO_OPENDB and get + * the write time from odb_lock() above. + */ + status = pvfs_resolve_name_fd(pvfs, h->fd, h->name, 0); NT_STATUS_NOT_OK_RETURN(status); return NT_STATUS_OK; @@ -755,7 +761,7 @@ NTSTATUS pvfs_resolve_parent(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx, (*name)->stream_name = NULL; (*name)->stream_id = 0; - status = pvfs_fill_dos_info(pvfs, *name, -1); + status = pvfs_fill_dos_info(pvfs, *name, PVFS_RESOLVE_NO_OPENDB, -1); return status; } -- cgit From 6e52c4feb80ef68659569ffef8796441df9a7cee Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 8 May 2008 22:16:55 +0200 Subject: pvfs_close: correctly handle the write time updates passed by close() metze (This used to be commit 7f033ce4fb6fc897f8159926d5a6d2e45dd447b6) --- source4/ntvfs/posix/pvfs_resolve.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_resolve.c') diff --git a/source4/ntvfs/posix/pvfs_resolve.c b/source4/ntvfs/posix/pvfs_resolve.c index 969a50239f..0f19788b97 100644 --- a/source4/ntvfs/posix/pvfs_resolve.c +++ b/source4/ntvfs/posix/pvfs_resolve.c @@ -712,6 +712,10 @@ NTSTATUS pvfs_resolve_name_handle(struct pvfs_state *pvfs, status = pvfs_resolve_name_fd(pvfs, h->fd, h->name, 0); NT_STATUS_NOT_OK_RETURN(status); + if (!null_nttime(h->write_time.close_time)) { + h->name->dos.write_time = h->write_time.close_time; + } + return NT_STATUS_OK; } -- cgit