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_open.c | 175 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 175 insertions(+) create mode 100644 source4/ntvfs/posix/pvfs_open.c (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c new file mode 100644 index 0000000000..74badb2443 --- /dev/null +++ b/source4/ntvfs/posix/pvfs_open.c @@ -0,0 +1,175 @@ +/* + Unix SMB/CIFS implementation. + + POSIX NTVFS backend - open and close + + 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" + + +/* + find open file handle given fnum +*/ +struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, uint16_t fnum) +{ + struct pvfs_file *f; + for (f=pvfs->open_files;f;f=f->next) { + if (f->fnum == fnum) { + return f; + } + } + return NULL; +} + +/* + open a file + TODO: this is a temporary implementation derived from the simple backend + its purpose is to allow other tests to run +*/ +NTSTATUS pvfs_open(struct smbsrv_request *req, union smb_open *io) +{ + struct pvfs_state *pvfs = req->tcon->ntvfs_private; + int fd, flags; + struct pvfs_filename *name; + struct pvfs_file *f; + NTSTATUS status; + + if (io->generic.level != RAW_OPEN_GENERIC) { + return ntvfs_map_open(req, io); + } + + /* resolve the cifs name to a posix name */ + status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, + PVFS_RESOLVE_NO_WILDCARD, &name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + switch (io->generic.in.open_disposition) { + case NTCREATEX_DISP_SUPERSEDE: + case NTCREATEX_DISP_OVERWRITE_IF: + flags = O_CREAT | O_TRUNC; + break; + case NTCREATEX_DISP_OPEN: + case NTCREATEX_DISP_OVERWRITE: + flags = 0; + break; + case NTCREATEX_DISP_CREATE: + flags = O_CREAT | O_EXCL; + break; + case NTCREATEX_DISP_OPEN_IF: + flags = O_CREAT; + break; + default: + flags = 0; + break; + } + + flags |= O_RDWR; + + if (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) { + flags = O_RDONLY | O_DIRECTORY; + if (pvfs->flags & PVFS_FLAG_READONLY) { + goto do_open; + } + switch (io->generic.in.open_disposition) { + case NTCREATEX_DISP_CREATE: + if (mkdir(name->full_name, 0755) == -1) { + return pvfs_map_errno(pvfs,errno); + } + break; + case NTCREATEX_DISP_OPEN_IF: + if (mkdir(name->full_name, 0755) == -1 && errno != EEXIST) { + return pvfs_map_errno(pvfs,errno); + } + break; + } + } + +do_open: + fd = open(name->full_name, flags, 0644); + if (fd == -1) { + if (errno == 0) + errno = ENOENT; + return pvfs_map_errno(pvfs,errno); + } + + f = talloc_p(pvfs, struct pvfs_file); + if (f == NULL) { + close(fd); + return NT_STATUS_NO_MEMORY; + } + + /* re-resolve the open fd */ + status = pvfs_resolve_name_fd(pvfs, fd, name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + f->fnum = fd; + f->fd = fd; + f->name = talloc_steal(f, name); + + DLIST_ADD(pvfs->open_files, f); + + ZERO_STRUCT(io->generic.out); + + io->generic.out.create_time = name->dos.create_time; + io->generic.out.access_time = name->dos.access_time; + io->generic.out.write_time = name->dos.write_time; + io->generic.out.change_time = name->dos.change_time; + io->generic.out.fnum = f->fnum; + io->generic.out.alloc_size = name->dos.alloc_size; + io->generic.out.size = name->st.st_size; + io->generic.out.attrib = name->dos.attrib; + io->generic.out.is_directory = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)?1:0; + + return NT_STATUS_OK; +} + + +/* + close a file +*/ +NTSTATUS pvfs_close(struct smbsrv_request *req, union smb_close *io) +{ + struct pvfs_state *pvfs = req->tcon->ntvfs_private; + struct pvfs_file *f; + + if (io->generic.level != RAW_CLOSE_CLOSE) { + /* we need a mapping function */ + return NT_STATUS_INVALID_LEVEL; + } + + f = pvfs_find_fd(pvfs, io->close.in.fnum); + if (!f) { + return NT_STATUS_INVALID_HANDLE; + } + + if (close(f->fd) != 0) { + return pvfs_map_errno(pvfs, errno); + } + + DLIST_REMOVE(pvfs->open_files, f); + talloc_free(f); + + return NT_STATUS_OK; +} + -- cgit From 635f5fa942c2ecd82a2a787b96bf2ce2a587c616 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 20 Sep 2004 08:53:45 +0000 Subject: r2438: compile on systems without O_DIRECTORY (probably won't work, but I'll get to that later) (This used to be commit 5e2027f8ec7248e48d1dfb94c3688c78c64a85c5) --- source4/ntvfs/posix/pvfs_open.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 74badb2443..26fd444984 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -84,6 +84,11 @@ NTSTATUS pvfs_open(struct smbsrv_request *req, union smb_open *io) flags |= O_RDWR; +/* we need to do this differently to support systems without O_DIRECTORY */ +#ifndef O_DIRECTORY +#define O_DIRECTORY 0 +#endif + if (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) { flags = O_RDONLY | O_DIRECTORY; if (pvfs->flags & PVFS_FLAG_READONLY) { -- 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_open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 26fd444984..1c6ecc1eb2 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -45,14 +45,14 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, uint16_t fnum) */ NTSTATUS pvfs_open(struct smbsrv_request *req, union smb_open *io) { - struct pvfs_state *pvfs = req->tcon->ntvfs_private; + NTVFS_GET_PRIVATE(pvfs_state, pvfs, req); int fd, flags; struct pvfs_filename *name; struct pvfs_file *f; NTSTATUS status; if (io->generic.level != RAW_OPEN_GENERIC) { - return ntvfs_map_open(req, io); + return ntvfs_map_open(req, io, pvfs->ops); } /* resolve the cifs name to a posix name */ @@ -155,7 +155,7 @@ do_open: */ NTSTATUS pvfs_close(struct smbsrv_request *req, union smb_close *io) { - struct pvfs_state *pvfs = req->tcon->ntvfs_private; + NTVFS_GET_PRIVATE(pvfs_state, pvfs, req); struct pvfs_file *f; if (io->generic.level != RAW_CLOSE_CLOSE) { -- cgit From 4fa2904290e2c345eae76ad66fc284b76eccd5f8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 25 Sep 2004 04:45:52 +0000 Subject: r2613: use a talloc destructor to ensure that file descriptors are not leaked on abnormal termination of a connection. As long as the top level connection structure is freed then that should cascade down to the file structure, and call this destructor which will close the open file descriptor. In general I'd like to use this technique in any place in Samba4 where we hold operating system resources that we need to make sure are released on abnormal termination. (This used to be commit ed87b7fcbd9fedc155528ce6dd8ab5d5fce637b2) --- source4/ntvfs/posix/pvfs_open.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 1c6ecc1eb2..a1c6dcdcfe 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -38,6 +38,21 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, uint16_t fnum) return NULL; } +/* + by using a destructor we make sure that abnormal cleanup will not + leak file descriptors (assuming at least the top level pointer is freed, which + will cascade down to here) +*/ +static int pvfs_fd_destructor(void *p) +{ + struct pvfs_file *f = p; + if (f->fd != -1) { + close(f->fd); + f->fd = -1; + } + return 0; +} + /* open a file TODO: this is a temporary implementation derived from the simple backend @@ -132,6 +147,10 @@ do_open: f->fd = fd; f->name = talloc_steal(f, name); + /* setup a destructor to avoid file descriptor leaks on + abnormal termination */ + talloc_set_destructor(f, pvfs_fd_destructor); + DLIST_ADD(pvfs->open_files, f); ZERO_STRUCT(io->generic.out); @@ -157,6 +176,7 @@ NTSTATUS pvfs_close(struct smbsrv_request *req, union smb_close *io) { NTVFS_GET_PRIVATE(pvfs_state, pvfs, req); struct pvfs_file *f; + NTSTATUS status; if (io->generic.level != RAW_CLOSE_CLOSE) { /* we need a mapping function */ @@ -169,12 +189,16 @@ NTSTATUS pvfs_close(struct smbsrv_request *req, union smb_close *io) } if (close(f->fd) != 0) { - return pvfs_map_errno(pvfs, errno); + status = pvfs_map_errno(pvfs, errno); + } else { + status = NT_STATUS_OK; } + talloc_set_destructor(f, NULL); + DLIST_REMOVE(pvfs->open_files, f); talloc_free(f); - return NT_STATUS_OK; + return status; } -- cgit From e3880fa759cfa03222262327854fe7bbe585fe01 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 26 Sep 2004 11:30:20 +0000 Subject: r2660: - converted the libcli/raw/ library to use talloc_increase_ref_count() rather than manual reference counts - properly support SMBexit in the cifs and posix backends - added a logoff method to all backends With these changes the RAW-CONTEXT test now passes against the posix backend (This used to be commit c315d6ac1cc40546fde1474702a6d66d07ee13c8) --- source4/ntvfs/posix/pvfs_open.c | 53 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index a1c6dcdcfe..f3bec4085e 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -27,11 +27,16 @@ /* find open file handle given fnum */ -struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, uint16_t fnum) +struct pvfs_file *pvfs_find_fd(struct smbsrv_request *req, uint16_t fnum) { + NTVFS_GET_PRIVATE(pvfs_state, pvfs, req); struct pvfs_file *f; for (f=pvfs->open_files;f;f=f->next) { if (f->fnum == fnum) { + if (req->session != f->session) { + DEBUG(2,("pvfs_find_fd: attempt to use wrong session for fnum %d\n", fnum)); + return NULL; + } return f; } } @@ -146,6 +151,8 @@ do_open: f->fnum = fd; f->fd = fd; f->name = talloc_steal(f, name); + f->session = req->session; + f->smbpid = req->smbpid; /* setup a destructor to avoid file descriptor leaks on abnormal termination */ @@ -183,7 +190,7 @@ NTSTATUS pvfs_close(struct smbsrv_request *req, union smb_close *io) return NT_STATUS_INVALID_LEVEL; } - f = pvfs_find_fd(pvfs, io->close.in.fnum); + f = pvfs_find_fd(req, io->close.in.fnum); if (!f) { return NT_STATUS_INVALID_HANDLE; } @@ -202,3 +209,45 @@ NTSTATUS pvfs_close(struct smbsrv_request *req, union smb_close *io) return status; } + +/* + logoff - close all file descriptors open by a vuid +*/ +NTSTATUS pvfs_logoff(struct smbsrv_request *req) +{ + NTVFS_GET_PRIVATE(pvfs_state, pvfs, req); + struct pvfs_file *f, *next; + + for (f=pvfs->open_files;f;f=next) { + next = f->next; + if (f->session == req->session) { + talloc_set_destructor(f, NULL); + DLIST_REMOVE(pvfs->open_files, f); + talloc_free(f); + } + } + + return NT_STATUS_OK; +} + + +/* + exit - close files for the current pid +*/ +NTSTATUS pvfs_exit(struct smbsrv_request *req) +{ + NTVFS_GET_PRIVATE(pvfs_state, pvfs, req); + struct pvfs_file *f, *next; + + for (f=pvfs->open_files;f;f=next) { + next = f->next; + if (f->smbpid == req->smbpid) { + talloc_set_destructor(f, NULL); + DLIST_REMOVE(pvfs->open_files, f); + talloc_free(f); + } + } + + return NT_STATUS_OK; +} + -- cgit From dcad0f6fd492506efd9a69b4e32c7bbfa5da90e5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 29 Sep 2004 13:17:09 +0000 Subject: r2751: this is a new ntvfs design which tries to solve: - the stacking of modules - finding the modules private data - hide the ntvfs details from the calling layer - I set NTVFS_INTERFACE_VERSION 0 till we are closer to release (because we need to solve some async problems with the module stacking) metze (This used to be commit 3ff03b5cb21bb79afdd3b1609be9635f6688a539) --- source4/ntvfs/posix/pvfs_open.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index f3bec4085e..560d194a34 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -27,9 +27,9 @@ /* find open file handle given fnum */ -struct pvfs_file *pvfs_find_fd(struct smbsrv_request *req, uint16_t fnum) +struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, + struct smbsrv_request *req, uint16_t fnum) { - NTVFS_GET_PRIVATE(pvfs_state, pvfs, req); struct pvfs_file *f; for (f=pvfs->open_files;f;f=f->next) { if (f->fnum == fnum) { @@ -63,16 +63,17 @@ static int pvfs_fd_destructor(void *p) TODO: this is a temporary implementation derived from the simple backend its purpose is to allow other tests to run */ -NTSTATUS pvfs_open(struct smbsrv_request *req, union smb_open *io) +NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, + struct smbsrv_request *req, union smb_open *io) { - NTVFS_GET_PRIVATE(pvfs_state, pvfs, req); + struct pvfs_state *pvfs = ntvfs->private_data; int fd, flags; struct pvfs_filename *name; struct pvfs_file *f; NTSTATUS status; if (io->generic.level != RAW_OPEN_GENERIC) { - return ntvfs_map_open(req, io, pvfs->ops); + return ntvfs_map_open(req, io, ntvfs); } /* resolve the cifs name to a posix name */ @@ -179,9 +180,10 @@ do_open: /* close a file */ -NTSTATUS pvfs_close(struct smbsrv_request *req, union smb_close *io) +NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, + struct smbsrv_request *req, union smb_close *io) { - NTVFS_GET_PRIVATE(pvfs_state, pvfs, req); + struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f; NTSTATUS status; @@ -190,7 +192,7 @@ NTSTATUS pvfs_close(struct smbsrv_request *req, union smb_close *io) return NT_STATUS_INVALID_LEVEL; } - f = pvfs_find_fd(req, io->close.in.fnum); + f = pvfs_find_fd(pvfs, req, io->close.in.fnum); if (!f) { return NT_STATUS_INVALID_HANDLE; } @@ -213,9 +215,10 @@ NTSTATUS pvfs_close(struct smbsrv_request *req, union smb_close *io) /* logoff - close all file descriptors open by a vuid */ -NTSTATUS pvfs_logoff(struct smbsrv_request *req) +NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs, + struct smbsrv_request *req) { - NTVFS_GET_PRIVATE(pvfs_state, pvfs, req); + struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f, *next; for (f=pvfs->open_files;f;f=next) { @@ -234,9 +237,10 @@ NTSTATUS pvfs_logoff(struct smbsrv_request *req) /* exit - close files for the current pid */ -NTSTATUS pvfs_exit(struct smbsrv_request *req) +NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs, + struct smbsrv_request *req) { - NTVFS_GET_PRIVATE(pvfs_state, pvfs, req); + struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f, *next; for (f=pvfs->open_files;f;f=next) { @@ -250,4 +254,3 @@ NTSTATUS pvfs_exit(struct smbsrv_request *req) return NT_STATUS_OK; } - -- cgit From 4d69d2d52b273359b481e1a7b99b9db3711d2768 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 11 Oct 2004 14:35:54 +0000 Subject: r2916: longhorn client doesn't bother setting the directory bit in ntcreatex when opening directories. This change allows samba4 server to work with longhorn client. (This used to be commit 4a8b0302eff37ccfcb66b91259ee5da20879c652) --- source4/ntvfs/posix/pvfs_open.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 560d194a34..271bd41429 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -110,7 +110,12 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, #define O_DIRECTORY 0 #endif - if (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) { + if ((io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) && + !(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) { + return NT_STATUS_NOT_A_DIRECTORY; + } + + if (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) { flags = O_RDONLY | O_DIRECTORY; if (pvfs->flags & PVFS_FLAG_READONLY) { goto do_open; -- cgit From c7130b816b29cab981646482e57cb6923ae91b4f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 12 Oct 2004 05:07:33 +0000 Subject: r2926: name->dos.attrib is not valid unless name->exists is true (This used to be commit f85a0b725d3bf67531e6874d4e8558fb050bb66f) --- source4/ntvfs/posix/pvfs_open.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 271bd41429..29e57e5a08 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -110,12 +110,14 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, #define O_DIRECTORY 0 #endif - if ((io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) && + if (name->exists && + (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) && !(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) { return NT_STATUS_NOT_A_DIRECTORY; } - if (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) { + if ((name->exists && name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) || + (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)) { flags = O_RDONLY | O_DIRECTORY; if (pvfs->flags & PVFS_FLAG_READONLY) { goto do_open; -- cgit From fef617c31bd4a8be09449d6bc726c729ae758423 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 17 Oct 2004 02:55:47 +0000 Subject: r3012: added initial support for byte range locking in the posix vfs. This is enough for us to pass locktest, but does not yet support lock timeouts and some of the other esoteric features. (This used to be commit 58a92abd88f190bc60894a68e0528e95ae33fe39) --- source4/ntvfs/posix/pvfs_open.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 29e57e5a08..51526461e0 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -51,6 +51,9 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, static int pvfs_fd_destructor(void *p) { struct pvfs_file *f = p; + + brl_close(f->pvfs->brl_context, &f->locking_key, f->fnum); + if (f->fd != -1) { close(f->fd); f->fd = -1; @@ -71,6 +74,10 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, struct pvfs_filename *name; struct pvfs_file *f; NTSTATUS status; + struct { + dev_t device; + ino_t inode; + } lock_context; if (io->generic.level != RAW_OPEN_GENERIC) { return ntvfs_map_open(req, io, ntvfs); @@ -161,6 +168,13 @@ do_open: f->name = talloc_steal(f, name); f->session = req->session; f->smbpid = req->smbpid; + f->pvfs = pvfs; + + /* we must zero here to take account of padding */ + ZERO_STRUCT(lock_context); + lock_context.device = name->st.st_dev; + lock_context.inode = name->st.st_ino; + f->locking_key = data_blob_talloc(f, &lock_context, sizeof(lock_context)); /* setup a destructor to avoid file descriptor leaks on abnormal termination */ @@ -204,6 +218,11 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_HANDLE; } + status = brl_close(pvfs->brl_context, &f->locking_key, f->fnum); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (close(f->fd) != 0) { status = pvfs_map_errno(pvfs, errno); } else { -- cgit From d0cc571e30bf49443ac7d1b1a0b896ee72d7d9a6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 18 Oct 2004 07:40:17 +0000 Subject: r3029: implemented byte range lock timeouts. This adds a pvfs_wait_message() routine which uses the new messaging system, event timers and talloc destructors to give a nice generic async event handling system with a easy to use interface. The extensions to pvfs_lock.c are based on calls to pvfs_wait_message() routines. We now pass all of our smbtorture locking tests, although while writing this code I have thought of some additonal tests that should be added, particularly for lock cancel operations. I'll work on that soon. This commit also extends the smbtorture lock tests to test the rather weird 0xEEFFFFFF locking semantics that I have discovered in win2003. Win2003 treats the 0xEEFFFFFF boundary as special, and will give different error codes on either side of it. Locks on both sides are allowed, the only difference is which error code is given when a lock is denied. Anyone like to hazard a guess as to why? It has me stumped. (This used to be commit 4395c0557ab175d6a8dd99df03c266325949ffa5) --- source4/ntvfs/posix/pvfs_open.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 51526461e0..5798aa782f 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -96,9 +96,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, flags = O_CREAT | O_TRUNC; break; case NTCREATEX_DISP_OPEN: - case NTCREATEX_DISP_OVERWRITE: flags = 0; break; + case NTCREATEX_DISP_OVERWRITE: + flags = O_TRUNC; + break; case NTCREATEX_DISP_CREATE: flags = O_CREAT | O_EXCL; break; @@ -222,7 +224,7 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, if (!NT_STATUS_IS_OK(status)) { return status; } - + if (close(f->fd) != 0) { status = pvfs_map_errno(pvfs, errno); } else { -- cgit From 43a80e1d83dad9450014b2a7e0ad5a5e495f69ce Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 18 Oct 2004 09:16:55 +0000 Subject: r3031: added support for lock cancelation, which effectively just triggers an early lock timeout added support for more of the bizarre special lock offset semantics of w2k3 (This used to be commit d5bfc910b1200fb283e26572dc57fcf93652fd32) --- source4/ntvfs/posix/pvfs_open.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 5798aa782f..05c2bdda28 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -171,6 +171,7 @@ do_open: f->session = req->session; f->smbpid = req->smbpid; f->pvfs = pvfs; + f->pending_list = NULL; /* we must zero here to take account of padding */ ZERO_STRUCT(lock_context); -- cgit From 384f87bd38c1133c90e2a57775f139532574e3cc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 18 Oct 2004 11:47:13 +0000 Subject: r3034: - fixed a bug in message dispatch, when the dispatch function called messaging_deregister() - added a pvfs_lock_close_pending() hook to remove pending locks on file close - fixed the private ptr argument to messaging_deregister() in pvfs_wait - fixed a bug in continuing lock requests after a lock that is blocking a pending lock is removed - removed bogus brl_unlock() call in lock continue - corrected error code for LOCKING_ANDX_CHANGE_LOCKTYPE - expanded the lock cancel test suite to test lock cancel by unlock and by close - added a testsuite for LOCKING_ANDX_CHANGE_LOCKTYPE (This used to be commit 5ef80f034d4aa4dd6810532c63ad041bfc019cb8) --- source4/ntvfs/posix/pvfs_open.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 05c2bdda28..429f519bca 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -52,6 +52,8 @@ static int pvfs_fd_destructor(void *p) { struct pvfs_file *f = p; + pvfs_lock_close_pending(f->pvfs, f); + brl_close(f->pvfs->brl_context, &f->locking_key, f->fnum); if (f->fd != -1) { @@ -221,6 +223,8 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_HANDLE; } + pvfs_lock_close_pending(pvfs, f); + status = brl_close(pvfs->brl_context, &f->locking_key, f->fnum); if (!NT_STATUS_IS_OK(status)) { return status; -- cgit From cf1b85348a0fc5bf4788291109c9dca9e95eb9c2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Oct 2004 06:39:51 +0000 Subject: r3056: added a id -> pointer data structure (a type of radix tree). This is an extremely efficient way of mapping from an integer handle (such as an open file handle) to a pointer (such as the structure containing the open file information). The code is taken from lib/idr.c in the 2.6 Linux kernel, and is very fast and space efficient. By using talloc it even has auto cleanup. This commit converts the handling of open file handles and open directory search handles to use the idtree routines. In combination with talloc destructors, this simplifies the structure handling in the pvfs backend a lot. For example, we no longer need to keep a linked list of open directory searches at all, and we no longer need to do linear scans of the list of open files on most operations. The end result is that the pvfs code is now extremely scalable. You can have 10s of thousands of open files and open searches and the code still runs very fast. I have also added a small optimisation into the file close path, to avoid looking in the byte range locking database if we know that there are no locks outstanding. (This used to be commit 16835a0ef91a16fa01145b773aad8d43da215dbf) --- source4/ntvfs/posix/pvfs_open.c | 63 +++++++++++++++++++++-------------------- 1 file changed, 33 insertions(+), 30 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 429f519bca..c255558369 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -31,16 +31,19 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, struct smbsrv_request *req, uint16_t fnum) { struct pvfs_file *f; - for (f=pvfs->open_files;f;f=f->next) { - if (f->fnum == fnum) { - if (req->session != f->session) { - DEBUG(2,("pvfs_find_fd: attempt to use wrong session for fnum %d\n", fnum)); - return NULL; - } - return f; - } + + f = idr_find(pvfs->idtree_fnum, fnum); + if (f == NULL) { + return NULL; } - return NULL; + + if (req->session != f->session) { + DEBUG(2,("pvfs_find_fd: attempt to use wrong session for fnum %d\n", + fnum)); + return NULL; + } + + return f; } /* @@ -52,14 +55,15 @@ static int pvfs_fd_destructor(void *p) { struct pvfs_file *f = p; - pvfs_lock_close_pending(f->pvfs, f); - - brl_close(f->pvfs->brl_context, &f->locking_key, f->fnum); + pvfs_lock_close(f->pvfs, f); if (f->fd != -1) { close(f->fd); f->fd = -1; } + + idr_remove(f->pvfs->idtree_fnum, f->fnum); + return 0; } @@ -80,6 +84,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, dev_t device; ino_t inode; } lock_context; + int fnum; if (io->generic.level != RAW_OPEN_GENERIC) { return ntvfs_map_open(req, io, ntvfs); @@ -147,6 +152,17 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } } + f = talloc_p(pvfs, struct pvfs_file); + if (f == NULL) { + return NT_STATUS_NO_MEMORY; + } + + fnum = idr_get_new(pvfs->idtree_fnum, f, 0x10000); + if (fnum == -1) { + talloc_free(f); + return NT_STATUS_TOO_MANY_OPENED_FILES; + } + do_open: fd = open(name->full_name, flags, 0644); if (fd == -1) { @@ -155,25 +171,20 @@ do_open: return pvfs_map_errno(pvfs,errno); } - f = talloc_p(pvfs, struct pvfs_file); - if (f == NULL) { - close(fd); - return NT_STATUS_NO_MEMORY; - } - /* re-resolve the open fd */ status = pvfs_resolve_name_fd(pvfs, fd, name); if (!NT_STATUS_IS_OK(status)) { return status; } - f->fnum = fd; + f->fnum = fnum; f->fd = fd; f->name = talloc_steal(f, name); f->session = req->session; f->smbpid = req->smbpid; f->pvfs = pvfs; f->pending_list = NULL; + f->lock_count = 0; /* we must zero here to take account of padding */ ZERO_STRUCT(lock_context); @@ -223,22 +234,16 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_HANDLE; } - pvfs_lock_close_pending(pvfs, f); - - status = brl_close(pvfs->brl_context, &f->locking_key, f->fnum); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - if (close(f->fd) != 0) { status = pvfs_map_errno(pvfs, errno); } else { status = NT_STATUS_OK; } - - talloc_set_destructor(f, NULL); + f->fd = -1; DLIST_REMOVE(pvfs->open_files, f); + + /* the destructor takes care of the rest */ talloc_free(f); return status; @@ -257,7 +262,6 @@ NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs, for (f=pvfs->open_files;f;f=next) { next = f->next; if (f->session == req->session) { - talloc_set_destructor(f, NULL); DLIST_REMOVE(pvfs->open_files, f); talloc_free(f); } @@ -279,7 +283,6 @@ NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs, for (f=pvfs->open_files;f;f=next) { next = f->next; if (f->smbpid == req->smbpid) { - talloc_set_destructor(f, NULL); DLIST_REMOVE(pvfs->open_files, f); talloc_free(f); } -- cgit From 72093ce62f1e09db86452720fe8280ad66824cde Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 19 Oct 2004 12:06:01 +0000 Subject: r3064: - use UINT8_MAX and UINT16_MAX instead of hex values for idr_get_new() limits - change idr_get_new() to use > instead of >= in the limit check (This used to be commit 834b09929bcb8aabdd151b7c2306001497cabdb4) --- source4/ntvfs/posix/pvfs_open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index c255558369..fb81c86bcc 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -157,7 +157,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_NO_MEMORY; } - fnum = idr_get_new(pvfs->idtree_fnum, f, 0x10000); + fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); if (fnum == -1) { talloc_free(f); return NT_STATUS_TOO_MANY_OPENED_FILES; -- cgit From 20d17b80571f0d0265c99c1ccdc21910c2eed043 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 20 Oct 2004 08:28:31 +0000 Subject: r3081: several updates to ntvfs and server side async request handling in preparation for the full share modes and ntcreatex code that I am working on. highlights include: - changed the way a backend determines if it is allowed to process a request asynchronously. The previous method of looking at the send_fn caused problems when an intermediate ntvfs module disabled it, and the caller then wanted to finished processing using this function. The new method is a REQ_CONTROL_MAY_ASYNC flag in req->control_flags, which is also a bit easier to read - fixed 2 bugs in the readbraw server code. One related to trying to answer a readbraw with smb signing (which can't work, and crashed our signing code), the second related to error handling, which attempted to send a normal SMB error packet, when readbraw must send a 0 read reply (as it has no header) - added several more ntvfs_generic.c generic mapping functions. This means that backends no longer need to implement such esoteric functions as SMBwriteunlock() if they don't want to. The backend can just request the mapping layer turn it into a write followed by an unlock. This makes the backends considerably simpler as they only need to implement one style of each function for lock, read, write, open etc, rather than the full host of functions that SMB provides. A backend can still choose to implement them individually, of course, and the CIFS backend does that. - simplified the generic structures to make them identical to the principal call for several common SMB calls (such as RAW_WRITE_GENERIC now being an alias for RAW_WRITE_WRITEX). - started rewriting the pvfs_open() code in preparation for the full ntcreatex semantics. - in pvfs_open and ipc_open, initially allocate the open file structure as a child of the request, so on error we don't need to clean up. Then when we are going to succeed the open steal the pointer into the long term backend context. This makes for much simpler error handling (and fixes some bugs) - use a destructor in the ipc backend to make sure that everthing is cleaned up on receive error conditions. - switched the ipc backend to using idtree for fnum allocation - in the ntvfs_generic mapping routines, use a allocated secondary structure not a stack structure to ensure the request pointer remains valid even if the backend replies async. (This used to be commit 3457c1836c09c82956697eb21627dfa2ed37682e) --- source4/ntvfs/posix/pvfs_open.c | 201 +++++++++++++++++++++++++++++++--------- 1 file changed, 157 insertions(+), 44 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index fb81c86bcc..eb5b94e753 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -46,6 +46,120 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, return f; } + +/* + cleanup a open directory handle +*/ +static int pvfs_dir_fd_destructor(void *p) +{ + struct pvfs_file *f = p; + DLIST_REMOVE(f->pvfs->open_files, f); + idr_remove(f->pvfs->idtree_fnum, f->fnum); + return 0; +} + + +/* + open a directory +*/ +static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, + struct smbsrv_request *req, + struct pvfs_filename *name, + union smb_open *io) +{ + struct pvfs_file *f; + int fnum; + NTSTATUS status; + + /* if the client says it must be a directory, and it isn't, + then fail */ + if (name->exists && !(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) { + return NT_STATUS_NOT_A_DIRECTORY; + } + + f = talloc_p(req, struct pvfs_file); + if (f == NULL) { + return NT_STATUS_NO_MEMORY; + } + + fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); + if (fnum == -1) { + talloc_free(f); + return NT_STATUS_TOO_MANY_OPENED_FILES; + } + + f->fnum = fnum; + f->fd = -1; + f->name = talloc_steal(f, name); + f->session = req->session; + f->smbpid = req->smbpid; + f->pvfs = pvfs; + f->pending_list = NULL; + f->lock_count = 0; + f->locking_key = data_blob(NULL, 0); + + /* setup a destructor to avoid leaks on abnormal termination */ + talloc_set_destructor(f, pvfs_dir_fd_destructor); + + switch (io->generic.in.open_disposition) { + case NTCREATEX_DISP_OPEN_IF: + break; + + case NTCREATEX_DISP_OPEN: + if (!name->exists) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + break; + + case NTCREATEX_DISP_CREATE: + if (name->exists) { + return NT_STATUS_OBJECT_NAME_COLLISION; + } + break; + + case NTCREATEX_DISP_OVERWRITE_IF: + case NTCREATEX_DISP_OVERWRITE: + case NTCREATEX_DISP_SUPERSEDE: + default: + return NT_STATUS_INVALID_PARAMETER; + } + + if (!name->exists) { + if (mkdir(name->full_name, 0755) == -1) { + return pvfs_map_errno(pvfs,errno); + } + status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, + PVFS_RESOLVE_NO_WILDCARD, &name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + if (!name->exists) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + + DLIST_ADD(pvfs->open_files, f); + + /* the open succeeded, keep this handle permanently */ + talloc_steal(pvfs, f); + + ZERO_STRUCT(io->generic.out); + + io->generic.out.create_time = name->dos.create_time; + io->generic.out.access_time = name->dos.access_time; + io->generic.out.write_time = name->dos.write_time; + io->generic.out.change_time = name->dos.change_time; + io->generic.out.fnum = f->fnum; + io->generic.out.alloc_size = 0; + io->generic.out.size = 0; + io->generic.out.attrib = name->dos.attrib; + io->generic.out.is_directory = 1; + + return NT_STATUS_OK; +} + + /* by using a destructor we make sure that abnormal cleanup will not leak file descriptors (assuming at least the top level pointer is freed, which @@ -55,6 +169,8 @@ static int pvfs_fd_destructor(void *p) { struct pvfs_file *f = p; + DLIST_REMOVE(f->pvfs->open_files, f); + pvfs_lock_close(f->pvfs, f); if (f->fd != -1) { @@ -97,83 +213,79 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } + /* directory opens are handled separately */ + if ((name->exists && (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) || + (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)) { + return pvfs_open_directory(pvfs, req, name, io); + } + + switch (io->generic.in.open_disposition) { case NTCREATEX_DISP_SUPERSEDE: + if (!name->exists) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + flags = O_TRUNC; + break; + case NTCREATEX_DISP_OVERWRITE_IF: flags = O_CREAT | O_TRUNC; break; + case NTCREATEX_DISP_OPEN: + if (!name->exists) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } flags = 0; break; + case NTCREATEX_DISP_OVERWRITE: + if (!name->exists) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } flags = O_TRUNC; break; + case NTCREATEX_DISP_CREATE: + if (name->exists) { + return NT_STATUS_OBJECT_NAME_COLLISION; + } flags = O_CREAT | O_EXCL; break; + case NTCREATEX_DISP_OPEN_IF: flags = O_CREAT; break; - default: - flags = 0; - break; - } - - flags |= O_RDWR; - -/* we need to do this differently to support systems without O_DIRECTORY */ -#ifndef O_DIRECTORY -#define O_DIRECTORY 0 -#endif - if (name->exists && - (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) && - !(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) { - return NT_STATUS_NOT_A_DIRECTORY; + default: + return NT_STATUS_INVALID_PARAMETER; } - if ((name->exists && name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) || - (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)) { - flags = O_RDONLY | O_DIRECTORY; - if (pvfs->flags & PVFS_FLAG_READONLY) { - goto do_open; - } - switch (io->generic.in.open_disposition) { - case NTCREATEX_DISP_CREATE: - if (mkdir(name->full_name, 0755) == -1) { - return pvfs_map_errno(pvfs,errno); - } - break; - case NTCREATEX_DISP_OPEN_IF: - if (mkdir(name->full_name, 0755) == -1 && errno != EEXIST) { - return pvfs_map_errno(pvfs,errno); - } - break; - } - } + flags |= O_RDWR; - f = talloc_p(pvfs, struct pvfs_file); + f = talloc_p(req, struct pvfs_file); if (f == NULL) { return NT_STATUS_NO_MEMORY; } fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); if (fnum == -1) { - talloc_free(f); return NT_STATUS_TOO_MANY_OPENED_FILES; } -do_open: fd = open(name->full_name, flags, 0644); if (fd == -1) { - if (errno == 0) + if (errno == 0) { errno = ENOENT; - return pvfs_map_errno(pvfs,errno); + } + idr_remove(pvfs->idtree_fnum, fnum); + return pvfs_map_errno(pvfs, errno); } /* re-resolve the open fd */ status = pvfs_resolve_name_fd(pvfs, fd, name); if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); return status; } @@ -210,6 +322,9 @@ do_open: io->generic.out.attrib = name->dos.attrib; io->generic.out.is_directory = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)?1:0; + /* success - keep the file handle */ + talloc_steal(pvfs, f); + return NT_STATUS_OK; } @@ -225,8 +340,7 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, NTSTATUS status; if (io->generic.level != RAW_CLOSE_CLOSE) { - /* we need a mapping function */ - return NT_STATUS_INVALID_LEVEL; + return ntvfs_map_close(req, io, ntvfs); } f = pvfs_find_fd(pvfs, req, io->close.in.fnum); @@ -234,15 +348,14 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_HANDLE; } - if (close(f->fd) != 0) { + if (f->fd != -1 && + close(f->fd) != 0) { status = pvfs_map_errno(pvfs, errno); } else { status = NT_STATUS_OK; } f->fd = -1; - DLIST_REMOVE(pvfs->open_files, f); - /* the destructor takes care of the rest */ talloc_free(f); -- cgit From 020b38656016d3adeeaa9b09d41ea0c29f686ed4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 22 Oct 2004 07:01:32 +0000 Subject: r3135: split the "create new" logic out from the "open existing" logic in pvfs_open, and handle the various race conditions that are inherent in cifs on unix, so we do the best we can when the race happens. the ntcreatex code is really starting to take shape now (This used to be commit 395c3815b468ae55de9a1135e478711f0e7d8cfc) --- source4/ntvfs/posix/pvfs_open.c | 213 +++++++++++++++++++++++++++++++++++----- 1 file changed, 186 insertions(+), 27 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index eb5b94e753..a16fbbe891 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -183,10 +183,133 @@ static int pvfs_fd_destructor(void *p) return 0; } + +/* + form the lock context used for byte range locking and opendb + locking. Note that we must zero here to take account of + possible padding on some architectures +*/ +static NTSTATUS pvfs_locking_key(struct pvfs_filename *name, + TALLOC_CTX *mem_ctx, DATA_BLOB *key) +{ + struct { + dev_t device; + ino_t inode; + } lock_context; + ZERO_STRUCT(lock_context); + + lock_context.device = name->st.st_dev; + lock_context.inode = name->st.st_ino; + + *key = data_blob_talloc(mem_ctx, &lock_context, sizeof(lock_context)); + if (key->data == NULL) { + return NT_STATUS_NO_MEMORY; + } + + return NT_STATUS_OK; +} + + +/* + create a new file +*/ +static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, + struct smbsrv_request *req, + struct pvfs_filename *name, + union smb_open *io) +{ + struct pvfs_file *f; + NTSTATUS status; + int flags, fnum, fd; + struct odb_lock *lck; + + flags = O_RDWR; + + f = talloc_p(req, struct pvfs_file); + if (f == NULL) { + return NT_STATUS_NO_MEMORY; + } + + fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); + if (fnum == -1) { + return NT_STATUS_TOO_MANY_OPENED_FILES; + } + + /* create the file */ + fd = open(name->full_name, flags | O_CREAT | O_EXCL, 0644); + if (fd == -1) { + idr_remove(pvfs->idtree_fnum, fnum); + return pvfs_map_errno(pvfs, errno); + } + + /* re-resolve the open fd */ + status = pvfs_resolve_name_fd(pvfs, fd, name); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); + return status; + } + + /* form the lock context used for byte range locking and + opendb locking */ + status = pvfs_locking_key(name, f, &f->locking_key); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); + return status; + } + + /* grab a lock on the open file record */ + lck = odb_lock(req, pvfs->odb_context, &f->locking_key); + if (lck == NULL) { + DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n", + name->full_name)); + /* we were supposed to do a blocking lock, so something + is badly wrong! */ + idr_remove(pvfs->idtree_fnum, fnum); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + f->fnum = fnum; + f->fd = fd; + f->name = talloc_steal(f, name); + f->session = req->session; + f->smbpid = req->smbpid; + f->pvfs = pvfs; + f->pending_list = NULL; + f->lock_count = 0; + + DLIST_ADD(pvfs->open_files, f); + + /* setup a destructor to avoid file descriptor leaks on + abnormal termination */ + talloc_set_destructor(f, pvfs_fd_destructor); + + ZERO_STRUCT(io->generic.out); + + io->generic.out.create_time = name->dos.create_time; + io->generic.out.access_time = name->dos.access_time; + io->generic.out.write_time = name->dos.write_time; + io->generic.out.change_time = name->dos.change_time; + io->generic.out.fnum = f->fnum; + io->generic.out.alloc_size = name->dos.alloc_size; + io->generic.out.size = name->st.st_size; + io->generic.out.attrib = name->dos.attrib; + io->generic.out.create_action = NTCREATEX_ACTION_CREATED; + io->generic.out.is_directory = 0; + io->generic.out.file_type = FILE_TYPE_DISK; + + /* success - keep the file handle */ + talloc_steal(pvfs, f); + + /* release the opendb lock (in case a chained request + blocks) */ + talloc_free(lck); + + return NT_STATUS_OK; +} + + /* open a file - TODO: this is a temporary implementation derived from the simple backend - its purpose is to allow other tests to run */ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, struct smbsrv_request *req, union smb_open *io) @@ -196,12 +319,14 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, struct pvfs_filename *name; struct pvfs_file *f; NTSTATUS status; - struct { - dev_t device; - ino_t inode; - } lock_context; int fnum; + struct odb_lock *lck; + /* use the generic mapping code to avoid implementing all the + different open calls. This won't allow openx to work + perfectly as the mapping code has no way of knowing if two + opens are on the same connection, so this will need to + change eventually */ if (io->generic.level != RAW_OPEN_GENERIC) { return ntvfs_map_open(req, io, ntvfs); } @@ -229,7 +354,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, break; case NTCREATEX_DISP_OVERWRITE_IF: - flags = O_CREAT | O_TRUNC; + flags = O_TRUNC; break; case NTCREATEX_DISP_OPEN: @@ -250,11 +375,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, if (name->exists) { return NT_STATUS_OBJECT_NAME_COLLISION; } - flags = O_CREAT | O_EXCL; + flags = 0; break; case NTCREATEX_DISP_OPEN_IF: - flags = O_CREAT; + flags = 0; break; default: @@ -263,32 +388,67 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, flags |= O_RDWR; + /* handle creating a new file separately */ + if (!name->exists) { + status = pvfs_create_file(pvfs, req, name, io); + if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + return status; + } + + /* we've hit a race - the file was created during this call */ + if (io->generic.in.open_disposition == NTCREATEX_DISP_CREATE) { + return status; + } + + /* try re-resolving the name */ + status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, + PVFS_RESOLVE_NO_WILDCARD, &name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /* fall through to a normal open */ + } + f = talloc_p(req, struct pvfs_file); if (f == NULL) { return NT_STATUS_NO_MEMORY; } - fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; + /* form the lock context used for byte range locking and + opendb locking */ + status = pvfs_locking_key(name, f, &f->locking_key); + if (!NT_STATUS_IS_OK(status)) { + return status; } - fd = open(name->full_name, flags, 0644); + /* get a lock on this file before the actual open */ + lck = odb_lock(req, pvfs->odb_context, &f->locking_key); + if (lck == NULL) { + DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n", + name->full_name)); + /* we were supposed to do a blocking lock, so something + is badly wrong! */ + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + /* do the actual open */ + fd = open(name->full_name, flags); if (fd == -1) { - if (errno == 0) { - errno = ENOENT; - } - idr_remove(pvfs->idtree_fnum, fnum); return pvfs_map_errno(pvfs, errno); } /* re-resolve the open fd */ status = pvfs_resolve_name_fd(pvfs, fd, name); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, fnum); return status; } + /* allocate a fnum */ + fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); + if (fnum == -1) { + return NT_STATUS_TOO_MANY_OPENED_FILES; + } + f->fnum = fnum; f->fd = fd; f->name = talloc_steal(f, name); @@ -298,18 +458,12 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->pending_list = NULL; f->lock_count = 0; - /* we must zero here to take account of padding */ - ZERO_STRUCT(lock_context); - lock_context.device = name->st.st_dev; - lock_context.inode = name->st.st_ino; - f->locking_key = data_blob_talloc(f, &lock_context, sizeof(lock_context)); + DLIST_ADD(pvfs->open_files, f); /* setup a destructor to avoid file descriptor leaks on abnormal termination */ talloc_set_destructor(f, pvfs_fd_destructor); - DLIST_ADD(pvfs->open_files, f); - ZERO_STRUCT(io->generic.out); io->generic.out.create_time = name->dos.create_time; @@ -320,11 +474,16 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, io->generic.out.alloc_size = name->dos.alloc_size; io->generic.out.size = name->st.st_size; io->generic.out.attrib = name->dos.attrib; - io->generic.out.is_directory = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)?1:0; + io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; + io->generic.out.is_directory = 0; + io->generic.out.file_type = FILE_TYPE_DISK; /* success - keep the file handle */ talloc_steal(pvfs, f); + /* unlock the locking database */ + talloc_free(lck); + return NT_STATUS_OK; } @@ -349,7 +508,7 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, } if (f->fd != -1 && - close(f->fd) != 0) { + close(f->fd) == -1) { status = pvfs_map_errno(pvfs, errno); } else { status = NT_STATUS_OK; -- cgit From c785ca65040d985599bba6736af55240eae894aa Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 23 Oct 2004 06:22:57 +0000 Subject: r3142: fill in all the ntcreatex response fields explicitly, rather than zeroing. This makes it clearer what bits are not yet implemented (and is more valgrind friendly) (This used to be commit 18b471327b596f3ea8f6a7b39ba0a83b2584ed0b) --- source4/ntvfs/posix/pvfs_open.c | 76 ++++++++++++++++++++++------------------- 1 file changed, 41 insertions(+), 35 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index a16fbbe891..482f71b9a3 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -70,6 +70,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, struct pvfs_file *f; int fnum; NTSTATUS status; + uint32_t create_action; /* if the client says it must be a directory, and it isn't, then fail */ @@ -133,6 +134,9 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, if (!NT_STATUS_IS_OK(status)) { return status; } + create_action = NTCREATEX_ACTION_CREATED; + } else { + create_action = NTCREATEX_ACTION_EXISTED; } if (!name->exists) { @@ -144,17 +148,19 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* the open succeeded, keep this handle permanently */ talloc_steal(pvfs, f); - ZERO_STRUCT(io->generic.out); - - io->generic.out.create_time = name->dos.create_time; - io->generic.out.access_time = name->dos.access_time; - io->generic.out.write_time = name->dos.write_time; - io->generic.out.change_time = name->dos.change_time; - io->generic.out.fnum = f->fnum; - io->generic.out.alloc_size = 0; - io->generic.out.size = 0; - io->generic.out.attrib = name->dos.attrib; - io->generic.out.is_directory = 1; + io->generic.out.oplock_level = NO_OPLOCK; + io->generic.out.fnum = f->fnum; + io->generic.out.create_action = create_action; + io->generic.out.create_time = name->dos.create_time; + io->generic.out.access_time = name->dos.access_time; + io->generic.out.write_time = name->dos.write_time; + io->generic.out.change_time = name->dos.change_time; + io->generic.out.attrib = name->dos.attrib; + io->generic.out.alloc_size = 0; + io->generic.out.size = 0; + io->generic.out.file_type = FILE_TYPE_DISK; + io->generic.out.ipc_state = 0; + io->generic.out.is_directory = 1; return NT_STATUS_OK; } @@ -283,19 +289,19 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, abnormal termination */ talloc_set_destructor(f, pvfs_fd_destructor); - ZERO_STRUCT(io->generic.out); - - io->generic.out.create_time = name->dos.create_time; - io->generic.out.access_time = name->dos.access_time; - io->generic.out.write_time = name->dos.write_time; - io->generic.out.change_time = name->dos.change_time; - io->generic.out.fnum = f->fnum; - io->generic.out.alloc_size = name->dos.alloc_size; - io->generic.out.size = name->st.st_size; - io->generic.out.attrib = name->dos.attrib; + io->generic.out.oplock_level = NO_OPLOCK; + io->generic.out.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_CREATED; - io->generic.out.is_directory = 0; - io->generic.out.file_type = FILE_TYPE_DISK; + io->generic.out.create_time = name->dos.create_time; + io->generic.out.access_time = name->dos.access_time; + io->generic.out.write_time = name->dos.write_time; + io->generic.out.change_time = name->dos.change_time; + io->generic.out.attrib = name->dos.attrib; + io->generic.out.alloc_size = name->dos.alloc_size; + io->generic.out.size = name->st.st_size; + io->generic.out.file_type = FILE_TYPE_DISK; + io->generic.out.ipc_state = 0; + io->generic.out.is_directory = 0; /* success - keep the file handle */ talloc_steal(pvfs, f); @@ -464,19 +470,19 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, abnormal termination */ talloc_set_destructor(f, pvfs_fd_destructor); - ZERO_STRUCT(io->generic.out); - - io->generic.out.create_time = name->dos.create_time; - io->generic.out.access_time = name->dos.access_time; - io->generic.out.write_time = name->dos.write_time; - io->generic.out.change_time = name->dos.change_time; - io->generic.out.fnum = f->fnum; - io->generic.out.alloc_size = name->dos.alloc_size; - io->generic.out.size = name->st.st_size; - io->generic.out.attrib = name->dos.attrib; + io->generic.out.oplock_level = NO_OPLOCK; + io->generic.out.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; - io->generic.out.is_directory = 0; - io->generic.out.file_type = FILE_TYPE_DISK; + io->generic.out.create_time = name->dos.create_time; + io->generic.out.access_time = name->dos.access_time; + io->generic.out.write_time = name->dos.write_time; + io->generic.out.change_time = name->dos.change_time; + io->generic.out.attrib = name->dos.attrib; + io->generic.out.alloc_size = name->dos.alloc_size; + io->generic.out.size = name->st.st_size; + io->generic.out.file_type = FILE_TYPE_DISK; + io->generic.out.ipc_state = 0; + io->generic.out.is_directory = 0; /* success - keep the file handle */ talloc_steal(pvfs, f); -- cgit From 3d5f3e39e5786612a2aa24ec98264c52907e67f2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 24 Oct 2004 08:31:41 +0000 Subject: r3147: added basic share modes support for pvfs (or more precisely, ntcreatex share_access support). This is enough for us to pass the BASE-DENY2 test, but is a long way from fully correct share modes. (This used to be commit b5a6dd3cbf28a3a3b3a3656042ac8f50fca29e1c) --- source4/ntvfs/posix/pvfs_open.c | 131 ++++++++++++++++++++++++++++------------ 1 file changed, 91 insertions(+), 40 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 482f71b9a3..90de303a9d 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -78,30 +78,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_NOT_A_DIRECTORY; } - f = talloc_p(req, struct pvfs_file); - if (f == NULL) { - return NT_STATUS_NO_MEMORY; - } - - fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); - if (fnum == -1) { - talloc_free(f); - return NT_STATUS_TOO_MANY_OPENED_FILES; - } - - f->fnum = fnum; - f->fd = -1; - f->name = talloc_steal(f, name); - f->session = req->session; - f->smbpid = req->smbpid; - f->pvfs = pvfs; - f->pending_list = NULL; - f->lock_count = 0; - f->locking_key = data_blob(NULL, 0); - - /* setup a destructor to avoid leaks on abnormal termination */ - talloc_set_destructor(f, pvfs_dir_fd_destructor); - switch (io->generic.in.open_disposition) { case NTCREATEX_DISP_OPEN_IF: break; @@ -125,6 +101,38 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_INVALID_PARAMETER; } + f = talloc_p(req, struct pvfs_file); + if (f == NULL) { + return NT_STATUS_NO_MEMORY; + } + + f->fnum = fnum; + f->fd = -1; + f->name = talloc_steal(f, name); + f->session = req->session; + f->smbpid = req->smbpid; + f->pvfs = pvfs; + f->pending_list = NULL; + f->lock_count = 0; + f->locking_key = data_blob(NULL, 0); + f->create_options = io->generic.in.create_options; + f->share_access = io->generic.in.share_access; + + fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); + if (fnum == -1) { + talloc_free(f); + return NT_STATUS_TOO_MANY_OPENED_FILES; + } + + DLIST_ADD(pvfs->open_files, f); + + /* TODO: should we check in the opendb? Do directory opens + follow the share_access rules? */ + + + /* setup a destructor to avoid leaks on abnormal termination */ + talloc_set_destructor(f, pvfs_dir_fd_destructor); + if (!name->exists) { if (mkdir(name->full_name, 0755) == -1) { return pvfs_map_errno(pvfs,errno); @@ -143,8 +151,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - DLIST_ADD(pvfs->open_files, f); - /* the open succeeded, keep this handle permanently */ talloc_steal(pvfs, f); @@ -174,6 +180,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, static int pvfs_fd_destructor(void *p) { struct pvfs_file *f = p; + struct odb_lock *lck; + NTSTATUS status; DLIST_REMOVE(f->pvfs->open_files, f); @@ -186,6 +194,18 @@ static int pvfs_fd_destructor(void *p) idr_remove(f->pvfs->idtree_fnum, f->fnum); + lck = odb_lock(f, f->pvfs->odb_context, &f->locking_key); + if (lck == NULL) { + DEBUG(0,("Unabled to lock opendb for close\n")); + return 0; + } + + status = odb_close_file(lck, f->fnum); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unabled to remove opendb entry for '%s' - %s\n", + f->name->full_name, nt_errstr(status))); + } + return 0; } @@ -228,7 +248,10 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, NTSTATUS status; int flags, fnum, fd; struct odb_lock *lck; - + uint32_t create_options = io->generic.in.create_options; + uint32_t share_access = io->generic.in.share_access; + uint32_t access_mask = io->generic.in.access_mask; + flags = O_RDWR; f = talloc_p(req, struct pvfs_file); @@ -252,6 +275,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, status = pvfs_resolve_name_fd(pvfs, fd, name); if (!NT_STATUS_IS_OK(status)) { idr_remove(pvfs->idtree_fnum, fnum); + close(fd); return status; } @@ -260,6 +284,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, status = pvfs_locking_key(name, f, &f->locking_key); if (!NT_STATUS_IS_OK(status)) { idr_remove(pvfs->idtree_fnum, fnum); + close(fd); return status; } @@ -271,9 +296,18 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* we were supposed to do a blocking lock, so something is badly wrong! */ idr_remove(pvfs->idtree_fnum, fnum); + close(fd); return NT_STATUS_INTERNAL_DB_CORRUPTION; } + status = odb_open_file(lck, fnum, share_access, create_options, access_mask); + if (!NT_STATUS_IS_OK(status)) { + /* bad news, we must have hit a race */ + idr_remove(pvfs->idtree_fnum, fnum); + close(fd); + return status; + } + f->fnum = fnum; f->fd = fd; f->name = talloc_steal(f, name); @@ -282,6 +316,9 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->pvfs = pvfs; f->pending_list = NULL; f->lock_count = 0; + f->create_options = io->generic.in.create_options; + f->share_access = io->generic.in.share_access; + f->access_mask = io->generic.in.access_mask; DLIST_ADD(pvfs->open_files, f); @@ -306,10 +343,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* success - keep the file handle */ talloc_steal(pvfs, f); - /* release the opendb lock (in case a chained request - blocks) */ - talloc_free(lck); - return NT_STATUS_OK; } @@ -327,6 +360,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, NTSTATUS status; int fnum; struct odb_lock *lck; + uint32_t create_options; + uint32_t share_access; + uint32_t access_mask; /* use the generic mapping code to avoid implementing all the different open calls. This won't allow openx to work @@ -420,10 +456,17 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_NO_MEMORY; } + /* allocate a fnum */ + fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); + if (fnum == -1) { + return NT_STATUS_TOO_MANY_OPENED_FILES; + } + /* form the lock context used for byte range locking and opendb locking */ status = pvfs_locking_key(name, f, &f->locking_key); if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); return status; } @@ -434,9 +477,21 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, name->full_name)); /* we were supposed to do a blocking lock, so something is badly wrong! */ + idr_remove(pvfs->idtree_fnum, fnum); return NT_STATUS_INTERNAL_DB_CORRUPTION; } + create_options = io->generic.in.create_options; + share_access = io->generic.in.share_access; + access_mask = io->generic.in.access_mask; + + /* see if we are allowed to open at the same time as existing opens */ + status = odb_open_file(lck, fnum, share_access, create_options, access_mask); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); + return status; + } + /* do the actual open */ fd = open(name->full_name, flags); if (fd == -1) { @@ -446,15 +501,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* re-resolve the open fd */ status = pvfs_resolve_name_fd(pvfs, fd, name); if (!NT_STATUS_IS_OK(status)) { + close(fd); + idr_remove(pvfs->idtree_fnum, fnum); return status; } - /* allocate a fnum */ - fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; - } - f->fnum = fnum; f->fd = fd; f->name = talloc_steal(f, name); @@ -463,6 +514,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->pvfs = pvfs; f->pending_list = NULL; f->lock_count = 0; + f->create_options = io->generic.in.create_options; + f->share_access = io->generic.in.share_access; + f->access_mask = io->generic.in.access_mask; DLIST_ADD(pvfs->open_files, f); @@ -487,9 +541,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* success - keep the file handle */ talloc_steal(pvfs, f); - /* unlock the locking database */ - talloc_free(lck); - return NT_STATUS_OK; } -- cgit From d5817271384ff74b3d0577d675476c28ccc0074b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 24 Oct 2004 12:39:15 +0000 Subject: r3153: pvfs now passes the first 9 of the BASE-DELETE tests (This used to be commit f8041feaebc9170763ce04d2dd90cfc1c7889c21) --- source4/ntvfs/posix/pvfs_open.c | 102 +++++++++++++++++++++++++++++----------- 1 file changed, 75 insertions(+), 27 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 90de303a9d..7c1e164575 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -55,6 +55,14 @@ static int pvfs_dir_fd_destructor(void *p) struct pvfs_file *f = p; DLIST_REMOVE(f->pvfs->open_files, f); idr_remove(f->pvfs->idtree_fnum, f->fnum); + + if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { + if (rmdir(f->name->full_name) != 0) { + DEBUG(0,("pvfs_close: failed to rmdir '%s'\n", + f->name->full_name)); + } + } + return 0; } @@ -106,6 +114,12 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_NO_MEMORY; } + fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); + if (fnum == -1) { + talloc_free(f); + return NT_STATUS_TOO_MANY_OPENED_FILES; + } + f->fnum = fnum; f->fd = -1; f->name = talloc_steal(f, name); @@ -118,12 +132,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->create_options = io->generic.in.create_options; f->share_access = io->generic.in.share_access; - fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); - if (fnum == -1) { - talloc_free(f); - return NT_STATUS_TOO_MANY_OPENED_FILES; - } - DLIST_ADD(pvfs->open_files, f); /* TODO: should we check in the opendb? Do directory opens @@ -196,16 +204,23 @@ static int pvfs_fd_destructor(void *p) lck = odb_lock(f, f->pvfs->odb_context, &f->locking_key); if (lck == NULL) { - DEBUG(0,("Unabled to lock opendb for close\n")); + DEBUG(0,("Unable to lock opendb for close\n")); return 0; } status = odb_close_file(lck, f->fnum); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("Unabled to remove opendb entry for '%s' - %s\n", + DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n", f->name->full_name, nt_errstr(status))); } + if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { + if (unlink(f->name->full_name) != 0) { + DEBUG(0,("pvfs_close: failed to delete '%s'\n", + f->name->full_name)); + } + } + return 0; } @@ -386,6 +401,15 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return pvfs_open_directory(pvfs, req, name, io); } + create_options = io->generic.in.create_options; + share_access = io->generic.in.share_access; + access_mask = io->generic.in.access_mask; + + /* certain create options are not allowed */ + if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && + !(share_access & NTCREATEX_SHARE_ACCESS_DELETE)) { + return NT_STATUS_INVALID_PARAMETER; + } switch (io->generic.in.open_disposition) { case NTCREATEX_DISP_SUPERSEDE: @@ -481,10 +505,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - create_options = io->generic.in.create_options; - share_access = io->generic.in.share_access; - access_mask = io->generic.in.access_mask; - /* see if we are allowed to open at the same time as existing opens */ status = odb_open_file(lck, fnum, share_access, create_options, access_mask); if (!NT_STATUS_IS_OK(status)) { @@ -492,22 +512,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } - /* do the actual open */ - fd = open(name->full_name, flags); - if (fd == -1) { - return pvfs_map_errno(pvfs, errno); - } - - /* re-resolve the open fd */ - status = pvfs_resolve_name_fd(pvfs, fd, name); - if (!NT_STATUS_IS_OK(status)) { - close(fd); - idr_remove(pvfs->idtree_fnum, fnum); - return status; - } - f->fnum = fnum; - f->fd = fd; + f->fd = -1; f->name = talloc_steal(f, name); f->session = req->session; f->smbpid = req->smbpid; @@ -524,6 +530,20 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, abnormal termination */ talloc_set_destructor(f, pvfs_fd_destructor); + /* do the actual open */ + fd = open(name->full_name, flags); + if (fd == -1) { + return pvfs_map_errno(pvfs, errno); + } + + f->fd = fd; + + /* re-resolve the open fd */ + status = pvfs_resolve_name_fd(pvfs, fd, name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + io->generic.out.oplock_level = NO_OPLOCK; io->generic.out.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; @@ -619,3 +639,31 @@ NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs, return NT_STATUS_OK; } + + +/* + change the create options on an already open file +*/ +NTSTATUS pvfs_change_create_options(struct pvfs_state *pvfs, + struct smbsrv_request *req, + struct pvfs_file *f, uint32_t create_options) +{ + struct odb_lock *lck; + NTSTATUS status; + + if (f->create_options == create_options) { + return NT_STATUS_OK; + } + + lck = odb_lock(req, pvfs->odb_context, &f->locking_key); + if (lck == NULL) { + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + status = odb_set_create_options(lck, f->fnum, create_options); + if (NT_STATUS_IS_OK(status)) { + f->create_options = create_options; + } + + return status; +} -- cgit From 2a16fd5453a47bc456ae831c0eab58a102d96bd8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 24 Oct 2004 12:53:13 +0000 Subject: r3154: pvfs now passes all of BASE-DELETE (This used to be commit abbfca1401818edd896493ab9c875224e3b7e0e7) --- source4/ntvfs/posix/pvfs_open.c | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 7c1e164575..95990f6332 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -266,6 +266,12 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, uint32_t create_options = io->generic.in.create_options; uint32_t share_access = io->generic.in.share_access; uint32_t access_mask = io->generic.in.access_mask; + mode_t mode; + + if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) && + (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { + return NT_STATUS_CANNOT_DELETE; + } flags = O_RDWR; @@ -279,8 +285,14 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return NT_STATUS_TOO_MANY_OPENED_FILES; } + if (io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) { + mode = 0444; + } else { + mode = 0644; + } + /* create the file */ - fd = open(name->full_name, flags | O_CREAT | O_EXCL, 0644); + fd = open(name->full_name, flags | O_CREAT | O_EXCL, mode); if (fd == -1) { idr_remove(pvfs->idtree_fnum, fnum); return pvfs_map_errno(pvfs, errno); @@ -407,7 +419,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* certain create options are not allowed */ if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && - !(share_access & NTCREATEX_SHARE_ACCESS_DELETE)) { + !(access_mask & STD_RIGHT_DELETE_ACCESS)) { return NT_STATUS_INVALID_PARAMETER; } @@ -475,6 +487,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* fall through to a normal open */ } + if ((name->dos.attrib & FILE_ATTRIBUTE_READONLY) && + (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { + return NT_STATUS_CANNOT_DELETE; + } + f = talloc_p(req, struct pvfs_file); if (f == NULL) { return NT_STATUS_NO_MEMORY; @@ -655,6 +672,11 @@ NTSTATUS pvfs_change_create_options(struct pvfs_state *pvfs, return NT_STATUS_OK; } + if ((f->name->dos.attrib & FILE_ATTRIBUTE_READONLY) && + (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { + return NT_STATUS_CANNOT_DELETE; + } + lck = odb_lock(req, pvfs->odb_context, &f->locking_key); if (lck == NULL) { return NT_STATUS_INTERNAL_DB_CORRUPTION; -- cgit From 5ea5d5c2355eb0789131cd5d9ffffc5b004b02c8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 24 Oct 2004 13:40:49 +0000 Subject: r3159: use easy to recognise file handle numbers for new file, old file and directory in pvfs_open, to make analysing sniffs easy (This used to be commit 5c16ed02542f7e143d66f4ba8d166bb6882bf53a) --- source4/ntvfs/posix/pvfs_open.c | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 95990f6332..44a09fe25d 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -23,6 +23,12 @@ #include "include/includes.h" #include "vfs_posix.h" +/* + create file handles with convenient numbers for sniffers +*/ +#define PVFS_MIN_FILE_FNUM 0x100 +#define PVFS_MIN_NEW_FNUM 0x200 +#define PVFS_MIN_DIR_FNUM 0x1000 /* find open file handle given fnum @@ -114,7 +120,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_NO_MEMORY; } - fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); + fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_DIR_FNUM, UINT16_MAX); if (fnum == -1) { talloc_free(f); return NT_STATUS_TOO_MANY_OPENED_FILES; @@ -202,6 +208,13 @@ static int pvfs_fd_destructor(void *p) idr_remove(f->pvfs->idtree_fnum, f->fnum); + if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { + if (unlink(f->name->full_name) != 0) { + DEBUG(0,("pvfs_close: failed to delete '%s'\n", + f->name->full_name)); + } + } + lck = odb_lock(f, f->pvfs->odb_context, &f->locking_key); if (lck == NULL) { DEBUG(0,("Unable to lock opendb for close\n")); @@ -214,12 +227,7 @@ static int pvfs_fd_destructor(void *p) f->name->full_name, nt_errstr(status))); } - if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { - if (unlink(f->name->full_name) != 0) { - DEBUG(0,("pvfs_close: failed to delete '%s'\n", - f->name->full_name)); - } - } + talloc_free(lck); return 0; } @@ -280,7 +288,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return NT_STATUS_NO_MEMORY; } - fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); + fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_NEW_FNUM, UINT16_MAX); if (fnum == -1) { return NT_STATUS_TOO_MANY_OPENED_FILES; } @@ -498,7 +506,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } /* allocate a fnum */ - fnum = idr_get_new(pvfs->idtree_fnum, f, UINT16_MAX); + fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_FILE_FNUM, UINT16_MAX); if (fnum == -1) { return NT_STATUS_TOO_MANY_OPENED_FILES; } -- cgit From 62e58ea7180e265ffe79b998e7488f20909d3fa0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 24 Oct 2004 14:18:03 +0000 Subject: r3161: pvfs now passes the RAW-SEEK test (This used to be commit a953d4a42c8fa3fe930c319d5157fc406a1035da) --- source4/ntvfs/posix/pvfs_open.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 44a09fe25d..e587ebbf95 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -137,6 +137,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->locking_key = data_blob(NULL, 0); f->create_options = io->generic.in.create_options; f->share_access = io->generic.in.share_access; + f->seek_offset = 0; + f->position = 0; DLIST_ADD(pvfs->open_files, f); @@ -354,6 +356,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->create_options = io->generic.in.create_options; f->share_access = io->generic.in.share_access; f->access_mask = io->generic.in.access_mask; + f->seek_offset = 0; + f->position = 0; DLIST_ADD(pvfs->open_files, f); @@ -548,6 +552,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->create_options = io->generic.in.create_options; f->share_access = io->generic.in.share_access; f->access_mask = io->generic.in.access_mask; + f->seek_offset = 0; + f->position = 0; DLIST_ADD(pvfs->open_files, f); -- cgit From c1c696460b74fa3dd381f3903ec0281f6f1865a9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Oct 2004 01:29:31 +0000 Subject: r3174: added pvfs_is_open() to allow us to check for open files on unlink. We now pass BASE-UNLINK. (This used to be commit f23a2f8538bda8f6790e86c93ee22436388b2975) --- source4/ntvfs/posix/pvfs_open.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index e587ebbf95..7f06626706 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -703,3 +703,20 @@ NTSTATUS pvfs_change_create_options(struct pvfs_state *pvfs, return status; } + + +/* + determine if a file is open - used to prevent some operations on open files +*/ +BOOL pvfs_is_open(struct pvfs_state *pvfs, struct pvfs_filename *name) +{ + NTSTATUS status; + DATA_BLOB key; + + status = pvfs_locking_key(name, name, &key); + if (!NT_STATUS_IS_OK(status)) { + return False; + } + + return odb_is_open(pvfs->odb_context, &key); +} -- cgit From e90ab07050f2fe8dd1c4399e5deff7eddf66e6d0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Oct 2004 01:56:01 +0000 Subject: r3178: honor the write_time on pvfs_close() (This used to be commit 4e28c45bafa453eaa94716a5b77d830b81efe6cf) --- source4/ntvfs/posix/pvfs_open.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 7f06626706..ac2742d357 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -605,6 +605,7 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f; NTSTATUS status; + struct utimbuf unix_times; if (io->generic.level != RAW_CLOSE_CLOSE) { return ntvfs_map_close(req, io, ntvfs); @@ -615,6 +616,10 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_HANDLE; } + unix_times.actime = 0; + unix_times.modtime = io->close.in.write_time; + utime(f->name->full_name, &unix_times); + if (f->fd != -1 && close(f->fd) == -1) { status = pvfs_map_errno(pvfs, errno); -- cgit From 3cf018b517de0afa006ac14d5185e3c95d8a923b Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Oct 2004 02:36:12 +0000 Subject: r3180: - basic support for SEC_RIGHT_MAXIMUM_ALLOWED in pvfs - RAW-CONTEXT test now passes (This used to be commit 0dae9fef09ec8bce19c39a0caf36e0882e507bc4) --- source4/ntvfs/posix/pvfs_open.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index ac2742d357..badd18d370 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -283,6 +283,10 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return NT_STATUS_CANNOT_DELETE; } + if (access_mask & SEC_RIGHT_MAXIMUM_ALLOWED) { + access_mask = GENERIC_RIGHTS_FILE_READ | GENERIC_RIGHTS_FILE_WRITE; + } + flags = O_RDWR; f = talloc_p(req, struct pvfs_file); @@ -355,7 +359,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->lock_count = 0; f->create_options = io->generic.in.create_options; f->share_access = io->generic.in.share_access; - f->access_mask = io->generic.in.access_mask; + f->access_mask = access_mask; f->seek_offset = 0; f->position = 0; @@ -429,6 +433,14 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, share_access = io->generic.in.share_access; access_mask = io->generic.in.access_mask; + if (access_mask & SEC_RIGHT_MAXIMUM_ALLOWED) { + if (name->dos.attrib & FILE_ATTRIBUTE_READONLY) { + access_mask = GENERIC_RIGHTS_FILE_READ; + } else { + access_mask = GENERIC_RIGHTS_FILE_READ | GENERIC_RIGHTS_FILE_WRITE; + } + } + /* certain create options are not allowed */ if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && !(access_mask & STD_RIGHT_DELETE_ACCESS)) { @@ -551,7 +563,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->lock_count = 0; f->create_options = io->generic.in.create_options; f->share_access = io->generic.in.share_access; - f->access_mask = io->generic.in.access_mask; + f->access_mask = access_mask; f->seek_offset = 0; f->position = 0; -- cgit From 5c95896499dd6f72c8fc9be84b0da880571731da Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Oct 2004 04:24:58 +0000 Subject: r3189: improved the share_conflict() logic (both in terms of readability and correctness). pvfs now passes the BASE-RENAME test. (This used to be commit 4cf3f65a5c19fdad62a0bdef225b2d9002cf8c8b) --- source4/ntvfs/posix/pvfs_open.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index badd18d370..b66b3725db 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -723,17 +723,24 @@ NTSTATUS pvfs_change_create_options(struct pvfs_state *pvfs, /* - determine if a file is open - used to prevent some operations on open files + determine if a file can be deleted, or if it is prevented by an + already open file */ -BOOL pvfs_is_open(struct pvfs_state *pvfs, struct pvfs_filename *name) +NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, struct pvfs_filename *name) { NTSTATUS status; DATA_BLOB key; status = pvfs_locking_key(name, name, &key); if (!NT_STATUS_IS_OK(status)) { - return False; + return NT_STATUS_NO_MEMORY; } - return odb_is_open(pvfs->odb_context, &key); + status = odb_can_open(pvfs->odb_context, &key, + NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE | + NTCREATEX_SHARE_ACCESS_DELETE, + 0, STD_RIGHT_DELETE_ACCESS); + + return status; } -- cgit From 1be85de5884d107f89eaf4221f225c9ec468365e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Oct 2004 05:27:49 +0000 Subject: r3193: improved the initial permissions choice for file create, based upon dos attribute (This used to be commit f6fb1e3493a2a0734747f769cd1013215d967cde) --- source4/ntvfs/posix/pvfs_open.c | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index b66b3725db..4844521c45 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -150,7 +150,9 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, talloc_set_destructor(f, pvfs_dir_fd_destructor); if (!name->exists) { - if (mkdir(name->full_name, 0755) == -1) { + uint32_t attrib = io->generic.in.file_attr | FILE_ATTRIBUTE_DIRECTORY; + mode_t mode = pvfs_fileperms(pvfs, attrib); + if (mkdir(name->full_name, mode) == -1) { return pvfs_map_errno(pvfs,errno); } status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, @@ -287,7 +289,17 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, access_mask = GENERIC_RIGHTS_FILE_READ | GENERIC_RIGHTS_FILE_WRITE; } - flags = O_RDWR; + switch (access_mask & (SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_WRITE_DATA)) { + case SA_RIGHT_FILE_READ_DATA: + flags = O_RDONLY; + break; + case SA_RIGHT_FILE_WRITE_DATA: + flags = O_WRONLY; + break; + case SA_RIGHT_FILE_WRITE_DATA|SA_RIGHT_FILE_READ_DATA: + flags = O_RDWR; + break; + } f = talloc_p(req, struct pvfs_file); if (f == NULL) { @@ -299,11 +311,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return NT_STATUS_TOO_MANY_OPENED_FILES; } - if (io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) { - mode = 0444; - } else { - mode = 0644; - } + mode = pvfs_fileperms(pvfs, io->ntcreatex.in.file_attr); /* create the file */ fd = open(name->full_name, flags | O_CREAT | O_EXCL, mode); @@ -434,7 +442,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, access_mask = io->generic.in.access_mask; if (access_mask & SEC_RIGHT_MAXIMUM_ALLOWED) { - if (name->dos.attrib & FILE_ATTRIBUTE_READONLY) { + if (name->exists && (name->dos.attrib & FILE_ATTRIBUTE_READONLY)) { access_mask = GENERIC_RIGHTS_FILE_READ; } else { access_mask = GENERIC_RIGHTS_FILE_READ | GENERIC_RIGHTS_FILE_WRITE; @@ -488,7 +496,17 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } - flags |= O_RDWR; + switch (access_mask & (SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_WRITE_DATA)) { + case SA_RIGHT_FILE_READ_DATA: + flags |= O_RDONLY; + break; + case SA_RIGHT_FILE_WRITE_DATA: + flags |= O_WRONLY; + break; + case SA_RIGHT_FILE_WRITE_DATA|SA_RIGHT_FILE_READ_DATA: + flags |= O_RDWR; + break; + } /* handle creating a new file separately */ if (!name->exists) { -- cgit From 7fa912e708331e729d5e4ffad28646d294d4745a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 25 Oct 2004 07:03:15 +0000 Subject: r3200: - improved the accuracy of openx emulation. We now nearly pass the openx portion of RAW-OPEN - fixed directory size reporting to make it consistent. we now pass the ntcreatex portion of RAW-OPEN (This used to be commit 6282e5811b8d4f1c17152d86875ac60d1323779d) --- source4/ntvfs/posix/pvfs_open.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 4844521c45..5e162ad147 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -180,8 +180,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, io->generic.out.write_time = name->dos.write_time; io->generic.out.change_time = name->dos.change_time; io->generic.out.attrib = name->dos.attrib; - io->generic.out.alloc_size = 0; - io->generic.out.size = 0; + io->generic.out.alloc_size = name->dos.alloc_size; + io->generic.out.size = name->st.st_size; io->generic.out.file_type = FILE_TYPE_DISK; io->generic.out.ipc_state = 0; io->generic.out.is_directory = 1; @@ -457,9 +457,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, switch (io->generic.in.open_disposition) { case NTCREATEX_DISP_SUPERSEDE: - if (!name->exists) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } flags = O_TRUNC; break; -- 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_open.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 5e162ad147..ffd1520b07 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -643,9 +643,11 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_HANDLE; } - unix_times.actime = 0; - unix_times.modtime = io->close.in.write_time; - utime(f->name->full_name, &unix_times); + if (!null_time(io->close.in.write_time)) { + unix_times.actime = 0; + unix_times.modtime = io->close.in.write_time; + utime(f->name->full_name, &unix_times); + } if (f->fd != -1 && close(f->fd) == -1) { -- cgit From 67bd7a7cb9589b0db874323aa87246a997fcf922 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Oct 2004 07:03:12 +0000 Subject: r3246: new files should get created with FILE_ATTRIBUTE_ARCHIVE (This used to be commit 090574c6982f703b124a5a123d2199be8f5b3968) --- source4/ntvfs/posix/pvfs_open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index ffd1520b07..f533a36637 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -311,7 +311,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return NT_STATUS_TOO_MANY_OPENED_FILES; } - mode = pvfs_fileperms(pvfs, io->ntcreatex.in.file_attr); + mode = pvfs_fileperms(pvfs, io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE); /* create the file */ fd = open(name->full_name, flags | O_CREAT | O_EXCL, mode); -- cgit From f1814e5a53d2f685e193ba5f28b38ea48efd9269 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 26 Oct 2004 07:11:49 +0000 Subject: r3249: - change_time is closer to ctime than mtime - pvfs now passes the RAW-CLOSE test (This used to be commit 98aea91ce67a0c64a98537bfe244495f10672323) --- source4/ntvfs/posix/pvfs_open.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index f533a36637..1575ca82c1 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -634,6 +634,10 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, NTSTATUS status; struct utimbuf unix_times; + if (io->generic.level == RAW_CLOSE_SPLCLOSE) { + return NT_STATUS_UNSUCCESSFUL; + } + if (io->generic.level != RAW_CLOSE_CLOSE) { return ntvfs_map_close(req, io, ntvfs); } -- cgit From 9752471973007289fb7659f0311cd316b401c034 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 29 Oct 2004 09:28:35 +0000 Subject: r3363: added basic support for SA_RIGHT_FILE_EXECUTE, needed for opening .dll files (This used to be commit ba1bfd51e1b694cb69afe559f695addaf03b4d81) --- source4/ntvfs/posix/pvfs_open.c | 30 ++++++++++++------------------ 1 file changed, 12 insertions(+), 18 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 1575ca82c1..73514f81b7 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -289,16 +289,13 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, access_mask = GENERIC_RIGHTS_FILE_READ | GENERIC_RIGHTS_FILE_WRITE; } - switch (access_mask & (SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_WRITE_DATA)) { - case SA_RIGHT_FILE_READ_DATA: - flags = O_RDONLY; - break; - case SA_RIGHT_FILE_WRITE_DATA: - flags = O_WRONLY; - break; - case SA_RIGHT_FILE_WRITE_DATA|SA_RIGHT_FILE_READ_DATA: + if ((access_mask & SA_RIGHT_FILE_READ_EXEC) && + (access_mask & SA_RIGHT_FILE_WRITE_DATA)) { flags = O_RDWR; - break; + } else if (access_mask & SA_RIGHT_FILE_WRITE_DATA) { + flags = O_WRONLY; + } else { + flags = O_RDONLY; } f = talloc_p(req, struct pvfs_file); @@ -493,16 +490,13 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } - switch (access_mask & (SA_RIGHT_FILE_READ_DATA | SA_RIGHT_FILE_WRITE_DATA)) { - case SA_RIGHT_FILE_READ_DATA: - flags |= O_RDONLY; - break; - case SA_RIGHT_FILE_WRITE_DATA: - flags |= O_WRONLY; - break; - case SA_RIGHT_FILE_WRITE_DATA|SA_RIGHT_FILE_READ_DATA: + if ((access_mask & SA_RIGHT_FILE_READ_EXEC) && + (access_mask & SA_RIGHT_FILE_WRITE_DATA)) { flags |= O_RDWR; - break; + } else if (access_mask & SA_RIGHT_FILE_WRITE_DATA) { + flags |= O_WRONLY; + } else { + flags |= O_RDONLY; } /* handle creating a new file separately */ -- cgit From b1c8e870d8340025f2cfbd6fe56c510be34bb0e1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 29 Oct 2004 21:52:49 +0000 Subject: r3373: added better error reporting in pvfs_open (This used to be commit 22abdfca961a00e7c48ba4231e12f254781d315d) --- source4/ntvfs/posix/pvfs_open.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 73514f81b7..346b1420e3 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -27,8 +27,8 @@ create file handles with convenient numbers for sniffers */ #define PVFS_MIN_FILE_FNUM 0x100 -#define PVFS_MIN_NEW_FNUM 0x200 -#define PVFS_MIN_DIR_FNUM 0x1000 +#define PVFS_MIN_NEW_FNUM 0x200 +#define PVFS_MIN_DIR_FNUM 0x300 /* find open file handle given fnum @@ -64,8 +64,8 @@ static int pvfs_dir_fd_destructor(void *p) if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { if (rmdir(f->name->full_name) != 0) { - DEBUG(0,("pvfs_close: failed to rmdir '%s'\n", - f->name->full_name)); + DEBUG(0,("pvfs_close: failed to rmdir '%s' - %s\n", + f->name->full_name, strerror(errno))); } } @@ -214,8 +214,8 @@ static int pvfs_fd_destructor(void *p) if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { if (unlink(f->name->full_name) != 0) { - DEBUG(0,("pvfs_close: failed to delete '%s'\n", - f->name->full_name)); + DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n", + f->name->full_name, strerror(errno))); } } -- cgit From d93636c29e4e0930e91c53b367145a0c88db7de1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 30 Oct 2004 05:53:56 +0000 Subject: r3387: fixed pvfs to pass the NTDENY tests. The tricky bit was SA_RIGHT_FILE_EXECUTE, which depends on a flags2 bit (This used to be commit c36851d230bcf552ed79322f8358060ab164ec09) --- source4/ntvfs/posix/pvfs_open.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 346b1420e3..bfaa7bf5a1 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -290,9 +290,9 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } if ((access_mask & SA_RIGHT_FILE_READ_EXEC) && - (access_mask & SA_RIGHT_FILE_WRITE_DATA)) { + (access_mask & SA_RIGHT_FILE_WRITE_APPEND)) { flags = O_RDWR; - } else if (access_mask & SA_RIGHT_FILE_WRITE_DATA) { + } else if (access_mask & SA_RIGHT_FILE_WRITE_APPEND) { flags = O_WRONLY; } else { flags = O_RDONLY; @@ -491,9 +491,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } if ((access_mask & SA_RIGHT_FILE_READ_EXEC) && - (access_mask & SA_RIGHT_FILE_WRITE_DATA)) { + (access_mask & SA_RIGHT_FILE_WRITE_APPEND)) { flags |= O_RDWR; - } else if (access_mask & SA_RIGHT_FILE_WRITE_DATA) { + } else if (access_mask & SA_RIGHT_FILE_WRITE_APPEND) { flags |= O_WRONLY; } else { flags |= O_RDONLY; -- 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_open.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index bfaa7bf5a1..bc56962912 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -22,6 +22,7 @@ #include "include/includes.h" #include "vfs_posix.h" +#include "system/time.h" /* create file handles with convenient numbers for sniffers -- cgit From f4ec1497a1047eab8a2077694c7629ca6bb9eaa4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 03:44:52 +0000 Subject: r3455: some more portability fixes. We nearly compile on solaris again now. (This used to be commit 4f33247f1ca60416415a61a7afac43c9dc8a61fd) --- source4/ntvfs/posix/pvfs_open.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index bc56962912..89da0f4b34 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -23,6 +23,7 @@ #include "include/includes.h" #include "vfs_posix.h" #include "system/time.h" +#include "system/filesys.h" /* create file handles with convenient numbers for sniffers -- cgit From 3643fb11092e28a9538ef32cedce8ff21ad86a28 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 2 Nov 2004 06:42:15 +0000 Subject: r3463: separated out some more headers (asn_1.h, messages.h, dlinklist.h and ioctl.h) (This used to be commit b97e395c814762024336c1cf4d7c25be8da5813a) --- source4/ntvfs/posix/pvfs_open.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 89da0f4b34..f3ef72f4ed 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -24,6 +24,7 @@ #include "vfs_posix.h" #include "system/time.h" #include "system/filesys.h" +#include "dlinklist.h" /* create file handles with convenient numbers for sniffers -- cgit From dde07058075d357cfdc63624c8dcaa67ebd40add Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 3 Nov 2004 10:09:48 +0000 Subject: r3507: - added deferred replies on sharing violation in pvfs open. The deferred reply is short-circuited immediately when the file is closed by another user, allowing it to be opened by the waiting user. - added a sane set of timeval manipulation routines - converted all the events code and code that uses it to use struct timeval instead of time_t, which allows for microsecond resolution instead of 1 second resolution. This was needed for doing the pvfs deferred open code, and is why the patch is so big. (This used to be commit 0d51511d408d91eb5f68a35e980e0875299b1831) --- source4/ntvfs/posix/pvfs_open.c | 254 +++++++++++++++++++++++++++++++--------- 1 file changed, 199 insertions(+), 55 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index f3ef72f4ed..8ad6ad0389 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -25,6 +25,7 @@ #include "system/time.h" #include "system/filesys.h" #include "dlinklist.h" +#include "messages.h" /* create file handles with convenient numbers for sniffers @@ -33,6 +34,8 @@ #define PVFS_MIN_NEW_FNUM 0x200 #define PVFS_MIN_DIR_FNUM 0x300 +#define SHARING_VIOLATION_DELAY 1000000 + /* find open file handle given fnum */ @@ -125,7 +128,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_DIR_FNUM, UINT16_MAX); if (fnum == -1) { - talloc_free(f); return NT_STATUS_TOO_MANY_OPENED_FILES; } @@ -228,10 +230,12 @@ static int pvfs_fd_destructor(void *p) return 0; } - status = odb_close_file(lck, f->fnum); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n", - f->name->full_name, nt_errstr(status))); + if (f->have_opendb_entry) { + status = odb_close_file(lck, f->fnum); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n", + f->name->full_name, nt_errstr(status))); + } } talloc_free(lck); @@ -370,6 +374,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->access_mask = access_mask; f->seek_offset = 0; f->position = 0; + f->have_opendb_entry = True; DLIST_ADD(pvfs->open_files, f); @@ -398,6 +403,166 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } +/* + open am existing file - called from both the open retry code + and the main open code +*/ +NTSTATUS pvfs_open_existing(struct pvfs_file *f, + union smb_open *io, + int open_flags) +{ + int fd; + NTSTATUS status; + + /* do the actual open */ + fd = open(f->name->full_name, open_flags); + if (fd == -1) { + return pvfs_map_errno(f->pvfs, errno); + } + + f->fd = fd; + + /* re-resolve the open fd */ + status = pvfs_resolve_name_fd(f->pvfs, fd, f->name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + io->generic.out.oplock_level = NO_OPLOCK; + io->generic.out.fnum = f->fnum; + io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; + io->generic.out.create_time = f->name->dos.create_time; + io->generic.out.access_time = f->name->dos.access_time; + io->generic.out.write_time = f->name->dos.write_time; + io->generic.out.change_time = f->name->dos.change_time; + io->generic.out.attrib = f->name->dos.attrib; + io->generic.out.alloc_size = f->name->dos.alloc_size; + io->generic.out.size = f->name->st.st_size; + io->generic.out.file_type = FILE_TYPE_DISK; + io->generic.out.ipc_state = 0; + io->generic.out.is_directory = 0; + + /* success - keep the file handle */ + talloc_steal(f->pvfs, f); + + return NT_STATUS_OK; +} + +/* + state of a pending open retry +*/ +struct pvfs_open_retry { + union smb_open *io; + struct pvfs_file *f; + struct smbsrv_request *req; + void *wait_handle; + struct timeval end_time; + int open_flags; +}; + +/* destroy a pending open request */ +static int pvfs_retry_destructor(void *ptr) +{ + struct pvfs_open_retry *r = ptr; + struct odb_lock *lck; + lck = odb_lock(r->req, r->f->pvfs->odb_context, &r->f->locking_key); + if (lck != NULL) { + odb_remove_pending(lck, r); + } + return 0; +} + +/* + retry an open +*/ +static void pvfs_open_retry(void *private, BOOL timed_out) +{ + struct pvfs_open_retry *r = private; + struct odb_lock *lck; + struct pvfs_file *f = r->f; + struct smbsrv_request *req = r->req; + NTSTATUS status; + + lck = odb_lock(req, f->pvfs->odb_context, &f->locking_key); + if (lck == NULL) { + req->async_states->status = NT_STATUS_INTERNAL_DB_CORRUPTION; + req->async_states->send_fn(req); + return; + } + + /* see if we are allowed to open at the same time as existing opens */ + status = odb_open_file(lck, f->fnum, f->share_access, + f->create_options, f->access_mask); + if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) && !timed_out) { + talloc_free(lck); + return; + } + + talloc_free(r->wait_handle); + + if (!NT_STATUS_IS_OK(status)) { + req->async_states->status = status; + req->async_states->send_fn(req); + return; + } + + f->have_opendb_entry = True; + + /* do the rest of the open work */ + status = pvfs_open_existing(f, r->io, r->open_flags); + + if (NT_STATUS_IS_OK(status)) { + talloc_steal(f->pvfs, f); + } + + req->async_states->status = status; + req->async_states->send_fn(req); +} + +/* + setup for a open retry after a sharing violation +*/ +static NTSTATUS pvfs_open_setup_retry(struct smbsrv_request *req, + union smb_open *io, + struct pvfs_file *f, + struct odb_lock *lck, + int open_flags) +{ + struct pvfs_open_retry *r; + struct pvfs_state *pvfs = f->pvfs; + NTSTATUS status; + + r = talloc_p(req, struct pvfs_open_retry); + if (r == NULL) { + return NT_STATUS_NO_MEMORY; + } + + r->io = io; + r->f = f; + r->req = req; + r->end_time = timeval_current_ofs(0, SHARING_VIOLATION_DELAY); + r->open_flags = open_flags; + + /* setup a pending lock */ + status = odb_open_file_pending(lck, r); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + r->wait_handle = pvfs_wait_message(pvfs, req, MSG_PVFS_RETRY_OPEN, r->end_time, + pvfs_open_retry, r); + if (r->wait_handle == NULL) { + return NT_STATUS_NO_MEMORY; + } + + talloc_free(lck); + talloc_steal(pvfs, req); + + talloc_set_destructor(r, pvfs_retry_destructor); + + return NT_STATUS_OK; +} + /* open a file */ @@ -405,7 +570,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, struct smbsrv_request *req, union smb_open *io) { struct pvfs_state *pvfs = ntvfs->private_data; - int fd, flags; + int flags; struct pvfs_filename *name; struct pvfs_file *f; NTSTATUS status; @@ -539,11 +704,26 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_TOO_MANY_OPENED_FILES; } + f->fnum = fnum; + f->fd = -1; + f->name = talloc_steal(f, name); + f->session = req->session; + f->smbpid = req->smbpid; + f->pvfs = pvfs; + f->pending_list = NULL; + f->lock_count = 0; + f->create_options = io->generic.in.create_options; + f->share_access = io->generic.in.share_access; + f->access_mask = access_mask; + f->seek_offset = 0; + f->position = 0; + f->have_opendb_entry = False; + /* form the lock context used for byte range locking and opendb locking */ status = pvfs_locking_key(name, f, &f->locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, fnum); + idr_remove(pvfs->idtree_fnum, f->fnum); return status; } @@ -558,65 +738,31 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - /* see if we are allowed to open at the same time as existing opens */ - status = odb_open_file(lck, fnum, share_access, create_options, access_mask); - if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, fnum); - return status; - } - - f->fnum = fnum; - f->fd = -1; - f->name = talloc_steal(f, name); - f->session = req->session; - f->smbpid = req->smbpid; - f->pvfs = pvfs; - f->pending_list = NULL; - f->lock_count = 0; - f->create_options = io->generic.in.create_options; - f->share_access = io->generic.in.share_access; - f->access_mask = access_mask; - f->seek_offset = 0; - f->position = 0; - DLIST_ADD(pvfs->open_files, f); /* setup a destructor to avoid file descriptor leaks on abnormal termination */ talloc_set_destructor(f, pvfs_fd_destructor); - /* do the actual open */ - fd = open(name->full_name, flags); - if (fd == -1) { - return pvfs_map_errno(pvfs, errno); - } - f->fd = fd; + /* see if we are allowed to open at the same time as existing opens */ + status = odb_open_file(lck, f->fnum, share_access, create_options, access_mask); + + /* on a sharing violation we need to retry when the file is closed by + the other user, or after 1 second */ + if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) && + (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { + return pvfs_open_setup_retry(req, io, f, lck, flags); + } - /* re-resolve the open fd */ - status = pvfs_resolve_name_fd(pvfs, fd, name); if (!NT_STATUS_IS_OK(status)) { return status; } - io->generic.out.oplock_level = NO_OPLOCK; - io->generic.out.fnum = f->fnum; - io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; - io->generic.out.create_time = name->dos.create_time; - io->generic.out.access_time = name->dos.access_time; - io->generic.out.write_time = name->dos.write_time; - io->generic.out.change_time = name->dos.change_time; - io->generic.out.attrib = name->dos.attrib; - io->generic.out.alloc_size = name->dos.alloc_size; - io->generic.out.size = name->st.st_size; - io->generic.out.file_type = FILE_TYPE_DISK; - io->generic.out.ipc_state = 0; - io->generic.out.is_directory = 0; - - /* success - keep the file handle */ - talloc_steal(pvfs, f); + f->have_opendb_entry = True; - return NT_STATUS_OK; + /* do the rest of the open work */ + return pvfs_open_existing(f, io, flags); } @@ -677,7 +823,6 @@ NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs, for (f=pvfs->open_files;f;f=next) { next = f->next; if (f->session == req->session) { - DLIST_REMOVE(pvfs->open_files, f); talloc_free(f); } } @@ -698,7 +843,6 @@ NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs, for (f=pvfs->open_files;f;f=next) { next = f->next; if (f->smbpid == req->smbpid) { - DLIST_REMOVE(pvfs->open_files, f); talloc_free(f); } } -- cgit From c870ae8b898d3bcc81ed9fd1afd505d78dea52cc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 4 Nov 2004 11:28:38 +0000 Subject: r3528: added support for the SMBntcancel() operation, which cancels any outstanding async operation (triggering an immediate timeout). pvfs now passes the RAW-MUX test (This used to be commit 3423e2f41461d054067ef168b9b986f62cc8f77c) --- source4/ntvfs/posix/pvfs_open.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 8ad6ad0389..2c0f55cf22 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -556,7 +556,6 @@ static NTSTATUS pvfs_open_setup_retry(struct smbsrv_request *req, } talloc_free(lck); - talloc_steal(pvfs, req); talloc_set_destructor(r, pvfs_retry_destructor); -- cgit From b2617daeb658af9959ea71432d87fa4273b7f1a4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 4 Nov 2004 13:27:29 +0000 Subject: r3532: make sharing violation delay in pvfs configurable with "posix:sharedelay = usecs" (This used to be commit c4758776491e5ed9f5b8c387226d1e75bc70eb2e) --- source4/ntvfs/posix/pvfs_open.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 2c0f55cf22..06191cee0a 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -34,8 +34,6 @@ #define PVFS_MIN_NEW_FNUM 0x200 #define PVFS_MIN_DIR_FNUM 0x300 -#define SHARING_VIOLATION_DELAY 1000000 - /* find open file handle given fnum */ @@ -540,7 +538,7 @@ static NTSTATUS pvfs_open_setup_retry(struct smbsrv_request *req, r->io = io; r->f = f; r->req = req; - r->end_time = timeval_current_ofs(0, SHARING_VIOLATION_DELAY); + r->end_time = timeval_current_ofs(0, pvfs->sharing_violation_delay); r->open_flags = open_flags; /* setup a pending lock */ -- cgit From 80eef3ea6647a9f8600466b2b468d38bd2eb0664 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 5 Nov 2004 01:14:06 +0000 Subject: r3539: much nicer async open delay code. The previous code didn't handle the case where the file got renamed or deleted while waiting for the sharing violation delay. To handle this we need to make the 2nd open a full open call, including the name resolve call etc. Luckily this simplifies the logic. I also expanded the RAW-MUX test to include the case where we do open/open/open/close/close, with the 3rd open async, and that open gets retried after both the first close and the 2nd close, with the first retry failing and the 2nd retry working. The tests the "async reply after a async reply" logic in pvfs_open(). (This used to be commit eded2ad9c91f5ba587ef4f7f5f5a6dceb4b51ff3) --- source4/ntvfs/posix/pvfs_open.c | 178 +++++++++++++++++++--------------------- 1 file changed, 83 insertions(+), 95 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 06191cee0a..73b1949acb 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -401,71 +401,28 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } -/* - open am existing file - called from both the open retry code - and the main open code -*/ -NTSTATUS pvfs_open_existing(struct pvfs_file *f, - union smb_open *io, - int open_flags) -{ - int fd; - NTSTATUS status; - - /* do the actual open */ - fd = open(f->name->full_name, open_flags); - if (fd == -1) { - return pvfs_map_errno(f->pvfs, errno); - } - - f->fd = fd; - - /* re-resolve the open fd */ - status = pvfs_resolve_name_fd(f->pvfs, fd, f->name); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - io->generic.out.oplock_level = NO_OPLOCK; - io->generic.out.fnum = f->fnum; - io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; - io->generic.out.create_time = f->name->dos.create_time; - io->generic.out.access_time = f->name->dos.access_time; - io->generic.out.write_time = f->name->dos.write_time; - io->generic.out.change_time = f->name->dos.change_time; - io->generic.out.attrib = f->name->dos.attrib; - io->generic.out.alloc_size = f->name->dos.alloc_size; - io->generic.out.size = f->name->st.st_size; - io->generic.out.file_type = FILE_TYPE_DISK; - io->generic.out.ipc_state = 0; - io->generic.out.is_directory = 0; - - /* success - keep the file handle */ - talloc_steal(f->pvfs, f); - - return NT_STATUS_OK; -} - /* state of a pending open retry */ struct pvfs_open_retry { - union smb_open *io; - struct pvfs_file *f; + struct ntvfs_module_context *ntvfs; struct smbsrv_request *req; + union smb_open *io; void *wait_handle; - struct timeval end_time; - int open_flags; + DATA_BLOB locking_key; }; /* destroy a pending open request */ static int pvfs_retry_destructor(void *ptr) { struct pvfs_open_retry *r = ptr; - struct odb_lock *lck; - lck = odb_lock(r->req, r->f->pvfs->odb_context, &r->f->locking_key); - if (lck != NULL) { - odb_remove_pending(lck, r); + struct pvfs_state *pvfs = r->ntvfs->private_data; + if (r->locking_key.data) { + struct odb_lock *lck; + lck = odb_lock(r->req, pvfs->odb_context, &r->locking_key); + if (lck != NULL) { + odb_remove_pending(lck, r); + } } return 0; } @@ -476,70 +433,70 @@ static int pvfs_retry_destructor(void *ptr) static void pvfs_open_retry(void *private, BOOL timed_out) { struct pvfs_open_retry *r = private; - struct odb_lock *lck; - struct pvfs_file *f = r->f; + struct ntvfs_module_context *ntvfs = r->ntvfs; struct smbsrv_request *req = r->req; + union smb_open *io = r->io; NTSTATUS status; - - lck = odb_lock(req, f->pvfs->odb_context, &f->locking_key); - if (lck == NULL) { - req->async_states->status = NT_STATUS_INTERNAL_DB_CORRUPTION; - req->async_states->send_fn(req); - return; - } - - /* see if we are allowed to open at the same time as existing opens */ - status = odb_open_file(lck, f->fnum, f->share_access, - f->create_options, f->access_mask); - if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) && !timed_out) { - talloc_free(lck); - return; - } talloc_free(r->wait_handle); - if (!NT_STATUS_IS_OK(status)) { - req->async_states->status = status; + if (timed_out) { + /* if it timed out, then give the failure + immediately */ + talloc_free(r); + req->async_states->status = NT_STATUS_SHARING_VIOLATION; req->async_states->send_fn(req); return; } - f->have_opendb_entry = True; + /* the pending odb entry is already removed. We use a null locking + key to indicate this */ + data_blob_free(&r->locking_key); + talloc_free(r); - /* do the rest of the open work */ - status = pvfs_open_existing(f, r->io, r->open_flags); + /* try the open again, which could trigger another retry setup + if it wants to, so we have to unmark the async flag so we + will know if it does a second async reply */ + req->async_states->state &= ~NTVFS_ASYNC_STATE_ASYNC; - if (NT_STATUS_IS_OK(status)) { - talloc_steal(f->pvfs, f); + status = pvfs_open(ntvfs, req, io); + if (req->async_states->state & NTVFS_ASYNC_STATE_ASYNC) { + /* the 2nd try also replied async, so we don't send + the reply yet */ + return; } + /* send the reply up the chain */ req->async_states->status = status; req->async_states->send_fn(req); } + /* setup for a open retry after a sharing violation */ -static NTSTATUS pvfs_open_setup_retry(struct smbsrv_request *req, +static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, + struct smbsrv_request *req, union smb_open *io, - struct pvfs_file *f, - struct odb_lock *lck, - int open_flags) + struct pvfs_file *f, + struct odb_lock *lck) { + struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_open_retry *r; - struct pvfs_state *pvfs = f->pvfs; NTSTATUS status; + struct timeval end_time; r = talloc_p(req, struct pvfs_open_retry); if (r == NULL) { return NT_STATUS_NO_MEMORY; } - r->io = io; - r->f = f; + r->ntvfs = ntvfs; r->req = req; - r->end_time = timeval_current_ofs(0, pvfs->sharing_violation_delay); - r->open_flags = open_flags; + r->io = io; + r->locking_key = data_blob_talloc(r, f->locking_key.data, f->locking_key.length); + + end_time = timeval_add(&req->request_time, 0, pvfs->sharing_violation_delay); /* setup a pending lock */ status = odb_open_file_pending(lck, r); @@ -547,16 +504,17 @@ static NTSTATUS pvfs_open_setup_retry(struct smbsrv_request *req, return status; } - r->wait_handle = pvfs_wait_message(pvfs, req, MSG_PVFS_RETRY_OPEN, r->end_time, + talloc_free(lck); + talloc_free(f); + + talloc_set_destructor(r, pvfs_retry_destructor); + + r->wait_handle = pvfs_wait_message(pvfs, req, MSG_PVFS_RETRY_OPEN, end_time, pvfs_open_retry, r); if (r->wait_handle == NULL) { return NT_STATUS_NO_MEMORY; } - talloc_free(lck); - - talloc_set_destructor(r, pvfs_retry_destructor); - return NT_STATUS_OK; } @@ -571,7 +529,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, struct pvfs_filename *name; struct pvfs_file *f; NTSTATUS status; - int fnum; + int fnum, fd; struct odb_lock *lck; uint32_t create_options; uint32_t share_access; @@ -749,7 +707,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, the other user, or after 1 second */ if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) && (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return pvfs_open_setup_retry(req, io, f, lck, flags); + return pvfs_open_setup_retry(ntvfs, req, io, f, lck); } if (!NT_STATUS_IS_OK(status)) { @@ -758,8 +716,38 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->have_opendb_entry = True; - /* do the rest of the open work */ - return pvfs_open_existing(f, io, flags); + /* do the actual open */ + fd = open(f->name->full_name, flags); + if (fd == -1) { + return pvfs_map_errno(f->pvfs, errno); + } + + f->fd = fd; + + /* re-resolve the open fd */ + status = pvfs_resolve_name_fd(f->pvfs, fd, f->name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + io->generic.out.oplock_level = NO_OPLOCK; + io->generic.out.fnum = f->fnum; + io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; + io->generic.out.create_time = f->name->dos.create_time; + io->generic.out.access_time = f->name->dos.access_time; + io->generic.out.write_time = f->name->dos.write_time; + io->generic.out.change_time = f->name->dos.change_time; + io->generic.out.attrib = f->name->dos.attrib; + io->generic.out.alloc_size = f->name->dos.alloc_size; + io->generic.out.size = f->name->st.st_size; + io->generic.out.file_type = FILE_TYPE_DISK; + io->generic.out.ipc_state = 0; + io->generic.out.is_directory = 0; + + /* success - keep the file handle */ + talloc_steal(f->pvfs, f); + + return NT_STATUS_OK; } -- cgit From 1d97e7b9d8a8e716cd50bb42065687a65d542b2d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 5 Nov 2004 02:22:07 +0000 Subject: r3540: added testing of SMBntcancel in the open/open/close mux testing. Interestingly, w2k3 does not allow the cancel of an outstanding async open request, whereas it does allow the cancel of an outstanding async lock request. To support this I have changed the pvfs_wait interface to provide a enum on why the event is happening, so the callback can decide what to do. (This used to be commit f23d6a28008a13588cde24b5012ec21e488ac47a) --- source4/ntvfs/posix/pvfs_open.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 73b1949acb..c8f96849ec 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -430,7 +430,7 @@ static int pvfs_retry_destructor(void *ptr) /* retry an open */ -static void pvfs_open_retry(void *private, BOOL timed_out) +static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason) { struct pvfs_open_retry *r = private; struct ntvfs_module_context *ntvfs = r->ntvfs; @@ -438,9 +438,15 @@ static void pvfs_open_retry(void *private, BOOL timed_out) union smb_open *io = r->io; NTSTATUS status; + /* w2k3 ignores SMBntcancel for outstanding open requests. It's probably + just a bug in their server, but we better do the same */ + if (reason == PVFS_WAIT_CANCEL) { + return; + } + talloc_free(r->wait_handle); - if (timed_out) { + if (reason == PVFS_WAIT_TIMEOUT) { /* if it timed out, then give the failure immediately */ talloc_free(r); -- 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_open.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index c8f96849ec..ed6da83e73 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -20,7 +20,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "include/includes.h" +#include "includes.h" #include "vfs_posix.h" #include "system/time.h" #include "system/filesys.h" @@ -330,6 +330,14 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return status; } + +#if HAVE_XATTR_SUPPORT + name->dos.attrib = io->ntcreatex.in.file_attr; + if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) { + status = pvfs_xattr_save(pvfs, name, fd); + } +#endif + /* form the lock context used for byte range locking and opendb locking */ status = pvfs_locking_key(name, f, &f->locking_key); @@ -472,6 +480,10 @@ static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason) return; } + /* re-mark it async, just in case someone up the chain does + paranoid checking */ + req->async_states->state |= NTVFS_ASYNC_STATE_ASYNC; + /* send the reply up the chain */ req->async_states->status = status; req->async_states->send_fn(req); -- cgit From 12f4a44cf549b4ccd729494c242a5ec186d2d670 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 5 Nov 2004 11:31:35 +0000 Subject: r3549: added support for DOS extended attribute lists (name/value pairs) stored in posix xattrs (This used to be commit bad6a88371264cffce2bf5d6ce904b7b357081de) --- source4/ntvfs/posix/pvfs_open.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index ed6da83e73..d640bae279 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -330,13 +330,13 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return status; } - -#if HAVE_XATTR_SUPPORT name->dos.attrib = io->ntcreatex.in.file_attr; - if (pvfs->flags & PVFS_FLAG_XATTR_ENABLE) { - status = pvfs_xattr_save(pvfs, name, fd); + status = pvfs_dosattrib_save(pvfs, name, fd); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); + close(fd); + return status; } -#endif /* form the lock context used for byte range locking and opendb locking */ -- cgit From d8ddb03e906d47a9b75238a2848d860228ab35a7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 5 Nov 2004 11:49:37 +0000 Subject: r3550: fixed initial attribute on file create (inlusion of FILE_ATTRIBUTE_ARCHIVE) (This used to be commit b07feaafd16e42e84ba51004a6a9d4a3cb8f9a37) --- source4/ntvfs/posix/pvfs_open.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index d640bae279..2430f9becb 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -284,6 +284,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, uint32_t share_access = io->generic.in.share_access; uint32_t access_mask = io->generic.in.access_mask; mode_t mode; + uint32_t attrib; if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) && (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { @@ -313,7 +314,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return NT_STATUS_TOO_MANY_OPENED_FILES; } - mode = pvfs_fileperms(pvfs, io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE); + attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE; + mode = pvfs_fileperms(pvfs, attrib); /* create the file */ fd = open(name->full_name, flags | O_CREAT | O_EXCL, mode); @@ -330,7 +332,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return status; } - name->dos.attrib = io->ntcreatex.in.file_attr; + name->dos.attrib = attrib; status = pvfs_dosattrib_save(pvfs, name, fd); if (!NT_STATUS_IS_OK(status)) { idr_remove(pvfs->idtree_fnum, fnum); -- cgit From 439c1524fba3b58abe9e353f9ff2bd7f103f3d12 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 6 Nov 2004 07:58:45 +0000 Subject: r3573: added trans2open support to smbd and pvfs, and fine-tuned the open->generic ntvfs mapping code. (This used to be commit ed844192d7f7ed487290f719df65f256a5b0b9bc) --- source4/ntvfs/posix/pvfs_open.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 2430f9becb..6f1fb1c87f 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -538,6 +538,39 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, return NT_STATUS_OK; } +/* + special handling for t2open +*/ +static NTSTATUS pvfs_open_t2open(struct ntvfs_module_context *ntvfs, + struct smbsrv_request *req, union smb_open *io) +{ + struct pvfs_state *pvfs = ntvfs->private_data; + struct pvfs_filename *name; + NTSTATUS status; + + status = pvfs_resolve_name(pvfs, req, io->t2open.in.fname, + PVFS_RESOLVE_NO_WILDCARD, &name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + if (io->t2open.in.open_func & OPENX_OPEN_FUNC_CREATE) { + if (!name->exists) return NT_STATUS_ACCESS_DENIED; + } + if (io->t2open.in.open_func & OPENX_OPEN_FUNC_TRUNC) { + if (name->exists) return NT_STATUS_ACCESS_DENIED; + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + if ((io->t2open.in.open_func & 0xF) == OPENX_OPEN_FUNC_FAIL) { + if (!name->exists) return NT_STATUS_ACCESS_DENIED; + return NT_STATUS_OBJECT_NAME_COLLISION; + } + + talloc_free(name); + + return ntvfs_map_open(req, io, ntvfs); +} + /* open a file */ @@ -555,6 +588,10 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, uint32_t share_access; uint32_t access_mask; + if (io->generic.level == RAW_OPEN_T2OPEN) { + return pvfs_open_t2open(ntvfs, req, io); + } + /* use the generic mapping code to avoid implementing all the different open calls. This won't allow openx to work perfectly as the mapping code has no way of knowing if two -- cgit From a9158e0d47636e25ce374391cd9b02df3d27b390 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 6 Nov 2004 09:12:53 +0000 Subject: r3574: the RAW-OPEN test changes broke a couple of the other tests. This fixes most of them, although RAW-SEARCH still fails (due to an interaction with the new xattr code) (This used to be commit 09b4652b40c4cfca027765178bd5a0adbaa666c2) --- source4/ntvfs/posix/pvfs_open.c | 27 ++++++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 6f1fb1c87f..f0c1478e66 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -944,7 +944,32 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, struct pvfs_filename *name) NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE, - 0, STD_RIGHT_DELETE_ACCESS); + NTCREATEX_OPTIONS_DELETE_ON_CLOSE, + STD_RIGHT_DELETE_ACCESS); + + return status; +} + +/* + determine if a file can be renamed, or if it is prevented by an + already open file +*/ +NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, struct pvfs_filename *name) +{ + NTSTATUS status; + DATA_BLOB key; + + status = pvfs_locking_key(name, name, &key); + if (!NT_STATUS_IS_OK(status)) { + return NT_STATUS_NO_MEMORY; + } + + status = odb_can_open(pvfs->odb_context, &key, + NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE | + NTCREATEX_SHARE_ACCESS_DELETE, + 0, + STD_RIGHT_DELETE_ACCESS); return status; } -- cgit From f45846084249540f3dee24fe92cfaab2974461cc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 6 Nov 2004 12:35:31 +0000 Subject: r3580: - on file overwrite in ntcreatex we need to replace the file permissions. - pvfs now passes BASE-OPENATTR - pvfs also passes the BASE-DEFER_OPEN test, but it is not a well formed test for regular running so I am removing it from the list of tests to run in test_posix.sh (the test is covered better by RAW-MUX anyway) (This used to be commit cb76bd218ed4194ea151264d495aa902ddf03b3c) --- source4/ntvfs/posix/pvfs_open.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index f0c1478e66..f30d53d51a 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -787,6 +787,22 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } + if (io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE || + io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE_IF) { + /* for overwrite we need to replace file permissions */ + uint32_t attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE; + mode_t mode = pvfs_fileperms(pvfs, attrib); + if (fchmod(fd, mode) == -1) { + return map_nt_error_from_unix(errno); + } + name->dos.attrib = attrib; + status = pvfs_dosattrib_save(pvfs, name, fd); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + io->generic.out.oplock_level = NO_OPLOCK; io->generic.out.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; -- cgit From 2db915e06564b42bf7ebfa526b1af2e42e591590 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 7 Nov 2004 10:05:35 +0000 Subject: r3595: - fixed a talloc_free ordering problem on cleanup with pending requests - added initial support for MODE_INFORMATION in setfileinfo (I have no idea what "mode information" on a file is - it takes a value of 0, 2, 4 or 6. What could it be?) (This used to be commit e53ec2f6b68e1d19149c36ea8fcd25a204db38fb) --- source4/ntvfs/posix/pvfs_open.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index f30d53d51a..1a25f57df1 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -142,6 +142,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->share_access = io->generic.in.share_access; f->seek_offset = 0; f->position = 0; + f->mode = 0; DLIST_ADD(pvfs->open_files, f); @@ -362,6 +363,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } status = odb_open_file(lck, fnum, share_access, create_options, access_mask); + talloc_free(lck); if (!NT_STATUS_IS_OK(status)) { /* bad news, we must have hit a race */ idr_remove(pvfs->idtree_fnum, fnum); @@ -382,6 +384,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->access_mask = access_mask; f->seek_offset = 0; f->position = 0; + f->mode = 0; f->have_opendb_entry = True; DLIST_ADD(pvfs->open_files, f); @@ -433,6 +436,7 @@ static int pvfs_retry_destructor(void *ptr) if (lck != NULL) { odb_remove_pending(lck, r); } + talloc_free(lck); } return 0; } @@ -768,6 +772,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); return status; } @@ -776,6 +781,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* do the actual open */ fd = open(f->name->full_name, flags); if (fd == -1) { + talloc_free(lck); return pvfs_map_errno(f->pvfs, errno); } @@ -784,6 +790,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* re-resolve the open fd */ status = pvfs_resolve_name_fd(f->pvfs, fd, f->name); if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); return status; } @@ -793,15 +800,18 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, uint32_t attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE; mode_t mode = pvfs_fileperms(pvfs, attrib); if (fchmod(fd, mode) == -1) { + talloc_free(lck); return map_nt_error_from_unix(errno); } name->dos.attrib = attrib; status = pvfs_dosattrib_save(pvfs, name, fd); if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); return status; } } + talloc_free(lck); io->generic.out.oplock_level = NO_OPLOCK; io->generic.out.fnum = f->fnum; -- cgit From 19fc6e8f511f028aa40122cc7e40c83908d07ebe Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 8 Nov 2004 03:54:12 +0000 Subject: r3615: split out struct pvfs_file_handle from struct pvfs_file. This is in preparation for adding code to pass the BASE-DENY1 and BASE-DENYDOS tests, which require a shared filesystem handle for some specific combinations of two DENY_DOS opens on the same connection. (This used to be commit 6e4fdf01d19051e3923d7703dbf990fc1722b09a) --- source4/ntvfs/posix/pvfs_open.c | 262 +++++++++++++++++++++++----------------- 1 file changed, 151 insertions(+), 111 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 1a25f57df1..5411f83e8d 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -47,6 +47,10 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, return NULL; } + if (f->fnum != fnum) { + smb_panic("pvfs_find_fd: idtree_fnum corruption\n"); + } + if (req->session != f->session) { DEBUG(2,("pvfs_find_fd: attempt to use wrong session for fnum %d\n", fnum)); @@ -60,22 +64,31 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, /* cleanup a open directory handle */ -static int pvfs_dir_fd_destructor(void *p) +static int pvfs_dir_handle_destructor(void *p) { - struct pvfs_file *f = p; - DLIST_REMOVE(f->pvfs->open_files, f); - idr_remove(f->pvfs->idtree_fnum, f->fnum); + struct pvfs_file_handle *h = p; - if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { - if (rmdir(f->name->full_name) != 0) { + if (h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { + if (rmdir(h->name->full_name) != 0) { DEBUG(0,("pvfs_close: failed to rmdir '%s' - %s\n", - f->name->full_name, strerror(errno))); + h->name->full_name, strerror(errno))); } } return 0; } +/* + cleanup a open directory fnum +*/ +static int pvfs_dir_fnum_destructor(void *p) +{ + struct pvfs_file *f = p; + DLIST_REMOVE(f->pvfs->open_files, f); + idr_remove(f->pvfs->idtree_fnum, f->fnum); + return 0; +} + /* open a directory @@ -124,34 +137,41 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_NO_MEMORY; } + f->handle = talloc_p(f, struct pvfs_file_handle); + if (f->handle == NULL) { + return NT_STATUS_NO_MEMORY; + } + fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_DIR_FNUM, UINT16_MAX); if (fnum == -1) { return NT_STATUS_TOO_MANY_OPENED_FILES; } - f->fnum = fnum; - f->fd = -1; - f->name = talloc_steal(f, name); - f->session = req->session; - f->smbpid = req->smbpid; - f->pvfs = pvfs; + f->fnum = fnum; + f->session = req->session; + f->smbpid = req->smbpid; + f->pvfs = pvfs; f->pending_list = NULL; - f->lock_count = 0; - f->locking_key = data_blob(NULL, 0); - f->create_options = io->generic.in.create_options; - f->share_access = io->generic.in.share_access; - f->seek_offset = 0; - f->position = 0; - f->mode = 0; + f->lock_count = 0; + + f->handle->pvfs = pvfs; + f->handle->name = talloc_steal(f->handle, name); + f->handle->fd = -1; + f->handle->locking_key = data_blob(NULL, 0); + f->handle->create_options = io->generic.in.create_options; + f->handle->share_access = io->generic.in.share_access; + f->handle->seek_offset = 0; + f->handle->position = 0; + f->handle->mode = 0; DLIST_ADD(pvfs->open_files, f); /* TODO: should we check in the opendb? Do directory opens follow the share_access rules? */ - - /* setup a destructor to avoid leaks on abnormal termination */ - talloc_set_destructor(f, pvfs_dir_fd_destructor); + /* setup destructors to avoid leaks on abnormal termination */ + talloc_set_destructor(f->handle, pvfs_dir_handle_destructor); + talloc_set_destructor(f, pvfs_dir_fnum_destructor); if (!name->exists) { uint32_t attrib = io->generic.in.file_attr | FILE_ATTRIBUTE_DIRECTORY; @@ -193,51 +213,61 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_OK; } - /* - by using a destructor we make sure that abnormal cleanup will not - leak file descriptors (assuming at least the top level pointer is freed, which - will cascade down to here) + destroy a struct pvfs_file_handle */ -static int pvfs_fd_destructor(void *p) +static int pvfs_handle_destructor(void *p) { - struct pvfs_file *f = p; - struct odb_lock *lck; - NTSTATUS status; - - DLIST_REMOVE(f->pvfs->open_files, f); - - pvfs_lock_close(f->pvfs, f); + struct pvfs_file_handle *h = p; - if (f->fd != -1) { - close(f->fd); - f->fd = -1; + if (h->fd != -1) { + if (close(h->fd) != 0) { + DEBUG(0,("pvfs_handle_destructor: close(%d) failed for %s - %s\n", + h->fd, h->name->full_name, strerror(errno))); + } + h->fd = -1; } - idr_remove(f->pvfs->idtree_fnum, f->fnum); - - if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { - if (unlink(f->name->full_name) != 0) { + if (h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { + if (unlink(h->name->full_name) != 0) { DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n", - f->name->full_name, strerror(errno))); + h->name->full_name, strerror(errno))); } } - lck = odb_lock(f, f->pvfs->odb_context, &f->locking_key); - if (lck == NULL) { - DEBUG(0,("Unable to lock opendb for close\n")); - return 0; - } + if (h->have_opendb_entry) { + struct odb_lock *lck; + NTSTATUS status; - if (f->have_opendb_entry) { - status = odb_close_file(lck, f->fnum); + lck = odb_lock(h, h->pvfs->odb_context, &h->locking_key); + if (lck == NULL) { + DEBUG(0,("Unable to lock opendb for close\n")); + return 0; + } + + status = odb_close_file(lck, h); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n", - f->name->full_name, nt_errstr(status))); + h->name->full_name, nt_errstr(status))); } + + talloc_free(lck); } - talloc_free(lck); + return 0; +} + + +/* + destroy a struct pvfs_file +*/ +static int pvfs_fnum_destructor(void *p) +{ + struct pvfs_file *f = p; + + DLIST_REMOVE(f->pvfs->open_files, f); + pvfs_lock_close(f->pvfs, f); + idr_remove(f->pvfs->idtree_fnum, f->fnum); return 0; } @@ -310,6 +340,11 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return NT_STATUS_NO_MEMORY; } + f->handle = talloc_p(f, struct pvfs_file_handle); + if (f->handle == NULL) { + return NT_STATUS_NO_MEMORY; + } + fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_NEW_FNUM, UINT16_MAX); if (fnum == -1) { return NT_STATUS_TOO_MANY_OPENED_FILES; @@ -343,7 +378,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* form the lock context used for byte range locking and opendb locking */ - status = pvfs_locking_key(name, f, &f->locking_key); + status = pvfs_locking_key(name, f->handle, &f->handle->locking_key); if (!NT_STATUS_IS_OK(status)) { idr_remove(pvfs->idtree_fnum, fnum); close(fd); @@ -351,7 +386,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } /* grab a lock on the open file record */ - lck = odb_lock(req, pvfs->odb_context, &f->locking_key); + lck = odb_lock(req, pvfs->odb_context, &f->handle->locking_key); if (lck == NULL) { DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n", name->full_name)); @@ -362,7 +397,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - status = odb_open_file(lck, fnum, share_access, create_options, access_mask); + status = odb_open_file(lck, f->handle, + share_access, create_options, access_mask); talloc_free(lck); if (!NT_STATUS_IS_OK(status)) { /* bad news, we must have hit a race */ @@ -372,26 +408,29 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } f->fnum = fnum; - f->fd = fd; - f->name = talloc_steal(f, name); f->session = req->session; f->smbpid = req->smbpid; f->pvfs = pvfs; f->pending_list = NULL; f->lock_count = 0; - f->create_options = io->generic.in.create_options; - f->share_access = io->generic.in.share_access; - f->access_mask = access_mask; - f->seek_offset = 0; - f->position = 0; - f->mode = 0; - f->have_opendb_entry = True; + + f->handle->pvfs = pvfs; + f->handle->name = talloc_steal(f->handle, name); + f->handle->fd = fd; + f->handle->create_options = io->generic.in.create_options; + f->handle->share_access = io->generic.in.share_access; + f->handle->access_mask = access_mask; + f->handle->seek_offset = 0; + f->handle->position = 0; + f->handle->mode = 0; + f->handle->have_opendb_entry = True; DLIST_ADD(pvfs->open_files, f); /* setup a destructor to avoid file descriptor leaks on abnormal termination */ - talloc_set_destructor(f, pvfs_fd_destructor); + talloc_set_destructor(f, pvfs_fnum_destructor); + talloc_set_destructor(f->handle, pvfs_handle_destructor); io->generic.out.oplock_level = NO_OPLOCK; io->generic.out.fnum = f->fnum; @@ -518,7 +557,9 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, r->ntvfs = ntvfs; r->req = req; r->io = io; - r->locking_key = data_blob_talloc(r, f->locking_key.data, f->locking_key.length); + r->locking_key = data_blob_talloc(r, + f->handle->locking_key.data, + f->handle->locking_key.length); end_time = timeval_add(&req->request_time, 0, pvfs->sharing_violation_delay); @@ -714,37 +755,44 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_NO_MEMORY; } + f->handle = talloc_p(f, struct pvfs_file_handle); + if (f->handle == NULL) { + return NT_STATUS_NO_MEMORY; + } + /* allocate a fnum */ fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_FILE_FNUM, UINT16_MAX); if (fnum == -1) { return NT_STATUS_TOO_MANY_OPENED_FILES; } - f->fnum = fnum; - f->fd = -1; - f->name = talloc_steal(f, name); - f->session = req->session; - f->smbpid = req->smbpid; - f->pvfs = pvfs; + f->fnum = fnum; + f->session = req->session; + f->smbpid = req->smbpid; + f->pvfs = pvfs; f->pending_list = NULL; - f->lock_count = 0; - f->create_options = io->generic.in.create_options; - f->share_access = io->generic.in.share_access; - f->access_mask = access_mask; - f->seek_offset = 0; - f->position = 0; - f->have_opendb_entry = False; + f->lock_count = 0; + + f->handle->pvfs = pvfs; + f->handle->fd = -1; + f->handle->name = talloc_steal(f->handle, name); + f->handle->create_options = io->generic.in.create_options; + f->handle->share_access = io->generic.in.share_access; + f->handle->access_mask = access_mask; + f->handle->seek_offset = 0; + f->handle->position = 0; + f->handle->have_opendb_entry = False; /* form the lock context used for byte range locking and opendb locking */ - status = pvfs_locking_key(name, f, &f->locking_key); + status = pvfs_locking_key(name, f->handle, &f->handle->locking_key); if (!NT_STATUS_IS_OK(status)) { idr_remove(pvfs->idtree_fnum, f->fnum); return status; } /* get a lock on this file before the actual open */ - lck = odb_lock(req, pvfs->odb_context, &f->locking_key); + lck = odb_lock(req, pvfs->odb_context, &f->handle->locking_key); if (lck == NULL) { DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n", name->full_name)); @@ -758,11 +806,13 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* setup a destructor to avoid file descriptor leaks on abnormal termination */ - talloc_set_destructor(f, pvfs_fd_destructor); + talloc_set_destructor(f, pvfs_fnum_destructor); + talloc_set_destructor(f->handle, pvfs_handle_destructor); /* see if we are allowed to open at the same time as existing opens */ - status = odb_open_file(lck, f->fnum, share_access, create_options, access_mask); + status = odb_open_file(lck, f->handle, + share_access, create_options, access_mask); /* on a sharing violation we need to retry when the file is closed by the other user, or after 1 second */ @@ -776,19 +826,19 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } - f->have_opendb_entry = True; + f->handle->have_opendb_entry = True; /* do the actual open */ - fd = open(f->name->full_name, flags); + fd = open(f->handle->name->full_name, flags); if (fd == -1) { talloc_free(lck); return pvfs_map_errno(f->pvfs, errno); } - f->fd = fd; + f->handle->fd = fd; /* re-resolve the open fd */ - status = pvfs_resolve_name_fd(f->pvfs, fd, f->name); + status = pvfs_resolve_name_fd(f->pvfs, fd, f->handle->name); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); return status; @@ -816,13 +866,13 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, io->generic.out.oplock_level = NO_OPLOCK; io->generic.out.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; - io->generic.out.create_time = f->name->dos.create_time; - io->generic.out.access_time = f->name->dos.access_time; - io->generic.out.write_time = f->name->dos.write_time; - io->generic.out.change_time = f->name->dos.change_time; - io->generic.out.attrib = f->name->dos.attrib; - io->generic.out.alloc_size = f->name->dos.alloc_size; - io->generic.out.size = f->name->st.st_size; + io->generic.out.create_time = name->dos.create_time; + io->generic.out.access_time = name->dos.access_time; + io->generic.out.write_time = name->dos.write_time; + io->generic.out.change_time = name->dos.change_time; + io->generic.out.attrib = name->dos.attrib; + io->generic.out.alloc_size = name->dos.alloc_size; + io->generic.out.size = name->st.st_size; io->generic.out.file_type = FILE_TYPE_DISK; io->generic.out.ipc_state = 0; io->generic.out.is_directory = 0; @@ -842,7 +892,6 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, { struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f; - NTSTATUS status; struct utimbuf unix_times; if (io->generic.level == RAW_CLOSE_SPLCLOSE) { @@ -861,21 +910,12 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, if (!null_time(io->close.in.write_time)) { unix_times.actime = 0; unix_times.modtime = io->close.in.write_time; - utime(f->name->full_name, &unix_times); + utime(f->handle->name->full_name, &unix_times); } - if (f->fd != -1 && - close(f->fd) == -1) { - status = pvfs_map_errno(pvfs, errno); - } else { - status = NT_STATUS_OK; - } - f->fd = -1; - - /* the destructor takes care of the rest */ talloc_free(f); - return status; + return NT_STATUS_OK; } @@ -929,23 +969,23 @@ NTSTATUS pvfs_change_create_options(struct pvfs_state *pvfs, struct odb_lock *lck; NTSTATUS status; - if (f->create_options == create_options) { + if (f->handle->create_options == create_options) { return NT_STATUS_OK; } - if ((f->name->dos.attrib & FILE_ATTRIBUTE_READONLY) && + if ((f->handle->name->dos.attrib & FILE_ATTRIBUTE_READONLY) && (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { return NT_STATUS_CANNOT_DELETE; } - lck = odb_lock(req, pvfs->odb_context, &f->locking_key); + lck = odb_lock(req, pvfs->odb_context, &f->handle->locking_key); if (lck == NULL) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } - status = odb_set_create_options(lck, f->fnum, create_options); + status = odb_set_create_options(lck, f->handle, create_options); if (NT_STATUS_IS_OK(status)) { - f->create_options = create_options; + f->handle->create_options = create_options; } return status; -- cgit From c077300a22806bab94d11a87c8ef96b6b541ada5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 8 Nov 2004 11:35:49 +0000 Subject: r3618: - this adds the special case for DENY_DOS semantics, as shown by the BASE-DENYDOS test. - pvfs now passes BASE-DENY1 and BASE-DENYDOS. (This used to be commit aa09df22ee729c02552638859236d9068e9748ae) --- source4/ntvfs/posix/pvfs_open.c | 154 +++++++++++++++++++++++++++++++--------- 1 file changed, 119 insertions(+), 35 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 5411f83e8d..cfd2b0f159 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -147,19 +147,20 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_TOO_MANY_OPENED_FILES; } - f->fnum = fnum; - f->session = req->session; - f->smbpid = req->smbpid; - f->pvfs = pvfs; - f->pending_list = NULL; - f->lock_count = 0; + f->fnum = fnum; + f->session = req->session; + f->smbpid = req->smbpid; + f->pvfs = pvfs; + f->pending_list = NULL; + f->lock_count = 0; + f->share_access = io->generic.in.share_access; + f->impersonation = io->generic.in.impersonation; f->handle->pvfs = pvfs; f->handle->name = talloc_steal(f->handle, name); f->handle->fd = -1; f->handle->locking_key = data_blob(NULL, 0); f->handle->create_options = io->generic.in.create_options; - f->handle->share_access = io->generic.in.share_access; f->handle->seek_offset = 0; f->handle->position = 0; f->handle->mode = 0; @@ -326,11 +327,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, access_mask = GENERIC_RIGHTS_FILE_READ | GENERIC_RIGHTS_FILE_WRITE; } - if ((access_mask & SA_RIGHT_FILE_READ_EXEC) && - (access_mask & SA_RIGHT_FILE_WRITE_APPEND)) { + if (access_mask & SA_RIGHT_FILE_WRITE_APPEND) { flags = O_RDWR; - } else if (access_mask & SA_RIGHT_FILE_WRITE_APPEND) { - flags = O_WRONLY; } else { flags = O_RDONLY; } @@ -407,19 +405,20 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return status; } - f->fnum = fnum; - f->session = req->session; - f->smbpid = req->smbpid; - f->pvfs = pvfs; - f->pending_list = NULL; - f->lock_count = 0; + f->fnum = fnum; + f->session = req->session; + f->smbpid = req->smbpid; + f->pvfs = pvfs; + f->pending_list = NULL; + f->lock_count = 0; + f->share_access = io->generic.in.share_access; + f->access_mask = access_mask; + f->impersonation = io->generic.in.impersonation; f->handle->pvfs = pvfs; f->handle->name = talloc_steal(f->handle, name); f->handle->fd = fd; f->handle->create_options = io->generic.in.create_options; - f->handle->share_access = io->generic.in.share_access; - f->handle->access_mask = access_mask; f->handle->seek_offset = 0; f->handle->position = 0; f->handle->mode = 0; @@ -535,6 +534,86 @@ static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason) } +/* + special handling for openx DENY_DOS semantics + + This function attempts a reference open using an existing handle. If its allowed, + then it returns NT_STATUS_OK, otherwise it returns any other code and normal + open processing continues. +*/ +static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, + struct smbsrv_request *req, union smb_open *io, + struct pvfs_file *f, struct odb_lock *lck) +{ + struct pvfs_state *pvfs = ntvfs->private_data; + struct pvfs_file *f2; + struct pvfs_filename *name; + + /* search for an existing open with the right parameters. Note + the magic ntcreatex options flag, which is set in the + generic mapping code. This might look ugly, but its + actually pretty much now w2k does it internally as well. + + If you look at the BASE-DENYDOS test you will see that a + DENY_DOS is a very special case, and in the right + circumstances you actually get the _same_ handle back + twice, rather than a new handle. + */ + for (f2=pvfs->open_files;f2;f2=f2->next) { + if (f2 != f && + f2->session == req->session && + f2->smbpid == req->smbpid && + (f2->handle->create_options & + (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | + NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) && + (f2->access_mask & SA_RIGHT_FILE_WRITE_DATA) && + StrCaseCmp(f2->handle->name->original_name, + io->generic.in.fname)==0) { + break; + } + } + + if (!f2) { + return NT_STATUS_SHARING_VIOLATION; + } + + /* quite an insane set of semantics ... */ + if (is_exe_filename(io->generic.in.fname) && + (f2->handle->create_options & NTCREATEX_OPTIONS_PRIVATE_DENY_DOS)) { + return NT_STATUS_SHARING_VIOLATION; + } + + /* + setup a reference to the existing handle + */ + talloc_free(f->handle); + f->handle = talloc_reference(f, f2->handle); + + talloc_free(lck); + + name = f->handle->name; + + io->generic.out.oplock_level = NO_OPLOCK; + io->generic.out.fnum = f->fnum; + io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; + io->generic.out.create_time = name->dos.create_time; + io->generic.out.access_time = name->dos.access_time; + io->generic.out.write_time = name->dos.write_time; + io->generic.out.change_time = name->dos.change_time; + io->generic.out.attrib = name->dos.attrib; + io->generic.out.alloc_size = name->dos.alloc_size; + io->generic.out.size = name->st.st_size; + io->generic.out.file_type = FILE_TYPE_DISK; + io->generic.out.ipc_state = 0; + io->generic.out.is_directory = 0; + + talloc_steal(f->pvfs, f); + + return NT_STATUS_OK; +} + + + /* setup for a open retry after a sharing violation */ @@ -549,6 +628,16 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, NTSTATUS status; struct timeval end_time; + if (io->generic.in.create_options & + (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { + /* see if we can satisfy the request using the special DENY_DOS + code */ + status = pvfs_open_deny_dos(ntvfs, req, io, f, lck); + if (NT_STATUS_IS_OK(status)) { + return status; + } + } + r = talloc_p(req, struct pvfs_open_retry); if (r == NULL) { return NT_STATUS_NO_MEMORY; @@ -638,10 +727,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } /* use the generic mapping code to avoid implementing all the - different open calls. This won't allow openx to work - perfectly as the mapping code has no way of knowing if two - opens are on the same connection, so this will need to - change eventually */ + different open calls. */ if (io->generic.level != RAW_OPEN_GENERIC) { return ntvfs_map_open(req, io, ntvfs); } @@ -715,11 +801,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } - if ((access_mask & SA_RIGHT_FILE_READ_EXEC) && - (access_mask & SA_RIGHT_FILE_WRITE_APPEND)) { + if (access_mask & SA_RIGHT_FILE_WRITE_APPEND) { flags |= O_RDWR; - } else if (access_mask & SA_RIGHT_FILE_WRITE_APPEND) { - flags |= O_WRONLY; } else { flags |= O_RDONLY; } @@ -766,19 +849,20 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_TOO_MANY_OPENED_FILES; } - f->fnum = fnum; - f->session = req->session; - f->smbpid = req->smbpid; - f->pvfs = pvfs; - f->pending_list = NULL; - f->lock_count = 0; + f->fnum = fnum; + f->session = req->session; + f->smbpid = req->smbpid; + f->pvfs = pvfs; + f->pending_list = NULL; + f->lock_count = 0; + f->share_access = io->generic.in.share_access; + f->access_mask = access_mask; + f->impersonation = io->generic.in.impersonation; f->handle->pvfs = pvfs; f->handle->fd = -1; f->handle->name = talloc_steal(f->handle, name); f->handle->create_options = io->generic.in.create_options; - f->handle->share_access = io->generic.in.share_access; - f->handle->access_mask = access_mask; f->handle->seek_offset = 0; f->handle->position = 0; f->handle->have_opendb_entry = False; -- cgit From 47b91c97cd5ec323b9c3b73bfa7951f8105da732 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 9 Nov 2004 02:12:57 +0000 Subject: r3631: a couple of tweaks to the talloc hierarchy for async requests in pvfs. This prevents a possible crash due to free ordering on unexpected disconnect. (This used to be commit bfca9eb7cb7a2caf3a232d538808ff2ade8e1ca9) --- source4/ntvfs/posix/pvfs_open.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index cfd2b0f159..cc4498eee1 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -669,6 +669,8 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, return NT_STATUS_NO_MEMORY; } + talloc_steal(pvfs, r); + return NT_STATUS_OK; } -- cgit From 1c59d825afc3cdfe2ea42821123ece934ad7b5e0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 13 Nov 2004 05:47:27 +0000 Subject: r3717: - expanded the RAW-RENAME test a little - added support for wildcard rename in pvfs - made more consistent use of pvfs_map_errno() (This used to be commit e255d1c3a811c480a850452aaf636d9fa36f69fe) --- source4/ntvfs/posix/pvfs_open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index cc4498eee1..af0f46ece3 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -937,7 +937,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, mode_t mode = pvfs_fileperms(pvfs, attrib); if (fchmod(fd, mode) == -1) { talloc_free(lck); - return map_nt_error_from_unix(errno); + return pvfs_map_errno(pvfs, errno); } name->dos.attrib = attrib; status = pvfs_dosattrib_save(pvfs, name, fd); -- cgit From 1b2b72ff61c6e81189fd0552bfce5d2c7d365554 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 13 Nov 2004 06:46:51 +0000 Subject: r3718: added support for the ntrename level in pvfs_rename(). (This used to be commit 3d50982f5419b9a5c53f2b82a2313669cdeaaa21) --- source4/ntvfs/posix/pvfs_open.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index af0f46ece3..b07922dcbd 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1118,8 +1118,7 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, struct pvfs_filename *name) status = odb_can_open(pvfs->odb_context, &key, NTCREATEX_SHARE_ACCESS_READ | - NTCREATEX_SHARE_ACCESS_WRITE | - NTCREATEX_SHARE_ACCESS_DELETE, + NTCREATEX_SHARE_ACCESS_WRITE, 0, STD_RIGHT_DELETE_ACCESS); -- cgit From 24a40fb41280a9eb22be89699c76eeeb8aab7111 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 14 Nov 2004 23:37:02 +0000 Subject: r3741: FILE_ATTRIBUTE_DIRECTORY is illegal in open of a file (This used to be commit ad7815fababe5783df5e8fb4a490921a5af693d6) --- source4/ntvfs/posix/pvfs_open.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index b07922dcbd..9bb3487679 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -809,6 +809,10 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, flags |= O_RDONLY; } + if (io->generic.in.file_attr & FILE_ATTRIBUTE_DIRECTORY) { + return NT_STATUS_INVALID_PARAMETER; + } + /* handle creating a new file separately */ if (!name->exists) { status = pvfs_create_file(pvfs, req, name, io); -- 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_open.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 9bb3487679..4f089a8c07 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -103,6 +103,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, NTSTATUS status; uint32_t create_action; + if (name->stream_name) { + return NT_STATUS_OBJECT_NAME_INVALID; + } + /* if the client says it must be a directory, and it isn't, then fail */ if (name->exists && !(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) { @@ -180,8 +184,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, if (mkdir(name->full_name, mode) == -1) { return pvfs_map_errno(pvfs,errno); } - status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, - PVFS_RESOLVE_NO_WILDCARD, &name); + status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 0, &name); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -684,8 +687,7 @@ static NTSTATUS pvfs_open_t2open(struct ntvfs_module_context *ntvfs, struct pvfs_filename *name; NTSTATUS status; - status = pvfs_resolve_name(pvfs, req, io->t2open.in.fname, - PVFS_RESOLVE_NO_WILDCARD, &name); + status = pvfs_resolve_name(pvfs, req, io->t2open.in.fname, 0, &name); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -735,8 +737,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } /* resolve the cifs name to a posix name */ - status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, - PVFS_RESOLVE_NO_WILDCARD, &name); + status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, + PVFS_RESOLVE_STREAMS, &name); if (!NT_STATUS_IS_OK(status)) { return status; } @@ -826,8 +828,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } /* try re-resolving the name */ - status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, - PVFS_RESOLVE_NO_WILDCARD, &name); + status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 0, &name); if (!NT_STATUS_IS_OK(status)) { return status; } -- 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_open.c | 126 +++++++++++++++++++++++++++++++--------- 1 file changed, 97 insertions(+), 29 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 4f089a8c07..a772feb623 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -104,7 +104,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, uint32_t create_action; if (name->stream_name) { - return NT_STATUS_OBJECT_NAME_INVALID; + return NT_STATUS_NOT_A_DIRECTORY; } /* if the client says it must be a directory, and it isn't, @@ -163,7 +163,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->handle->pvfs = pvfs; f->handle->name = talloc_steal(f->handle, name); f->handle->fd = -1; - f->handle->locking_key = data_blob(NULL, 0); + f->handle->odb_locking_key = data_blob(NULL, 0); + f->handle->brl_locking_key = data_blob(NULL, 0); f->handle->create_options = io->generic.in.create_options; f->handle->seek_offset = 0; f->handle->position = 0; @@ -243,7 +244,7 @@ static int pvfs_handle_destructor(void *p) struct odb_lock *lck; NTSTATUS status; - lck = odb_lock(h, h->pvfs->odb_context, &h->locking_key); + lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key); if (lck == NULL) { DEBUG(0,("Unable to lock opendb for close\n")); return 0; @@ -278,9 +279,8 @@ static int pvfs_fnum_destructor(void *p) /* - form the lock context used for byte range locking and opendb - locking. Note that we must zero here to take account of - possible padding on some architectures + form the lock context used for opendb locking. Note that we must + zero here to take account of possible padding on some architectures */ static NTSTATUS pvfs_locking_key(struct pvfs_filename *name, TALLOC_CTX *mem_ctx, DATA_BLOB *key) @@ -302,6 +302,37 @@ static NTSTATUS pvfs_locking_key(struct pvfs_filename *name, return NT_STATUS_OK; } +/* + form the lock context used for byte range locking. This is separate + from the locking key used for opendb locking as it needs to take + account of file streams (each stream is a separate byte range + locking space) +*/ +static NTSTATUS pvfs_brl_locking_key(struct pvfs_filename *name, + TALLOC_CTX *mem_ctx, DATA_BLOB *key) +{ + DATA_BLOB odb_key; + NTSTATUS status; + status = pvfs_locking_key(name, mem_ctx, &odb_key); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if (name->stream_name == NULL) { + *key = odb_key; + return NT_STATUS_OK; + } + *key = data_blob_talloc(mem_ctx, NULL, + odb_key.length + strlen(name->stream_name) + 1); + if (key->data == NULL) { + return NT_STATUS_NO_MEMORY; + } + memcpy(key->data, odb_key.data, odb_key.length); + memcpy(key->data + odb_key.length, + name->stream_name, strlen(name->stream_name)+1); + data_blob_free(&odb_key); + return NT_STATUS_OK; +} + /* create a new file @@ -361,6 +392,16 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return pvfs_map_errno(pvfs, errno); } + /* if this was a stream create then create the stream as well */ + if (name->stream_name) { + status = pvfs_stream_create(pvfs, name, fd); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); + close(fd); + return status; + } + } + /* re-resolve the open fd */ status = pvfs_resolve_name_fd(pvfs, fd, name); if (!NT_STATUS_IS_OK(status)) { @@ -379,7 +420,14 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* form the lock context used for byte range locking and opendb locking */ - status = pvfs_locking_key(name, f->handle, &f->handle->locking_key); + status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); + close(fd); + return status; + } + + status = pvfs_brl_locking_key(name, f->handle, &f->handle->brl_locking_key); if (!NT_STATUS_IS_OK(status)) { idr_remove(pvfs->idtree_fnum, fnum); close(fd); @@ -387,7 +435,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } /* grab a lock on the open file record */ - lck = odb_lock(req, pvfs->odb_context, &f->handle->locking_key); + lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key); if (lck == NULL) { DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n", name->full_name)); @@ -398,7 +446,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - status = odb_open_file(lck, f->handle, + status = odb_open_file(lck, f->handle, name->stream_id, share_access, create_options, access_mask); talloc_free(lck); if (!NT_STATUS_IS_OK(status)) { @@ -463,7 +511,7 @@ struct pvfs_open_retry { struct smbsrv_request *req; union smb_open *io; void *wait_handle; - DATA_BLOB locking_key; + DATA_BLOB odb_locking_key; }; /* destroy a pending open request */ @@ -471,9 +519,9 @@ static int pvfs_retry_destructor(void *ptr) { struct pvfs_open_retry *r = ptr; struct pvfs_state *pvfs = r->ntvfs->private_data; - if (r->locking_key.data) { + if (r->odb_locking_key.data) { struct odb_lock *lck; - lck = odb_lock(r->req, pvfs->odb_context, &r->locking_key); + lck = odb_lock(r->req, pvfs->odb_context, &r->odb_locking_key); if (lck != NULL) { odb_remove_pending(lck, r); } @@ -512,7 +560,7 @@ static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason) /* the pending odb entry is already removed. We use a null locking key to indicate this */ - data_blob_free(&r->locking_key); + data_blob_free(&r->odb_locking_key); talloc_free(r); /* try the open again, which could trigger another retry setup @@ -649,9 +697,9 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, r->ntvfs = ntvfs; r->req = req; r->io = io; - r->locking_key = data_blob_talloc(r, - f->handle->locking_key.data, - f->handle->locking_key.length); + r->odb_locking_key = data_blob_talloc(r, + f->handle->odb_locking_key.data, + f->handle->odb_locking_key.length); end_time = timeval_add(&req->request_time, 0, pvfs->sharing_violation_delay); @@ -693,14 +741,14 @@ static NTSTATUS pvfs_open_t2open(struct ntvfs_module_context *ntvfs, } if (io->t2open.in.open_func & OPENX_OPEN_FUNC_CREATE) { - if (!name->exists) return NT_STATUS_ACCESS_DENIED; + if (!name->stream_exists) return NT_STATUS_ACCESS_DENIED; } if (io->t2open.in.open_func & OPENX_OPEN_FUNC_TRUNC) { - if (name->exists) return NT_STATUS_ACCESS_DENIED; + if (name->stream_exists) return NT_STATUS_ACCESS_DENIED; return NT_STATUS_OBJECT_NAME_NOT_FOUND; } if ((io->t2open.in.open_func & 0xF) == OPENX_OPEN_FUNC_FAIL) { - if (!name->exists) return NT_STATUS_ACCESS_DENIED; + if (!name->stream_exists) return NT_STATUS_ACCESS_DENIED; return NT_STATUS_OBJECT_NAME_COLLISION; } @@ -725,6 +773,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, uint32_t create_options; uint32_t share_access; uint32_t access_mask; + BOOL stream_existed; if (io->generic.level == RAW_OPEN_T2OPEN) { return pvfs_open_t2open(ntvfs, req, io); @@ -777,21 +826,21 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, break; case NTCREATEX_DISP_OPEN: - if (!name->exists) { + if (!name->stream_exists) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } flags = 0; break; case NTCREATEX_DISP_OVERWRITE: - if (!name->exists) { + if (!name->stream_exists) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } flags = O_TRUNC; break; case NTCREATEX_DISP_CREATE: - if (name->exists) { + if (name->stream_exists) { return NT_STATUS_OBJECT_NAME_COLLISION; } flags = 0; @@ -876,14 +925,20 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* form the lock context used for byte range locking and opendb locking */ - status = pvfs_locking_key(name, f->handle, &f->handle->locking_key); + status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, f->fnum); + return status; + } + + status = pvfs_brl_locking_key(name, f->handle, &f->handle->brl_locking_key); if (!NT_STATUS_IS_OK(status)) { idr_remove(pvfs->idtree_fnum, f->fnum); return status; } /* get a lock on this file before the actual open */ - lck = odb_lock(req, pvfs->odb_context, &f->handle->locking_key); + lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key); if (lck == NULL) { DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n", name->full_name)); @@ -902,7 +957,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* see if we are allowed to open at the same time as existing opens */ - status = odb_open_file(lck, f->handle, + status = odb_open_file(lck, f->handle, f->handle->name->stream_id, share_access, create_options, access_mask); /* on a sharing violation we need to retry when the file is closed by @@ -928,6 +983,17 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->handle->fd = fd; + stream_existed = name->stream_exists; + + /* if this was a stream create then create the stream as well */ + if (!name->stream_exists) { + status = pvfs_stream_create(pvfs, f->handle->name, fd); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + return status; + } + } + /* re-resolve the open fd */ status = pvfs_resolve_name_fd(f->pvfs, fd, f->handle->name); if (!NT_STATUS_IS_OK(status)) { @@ -935,8 +1001,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } - if (io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE || - io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE_IF) { + if (f->handle->name->stream_id == 0 && + (io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE || + io->generic.in.open_disposition == NTCREATEX_DISP_OVERWRITE_IF)) { /* for overwrite we need to replace file permissions */ uint32_t attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE; mode_t mode = pvfs_fileperms(pvfs, attrib); @@ -956,7 +1023,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, io->generic.out.oplock_level = NO_OPLOCK; io->generic.out.fnum = f->fnum; - io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; + io->generic.out.create_action = stream_existed? + NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; io->generic.out.write_time = name->dos.write_time; @@ -1069,7 +1137,7 @@ NTSTATUS pvfs_change_create_options(struct pvfs_state *pvfs, return NT_STATUS_CANNOT_DELETE; } - lck = odb_lock(req, pvfs->odb_context, &f->handle->locking_key); + lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key); if (lck == NULL) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } -- cgit From 856f663adc2459044f7a20c2974bcb41ed561f77 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 17 Nov 2004 06:44:50 +0000 Subject: r3800: - fixed delete-on-close behaviour for streams - added a delete-on-close test to RAW-STREAMS - don't allow rename of streams at the moment (I need to work out if its supposed to be allowed first) (This used to be commit f4b2b1311da6e37ac0947a3419d89c77ebbd6b63) --- source4/ntvfs/posix/pvfs_open.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index a772feb623..d8f3342f0d 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -225,6 +225,16 @@ static int pvfs_handle_destructor(void *p) { struct pvfs_file_handle *h = p; + if ((h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && + h->name->stream_name) { + NTSTATUS status; + status = pvfs_stream_delete(h->pvfs, h->name, h->fd); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Failed to delete stream '%s' on close of '%s'\n", + h->name->stream_name, h->name->full_name)); + } + } + if (h->fd != -1) { if (close(h->fd) != 0) { DEBUG(0,("pvfs_handle_destructor: close(%d) failed for %s - %s\n", @@ -233,7 +243,8 @@ static int pvfs_handle_destructor(void *p) h->fd = -1; } - if (h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { + if ((h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && + h->name->stream_name == NULL) { if (unlink(h->name->full_name) != 0) { DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n", h->name->full_name, strerror(errno))); -- cgit From 696fdc8cf91cc1660725fd93c2b91ec6b65d06b5 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 17 Nov 2004 12:36:14 +0000 Subject: r3806: added support to smb_server and pvfs for the NTTRANS Create call. This call has an optional sec_desc and ea_list. (This used to be commit 8379ad14e3d51a848a99865d9ce8d56a301e8a3c) --- source4/ntvfs/posix/pvfs_open.c | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index d8f3342f0d..1b9538d7e2 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -429,6 +429,20 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return status; } + /* setup any EAs that were asked for */ + if (io->ntcreatex.in.ea_list) { + int i; + for (i=0;intcreatex.in.ea_list->num_eas;i++) { + status = pvfs_setfileinfo_ea_set(pvfs, name, fd, + &io->ntcreatex.in.ea_list->eas[i]); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); + close(fd); + return status; + } + } + } + /* form the lock context used for byte range locking and opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); @@ -792,7 +806,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* use the generic mapping code to avoid implementing all the different open calls. */ - if (io->generic.level != RAW_OPEN_GENERIC) { + if (io->generic.level != RAW_OPEN_GENERIC && + io->generic.level != RAW_OPEN_NTTRANS_CREATE) { return ntvfs_map_open(req, io, ntvfs); } -- cgit From 85215a9a265b006497ec365d421be1f2b54cdca1 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 18 Nov 2004 03:59:24 +0000 Subject: r3835: - added testing of setting an initial ACL on a file using NTTRANS create - added support for initial ACLs in pvfs backend (This used to be commit 05ee9179f74d243aa22fa00be7873c5db76a8ad1) --- source4/ntvfs/posix/pvfs_open.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 1b9538d7e2..5a23ffaa67 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -443,6 +443,22 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } } + /* setup an initial sec_desc is required */ + if (io->ntcreatex.in.sec_desc) { + union smb_setfileinfo set; + + set.set_secdesc.file.fnum = fnum; + set.set_secdesc.in.secinfo_flags = DACL_SECURITY_INFORMATION; + set.set_secdesc.in.sd = io->ntcreatex.in.sec_desc; + + status = pvfs_acl_set(pvfs, req, name, fd, &set); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); + close(fd); + return status; + } + } + /* form the lock context used for byte range locking and opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); -- cgit From f2a605eeab5752e4884987496f2661368f85b271 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 24 Nov 2004 06:09:14 +0000 Subject: r3939: - added "posix:fakeoplocks" option for testing with oplocks forced on - added support for sticky write times after a setfileinfo, by using a write_time field in the DosAttrib xattr structure. (This used to be commit 4a52fae82d8305e999f94f1947daa21dab54cdfd) --- source4/ntvfs/posix/pvfs_open.c | 56 ++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 14 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 5a23ffaa67..3d0e444d29 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -26,6 +26,7 @@ #include "system/filesys.h" #include "dlinklist.h" #include "messages.h" +#include "librpc/gen_ndr/ndr_xattr.h" /* create file handles with convenient numbers for sniffers @@ -160,15 +161,16 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->share_access = io->generic.in.share_access; f->impersonation = io->generic.in.impersonation; - f->handle->pvfs = pvfs; - f->handle->name = talloc_steal(f->handle, name); - f->handle->fd = -1; - f->handle->odb_locking_key = data_blob(NULL, 0); - f->handle->brl_locking_key = data_blob(NULL, 0); - f->handle->create_options = io->generic.in.create_options; - f->handle->seek_offset = 0; - f->handle->position = 0; - f->handle->mode = 0; + f->handle->pvfs = pvfs; + f->handle->name = talloc_steal(f->handle, name); + f->handle->fd = -1; + f->handle->odb_locking_key = data_blob(NULL, 0); + f->handle->brl_locking_key = data_blob(NULL, 0); + f->handle->create_options = io->generic.in.create_options; + f->handle->seek_offset = 0; + f->handle->position = 0; + f->handle->mode = 0; + f->handle->sticky_write_time = False; DLIST_ADD(pvfs->open_files, f); @@ -201,7 +203,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* the open succeeded, keep this handle permanently */ talloc_steal(pvfs, f); - io->generic.out.oplock_level = NO_OPLOCK; + io->generic.out.oplock_level = OPLOCK_NONE; io->generic.out.fnum = f->fnum; io->generic.out.create_action = create_action; io->generic.out.create_time = name->dos.create_time; @@ -225,6 +227,16 @@ static int pvfs_handle_destructor(void *p) { struct pvfs_file_handle *h = p; + /* the write time is no longer sticky */ + if (h->sticky_write_time) { + NTSTATUS status; + status = pvfs_dosattrib_load(h->pvfs, h->name, h->fd); + if (NT_STATUS_IS_OK(status)) { + h->name->dos.flags &= ~XATTR_ATTRIB_FLAG_STICKY_WRITE_TIME; + pvfs_dosattrib_save(h->pvfs, h->name, h->fd); + } + } + if ((h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && h->name->stream_name) { NTSTATUS status; @@ -515,6 +527,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->handle->position = 0; f->handle->mode = 0; f->handle->have_opendb_entry = True; + f->handle->sticky_write_time = False; DLIST_ADD(pvfs->open_files, f); @@ -523,7 +536,12 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, talloc_set_destructor(f, pvfs_fnum_destructor); talloc_set_destructor(f->handle, pvfs_handle_destructor); - io->generic.out.oplock_level = NO_OPLOCK; + + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { + io->generic.out.oplock_level = OPLOCK_EXCLUSIVE; + } else { + io->generic.out.oplock_level = OPLOCK_NONE; + } io->generic.out.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_CREATED; io->generic.out.create_time = name->dos.create_time; @@ -685,7 +703,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, name = f->handle->name; - io->generic.out.oplock_level = NO_OPLOCK; + io->generic.out.oplock_level = OPLOCK_NONE; io->generic.out.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; io->generic.out.create_time = name->dos.create_time; @@ -963,7 +981,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->handle->create_options = io->generic.in.create_options; f->handle->seek_offset = 0; f->handle->position = 0; + f->handle->mode = 0; f->handle->have_opendb_entry = False; + f->handle->sticky_write_time = False; /* form the lock context used for byte range locking and opendb locking */ @@ -1063,7 +1083,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, talloc_free(lck); - io->generic.out.oplock_level = NO_OPLOCK; + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { + io->generic.out.oplock_level = OPLOCK_EXCLUSIVE; + } else { + io->generic.out.oplock_level = OPLOCK_NONE; + } io->generic.out.fnum = f->fnum; io->generic.out.create_action = stream_existed? NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED; @@ -1112,8 +1136,12 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, unix_times.actime = 0; unix_times.modtime = io->close.in.write_time; utime(f->handle->name->full_name, &unix_times); + } else if (f->handle->sticky_write_time) { + unix_times.actime = 0; + unix_times.modtime = nt_time_to_unix(f->handle->name->dos.write_time); + utime(f->handle->name->full_name, &unix_times); } - + talloc_free(f); return NT_STATUS_OK; -- cgit From fdc9f417d89fdf9dd6afbc22843d70585e195c9d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 30 Nov 2004 04:33:27 +0000 Subject: r4011: get rid of rpc_secdes.h and replace it with a single sane set of definitions for security access masks, in security.idl The previous definitions were inconsistently named, and contained many duplicate and misleading entries. I kept finding myself tripping up while using them. (This used to be commit 01c0fa722f80ceeb3f81f01987de95f365a2ed3d) --- source4/ntvfs/posix/pvfs_open.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 3d0e444d29..4b8de28488 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -380,11 +380,11 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return NT_STATUS_CANNOT_DELETE; } - if (access_mask & SEC_RIGHT_MAXIMUM_ALLOWED) { - access_mask = GENERIC_RIGHTS_FILE_READ | GENERIC_RIGHTS_FILE_WRITE; + if (access_mask & SEC_FLAG_MAXIMUM_ALLOWED) { + access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE; } - if (access_mask & SA_RIGHT_FILE_WRITE_APPEND) { + if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) { flags = O_RDWR; } else { flags = O_RDONLY; @@ -460,7 +460,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, union smb_setfileinfo set; set.set_secdesc.file.fnum = fnum; - set.set_secdesc.in.secinfo_flags = DACL_SECURITY_INFORMATION; + set.set_secdesc.in.secinfo_flags = SECINFO_DACL; set.set_secdesc.in.sd = io->ntcreatex.in.sec_desc; status = pvfs_acl_set(pvfs, req, name, fd, &set); @@ -676,7 +676,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, (f2->handle->create_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) && - (f2->access_mask & SA_RIGHT_FILE_WRITE_DATA) && + (f2->access_mask & SEC_FILE_WRITE_DATA) && StrCaseCmp(f2->handle->name->original_name, io->generic.in.fname)==0) { break; @@ -862,17 +862,17 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, share_access = io->generic.in.share_access; access_mask = io->generic.in.access_mask; - if (access_mask & SEC_RIGHT_MAXIMUM_ALLOWED) { + if (access_mask & SEC_FLAG_MAXIMUM_ALLOWED) { if (name->exists && (name->dos.attrib & FILE_ATTRIBUTE_READONLY)) { - access_mask = GENERIC_RIGHTS_FILE_READ; + access_mask = SEC_RIGHTS_FILE_READ; } else { - access_mask = GENERIC_RIGHTS_FILE_READ | GENERIC_RIGHTS_FILE_WRITE; + access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE; } } /* certain create options are not allowed */ if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && - !(access_mask & STD_RIGHT_DELETE_ACCESS)) { + !(access_mask & SEC_STD_DELETE)) { return NT_STATUS_INVALID_PARAMETER; } @@ -914,7 +914,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } - if (access_mask & SA_RIGHT_FILE_WRITE_APPEND) { + if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) { flags |= O_RDWR; } else { flags |= O_RDONLY; @@ -1240,7 +1240,7 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, struct pvfs_filename *name) NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE, NTCREATEX_OPTIONS_DELETE_ON_CLOSE, - STD_RIGHT_DELETE_ACCESS); + SEC_STD_DELETE); return status; } @@ -1263,7 +1263,7 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, struct pvfs_filename *name) NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE, 0, - STD_RIGHT_DELETE_ACCESS); + SEC_STD_DELETE); return status; } -- cgit From a8a3fec528f6ee9a4a0171fb4186e8dcaba76518 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 1 Dec 2004 11:35:01 +0000 Subject: r4026: added NT ACL checking on pvfs_open() for existing files. I need to work out some way to do a decent test suite for this. (This used to be commit 9a9a0d0e791e4b64f0a35c921729e623b977af47) --- source4/ntvfs/posix/pvfs_open.c | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 4b8de28488..17740f7636 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -862,14 +862,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, share_access = io->generic.in.share_access; access_mask = io->generic.in.access_mask; - if (access_mask & SEC_FLAG_MAXIMUM_ALLOWED) { - if (name->exists && (name->dos.attrib & FILE_ATTRIBUTE_READONLY)) { - access_mask = SEC_RIGHTS_FILE_READ; - } else { - access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE; - } - } - /* certain create options are not allowed */ if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && !(access_mask & SEC_STD_DELETE)) { @@ -914,12 +906,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } - if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) { - flags |= O_RDWR; - } else { - flags |= O_RDONLY; - } - if (io->generic.in.file_attr & FILE_ATTRIBUTE_DIRECTORY) { return NT_STATUS_INVALID_PARAMETER; } @@ -949,6 +935,12 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_CANNOT_DELETE; } + /* check the security descriptor */ + status = pvfs_access_check(pvfs, req, name, &access_mask); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + f = talloc_p(req, struct pvfs_file); if (f == NULL) { return NT_STATUS_NO_MEMORY; @@ -1036,6 +1028,12 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->handle->have_opendb_entry = True; + if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) { + flags |= O_RDWR; + } else { + flags |= O_RDONLY; + } + /* do the actual open */ fd = open(f->handle->name->full_name, flags); if (fd == -1) { -- cgit From 4127edc1afd702ac3bcb77893ba864eb98729451 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sat, 4 Dec 2004 12:42:40 +0000 Subject: r4062: the RAW-ACLS test now passes. The SEC_STD_DELETE bit is rather strange though - I expect we'll need to tweak that some more. (This used to be commit e3500811b90b8423ee7694609340f394957d1160) --- source4/ntvfs/posix/pvfs_open.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 17740f7636..a53deda270 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -103,6 +103,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, int fnum; NTSTATUS status; uint32_t create_action; + uint32_t access_mask = io->generic.in.access_mask; if (name->stream_name) { return NT_STATUS_NOT_A_DIRECTORY; @@ -152,6 +153,14 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_TOO_MANY_OPENED_FILES; } + if (name->exists) { + /* check the security descriptor */ + status = pvfs_access_check(pvfs, req, name, &access_mask); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + f->fnum = fnum; f->session = req->session; f->smbpid = req->smbpid; @@ -160,6 +169,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->lock_count = 0; f->share_access = io->generic.in.share_access; f->impersonation = io->generic.in.impersonation; + f->access_mask = access_mask; f->handle->pvfs = pvfs; f->handle->name = talloc_steal(f->handle, name); -- cgit From fbd8c61ff7a7c41d16c400ddb87ad290f4af167d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 13 Dec 2004 10:48:21 +0000 Subject: r4173: - new t2open code, that can cope with "create with EAs". Many thanks to kukks on #samba-technical for the sniffs that allowed me to work this out - much simpler ntvfs open generic mapping code - added t2open create with EA torture test to RAW-OPEN test (This used to be commit a56d95ad89b4f32a05974c4fe9a816d67aa369e3) --- source4/ntvfs/posix/pvfs_open.c | 36 ------------------------------------ 1 file changed, 36 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index a53deda270..af0858f639 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -794,38 +794,6 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, return NT_STATUS_OK; } -/* - special handling for t2open -*/ -static NTSTATUS pvfs_open_t2open(struct ntvfs_module_context *ntvfs, - struct smbsrv_request *req, union smb_open *io) -{ - struct pvfs_state *pvfs = ntvfs->private_data; - struct pvfs_filename *name; - NTSTATUS status; - - status = pvfs_resolve_name(pvfs, req, io->t2open.in.fname, 0, &name); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - if (io->t2open.in.open_func & OPENX_OPEN_FUNC_CREATE) { - if (!name->stream_exists) return NT_STATUS_ACCESS_DENIED; - } - if (io->t2open.in.open_func & OPENX_OPEN_FUNC_TRUNC) { - if (name->stream_exists) return NT_STATUS_ACCESS_DENIED; - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - if ((io->t2open.in.open_func & 0xF) == OPENX_OPEN_FUNC_FAIL) { - if (!name->stream_exists) return NT_STATUS_ACCESS_DENIED; - return NT_STATUS_OBJECT_NAME_COLLISION; - } - - talloc_free(name); - - return ntvfs_map_open(req, io, ntvfs); -} - /* open a file */ @@ -844,10 +812,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, uint32_t access_mask; BOOL stream_existed; - if (io->generic.level == RAW_OPEN_T2OPEN) { - return pvfs_open_t2open(ntvfs, req, io); - } - /* use the generic mapping code to avoid implementing all the different open calls. */ if (io->generic.level != RAW_OPEN_GENERIC && -- cgit From 50005129ab0a5c5f2422460e6d7c19616e5e1124 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 17 Dec 2004 03:39:29 +0000 Subject: r4242: added support for storing xattrs in a tdb. This allows all advanced NT attributes (streams, EAs, NT ACLs, timestamps etc) to be used on filesystems that don't support xattrs. It also allows for large streams, although they are very inefficient. I won't enable this by default, as I really wrote it as a way of testing large stream support while still using ext3, but perhaps with a bit more work this could be generally usable. To enable this use: posix:eadb = /home/test/myeas.tdb (This used to be commit 0c927d912cb65754351189d3a0442004a14aa5c6) --- source4/ntvfs/posix/pvfs_open.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index af0858f639..e31d79b9e0 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -267,6 +267,12 @@ static int pvfs_handle_destructor(void *p) if ((h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && h->name->stream_name == NULL) { + NTSTATUS status; + status = pvfs_xattr_unlink_hook(h->pvfs, h->name->full_name); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n", + h->name->full_name, nt_errstr(status))); + } if (unlink(h->name->full_name) != 0) { DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n", h->name->full_name, strerror(errno))); -- cgit From 3b8e83a8c8f32ca658841f1fae344399a48d66a4 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 17 Dec 2004 04:51:23 +0000 Subject: r4243: a sniff from kukks showed that the ea_set interface in trans2 setfileinfo allows for multiple EAs to be set at once. This fixes all the ea code to allow for that. (This used to be commit b26828bef5d55e5eef0e34a164e76292df45e207) --- source4/ntvfs/posix/pvfs_open.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index e31d79b9e0..bd96b935ad 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -70,6 +70,11 @@ static int pvfs_dir_handle_destructor(void *p) struct pvfs_file_handle *h = p; if (h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { + NTSTATUS status = pvfs_xattr_unlink_hook(h->pvfs, h->name->full_name); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Warning: xattr rmdir hook failed for '%s' - %s\n", + h->name->full_name, nt_errstr(status))); + } if (rmdir(h->name->full_name) != 0) { DEBUG(0,("pvfs_close: failed to rmdir '%s' - %s\n", h->name->full_name, strerror(errno))); @@ -459,15 +464,13 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* setup any EAs that were asked for */ if (io->ntcreatex.in.ea_list) { - int i; - for (i=0;intcreatex.in.ea_list->num_eas;i++) { - status = pvfs_setfileinfo_ea_set(pvfs, name, fd, - &io->ntcreatex.in.ea_list->eas[i]); - if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, fnum); - close(fd); - return status; - } + status = pvfs_setfileinfo_ea_set(pvfs, name, fd, + io->ntcreatex.in.ea_list->num_eas, + io->ntcreatex.in.ea_list->eas); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); + close(fd); + return status; } } -- cgit From daae3bbb290ce0f4467c806acaefe3b1d6f4ae4d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 17 Dec 2004 06:35:11 +0000 Subject: r4247: two more places that need the unlink hook (This used to be commit 795897b64f3c63baaf53a36eb1611293c2fd8974) --- source4/ntvfs/posix/pvfs_open.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index bd96b935ad..7cb8a5d90c 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -202,6 +202,9 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, if (mkdir(name->full_name, mode) == -1) { return pvfs_map_errno(pvfs,errno); } + + pvfs_xattr_unlink_hook(pvfs, name->full_name); + status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 0, &name); if (!NT_STATUS_IS_OK(status)) { return status; @@ -436,6 +439,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return pvfs_map_errno(pvfs, errno); } + pvfs_xattr_unlink_hook(pvfs, name->full_name); + /* if this was a stream create then create the stream as well */ if (name->stream_name) { status = pvfs_stream_create(pvfs, name, fd); -- cgit From a66a985cde1606d0ed6f66f2dc80357b0f7d3363 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Dec 2004 11:44:32 +0000 Subject: r4314: added ACL checking on unlink (This used to be commit f25c469693517ed993e0379d8b07cd7eb235a669) --- source4/ntvfs/posix/pvfs_open.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 7cb8a5d90c..34052fc44a 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1211,7 +1211,9 @@ NTSTATUS pvfs_change_create_options(struct pvfs_state *pvfs, determine if a file can be deleted, or if it is prevented by an already open file */ -NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, struct pvfs_filename *name) +NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, + struct smbsrv_request *req, + struct pvfs_filename *name) { NTSTATUS status; DATA_BLOB key; @@ -1228,6 +1230,10 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, struct pvfs_filename *name) NTCREATEX_OPTIONS_DELETE_ON_CLOSE, SEC_STD_DELETE); + if (NT_STATUS_IS_OK(status)) { + status = pvfs_access_check_simple(pvfs, req, name, SEC_STD_DELETE); + } + return status; } -- 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_open.c | 116 +++++++++++++++++++++++++--------------- 1 file changed, 73 insertions(+), 43 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 34052fc44a..1695d8e1d9 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -95,6 +95,43 @@ static int pvfs_dir_fnum_destructor(void *p) return 0; } +/* + setup any EAs and the ACL on newly created files/directories +*/ +static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs, + struct smbsrv_request *req, + struct pvfs_filename *name, + int fd, int fnum, + union smb_open *io) +{ + NTSTATUS status; + + /* setup any EAs that were asked for */ + if (io->ntcreatex.in.ea_list) { + status = pvfs_setfileinfo_ea_set(pvfs, name, fd, + io->ntcreatex.in.ea_list->num_eas, + io->ntcreatex.in.ea_list->eas); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + } + + /* setup an initial sec_desc if requested */ + if (io->ntcreatex.in.sec_desc) { + union smb_setfileinfo set; + + set.set_secdesc.file.fnum = fnum; + set.set_secdesc.in.secinfo_flags = SECINFO_DACL; + set.set_secdesc.in.sd = io->ntcreatex.in.sec_desc; + + status = pvfs_acl_set(pvfs, req, name, fd, &set); + } else { + /* otherwise setup an inherited acl from the parent */ + status = pvfs_acl_inherit(pvfs, req, name, fd); + } + + return status; +} /* open a directory @@ -162,6 +199,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* check the security descriptor */ status = pvfs_access_check(pvfs, req, name, &access_mask); if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); return status; } } @@ -200,6 +238,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, uint32_t attrib = io->generic.in.file_attr | FILE_ATTRIBUTE_DIRECTORY; mode_t mode = pvfs_fileperms(pvfs, attrib); if (mkdir(name->full_name, mode) == -1) { + idr_remove(pvfs->idtree_fnum, fnum); return pvfs_map_errno(pvfs,errno); } @@ -207,14 +246,21 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 0, &name); if (!NT_STATUS_IS_OK(status)) { - return status; + goto cleanup_delete; } + + status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, fnum, io); + if (!NT_STATUS_IS_OK(status)) { + goto cleanup_delete; + } + create_action = NTCREATEX_ACTION_CREATED; } else { create_action = NTCREATEX_ACTION_EXISTED; } if (!name->exists) { + idr_remove(pvfs->idtree_fnum, fnum); return NT_STATUS_OBJECT_NAME_NOT_FOUND; } @@ -236,6 +282,11 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, io->generic.out.is_directory = 1; return NT_STATUS_OK; + +cleanup_delete: + idr_remove(pvfs->idtree_fnum, fnum); + rmdir(name->full_name); + return status; } /* @@ -462,53 +513,25 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, name->dos.attrib = attrib; status = pvfs_dosattrib_save(pvfs, name, fd); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, fnum); - close(fd); - return status; + goto cleanup_delete; } - /* setup any EAs that were asked for */ - if (io->ntcreatex.in.ea_list) { - status = pvfs_setfileinfo_ea_set(pvfs, name, fd, - io->ntcreatex.in.ea_list->num_eas, - io->ntcreatex.in.ea_list->eas); - if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, fnum); - close(fd); - return status; - } - } - - /* setup an initial sec_desc is required */ - if (io->ntcreatex.in.sec_desc) { - union smb_setfileinfo set; - - set.set_secdesc.file.fnum = fnum; - set.set_secdesc.in.secinfo_flags = SECINFO_DACL; - set.set_secdesc.in.sd = io->ntcreatex.in.sec_desc; - status = pvfs_acl_set(pvfs, req, name, fd, &set); - if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, fnum); - close(fd); - return status; - } + status = pvfs_open_setup_eas_acl(pvfs, req, name, fd, fnum, io); + if (!NT_STATUS_IS_OK(status)) { + goto cleanup_delete; } /* form the lock context used for byte range locking and opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, fnum); - close(fd); - return status; + goto cleanup_delete; } status = pvfs_brl_locking_key(name, f->handle, &f->handle->brl_locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, fnum); - close(fd); - return status; + goto cleanup_delete; } /* grab a lock on the open file record */ @@ -518,16 +541,17 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, name->full_name)); /* we were supposed to do a blocking lock, so something is badly wrong! */ - idr_remove(pvfs->idtree_fnum, fnum); - close(fd); - return NT_STATUS_INTERNAL_DB_CORRUPTION; + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto cleanup_delete; } status = odb_open_file(lck, f->handle, name->stream_id, share_access, create_options, access_mask); talloc_free(lck); if (!NT_STATUS_IS_OK(status)) { - /* bad news, we must have hit a race */ + /* bad news, we must have hit a race - we don't delete the file + here as the most likely scenario is that someone else created + the file at the same time */ idr_remove(pvfs->idtree_fnum, fnum); close(fd); return status; @@ -583,6 +607,12 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, talloc_steal(pvfs, f); return NT_STATUS_OK; + +cleanup_delete: + idr_remove(pvfs->idtree_fnum, fnum); + close(fd); + unlink(name->full_name); + return status; } @@ -846,6 +876,10 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return pvfs_open_directory(pvfs, req, name, io); } + /* FILE_ATTRIBUTE_DIRECTORY is ignored if the above test for directory + open doesn't match */ + io->generic.in.file_attr &= ~FILE_ATTRIBUTE_DIRECTORY; + create_options = io->generic.in.create_options; share_access = io->generic.in.share_access; access_mask = io->generic.in.access_mask; @@ -894,10 +928,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } - if (io->generic.in.file_attr & FILE_ATTRIBUTE_DIRECTORY) { - return NT_STATUS_INVALID_PARAMETER; - } - /* handle creating a new file separately */ if (!name->exists) { status = pvfs_create_file(pvfs, req, name, io); -- cgit From e913a48ded85e7baf91a355fff46fe270afed936 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 30 Dec 2004 05:50:23 +0000 Subject: r4408: added the remaining access check hooks into pvfs. All calls should now have acl checking, and obey the various inheritance rules. (This used to be commit 5fe51807d6b97e68b65f152c0f405e5c5a025d21) --- source4/ntvfs/posix/pvfs_open.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 1695d8e1d9..3941414cd8 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -198,10 +198,12 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, if (name->exists) { /* check the security descriptor */ status = pvfs_access_check(pvfs, req, name, &access_mask); - if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, fnum); - return status; - } + } else { + status = pvfs_access_check_create(pvfs, req, name); + } + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); + return status; } f->fnum = fnum; @@ -450,6 +452,11 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, mode_t mode; uint32_t attrib; + status = pvfs_access_check_create(pvfs, req, name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) && (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { return NT_STATUS_CANNOT_DELETE; @@ -1065,6 +1072,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* if this was a stream create then create the stream as well */ if (!name->stream_exists) { + if (!(access_mask & SEC_FILE_WRITE_ATTRIBUTE)) { + return NT_STATUS_ACCESS_DENIED; + } status = pvfs_stream_create(pvfs, f->handle->name, fd); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); -- cgit From 291b02a639aa6551ac1f59e47a78d5590d2b7f6e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 31 Dec 2004 08:56:32 +0000 Subject: r4448: - fixed access_mask checking on acl set - honor the change ownership requests of acl set, changing the underlying unix owner/group - fix the access mask on file create with SEC_FLAG_MAXIMUM_ALLOWED (This used to be commit 5761fa35ab727b51ef1b52459911bafbdd788755) --- source4/ntvfs/posix/pvfs_open.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 3941414cd8..c59f2d22e9 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -124,7 +124,7 @@ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs, set.set_secdesc.in.secinfo_flags = SECINFO_DACL; set.set_secdesc.in.sd = io->ntcreatex.in.sec_desc; - status = pvfs_acl_set(pvfs, req, name, fd, &set); + status = pvfs_acl_set(pvfs, req, name, fd, SEC_STD_WRITE_DAC, &set); } else { /* otherwise setup an inherited acl from the parent */ status = pvfs_acl_inherit(pvfs, req, name, fd); @@ -463,9 +463,12 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } if (access_mask & SEC_FLAG_MAXIMUM_ALLOWED) { - access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE; + access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE | + SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL; } + access_mask |= SEC_FILE_READ_ATTRIBUTE; + if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) { flags = O_RDWR; } else { -- cgit From ad7da47948a5a3ed2c3fc18392b83c059bec5b6e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 7 Jan 2005 02:14:34 +0000 Subject: r4584: fix pvfs backend to pass the new enhanced RAW-ACLS test. Easy once I really the strange behaviour I saw was a w2k3 bug :-) (This used to be commit e729061bcde25d0565a72222e4720ca8074ef23f) --- source4/ntvfs/posix/pvfs_open.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index c59f2d22e9..b34d75d24d 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -199,7 +199,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* check the security descriptor */ status = pvfs_access_check(pvfs, req, name, &access_mask); } else { - status = pvfs_access_check_create(pvfs, req, name); + status = pvfs_access_check_create(pvfs, req, name, &access_mask); } if (!NT_STATUS_IS_OK(status)) { idr_remove(pvfs->idtree_fnum, fnum); @@ -452,23 +452,16 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, mode_t mode; uint32_t attrib; - status = pvfs_access_check_create(pvfs, req, name); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) && (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { return NT_STATUS_CANNOT_DELETE; } - if (access_mask & SEC_FLAG_MAXIMUM_ALLOWED) { - access_mask = SEC_RIGHTS_FILE_READ | SEC_RIGHTS_FILE_WRITE | - SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL; + status = pvfs_access_check_create(pvfs, req, name, &access_mask); + if (!NT_STATUS_IS_OK(status)) { + return status; } - access_mask |= SEC_FILE_READ_ATTRIBUTE; - if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) { flags = O_RDWR; } else { -- 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_open.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index b34d75d24d..ae8841e7b5 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -180,12 +180,12 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_INVALID_PARAMETER; } - f = talloc_p(req, struct pvfs_file); + f = talloc(req, struct pvfs_file); if (f == NULL) { return NT_STATUS_NO_MEMORY; } - f->handle = talloc_p(f, struct pvfs_file_handle); + f->handle = talloc(f, struct pvfs_file_handle); if (f->handle == NULL) { return NT_STATUS_NO_MEMORY; } @@ -468,12 +468,12 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, flags = O_RDONLY; } - f = talloc_p(req, struct pvfs_file); + f = talloc(req, struct pvfs_file); if (f == NULL) { return NT_STATUS_NO_MEMORY; } - f->handle = talloc_p(f, struct pvfs_file_handle); + f->handle = talloc(f, struct pvfs_file_handle); if (f->handle == NULL) { return NT_STATUS_NO_MEMORY; } @@ -805,7 +805,7 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, } } - r = talloc_p(req, struct pvfs_open_retry); + r = talloc(req, struct pvfs_open_retry); if (r == NULL) { return NT_STATUS_NO_MEMORY; } @@ -962,12 +962,12 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } - f = talloc_p(req, struct pvfs_file); + f = talloc(req, struct pvfs_file); if (f == NULL) { return NT_STATUS_NO_MEMORY; } - f->handle = talloc_p(f, struct pvfs_file_handle); + f->handle = talloc(f, struct pvfs_file_handle); if (f->handle == NULL) { return NT_STATUS_NO_MEMORY; } -- cgit From e82aad1ce39a6b7a2e51b9e2cb494d74ec70e158 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 10 Feb 2005 05:09:35 +0000 Subject: r5298: - got rid of pstring.h from includes.h. This at least makes it a bit less likely that anyone will use pstring for new code - got rid of winbind_client.h from includes.h. This one triggered a huge change, as winbind_client.h was including system/filesys.h and defining the old uint32 and uint16 types, as well as its own pstring and fstring. (This used to be commit 9db6c79e902ec538108d6b7d3324039aabe1704f) --- source4/ntvfs/posix/pvfs_open.c | 1 - 1 file changed, 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index ae8841e7b5..e68670f7cc 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -23,7 +23,6 @@ #include "includes.h" #include "vfs_posix.h" #include "system/time.h" -#include "system/filesys.h" #include "dlinklist.h" #include "messages.h" #include "librpc/gen_ndr/ndr_xattr.h" -- cgit From 289bc557ebbad8c3ad8b24a37eb48a5d4de43ee2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 2 May 2005 15:59:34 +0000 Subject: r6580: fixed the bug that caused the truncation of the main file on a stream open with openx and the 'truncate if exists' flag (This used to be commit aa82b105d5871b3ca693a0757bb48cc589d88824) --- source4/ntvfs/posix/pvfs_open.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index e68670f7cc..4a2c8ea247 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -856,7 +856,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, uint32_t create_options; uint32_t share_access; uint32_t access_mask; - BOOL stream_existed; + BOOL stream_existed, stream_truncate=False; /* use the generic mapping code to avoid implementing all the different open calls. */ @@ -892,13 +892,16 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } + flags = 0; + switch (io->generic.in.open_disposition) { case NTCREATEX_DISP_SUPERSEDE: - flags = O_TRUNC; - break; - case NTCREATEX_DISP_OVERWRITE_IF: - flags = O_TRUNC; + if (name->stream_name == NULL) { + flags = O_TRUNC; + } else { + stream_truncate = True; + } break; case NTCREATEX_DISP_OPEN: @@ -912,7 +915,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, if (!name->stream_exists) { return NT_STATUS_OBJECT_NAME_NOT_FOUND; } - flags = O_TRUNC; + if (name->stream_name == NULL) { + flags = O_TRUNC; + } else { + stream_truncate = True; + } break; case NTCREATEX_DISP_CREATE: @@ -1075,6 +1082,13 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, talloc_free(lck); return status; } + if (stream_truncate) { + status = pvfs_stream_truncate(pvfs, f->handle->name, fd, 0); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + return status; + } + } } /* re-resolve the open fd */ -- cgit From 66a52992ff6a9f2f926249ac428d6fad72303637 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 23 Jun 2005 22:30:26 +0000 Subject: r7850: Support mkdir() with just one parameter. Patch from Steven Edwards . I've moved the Win32-specific tests to win32.m4 so it does not make any of the POSIX configure stuff more complicated. (This used to be commit bf85fdd01552f75b745fdf3159a7a87cd6521ed2) --- source4/ntvfs/posix/pvfs_open.c | 1 + 1 file changed, 1 insertion(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 4a2c8ea247..8dd9689863 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -22,6 +22,7 @@ #include "includes.h" #include "vfs_posix.h" +#include "system/dir.h" #include "system/time.h" #include "dlinklist.h" #include "messages.h" -- cgit From 95a9d9aabf1af1faada43ecdfffc68b04f917e4c Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 1 Jul 2005 12:59:23 +0000 Subject: r8059: fixed handling of delete on close fir directories (This used to be commit 14f51a99bccffac0ca284d1315ab6d4b10f3711f) --- source4/ntvfs/posix/pvfs_open.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 8dd9689863..f58cc60f9a 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1243,6 +1243,11 @@ NTSTATUS pvfs_change_create_options(struct pvfs_state *pvfs, return NT_STATUS_CANNOT_DELETE; } + if (f->handle->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) { + f->handle->create_options = create_options; + return NT_STATUS_OK; + } + lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key); if (lck == NULL) { return NT_STATUS_INTERNAL_DB_CORRUPTION; -- cgit From a703329908431b473483fe0e70a121fff1e5fbf6 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 4 Jul 2005 05:24:39 +0000 Subject: r8122: more fixes from testing dos error code handling against w2k3 (This used to be commit b71fbcf5e2c627d918aef555b8cc8dd4591d8fe7) --- source4/ntvfs/posix/pvfs_open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index f58cc60f9a..327f096e7c 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1156,7 +1156,7 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, struct utimbuf unix_times; if (io->generic.level == RAW_CLOSE_SPLCLOSE) { - return NT_STATUS_UNSUCCESSFUL; + return NT_STATUS_DOS(ERRSRV, ERRerror); } if (io->generic.level != RAW_CLOSE_CLOSE) { -- cgit From bb8362986571b931c7a69fa0d4d97354ff5bba4f Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Sat, 9 Jul 2005 11:06:33 +0000 Subject: r8258: Release the opendb lock in pvfs_change_create_options. Volker (This used to be commit 2c4fd3ff99a4ade613030b3eb47d0ed527a95be3) --- source4/ntvfs/posix/pvfs_open.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 327f096e7c..d0e7d82117 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1258,6 +1258,8 @@ NTSTATUS pvfs_change_create_options(struct pvfs_state *pvfs, f->handle->create_options = create_options; } + talloc_free(lck); + return status; } -- cgit From 5ef83290bc4db2ac409b0de32f459aef3c52faeb Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 3 Aug 2005 17:22:33 +0000 Subject: r9007: fixed error code for setting delete on close on a non-empty directory (This used to be commit 320ab3c93b05a79b77dbbb85e9b038bb07848ba5) --- source4/ntvfs/posix/pvfs_open.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index d0e7d82117..3ae8e2150f 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1244,6 +1244,9 @@ NTSTATUS pvfs_change_create_options(struct pvfs_state *pvfs, } if (f->handle->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) { + if (!pvfs_directory_empty(pvfs, f->handle->name)) { + return NT_STATUS_DIRECTORY_NOT_EMPTY; + } f->handle->create_options = create_options; return NT_STATUS_OK; } -- cgit From 6eb9567c3f68869f691e29d5daffe3ea28858a46 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 3 Aug 2005 17:52:33 +0000 Subject: r9009: directory not empty is not an error on failure to delete directory in delete on close (This used to be commit dada509f5e374872cded9035611c9d4fd9f4c4c7) --- source4/ntvfs/posix/pvfs_open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 3ae8e2150f..d3b9681b58 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -75,7 +75,7 @@ static int pvfs_dir_handle_destructor(void *p) DEBUG(0,("Warning: xattr rmdir hook failed for '%s' - %s\n", h->name->full_name, nt_errstr(status))); } - if (rmdir(h->name->full_name) != 0) { + if (rmdir(h->name->full_name) != 0 && errno != ENOTEMPTY) { DEBUG(0,("pvfs_close: failed to rmdir '%s' - %s\n", h->name->full_name, strerror(errno))); } -- cgit From ba205b314390474ecf263a9b6094330d6bc37a80 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 4 Aug 2005 06:14:34 +0000 Subject: r9054: removed incorrect paranoia check on opening streams (this caused RAW-STREAMS to fail) (This used to be commit c164ee5b19f6880b7b5df8d8fb96704350432862) --- source4/ntvfs/posix/pvfs_open.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index d3b9681b58..94749600e1 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1075,9 +1075,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* if this was a stream create then create the stream as well */ if (!name->stream_exists) { - if (!(access_mask & SEC_FILE_WRITE_ATTRIBUTE)) { - return NT_STATUS_ACCESS_DENIED; - } status = pvfs_stream_create(pvfs, f->handle->name, fd); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); -- 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_open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 94749600e1..0e2a85bab1 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -734,7 +734,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) && (f2->access_mask & SEC_FILE_WRITE_DATA) && - StrCaseCmp(f2->handle->name->original_name, + strcasecmp_m(f2->handle->name->original_name, io->generic.in.fname)==0) { break; } -- cgit From 78c50015bb8bd5a1d831a6e7ec796b3367c73145 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Tue, 3 Jan 2006 15:40:05 +0000 Subject: r12694: Move some headers to the directory of the subsystem they belong to. (This used to be commit c722f665c90103f3ed57621c460e32ad33e7a8a3) --- source4/ntvfs/posix/pvfs_open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 0e2a85bab1..5aeb5eb7e8 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -25,7 +25,7 @@ #include "system/dir.h" #include "system/time.h" #include "dlinklist.h" -#include "messages.h" +#include "messaging/messaging.h" #include "librpc/gen_ndr/ndr_xattr.h" /* -- cgit From 40a8d58551526a0f367d23d0c9603a5b9d86b270 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 28 Feb 2006 03:47:02 +0000 Subject: r13739: a fairly major overhaul of the opendb code to allow the BASE-DELETE test to pass. To try to make the code a bit more understandable, I moved to using an IDL description of the opendb tdb record format. One of the larger changes was to make directory opens and creates go via the opendb code, so directory operations now obey all the share mode restrictions, as well as delete on close semantics. I also changed the period over which the opendb locks are held, to try to minimise races due to two open operations happening at the same time. (This used to be commit cd2602d05725e1734b0862131dd91601c6b6d51a) --- source4/ntvfs/posix/pvfs_open.c | 685 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 615 insertions(+), 70 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 5aeb5eb7e8..a8c0bba97f 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -68,17 +68,41 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, static int pvfs_dir_handle_destructor(void *p) { struct pvfs_file_handle *h = p; + int open_count; + char *path; - if (h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { - NTSTATUS status = pvfs_xattr_unlink_hook(h->pvfs, h->name->full_name); + if (h->name->stream_name == NULL && + pvfs_delete_on_close_set(h->pvfs, h, &open_count, &path) && + open_count == 1) { + NTSTATUS status; + status = pvfs_xattr_unlink_hook(h->pvfs, path); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("Warning: xattr rmdir hook failed for '%s' - %s\n", - h->name->full_name, nt_errstr(status))); + DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n", + path, nt_errstr(status))); + } + if (rmdir(path) != 0) { + DEBUG(0,("pvfs_dir_handle_destructor: failed to rmdir '%s' - %s\n", + path, strerror(errno))); + } + } + + if (h->have_opendb_entry) { + struct odb_lock *lck; + NTSTATUS status; + + lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key); + if (lck == NULL) { + DEBUG(0,("Unable to lock opendb for close\n")); + return 0; } - if (rmdir(h->name->full_name) != 0 && errno != ENOTEMPTY) { - DEBUG(0,("pvfs_close: failed to rmdir '%s' - %s\n", - h->name->full_name, strerror(errno))); + + status = odb_close_file(lck, h); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n", + h->name->full_name, nt_errstr(status))); } + + talloc_free(lck); } return 0; @@ -133,6 +157,379 @@ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs, return status; } +/* + form the lock context used for opendb locking. Note that we must + zero here to take account of possible padding on some architectures +*/ +static NTSTATUS pvfs_locking_key(struct pvfs_filename *name, + TALLOC_CTX *mem_ctx, DATA_BLOB *key) +{ + struct { + dev_t device; + ino_t inode; + } lock_context; + ZERO_STRUCT(lock_context); + + lock_context.device = name->st.st_dev; + lock_context.inode = name->st.st_ino; + + *key = data_blob_talloc(mem_ctx, &lock_context, sizeof(lock_context)); + if (key->data == NULL) { + return NT_STATUS_NO_MEMORY; + } + + return NT_STATUS_OK; +} + + +/* + create a new directory +*/ +static NTSTATUS pvfs_create_directory(struct pvfs_state *pvfs, + struct smbsrv_request *req, + struct pvfs_filename *name, + union smb_open *io) +{ + struct pvfs_file *f; + NTSTATUS status; + int fnum, ret; + struct odb_lock *lck; + uint32_t create_options = io->generic.in.create_options; + uint32_t share_access = io->generic.in.share_access; + uint32_t access_mask = io->generic.in.access_mask; + mode_t mode; + uint32_t attrib; + BOOL del_on_close; + + if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) && + (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { + return NT_STATUS_CANNOT_DELETE; + } + + status = pvfs_access_check_create(pvfs, req, name, &access_mask); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + f = talloc(req, struct pvfs_file); + if (f == NULL) { + return NT_STATUS_NO_MEMORY; + } + + f->handle = talloc(f, struct pvfs_file_handle); + if (f->handle == NULL) { + return NT_STATUS_NO_MEMORY; + } + + fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_NEW_FNUM, UINT16_MAX); + if (fnum == -1) { + return NT_STATUS_TOO_MANY_OPENED_FILES; + } + + attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_DIRECTORY; + mode = pvfs_fileperms(pvfs, attrib); + + /* create the directory */ + ret = mkdir(name->full_name, mode); + if (ret == -1) { + idr_remove(pvfs->idtree_fnum, fnum); + return pvfs_map_errno(pvfs, errno); + } + + pvfs_xattr_unlink_hook(pvfs, name->full_name); + + /* re-resolve the new directory */ + status = pvfs_resolve_name_fd(pvfs, -1, name); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, fnum); + rmdir(name->full_name); + return status; + } + + name->dos.attrib = attrib; + + status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, fnum, io); + if (!NT_STATUS_IS_OK(status)) { + goto cleanup_delete; + } + + /* form the lock context used for opendb locking */ + status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); + if (!NT_STATUS_IS_OK(status)) { + goto cleanup_delete; + } + + /* grab a lock on the open file record */ + lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key); + if (lck == NULL) { + DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n", + name->full_name)); + /* we were supposed to do a blocking lock, so something + is badly wrong! */ + status = NT_STATUS_INTERNAL_DB_CORRUPTION; + goto cleanup_delete; + } + + if (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { + del_on_close = True; + } else { + del_on_close = False; + } + + status = odb_open_file(lck, f->handle, name->stream_id, + share_access, access_mask, del_on_close, name->full_name); + talloc_free(lck); + if (!NT_STATUS_IS_OK(status)) { + /* bad news, we must have hit a race */ + idr_remove(pvfs->idtree_fnum, fnum); + return status; + } + + f->fnum = fnum; + f->session = req->session; + f->smbpid = req->smbpid; + f->pvfs = pvfs; + f->pending_list = NULL; + f->lock_count = 0; + f->share_access = io->generic.in.share_access; + f->access_mask = access_mask; + f->impersonation = io->generic.in.impersonation; + + f->handle->pvfs = pvfs; + f->handle->name = talloc_steal(f->handle, name); + f->handle->fd = -1; + f->handle->create_options = io->generic.in.create_options; + f->handle->seek_offset = 0; + f->handle->position = 0; + f->handle->mode = 0; + f->handle->have_opendb_entry = True; + f->handle->sticky_write_time = False; + + DLIST_ADD(pvfs->open_files, f); + + /* setup a destructor to avoid file descriptor leaks on + abnormal termination */ + talloc_set_destructor(f, pvfs_dir_fnum_destructor); + talloc_set_destructor(f->handle, pvfs_dir_handle_destructor); + + io->generic.out.oplock_level = OPLOCK_NONE; + io->generic.out.fnum = f->fnum; + io->generic.out.create_action = NTCREATEX_ACTION_CREATED; + io->generic.out.create_time = name->dos.create_time; + io->generic.out.access_time = name->dos.access_time; + io->generic.out.write_time = name->dos.write_time; + io->generic.out.change_time = name->dos.change_time; + io->generic.out.attrib = name->dos.attrib; + io->generic.out.alloc_size = name->dos.alloc_size; + io->generic.out.size = name->st.st_size; + io->generic.out.file_type = FILE_TYPE_DISK; + io->generic.out.ipc_state = 0; + io->generic.out.is_directory = 0; + + /* success - keep the file handle */ + talloc_steal(pvfs, f); + + return NT_STATUS_OK; + +cleanup_delete: + idr_remove(pvfs->idtree_fnum, fnum); + rmdir(name->full_name); + return status; +} + +#if 0 +/* + open a directory +*/ +static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, + struct smbsrv_request *req, + struct pvfs_filename *name, + union smb_open *io) +{ + struct pvfs_file *f; + NTSTATUS status; + int fnum; + struct odb_lock *lck; + uint32_t create_options; + uint32_t share_access; + uint32_t access_mask; + BOOL del_on_close; + + create_options = io->generic.in.create_options; + share_access = io->generic.in.share_access; + access_mask = io->generic.in.access_mask; + + /* certain create options are not allowed */ + if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && + !(access_mask & SEC_STD_DELETE)) { + return NT_STATUS_INVALID_PARAMETER; + } + + switch (io->generic.in.open_disposition) { + case NTCREATEX_DISP_SUPERSEDE: + case NTCREATEX_DISP_OVERWRITE_IF: + case NTCREATEX_DISP_OPEN_IF: + break; + + case NTCREATEX_DISP_OPEN: + case NTCREATEX_DISP_OVERWRITE: + if (!name->exists) { + return NT_STATUS_OBJECT_NAME_NOT_FOUND; + } + break; + + case NTCREATEX_DISP_CREATE: + if (name->exists) { + return NT_STATUS_OBJECT_NAME_COLLISION; + } + break; + + default: + return NT_STATUS_INVALID_PARAMETER; + } + + /* handle creating a new directory separately */ + if (!name->exists) { + status = pvfs_create_directory(pvfs, req, name, io); + if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { + return status; + } + + /* we've hit a race - the directory was created during this call */ + if (io->generic.in.open_disposition == NTCREATEX_DISP_CREATE) { + return status; + } + + /* try re-resolving the name */ + status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 0, &name); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + /* fall through to a normal open */ + } + + if ((name->dos.attrib & FILE_ATTRIBUTE_READONLY) && + (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { + return NT_STATUS_CANNOT_DELETE; + } + + /* check the security descriptor */ + status = pvfs_access_check(pvfs, req, name, &access_mask); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + f = talloc(req, struct pvfs_file); + if (f == NULL) { + return NT_STATUS_NO_MEMORY; + } + + f->handle = talloc(f, struct pvfs_file_handle); + if (f->handle == NULL) { + return NT_STATUS_NO_MEMORY; + } + + /* allocate a fnum */ + fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_DIR_FNUM, UINT16_MAX); + if (fnum == -1) { + return NT_STATUS_TOO_MANY_OPENED_FILES; + } + + f->fnum = fnum; + f->session = req->session; + f->smbpid = req->smbpid; + f->pvfs = pvfs; + f->pending_list = NULL; + f->lock_count = 0; + f->share_access = io->generic.in.share_access; + f->access_mask = access_mask; + f->impersonation = io->generic.in.impersonation; + + f->handle->pvfs = pvfs; + f->handle->fd = -1; + f->handle->name = talloc_steal(f->handle, name); + f->handle->create_options = io->generic.in.create_options; + f->handle->seek_offset = 0; + f->handle->position = 0; + f->handle->mode = 0; + f->handle->have_opendb_entry = False; + f->handle->sticky_write_time = False; + + /* form the lock context used for opendb locking */ + status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, f->fnum); + return status; + } + + /* get a lock on this file before the actual open */ + lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key); + if (lck == NULL) { + DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n", + name->full_name)); + /* we were supposed to do a blocking lock, so something + is badly wrong! */ + idr_remove(pvfs->idtree_fnum, fnum); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + DLIST_ADD(pvfs->open_files, f); + + /* setup a destructor to avoid file descriptor leaks on + abnormal termination */ + talloc_set_destructor(f, pvfs_dir_fnum_destructor); + talloc_set_destructor(f->handle, pvfs_dir_handle_destructor); + + if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && + pvfs_directory_empty(pvfs, f->handle->name)) { + del_on_close = True; + } else { + del_on_close = False; + } + + /* see if we are allowed to open at the same time as existing opens */ + status = odb_open_file(lck, f->handle, f->handle->name->stream_id, + share_access, access_mask, del_on_close, name->full_name); + +#if 0 + /* we don't do async open retries on directories yet */ + if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) && + (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { + return pvfs_open_setup_retry(ntvfs, req, io, f, lck); + } +#endif + + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + return status; + } + + f->handle->have_opendb_entry = True; + + talloc_free(lck); + + io->generic.out.oplock_level = OPLOCK_NONE; + io->generic.out.fnum = f->fnum; + io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; + io->generic.out.create_time = name->dos.create_time; + io->generic.out.access_time = name->dos.access_time; + io->generic.out.write_time = name->dos.write_time; + io->generic.out.change_time = name->dos.change_time; + io->generic.out.attrib = name->dos.attrib; + io->generic.out.alloc_size = name->dos.alloc_size; + io->generic.out.size = name->st.st_size; + io->generic.out.file_type = FILE_TYPE_DISK; + io->generic.out.ipc_state = 0; + io->generic.out.is_directory = 0; + + /* success - keep the file handle */ + talloc_steal(f->pvfs, f); + + return NT_STATUS_OK; +} +#endif + +#if 1 /* open a directory */ @@ -146,6 +543,13 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, NTSTATUS status; uint32_t create_action; uint32_t access_mask = io->generic.in.access_mask; + struct odb_lock *lck; + BOOL del_on_close; + uint32_t create_options; + uint32_t share_access; + + create_options = io->generic.in.create_options; + share_access = io->generic.in.share_access; if (name->stream_name) { return NT_STATUS_NOT_A_DIRECTORY; @@ -227,10 +631,47 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->handle->mode = 0; f->handle->sticky_write_time = False; - DLIST_ADD(pvfs->open_files, f); + if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && + pvfs_directory_empty(pvfs, f->handle->name)) { + del_on_close = True; + } else { + del_on_close = False; + } + + + if (name->exists) { + /* form the lock context used for opendb locking */ + status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, f->fnum); + return status; + } + + /* get a lock on this file before the actual open */ + lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key); + if (lck == NULL) { + DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n", + name->full_name)); + /* we were supposed to do a blocking lock, so something + is badly wrong! */ + idr_remove(pvfs->idtree_fnum, fnum); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + /* see if we are allowed to open at the same time as existing opens */ + status = odb_open_file(lck, f->handle, f->handle->name->stream_id, + share_access, access_mask, del_on_close, name->full_name); + + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, f->fnum); + talloc_free(lck); + return status; + } + + f->handle->have_opendb_entry = True; + } - /* TODO: should we check in the opendb? Do directory opens - follow the share_access rules? */ + DLIST_ADD(pvfs->open_files, f); /* setup destructors to avoid leaks on abnormal termination */ talloc_set_destructor(f->handle, pvfs_dir_handle_destructor); @@ -239,6 +680,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, if (!name->exists) { uint32_t attrib = io->generic.in.file_attr | FILE_ATTRIBUTE_DIRECTORY; mode_t mode = pvfs_fileperms(pvfs, attrib); + if (mkdir(name->full_name, mode) == -1) { idr_remove(pvfs->idtree_fnum, fnum); return pvfs_map_errno(pvfs,errno); @@ -256,6 +698,32 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, goto cleanup_delete; } + /* form the lock context used for opendb locking */ + status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); + if (!NT_STATUS_IS_OK(status)) { + idr_remove(pvfs->idtree_fnum, f->fnum); + return status; + } + + lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key); + if (lck == NULL) { + DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n", + name->full_name)); + /* we were supposed to do a blocking lock, so something + is badly wrong! */ + idr_remove(pvfs->idtree_fnum, fnum); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + status = odb_open_file(lck, f->handle, f->handle->name->stream_id, + share_access, access_mask, del_on_close, name->full_name); + + if (!NT_STATUS_IS_OK(status)) { + goto cleanup_delete; + } + + f->handle->have_opendb_entry = True; + create_action = NTCREATEX_ACTION_CREATED; } else { create_action = NTCREATEX_ACTION_EXISTED; @@ -290,6 +758,7 @@ cleanup_delete: rmdir(name->full_name); return status; } +#endif /* destroy a struct pvfs_file_handle @@ -297,6 +766,8 @@ cleanup_delete: static int pvfs_handle_destructor(void *p) { struct pvfs_file_handle *h = p; + int open_count; + char *path; /* the write time is no longer sticky */ if (h->sticky_write_time) { @@ -326,17 +797,18 @@ static int pvfs_handle_destructor(void *p) h->fd = -1; } - if ((h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && - h->name->stream_name == NULL) { + if (h->name->stream_name == NULL && + pvfs_delete_on_close_set(h->pvfs, h, &open_count, &path) && + open_count == 1) { NTSTATUS status; - status = pvfs_xattr_unlink_hook(h->pvfs, h->name->full_name); + status = pvfs_xattr_unlink_hook(h->pvfs, path); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n", - h->name->full_name, nt_errstr(status))); + path, nt_errstr(status))); } - if (unlink(h->name->full_name) != 0) { + if (unlink(path) != 0) { DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n", - h->name->full_name, strerror(errno))); + path, strerror(errno))); } } @@ -378,30 +850,6 @@ static int pvfs_fnum_destructor(void *p) } -/* - form the lock context used for opendb locking. Note that we must - zero here to take account of possible padding on some architectures -*/ -static NTSTATUS pvfs_locking_key(struct pvfs_filename *name, - TALLOC_CTX *mem_ctx, DATA_BLOB *key) -{ - struct { - dev_t device; - ino_t inode; - } lock_context; - ZERO_STRUCT(lock_context); - - lock_context.device = name->st.st_dev; - lock_context.inode = name->st.st_ino; - - *key = data_blob_talloc(mem_ctx, &lock_context, sizeof(lock_context)); - if (key->data == NULL) { - return NT_STATUS_NO_MEMORY; - } - - return NT_STATUS_OK; -} - /* form the lock context used for byte range locking. This is separate from the locking key used for opendb locking as it needs to take @@ -451,6 +899,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, uint32_t access_mask = io->generic.in.access_mask; mode_t mode; uint32_t attrib; + BOOL del_on_close; + struct pvfs_filename *parent; if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) && (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { @@ -458,8 +908,20 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } status = pvfs_access_check_create(pvfs, req, name, &access_mask); - if (!NT_STATUS_IS_OK(status)) { - return status; + NT_STATUS_NOT_OK_RETURN(status); + + /* check that the parent isn't opened with delete on close set */ + status = pvfs_resolve_parent(pvfs, req, name, &parent); + if (NT_STATUS_IS_OK(status)) { + DATA_BLOB locking_key; + status = pvfs_locking_key(parent, req, &locking_key); + NT_STATUS_NOT_OK_RETURN(status); + status = odb_get_delete_on_close(pvfs->odb_context, &locking_key, + &del_on_close, NULL, NULL); + NT_STATUS_NOT_OK_RETURN(status); + if (del_on_close) { + return NT_STATUS_DELETE_PENDING; + } } if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) { @@ -548,8 +1010,14 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, goto cleanup_delete; } + if (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { + del_on_close = True; + } else { + del_on_close = False; + } + status = odb_open_file(lck, f->handle, name->stream_id, - share_access, create_options, access_mask); + share_access, access_mask, del_on_close, name->full_name); talloc_free(lck); if (!NT_STATUS_IS_OK(status)) { /* bad news, we must have hit a race - we don't delete the file @@ -1037,10 +1505,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, talloc_set_destructor(f, pvfs_fnum_destructor); talloc_set_destructor(f->handle, pvfs_handle_destructor); - /* see if we are allowed to open at the same time as existing opens */ status = odb_open_file(lck, f->handle, f->handle->name->stream_id, - share_access, create_options, access_mask); + share_access, access_mask, False, name->full_name); /* on a sharing violation we need to retry when the file is closed by the other user, or after 1 second */ @@ -1222,41 +1689,36 @@ NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs, /* - change the create options on an already open file + change the delete on close flag on an already open file */ -NTSTATUS pvfs_change_create_options(struct pvfs_state *pvfs, - struct smbsrv_request *req, - struct pvfs_file *f, uint32_t create_options) +NTSTATUS pvfs_set_delete_on_close(struct pvfs_state *pvfs, + struct smbsrv_request *req, + struct pvfs_file *f, BOOL del_on_close) { struct odb_lock *lck; NTSTATUS status; - if (f->handle->create_options == create_options) { - return NT_STATUS_OK; - } - - if ((f->handle->name->dos.attrib & FILE_ATTRIBUTE_READONLY) && - (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { + if ((f->handle->name->dos.attrib & FILE_ATTRIBUTE_READONLY) && del_on_close) { return NT_STATUS_CANNOT_DELETE; } - - if (f->handle->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) { - if (!pvfs_directory_empty(pvfs, f->handle->name)) { - return NT_STATUS_DIRECTORY_NOT_EMPTY; - } - f->handle->create_options = create_options; - return NT_STATUS_OK; + + if ((f->handle->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) && + !pvfs_directory_empty(pvfs, f->handle->name)) { + return NT_STATUS_DIRECTORY_NOT_EMPTY; } + if (del_on_close) { + f->handle->create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE; + } else { + f->handle->create_options &= ~NTCREATEX_OPTIONS_DELETE_ON_CLOSE; + } + lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key); if (lck == NULL) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } - status = odb_set_create_options(lck, f->handle, create_options); - if (NT_STATUS_IS_OK(status)) { - f->handle->create_options = create_options; - } + status = odb_set_delete_on_close(lck, del_on_close); talloc_free(lck); @@ -1270,17 +1732,25 @@ NTSTATUS pvfs_change_create_options(struct pvfs_state *pvfs, */ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, struct smbsrv_request *req, - struct pvfs_filename *name) + struct pvfs_filename *name, + struct odb_lock **lckp) { NTSTATUS status; DATA_BLOB key; + struct odb_lock *lck; status = pvfs_locking_key(name, name, &key); if (!NT_STATUS_IS_OK(status)) { return NT_STATUS_NO_MEMORY; } - status = odb_can_open(pvfs->odb_context, &key, + lck = odb_lock(req, pvfs->odb_context, &key); + if (lck == NULL) { + DEBUG(0,("Unable to lock opendb for can_delete\n")); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + status = odb_can_open(lck, NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE | NTCREATEX_SHARE_ACCESS_DELETE, @@ -1291,6 +1761,13 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, status = pvfs_access_check_simple(pvfs, req, name, SEC_STD_DELETE); } + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + *lckp = lck; + } else if (lckp != NULL) { + *lckp = lck; + } + return status; } @@ -1298,21 +1775,89 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, determine if a file can be renamed, or if it is prevented by an already open file */ -NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, struct pvfs_filename *name) +NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, + struct smbsrv_request *req, + struct pvfs_filename *name, + struct odb_lock **lckp) { NTSTATUS status; DATA_BLOB key; + struct odb_lock *lck; status = pvfs_locking_key(name, name, &key); if (!NT_STATUS_IS_OK(status)) { return NT_STATUS_NO_MEMORY; } - status = odb_can_open(pvfs->odb_context, &key, + lck = odb_lock(req, pvfs->odb_context, &key); + if (lck == NULL) { + DEBUG(0,("Unable to lock opendb for can_stat\n")); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + status = odb_can_open(lck, NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE, 0, SEC_STD_DELETE); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + *lckp = lck; + } else if (lckp != NULL) { + *lckp = lck; + } + return status; } + +/* + determine if file meta data can be accessed, or if it is prevented by an + already open file +*/ +NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, + struct smbsrv_request *req, + struct pvfs_filename *name) +{ + NTSTATUS status; + DATA_BLOB key; + struct odb_lock *lck; + + status = pvfs_locking_key(name, name, &key); + if (!NT_STATUS_IS_OK(status)) { + return NT_STATUS_NO_MEMORY; + } + + lck = odb_lock(req, pvfs->odb_context, &key); + if (lck == NULL) { + DEBUG(0,("Unable to lock opendb for can_stat\n")); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + status = odb_can_open(lck, + NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE, + 0, 0); + + return status; +} + + +/* + determine if delete on close is set on +*/ +BOOL pvfs_delete_on_close_set(struct pvfs_state *pvfs, struct pvfs_file_handle *h, + int *open_count, char **path) +{ + NTSTATUS status; + BOOL del_on_close; + + status = odb_get_delete_on_close(pvfs->odb_context, &h->odb_locking_key, + &del_on_close, open_count, path); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(1,("WARNING: unable to determine delete on close status for open file\n")); + return False; + } + + return del_on_close; +} -- cgit From 4d3cc7384338fe2182a2029c2e6d2fcca2ec8813 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 28 Feb 2006 05:48:21 +0000 Subject: r13745: remove some code I was experimenting with and forgot was there when I committed that will teach me to run svn diff before committing .... (This used to be commit ef6e30c72cf610728584dfab1755b47bfc53f01c) --- source4/ntvfs/posix/pvfs_open.c | 349 ---------------------------------------- 1 file changed, 349 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index a8c0bba97f..e24887ca96 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -182,354 +182,6 @@ static NTSTATUS pvfs_locking_key(struct pvfs_filename *name, } -/* - create a new directory -*/ -static NTSTATUS pvfs_create_directory(struct pvfs_state *pvfs, - struct smbsrv_request *req, - struct pvfs_filename *name, - union smb_open *io) -{ - struct pvfs_file *f; - NTSTATUS status; - int fnum, ret; - struct odb_lock *lck; - uint32_t create_options = io->generic.in.create_options; - uint32_t share_access = io->generic.in.share_access; - uint32_t access_mask = io->generic.in.access_mask; - mode_t mode; - uint32_t attrib; - BOOL del_on_close; - - if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) && - (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { - return NT_STATUS_CANNOT_DELETE; - } - - status = pvfs_access_check_create(pvfs, req, name, &access_mask); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - f = talloc(req, struct pvfs_file); - if (f == NULL) { - return NT_STATUS_NO_MEMORY; - } - - f->handle = talloc(f, struct pvfs_file_handle); - if (f->handle == NULL) { - return NT_STATUS_NO_MEMORY; - } - - fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_NEW_FNUM, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; - } - - attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_DIRECTORY; - mode = pvfs_fileperms(pvfs, attrib); - - /* create the directory */ - ret = mkdir(name->full_name, mode); - if (ret == -1) { - idr_remove(pvfs->idtree_fnum, fnum); - return pvfs_map_errno(pvfs, errno); - } - - pvfs_xattr_unlink_hook(pvfs, name->full_name); - - /* re-resolve the new directory */ - status = pvfs_resolve_name_fd(pvfs, -1, name); - if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, fnum); - rmdir(name->full_name); - return status; - } - - name->dos.attrib = attrib; - - status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, fnum, io); - if (!NT_STATUS_IS_OK(status)) { - goto cleanup_delete; - } - - /* form the lock context used for opendb locking */ - status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); - if (!NT_STATUS_IS_OK(status)) { - goto cleanup_delete; - } - - /* grab a lock on the open file record */ - lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key); - if (lck == NULL) { - DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n", - name->full_name)); - /* we were supposed to do a blocking lock, so something - is badly wrong! */ - status = NT_STATUS_INTERNAL_DB_CORRUPTION; - goto cleanup_delete; - } - - if (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { - del_on_close = True; - } else { - del_on_close = False; - } - - status = odb_open_file(lck, f->handle, name->stream_id, - share_access, access_mask, del_on_close, name->full_name); - talloc_free(lck); - if (!NT_STATUS_IS_OK(status)) { - /* bad news, we must have hit a race */ - idr_remove(pvfs->idtree_fnum, fnum); - return status; - } - - f->fnum = fnum; - f->session = req->session; - f->smbpid = req->smbpid; - f->pvfs = pvfs; - f->pending_list = NULL; - f->lock_count = 0; - f->share_access = io->generic.in.share_access; - f->access_mask = access_mask; - f->impersonation = io->generic.in.impersonation; - - f->handle->pvfs = pvfs; - f->handle->name = talloc_steal(f->handle, name); - f->handle->fd = -1; - f->handle->create_options = io->generic.in.create_options; - f->handle->seek_offset = 0; - f->handle->position = 0; - f->handle->mode = 0; - f->handle->have_opendb_entry = True; - f->handle->sticky_write_time = False; - - DLIST_ADD(pvfs->open_files, f); - - /* setup a destructor to avoid file descriptor leaks on - abnormal termination */ - talloc_set_destructor(f, pvfs_dir_fnum_destructor); - talloc_set_destructor(f->handle, pvfs_dir_handle_destructor); - - io->generic.out.oplock_level = OPLOCK_NONE; - io->generic.out.fnum = f->fnum; - io->generic.out.create_action = NTCREATEX_ACTION_CREATED; - io->generic.out.create_time = name->dos.create_time; - io->generic.out.access_time = name->dos.access_time; - io->generic.out.write_time = name->dos.write_time; - io->generic.out.change_time = name->dos.change_time; - io->generic.out.attrib = name->dos.attrib; - io->generic.out.alloc_size = name->dos.alloc_size; - io->generic.out.size = name->st.st_size; - io->generic.out.file_type = FILE_TYPE_DISK; - io->generic.out.ipc_state = 0; - io->generic.out.is_directory = 0; - - /* success - keep the file handle */ - talloc_steal(pvfs, f); - - return NT_STATUS_OK; - -cleanup_delete: - idr_remove(pvfs->idtree_fnum, fnum); - rmdir(name->full_name); - return status; -} - -#if 0 -/* - open a directory -*/ -static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, - struct smbsrv_request *req, - struct pvfs_filename *name, - union smb_open *io) -{ - struct pvfs_file *f; - NTSTATUS status; - int fnum; - struct odb_lock *lck; - uint32_t create_options; - uint32_t share_access; - uint32_t access_mask; - BOOL del_on_close; - - create_options = io->generic.in.create_options; - share_access = io->generic.in.share_access; - access_mask = io->generic.in.access_mask; - - /* certain create options are not allowed */ - if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && - !(access_mask & SEC_STD_DELETE)) { - return NT_STATUS_INVALID_PARAMETER; - } - - switch (io->generic.in.open_disposition) { - case NTCREATEX_DISP_SUPERSEDE: - case NTCREATEX_DISP_OVERWRITE_IF: - case NTCREATEX_DISP_OPEN_IF: - break; - - case NTCREATEX_DISP_OPEN: - case NTCREATEX_DISP_OVERWRITE: - if (!name->exists) { - return NT_STATUS_OBJECT_NAME_NOT_FOUND; - } - break; - - case NTCREATEX_DISP_CREATE: - if (name->exists) { - return NT_STATUS_OBJECT_NAME_COLLISION; - } - break; - - default: - return NT_STATUS_INVALID_PARAMETER; - } - - /* handle creating a new directory separately */ - if (!name->exists) { - status = pvfs_create_directory(pvfs, req, name, io); - if (!NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) { - return status; - } - - /* we've hit a race - the directory was created during this call */ - if (io->generic.in.open_disposition == NTCREATEX_DISP_CREATE) { - return status; - } - - /* try re-resolving the name */ - status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, 0, &name); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - /* fall through to a normal open */ - } - - if ((name->dos.attrib & FILE_ATTRIBUTE_READONLY) && - (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { - return NT_STATUS_CANNOT_DELETE; - } - - /* check the security descriptor */ - status = pvfs_access_check(pvfs, req, name, &access_mask); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - f = talloc(req, struct pvfs_file); - if (f == NULL) { - return NT_STATUS_NO_MEMORY; - } - - f->handle = talloc(f, struct pvfs_file_handle); - if (f->handle == NULL) { - return NT_STATUS_NO_MEMORY; - } - - /* allocate a fnum */ - fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_DIR_FNUM, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; - } - - f->fnum = fnum; - f->session = req->session; - f->smbpid = req->smbpid; - f->pvfs = pvfs; - f->pending_list = NULL; - f->lock_count = 0; - f->share_access = io->generic.in.share_access; - f->access_mask = access_mask; - f->impersonation = io->generic.in.impersonation; - - f->handle->pvfs = pvfs; - f->handle->fd = -1; - f->handle->name = talloc_steal(f->handle, name); - f->handle->create_options = io->generic.in.create_options; - f->handle->seek_offset = 0; - f->handle->position = 0; - f->handle->mode = 0; - f->handle->have_opendb_entry = False; - f->handle->sticky_write_time = False; - - /* form the lock context used for opendb locking */ - status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); - if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, f->fnum); - return status; - } - - /* get a lock on this file before the actual open */ - lck = odb_lock(req, pvfs->odb_context, &f->handle->odb_locking_key); - if (lck == NULL) { - DEBUG(0,("pvfs_open: failed to lock file '%s' in opendb\n", - name->full_name)); - /* we were supposed to do a blocking lock, so something - is badly wrong! */ - idr_remove(pvfs->idtree_fnum, fnum); - return NT_STATUS_INTERNAL_DB_CORRUPTION; - } - - DLIST_ADD(pvfs->open_files, f); - - /* setup a destructor to avoid file descriptor leaks on - abnormal termination */ - talloc_set_destructor(f, pvfs_dir_fnum_destructor); - talloc_set_destructor(f->handle, pvfs_dir_handle_destructor); - - if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && - pvfs_directory_empty(pvfs, f->handle->name)) { - del_on_close = True; - } else { - del_on_close = False; - } - - /* see if we are allowed to open at the same time as existing opens */ - status = odb_open_file(lck, f->handle, f->handle->name->stream_id, - share_access, access_mask, del_on_close, name->full_name); - -#if 0 - /* we don't do async open retries on directories yet */ - if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) && - (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return pvfs_open_setup_retry(ntvfs, req, io, f, lck); - } -#endif - - if (!NT_STATUS_IS_OK(status)) { - talloc_free(lck); - return status; - } - - f->handle->have_opendb_entry = True; - - talloc_free(lck); - - io->generic.out.oplock_level = OPLOCK_NONE; - io->generic.out.fnum = f->fnum; - io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; - io->generic.out.create_time = name->dos.create_time; - io->generic.out.access_time = name->dos.access_time; - io->generic.out.write_time = name->dos.write_time; - io->generic.out.change_time = name->dos.change_time; - io->generic.out.attrib = name->dos.attrib; - io->generic.out.alloc_size = name->dos.alloc_size; - io->generic.out.size = name->st.st_size; - io->generic.out.file_type = FILE_TYPE_DISK; - io->generic.out.ipc_state = 0; - io->generic.out.is_directory = 0; - - /* success - keep the file handle */ - talloc_steal(f->pvfs, f); - - return NT_STATUS_OK; -} -#endif - -#if 1 /* open a directory */ @@ -758,7 +410,6 @@ cleanup_delete: rmdir(name->full_name); return status; } -#endif /* destroy a struct pvfs_file_handle -- cgit From 86497db6113c4ec3210d671c3fcf957d1026098c Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 10 Mar 2006 14:31:17 +0000 Subject: r14157: - pass a struct ntvfs_request to the ntvfs layer (for now we just do #define ntvfs_request smbsrv_request, but it's the first step...) - rename ntvfs_openfile() -> ntvfs_open() - fix the talloc hierachie in some places in the ntvfs_map_*() code metze (This used to be commit ed9ed1f48f602354810937c0b0de850b44322191) --- source4/ntvfs/posix/pvfs_open.c | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index e24887ca96..618ddf141b 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -39,7 +39,7 @@ find open file handle given fnum */ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, - struct smbsrv_request *req, uint16_t fnum) + struct ntvfs_request *req, uint16_t fnum) { struct pvfs_file *f; @@ -123,7 +123,7 @@ static int pvfs_dir_fnum_destructor(void *p) setup any EAs and the ACL on newly created files/directories */ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs, - struct smbsrv_request *req, + struct ntvfs_request *req, struct pvfs_filename *name, int fd, int fnum, union smb_open *io) @@ -186,7 +186,7 @@ static NTSTATUS pvfs_locking_key(struct pvfs_filename *name, open a directory */ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, - struct smbsrv_request *req, + struct ntvfs_request *req, struct pvfs_filename *name, union smb_open *io) { @@ -537,7 +537,7 @@ static NTSTATUS pvfs_brl_locking_key(struct pvfs_filename *name, create a new file */ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, - struct smbsrv_request *req, + struct ntvfs_request *req, struct pvfs_filename *name, union smb_open *io) { @@ -743,7 +743,7 @@ cleanup_delete: */ struct pvfs_open_retry { struct ntvfs_module_context *ntvfs; - struct smbsrv_request *req; + struct ntvfs_request *req; union smb_open *io; void *wait_handle; DATA_BLOB odb_locking_key; @@ -772,7 +772,7 @@ static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason) { struct pvfs_open_retry *r = private; struct ntvfs_module_context *ntvfs = r->ntvfs; - struct smbsrv_request *req = r->req; + struct ntvfs_request *req = r->req; union smb_open *io = r->io; NTSTATUS status; @@ -828,7 +828,7 @@ static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason) open processing continues. */ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, - struct smbsrv_request *req, union smb_open *io, + struct ntvfs_request *req, union smb_open *io, struct pvfs_file *f, struct odb_lock *lck) { struct pvfs_state *pvfs = ntvfs->private_data; @@ -904,7 +904,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, setup for a open retry after a sharing violation */ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, - struct smbsrv_request *req, + struct ntvfs_request *req, union smb_open *io, struct pvfs_file *f, struct odb_lock *lck) @@ -964,7 +964,7 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, open a file */ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, - struct smbsrv_request *req, union smb_open *io) + struct ntvfs_request *req, union smb_open *io) { struct pvfs_state *pvfs = ntvfs->private_data; int flags; @@ -982,7 +982,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, different open calls. */ if (io->generic.level != RAW_OPEN_GENERIC && io->generic.level != RAW_OPEN_NTTRANS_CREATE) { - return ntvfs_map_open(req, io, ntvfs); + return ntvfs_map_open(ntvfs, req, io); } /* resolve the cifs name to a posix name */ @@ -1264,7 +1264,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, close a file */ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, - struct smbsrv_request *req, union smb_close *io) + struct ntvfs_request *req, union smb_close *io) { struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f; @@ -1275,7 +1275,7 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, } if (io->generic.level != RAW_CLOSE_CLOSE) { - return ntvfs_map_close(req, io, ntvfs); + return ntvfs_map_close(ntvfs, req, io); } f = pvfs_find_fd(pvfs, req, io->close.in.fnum); @@ -1303,7 +1303,7 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, logoff - close all file descriptors open by a vuid */ NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs, - struct smbsrv_request *req) + struct ntvfs_request *req) { struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f, *next; @@ -1323,7 +1323,7 @@ NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs, exit - close files for the current pid */ NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs, - struct smbsrv_request *req) + struct ntvfs_request *req) { struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f, *next; @@ -1343,7 +1343,7 @@ NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs, change the delete on close flag on an already open file */ NTSTATUS pvfs_set_delete_on_close(struct pvfs_state *pvfs, - struct smbsrv_request *req, + struct ntvfs_request *req, struct pvfs_file *f, BOOL del_on_close) { struct odb_lock *lck; @@ -1382,7 +1382,7 @@ NTSTATUS pvfs_set_delete_on_close(struct pvfs_state *pvfs, already open file */ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, - struct smbsrv_request *req, + struct ntvfs_request *req, struct pvfs_filename *name, struct odb_lock **lckp) { @@ -1427,7 +1427,7 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, already open file */ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, - struct smbsrv_request *req, + struct ntvfs_request *req, struct pvfs_filename *name, struct odb_lock **lckp) { @@ -1467,7 +1467,7 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, already open file */ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, - struct smbsrv_request *req, + struct ntvfs_request *req, struct pvfs_filename *name) { NTSTATUS status; -- cgit From 307e43bb5628e8b53a930c2928279af994281ba5 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 10 Mar 2006 20:49:20 +0000 Subject: r14173: change smb interface structures to always use a union smb_file, to abtract - const char *path fot qpathinfo and setpathinfo - uint16_t fnum for SMB - smb2_handle handle for SMB2 the idea is to later add a struct ntvfs_handle *ntvfs so that the ntvfs subsystem don't need to know the difference between SMB and SMB2 metze (This used to be commit 2ef3f5970901b5accdb50f0d0115b5d46b0c788f) --- source4/ntvfs/posix/pvfs_open.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 618ddf141b..fcae5f8d61 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -390,7 +390,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, talloc_steal(pvfs, f); io->generic.out.oplock_level = OPLOCK_NONE; - io->generic.out.fnum = f->fnum; + io->generic.file.fnum = f->fnum; io->generic.out.create_action = create_action; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; @@ -712,7 +712,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } else { io->generic.out.oplock_level = OPLOCK_NONE; } - io->generic.out.fnum = f->fnum; + io->generic.file.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_CREATED; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; @@ -880,7 +880,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, name = f->handle->name; io->generic.out.oplock_level = OPLOCK_NONE; - io->generic.out.fnum = f->fnum; + io->generic.file.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; @@ -1239,7 +1239,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } else { io->generic.out.oplock_level = OPLOCK_NONE; } - io->generic.out.fnum = f->fnum; + io->generic.file.fnum = f->fnum; io->generic.out.create_action = stream_existed? NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED; io->generic.out.create_time = name->dos.create_time; @@ -1278,7 +1278,7 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return ntvfs_map_close(ntvfs, req, io); } - f = pvfs_find_fd(pvfs, req, io->close.in.fnum); + f = pvfs_find_fd(pvfs, req, io->close.file.fnum); if (!f) { return NT_STATUS_INVALID_HANDLE; } -- cgit From a1b295ed4823ce8d06f830b8db9a5d965c934b54 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sun, 12 Mar 2006 22:48:25 +0000 Subject: r14256: - rename smb_file -> smb_handle - move it into the in/out substructs again - allow file.path only on smb_fileinfo/smb_setfileinfo metze (This used to be commit be6d5298a2cdb7e7c61d70471bad445645af5963) --- source4/ntvfs/posix/pvfs_open.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index fcae5f8d61..d4b2d0b30a 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -144,7 +144,7 @@ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs, if (io->ntcreatex.in.sec_desc) { union smb_setfileinfo set; - set.set_secdesc.file.fnum = fnum; + set.set_secdesc.in.file.fnum = fnum; set.set_secdesc.in.secinfo_flags = SECINFO_DACL; set.set_secdesc.in.sd = io->ntcreatex.in.sec_desc; @@ -390,7 +390,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, talloc_steal(pvfs, f); io->generic.out.oplock_level = OPLOCK_NONE; - io->generic.file.fnum = f->fnum; + io->generic.out.file.fnum = f->fnum; io->generic.out.create_action = create_action; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; @@ -712,7 +712,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } else { io->generic.out.oplock_level = OPLOCK_NONE; } - io->generic.file.fnum = f->fnum; + io->generic.out.file.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_CREATED; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; @@ -880,7 +880,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, name = f->handle->name; io->generic.out.oplock_level = OPLOCK_NONE; - io->generic.file.fnum = f->fnum; + io->generic.out.file.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; @@ -1239,7 +1239,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } else { io->generic.out.oplock_level = OPLOCK_NONE; } - io->generic.file.fnum = f->fnum; + io->generic.out.file.fnum = f->fnum; io->generic.out.create_action = stream_existed? NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED; io->generic.out.create_time = name->dos.create_time; @@ -1278,7 +1278,7 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return ntvfs_map_close(ntvfs, req, io); } - f = pvfs_find_fd(pvfs, req, io->close.file.fnum); + f = pvfs_find_fd(pvfs, req, io->close.in.file.fnum); if (!f) { return NT_STATUS_INVALID_HANDLE; } -- cgit From 3f6ede84dae170478dd1d8205e99c5f5c0921e28 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 15 Mar 2006 11:27:40 +0000 Subject: r14440: demonstrate that the smbpid is attached to a session (vuid), so SMBexit() only closes files for the given user session and the given PID can someone check if samba3 passes this test, please? metze (This used to be commit fd291ff003ed934b2163d9ad93af9ef2dd631e11) --- source4/ntvfs/posix/pvfs_open.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index d4b2d0b30a..174cab51ec 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1330,7 +1330,8 @@ NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs, for (f=pvfs->open_files;f;f=next) { next = f->next; - if (f->smbpid == req->smbpid) { + if (f->session == req->session && + f->smbpid == req->smbpid) { talloc_free(f); } } -- cgit From 8528016978b084213ef53d66e1b6e831b1a01acc Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Thu, 16 Mar 2006 00:23:11 +0000 Subject: r14464: Don't include ndr_BASENAME.h files unless strictly required, instead try to include just the BASENAME.h files (containing only structs) (This used to be commit 3dd477ca5147f28a962b8437e2611a8222d706bd) --- source4/ntvfs/posix/pvfs_open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 174cab51ec..4f0615087a 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -26,7 +26,7 @@ #include "system/time.h" #include "dlinklist.h" #include "messaging/messaging.h" -#include "librpc/gen_ndr/ndr_xattr.h" +#include "librpc/gen_ndr/xattr.h" /* create file handles with convenient numbers for sniffers -- cgit From d3087451c4ec25171ba956fe2cd4e1d0f64f7edc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 16 Mar 2006 18:54:19 +0000 Subject: r14487: split smbsrv_request into two parts, one will be moved to ntvfs_request but I don't to get the commit to large, to I'll do this tomorrow... metze (This used to be commit 10e627032d7d04f1ebf6efed248c426614f5aa6f) --- source4/ntvfs/posix/pvfs_open.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 4f0615087a..3160519f73 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -52,7 +52,7 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, smb_panic("pvfs_find_fd: idtree_fnum corruption\n"); } - if (req->session != f->session) { + if (req->session_info != f->session_info) { DEBUG(2,("pvfs_find_fd: attempt to use wrong session for fnum %d\n", fnum)); return NULL; @@ -263,7 +263,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } f->fnum = fnum; - f->session = req->session; + f->session_info = req->session_info; f->smbpid = req->smbpid; f->pvfs = pvfs; f->pending_list = NULL; @@ -680,7 +680,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } f->fnum = fnum; - f->session = req->session; + f->session_info = req->session_info; f->smbpid = req->smbpid; f->pvfs = pvfs; f->pending_list = NULL; @@ -847,7 +847,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, */ for (f2=pvfs->open_files;f2;f2=f2->next) { if (f2 != f && - f2->session == req->session && + f2->session_info == req->session_info && f2->smbpid == req->smbpid && (f2->handle->create_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | @@ -936,7 +936,7 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, f->handle->odb_locking_key.data, f->handle->odb_locking_key.length); - end_time = timeval_add(&req->request_time, 0, pvfs->sharing_violation_delay); + end_time = timeval_add(&req->statistics.request_time, 0, pvfs->sharing_violation_delay); /* setup a pending lock */ status = odb_open_file_pending(lck, r); @@ -1105,7 +1105,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } f->fnum = fnum; - f->session = req->session; + f->session_info = req->session_info; f->smbpid = req->smbpid; f->pvfs = pvfs; f->pending_list = NULL; @@ -1310,7 +1310,7 @@ NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs, for (f=pvfs->open_files;f;f=next) { next = f->next; - if (f->session == req->session) { + if (f->session_info == req->session_info) { talloc_free(f); } } @@ -1330,7 +1330,7 @@ NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs, for (f=pvfs->open_files;f;f=next) { next = f->next; - if (f->session == req->session && + if (f->session_info == req->session_info && f->smbpid == req->smbpid) { talloc_free(f); } -- cgit From 75140d6150264ba50a47e104c3ce1ae40bd3f0c8 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 18 Mar 2006 10:38:38 +0000 Subject: r14540: fix a talloc hierachie problem, make sure file and search handles are cleaned up before anything else in the pvfs_state struct, as there destructors reply on a valid pvfs_state struct metze (This used to be commit aaa5d377b9b6145a83c0e686c7fbb7b561ae8988) --- source4/ntvfs/posix/pvfs_open.c | 62 ++++++++++++++++++++--------------------- 1 file changed, 31 insertions(+), 31 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 3160519f73..2724339323 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -43,7 +43,7 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, { struct pvfs_file *f; - f = idr_find(pvfs->idtree_fnum, fnum); + f = idr_find(pvfs->files.idtree, fnum); if (f == NULL) { return NULL; } @@ -114,8 +114,8 @@ static int pvfs_dir_handle_destructor(void *p) static int pvfs_dir_fnum_destructor(void *p) { struct pvfs_file *f = p; - DLIST_REMOVE(f->pvfs->open_files, f); - idr_remove(f->pvfs->idtree_fnum, f->fnum); + DLIST_REMOVE(f->pvfs->files.list, f); + idr_remove(f->pvfs->files.idtree, f->fnum); return 0; } @@ -246,7 +246,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_NO_MEMORY; } - fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_DIR_FNUM, UINT16_MAX); + fnum = idr_get_new_above(pvfs->files.idtree, f, PVFS_MIN_DIR_FNUM, UINT16_MAX); if (fnum == -1) { return NT_STATUS_TOO_MANY_OPENED_FILES; } @@ -258,7 +258,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, status = pvfs_access_check_create(pvfs, req, name, &access_mask); } if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, fnum); + idr_remove(pvfs->files.idtree, fnum); return status; } @@ -295,7 +295,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* form the lock context used for opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, f->fnum); + idr_remove(pvfs->files.idtree, f->fnum); return status; } @@ -306,7 +306,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, name->full_name)); /* we were supposed to do a blocking lock, so something is badly wrong! */ - idr_remove(pvfs->idtree_fnum, fnum); + idr_remove(pvfs->files.idtree, fnum); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -315,7 +315,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, share_access, access_mask, del_on_close, name->full_name); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, f->fnum); + idr_remove(pvfs->files.idtree, f->fnum); talloc_free(lck); return status; } @@ -323,7 +323,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->handle->have_opendb_entry = True; } - DLIST_ADD(pvfs->open_files, f); + DLIST_ADD(pvfs->files.list, f); /* setup destructors to avoid leaks on abnormal termination */ talloc_set_destructor(f->handle, pvfs_dir_handle_destructor); @@ -334,7 +334,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, mode_t mode = pvfs_fileperms(pvfs, attrib); if (mkdir(name->full_name, mode) == -1) { - idr_remove(pvfs->idtree_fnum, fnum); + idr_remove(pvfs->files.idtree, fnum); return pvfs_map_errno(pvfs,errno); } @@ -353,7 +353,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* form the lock context used for opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, f->fnum); + idr_remove(pvfs->files.idtree, f->fnum); return status; } @@ -363,7 +363,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, name->full_name)); /* we were supposed to do a blocking lock, so something is badly wrong! */ - idr_remove(pvfs->idtree_fnum, fnum); + idr_remove(pvfs->files.idtree, fnum); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -382,7 +382,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } if (!name->exists) { - idr_remove(pvfs->idtree_fnum, fnum); + idr_remove(pvfs->files.idtree, fnum); return NT_STATUS_OBJECT_NAME_NOT_FOUND; } @@ -406,7 +406,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_OK; cleanup_delete: - idr_remove(pvfs->idtree_fnum, fnum); + idr_remove(pvfs->files.idtree, fnum); rmdir(name->full_name); return status; } @@ -493,9 +493,9 @@ static int pvfs_fnum_destructor(void *p) { struct pvfs_file *f = p; - DLIST_REMOVE(f->pvfs->open_files, f); + DLIST_REMOVE(f->pvfs->files.list, f); pvfs_lock_close(f->pvfs, f); - idr_remove(f->pvfs->idtree_fnum, f->fnum); + idr_remove(f->pvfs->files.idtree, f->fnum); return 0; } @@ -591,7 +591,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return NT_STATUS_NO_MEMORY; } - fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_NEW_FNUM, UINT16_MAX); + fnum = idr_get_new_above(pvfs->files.idtree, f, PVFS_MIN_NEW_FNUM, UINT16_MAX); if (fnum == -1) { return NT_STATUS_TOO_MANY_OPENED_FILES; } @@ -602,7 +602,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* create the file */ fd = open(name->full_name, flags | O_CREAT | O_EXCL, mode); if (fd == -1) { - idr_remove(pvfs->idtree_fnum, fnum); + idr_remove(pvfs->files.idtree, fnum); return pvfs_map_errno(pvfs, errno); } @@ -612,7 +612,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, if (name->stream_name) { status = pvfs_stream_create(pvfs, name, fd); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, fnum); + idr_remove(pvfs->files.idtree, fnum); close(fd); return status; } @@ -621,7 +621,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* re-resolve the open fd */ status = pvfs_resolve_name_fd(pvfs, fd, name); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, fnum); + idr_remove(pvfs->files.idtree, fnum); close(fd); return status; } @@ -674,7 +674,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* bad news, we must have hit a race - we don't delete the file here as the most likely scenario is that someone else created the file at the same time */ - idr_remove(pvfs->idtree_fnum, fnum); + idr_remove(pvfs->files.idtree, fnum); close(fd); return status; } @@ -699,7 +699,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->handle->have_opendb_entry = True; f->handle->sticky_write_time = False; - DLIST_ADD(pvfs->open_files, f); + DLIST_ADD(pvfs->files.list, f); /* setup a destructor to avoid file descriptor leaks on abnormal termination */ @@ -731,7 +731,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return NT_STATUS_OK; cleanup_delete: - idr_remove(pvfs->idtree_fnum, fnum); + idr_remove(pvfs->files.idtree, fnum); close(fd); unlink(name->full_name); return status; @@ -845,7 +845,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, circumstances you actually get the _same_ handle back twice, rather than a new handle. */ - for (f2=pvfs->open_files;f2;f2=f2->next) { + for (f2=pvfs->files.list;f2;f2=f2->next) { if (f2 != f && f2->session_info == req->session_info && f2->smbpid == req->smbpid && @@ -1099,7 +1099,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } /* allocate a fnum */ - fnum = idr_get_new_above(pvfs->idtree_fnum, f, PVFS_MIN_FILE_FNUM, UINT16_MAX); + fnum = idr_get_new_above(pvfs->files.idtree, f, PVFS_MIN_FILE_FNUM, UINT16_MAX); if (fnum == -1) { return NT_STATUS_TOO_MANY_OPENED_FILES; } @@ -1128,13 +1128,13 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, f->fnum); + idr_remove(pvfs->files.idtree, f->fnum); return status; } status = pvfs_brl_locking_key(name, f->handle, &f->handle->brl_locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->idtree_fnum, f->fnum); + idr_remove(pvfs->files.idtree, f->fnum); return status; } @@ -1145,11 +1145,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, name->full_name)); /* we were supposed to do a blocking lock, so something is badly wrong! */ - idr_remove(pvfs->idtree_fnum, fnum); + idr_remove(pvfs->files.idtree, fnum); return NT_STATUS_INTERNAL_DB_CORRUPTION; } - DLIST_ADD(pvfs->open_files, f); + DLIST_ADD(pvfs->files.list, f); /* setup a destructor to avoid file descriptor leaks on abnormal termination */ @@ -1308,7 +1308,7 @@ NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs, struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f, *next; - for (f=pvfs->open_files;f;f=next) { + for (f=pvfs->files.list;f;f=next) { next = f->next; if (f->session_info == req->session_info) { talloc_free(f); @@ -1328,7 +1328,7 @@ NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs, struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f, *next; - for (f=pvfs->open_files;f;f=next) { + for (f=pvfs->files.list;f;f=next) { next = f->next; if (f->session_info == req->session_info && f->smbpid == req->smbpid) { -- cgit From 3434cd778c975eb1bb29d257770bd6dbb2335ce9 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 21 Mar 2006 11:47:24 +0000 Subject: r14616: added notify change support to the posix backend It doesn't fully work yet, and doesn't yet have all the efficiency that is planned, but it doesn't break anything and I wanted to get the code in the tree to minimise the chance of collisions with the work metze is doing. (This used to be commit 1624ea88e6eef89caacc36e7513aa79df0d579b9) --- source4/ntvfs/posix/pvfs_open.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 2724339323..3c3e13bc91 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -271,6 +271,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->share_access = io->generic.in.share_access; f->impersonation = io->generic.in.impersonation; f->access_mask = access_mask; + f->notify_buffer = NULL; f->handle->pvfs = pvfs; f->handle->name = talloc_steal(f->handle, name); @@ -688,6 +689,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->share_access = io->generic.in.share_access; f->access_mask = access_mask; f->impersonation = io->generic.in.impersonation; + f->notify_buffer = NULL; f->handle->pvfs = pvfs; f->handle->name = talloc_steal(f->handle, name); @@ -1113,6 +1115,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->share_access = io->generic.in.share_access; f->access_mask = access_mask; f->impersonation = io->generic.in.impersonation; + f->notify_buffer = NULL; f->handle->pvfs = pvfs; f->handle->fd = -1; -- cgit From 33f663b25206c6cc4b2c33dfca3983d9dfee73dc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 30 Mar 2006 01:09:46 +0000 Subject: r14792: when we enable fake oplocks, give out batch oplocks not exclusive oplocks (This used to be commit 182aee1a213c1219772895deed31e1ed8aed00c4) --- source4/ntvfs/posix/pvfs_open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 3c3e13bc91..1b1c32cab5 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -710,7 +710,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { - io->generic.out.oplock_level = OPLOCK_EXCLUSIVE; + io->generic.out.oplock_level = OPLOCK_BATCH; } else { io->generic.out.oplock_level = OPLOCK_NONE; } @@ -1238,7 +1238,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, talloc_free(lck); if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { - io->generic.out.oplock_level = OPLOCK_EXCLUSIVE; + io->generic.out.oplock_level = OPLOCK_BATCH; } else { io->generic.out.oplock_level = OPLOCK_NONE; } -- cgit From 8a95fa446e1eca4c9ff332202f23183411b44c04 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 30 Mar 2006 02:06:06 +0000 Subject: r14793: the RAW-NOTIFY test now passes. Next I need to make it efficient, and add the hooks in all the other places (This used to be commit d1937589029ac2a75d15f006685769c44a274a65) --- source4/ntvfs/posix/pvfs_open.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 1b1c32cab5..38123c3a9e 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -730,6 +730,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* success - keep the file handle */ talloc_steal(pvfs, f); + notify_trigger(pvfs->notify_context, NOTIFY_ACTION_ADDED, name->full_name); + return NT_STATUS_OK; cleanup_delete: -- cgit From ed3fc628713e1f9552b523c9aec9bd8993e0b771 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 30 Mar 2006 03:51:49 +0000 Subject: r14797: added checking of the filter in notify requests (This used to be commit 1db0a5a7f4c1ff915d91bc15d8e40cc90a78961d) --- source4/ntvfs/posix/pvfs_open.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 38123c3a9e..264234a09b 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -378,6 +378,11 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->handle->have_opendb_entry = True; create_action = NTCREATEX_ACTION_CREATED; + + notify_trigger(pvfs->notify_context, + NOTIFY_ACTION_REMOVED, + FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME, + name->full_name); } else { create_action = NTCREATEX_ACTION_EXISTED; } @@ -461,6 +466,11 @@ static int pvfs_handle_destructor(void *p) if (unlink(path) != 0) { DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n", path, strerror(errno))); + } else { + notify_trigger(h->pvfs->notify_context, + NOTIFY_ACTION_REMOVED, + FILE_NOTIFY_CHANGE_FILE_NAME, + path); } } @@ -730,7 +740,10 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* success - keep the file handle */ talloc_steal(pvfs, f); - notify_trigger(pvfs->notify_context, NOTIFY_ACTION_ADDED, name->full_name); + notify_trigger(pvfs->notify_context, + NOTIFY_ACTION_ADDED, + FILE_NOTIFY_CHANGE_FILE_NAME, + name->full_name); return NT_STATUS_OK; -- cgit From e54abee4e19538760119e8e63eb23f78fd88da4f Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 6 Apr 2006 01:56:04 +0000 Subject: r14933: fix the handling of notify filters to be much closer to the behaviour of w2k3. The behaviour is particularly tricky for rename. (This used to be commit 4d3b8d95498a328ffc08ecb62d9531b6bfe4e2b5) --- source4/ntvfs/posix/pvfs_open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 264234a09b..5afb538db7 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -380,8 +380,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, create_action = NTCREATEX_ACTION_CREATED; notify_trigger(pvfs->notify_context, - NOTIFY_ACTION_REMOVED, - FILE_NOTIFY_CHANGE_FILE_NAME|FILE_NOTIFY_CHANGE_DIR_NAME, + NOTIFY_ACTION_ADDED, + FILE_NOTIFY_CHANGE_DIR_NAME, name->full_name); } else { create_action = NTCREATEX_ACTION_EXISTED; -- cgit From 289911bb4e7980bf42cc87305d3f94477c5f2b75 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 12 Apr 2006 04:42:40 +0000 Subject: r15048: started on the server side implementation of oplocks. The code is not functional yet, I'm committing so it doesn't diverge too much from other peoples work. It is disabled by default. (This used to be commit ba0b8a218dfe1ef6cdf7de724fb30650301369dd) --- source4/ntvfs/posix/pvfs_open.c | 51 +++++++++++++++++++++++++++++------------ 1 file changed, 36 insertions(+), 15 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 5afb538db7..0a2cab8747 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -313,7 +313,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* see if we are allowed to open at the same time as existing opens */ status = odb_open_file(lck, f->handle, f->handle->name->stream_id, - share_access, access_mask, del_on_close, name->full_name); + share_access, access_mask, del_on_close, + name->full_name, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { idr_remove(pvfs->files.idtree, f->fnum); @@ -369,7 +370,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } status = odb_open_file(lck, f->handle, f->handle->name->stream_id, - share_access, access_mask, del_on_close, name->full_name); + share_access, access_mask, del_on_close, + name->full_name, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; @@ -563,6 +565,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, uint32_t attrib; BOOL del_on_close; struct pvfs_filename *parent; + uint32_t oplock_level = OPLOCK_NONE, oplock_granted; if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) && (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { @@ -678,8 +681,17 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, del_on_close = False; } + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { + oplock_level = OPLOCK_NONE; + } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK) { + oplock_level = OPLOCK_BATCH; + } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_OPLOCK) { + oplock_level = OPLOCK_EXCLUSIVE; + } + status = odb_open_file(lck, f->handle, name->stream_id, - share_access, access_mask, del_on_close, name->full_name); + share_access, access_mask, del_on_close, + name->full_name, oplock_level, &oplock_granted); talloc_free(lck); if (!NT_STATUS_IS_OK(status)) { /* bad news, we must have hit a race - we don't delete the file @@ -690,6 +702,10 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return status; } + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { + oplock_granted = OPLOCK_BATCH; + } + f->fnum = fnum; f->session_info = req->session_info; f->smbpid = req->smbpid; @@ -718,12 +734,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, talloc_set_destructor(f, pvfs_fnum_destructor); talloc_set_destructor(f->handle, pvfs_handle_destructor); - - if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { - io->generic.out.oplock_level = OPLOCK_BATCH; - } else { - io->generic.out.oplock_level = OPLOCK_NONE; - } + io->generic.out.oplock_level = oplock_granted; io->generic.out.file.fnum = f->fnum; io->generic.out.create_action = NTCREATEX_ACTION_CREATED; io->generic.out.create_time = name->dos.create_time; @@ -994,6 +1005,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, uint32_t share_access; uint32_t access_mask; BOOL stream_existed, stream_truncate=False; + uint32_t oplock_level = OPLOCK_NONE, oplock_granted; /* use the generic mapping code to avoid implementing all the different open calls. */ @@ -1174,9 +1186,18 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, talloc_set_destructor(f, pvfs_fnum_destructor); talloc_set_destructor(f->handle, pvfs_handle_destructor); + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { + oplock_level = OPLOCK_NONE; + } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK) { + oplock_level = OPLOCK_BATCH; + } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_OPLOCK) { + oplock_level = OPLOCK_EXCLUSIVE; + } + /* see if we are allowed to open at the same time as existing opens */ status = odb_open_file(lck, f->handle, f->handle->name->stream_id, - share_access, access_mask, False, name->full_name); + share_access, access_mask, False, name->full_name, + oplock_level, &oplock_granted); /* on a sharing violation we need to retry when the file is closed by the other user, or after 1 second */ @@ -1190,6 +1211,10 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { + oplock_granted = OPLOCK_BATCH; + } + f->handle->have_opendb_entry = True; if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) { @@ -1252,11 +1277,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, talloc_free(lck); - if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { - io->generic.out.oplock_level = OPLOCK_BATCH; - } else { - io->generic.out.oplock_level = OPLOCK_NONE; - } + io->generic.out.oplock_level = oplock_granted; io->generic.out.file.fnum = f->fnum; io->generic.out.create_action = stream_existed? NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED; -- cgit From 8302b889b410934330ed9c7c492d9b26b3bce58a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 Apr 2006 12:59:41 +0000 Subject: r15078: add TODO about setting the full ACL with an NTTRANS_CREATE metze (This used to be commit bd2c899d83615066fbd1332495a4610eeea8f8ee) --- source4/ntvfs/posix/pvfs_open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 0a2cab8747..488f2d9568 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -143,7 +143,7 @@ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs, /* setup an initial sec_desc if requested */ if (io->ntcreatex.in.sec_desc) { union smb_setfileinfo set; - +/* TODO: set the full ACL! */ set.set_secdesc.in.file.fnum = fnum; set.set_secdesc.in.secinfo_flags = SECINFO_DACL; set.set_secdesc.in.sd = io->ntcreatex.in.sec_desc; -- cgit From dd894d56267009f76977502d49a82ca34bdd8a41 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 18 Apr 2006 08:07:35 +0000 Subject: r15117: add more comments metze (This used to be commit d76f3e2fb61317633876afc90c1cea1130e58dea) --- source4/ntvfs/posix/pvfs_open.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 488f2d9568..9570fa08d9 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -143,7 +143,13 @@ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs, /* setup an initial sec_desc if requested */ if (io->ntcreatex.in.sec_desc) { union smb_setfileinfo set; -/* TODO: set the full ACL! */ +/* + * TODO: set the full ACL! + * - vista denies the creation of the file with NT_STATUS_PRIVILEGE_NOT_HELD, + * when a SACL is present on the sd, + * but the user doesn't have SeSecurityPrivilege + * - w2k3 allows it + */ set.set_secdesc.in.file.fnum = fnum; set.set_secdesc.in.secinfo_flags = SECINFO_DACL; set.set_secdesc.in.sd = io->ntcreatex.in.sec_desc; -- cgit From 5e6d1ea2618851ef99522a806f36916127e5294a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 15 May 2006 12:22:00 +0000 Subject: r15614: the byte range locking error handling caches the last failed lock per file handle and not per tree connect metze (This used to be commit 5d825261c0b8341f0a7f0f6d96d83807352566f4) --- source4/ntvfs/posix/pvfs_open.c | 47 +++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 21 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 9570fa08d9..3bbf840154 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -277,13 +277,13 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->share_access = io->generic.in.share_access; f->impersonation = io->generic.in.impersonation; f->access_mask = access_mask; + f->brl_handle = NULL; f->notify_buffer = NULL; f->handle->pvfs = pvfs; f->handle->name = talloc_steal(f->handle, name); f->handle->fd = -1; f->handle->odb_locking_key = data_blob(NULL, 0); - f->handle->brl_locking_key = data_blob(NULL, 0); f->handle->create_options = io->generic.in.create_options; f->handle->seek_offset = 0; f->handle->position = 0; @@ -526,32 +526,37 @@ static int pvfs_fnum_destructor(void *p) account of file streams (each stream is a separate byte range locking space) */ -static NTSTATUS pvfs_brl_locking_key(struct pvfs_filename *name, - TALLOC_CTX *mem_ctx, DATA_BLOB *key) +static NTSTATUS pvfs_brl_locking_handle(TALLOC_CTX *mem_ctx, + struct pvfs_filename *name, + uint16_t fnum, + struct brl_handle **_h) { - DATA_BLOB odb_key; + DATA_BLOB odb_key, key; NTSTATUS status; + struct brl_handle *h; + status = pvfs_locking_key(name, mem_ctx, &odb_key); - if (!NT_STATUS_IS_OK(status)) { - return status; - } + NT_STATUS_NOT_OK_RETURN(status); + if (name->stream_name == NULL) { - *key = odb_key; - return NT_STATUS_OK; - } - *key = data_blob_talloc(mem_ctx, NULL, - odb_key.length + strlen(name->stream_name) + 1); - if (key->data == NULL) { - return NT_STATUS_NO_MEMORY; + key = odb_key; + } else { + key = data_blob_talloc(mem_ctx, NULL, + odb_key.length + strlen(name->stream_name) + 1); + NT_STATUS_HAVE_NO_MEMORY(key.data); + memcpy(key.data, odb_key.data, odb_key.length); + memcpy(key.data + odb_key.length, + name->stream_name, strlen(name->stream_name) + 1); + data_blob_free(&odb_key); } - memcpy(key->data, odb_key.data, odb_key.length); - memcpy(key->data + odb_key.length, - name->stream_name, strlen(name->stream_name)+1); - data_blob_free(&odb_key); + + h = brl_create_handle(mem_ctx, &key, fnum); + NT_STATUS_HAVE_NO_MEMORY(h); + + *_h = h; return NT_STATUS_OK; } - /* create a new file */ @@ -665,7 +670,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, goto cleanup_delete; } - status = pvfs_brl_locking_key(name, f->handle, &f->handle->brl_locking_key); + status = pvfs_brl_locking_handle(f, name, fnum, &f->brl_handle); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; } @@ -1168,7 +1173,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } - status = pvfs_brl_locking_key(name, f->handle, &f->handle->brl_locking_key); + status = pvfs_brl_locking_handle(f, name, f->fnum, &f->brl_handle); if (!NT_STATUS_IS_OK(status)) { idr_remove(pvfs->files.idtree, f->fnum); return status; -- cgit From 9ef33f5f5c786b83311ca088357fb2f0aa72fc9e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 20 May 2006 08:15:22 +0000 Subject: r15734: This is a major change to the NTVFS subsystem: - to use a struct ntvfs_handle instead of a uint16_t fnum. (to make it independend from the frontend protocol) - the allocation of handles now is provided by the frontend (smbsrv_*) via callbacks and not by each backend module - this also makes sure that file handles are only passed to the ntvfs subsystem when the tcon and session matches, so modules can rely on this and need to check this. - this allows multiple modules in the ntvfs module chain to allocate file handles. This can be used for virtual files like "\\$Extend\\$Quota:$Q:$INDEX_ALLOCATION"... - also this will make SMB2 with 128 bit file handles possible metze (This used to be commit 287fc1c22d670f6e568014b420f7f4cb31dc7958) --- source4/ntvfs/posix/pvfs_open.c | 154 ++++++++++++++++------------------------ 1 file changed, 63 insertions(+), 91 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 3bbf840154..fd382ba1d9 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -28,40 +28,29 @@ #include "messaging/messaging.h" #include "librpc/gen_ndr/xattr.h" -/* - create file handles with convenient numbers for sniffers -*/ -#define PVFS_MIN_FILE_FNUM 0x100 -#define PVFS_MIN_NEW_FNUM 0x200 -#define PVFS_MIN_DIR_FNUM 0x300 - /* find open file handle given fnum */ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, - struct ntvfs_request *req, uint16_t fnum) + struct ntvfs_request *req, struct ntvfs_handle *h) { + void *p; struct pvfs_file *f; - f = idr_find(pvfs->files.idtree, fnum); - if (f == NULL) { - return NULL; - } + p = ntvfs_handle_get_backend_data(h, pvfs->ntvfs); + if (!p) return NULL; - if (f->fnum != fnum) { - smb_panic("pvfs_find_fd: idtree_fnum corruption\n"); - } + f = talloc_get_type(p, struct pvfs_file); + if (!f) return NULL; if (req->session_info != f->session_info) { - DEBUG(2,("pvfs_find_fd: attempt to use wrong session for fnum %d\n", - fnum)); + DEBUG(2,("pvfs_find_fd: attempt to use wrong session for handle %p\n",h)); return NULL; } return f; } - /* cleanup a open directory handle */ @@ -114,8 +103,10 @@ static int pvfs_dir_handle_destructor(void *p) static int pvfs_dir_fnum_destructor(void *p) { struct pvfs_file *f = p; + DLIST_REMOVE(f->pvfs->files.list, f); - idr_remove(f->pvfs->files.idtree, f->fnum); + ntvfs_handle_remove_backend_data(f->ntvfs, f->pvfs->ntvfs); + return 0; } @@ -125,7 +116,7 @@ static int pvfs_dir_fnum_destructor(void *p) static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs, struct ntvfs_request *req, struct pvfs_filename *name, - int fd, int fnum, + int fd, struct pvfs_file *f, union smb_open *io) { NTSTATUS status; @@ -150,7 +141,7 @@ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs, * but the user doesn't have SeSecurityPrivilege * - w2k3 allows it */ - set.set_secdesc.in.file.fnum = fnum; + set.set_secdesc.in.file.ntvfs = f->ntvfs; set.set_secdesc.in.secinfo_flags = SECINFO_DACL; set.set_secdesc.in.sd = io->ntcreatex.in.sec_desc; @@ -197,7 +188,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, union smb_open *io) { struct pvfs_file *f; - int fnum; + struct ntvfs_handle *h; NTSTATUS status; uint32_t create_action; uint32_t access_mask = io->generic.in.access_mask; @@ -242,7 +233,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_INVALID_PARAMETER; } - f = talloc(req, struct pvfs_file); + status = ntvfs_handle_new(pvfs->ntvfs, req, &h); + NT_STATUS_NOT_OK_RETURN(status); + + f = talloc(h, struct pvfs_file); if (f == NULL) { return NT_STATUS_NO_MEMORY; } @@ -252,11 +246,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_NO_MEMORY; } - fnum = idr_get_new_above(pvfs->files.idtree, f, PVFS_MIN_DIR_FNUM, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; - } - if (name->exists) { /* check the security descriptor */ status = pvfs_access_check(pvfs, req, name, &access_mask); @@ -264,11 +253,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, status = pvfs_access_check_create(pvfs, req, name, &access_mask); } if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, fnum); return status; } - f->fnum = fnum; + f->ntvfs = h; f->session_info = req->session_info; f->smbpid = req->smbpid; f->pvfs = pvfs; @@ -297,12 +285,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, del_on_close = False; } - if (name->exists) { /* form the lock context used for opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, f->fnum); return status; } @@ -313,7 +299,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, name->full_name)); /* we were supposed to do a blocking lock, so something is badly wrong! */ - idr_remove(pvfs->files.idtree, fnum); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -323,7 +308,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, name->full_name, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, f->fnum); talloc_free(lck); return status; } @@ -342,7 +326,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, mode_t mode = pvfs_fileperms(pvfs, attrib); if (mkdir(name->full_name, mode) == -1) { - idr_remove(pvfs->files.idtree, fnum); return pvfs_map_errno(pvfs,errno); } @@ -353,7 +336,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, goto cleanup_delete; } - status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, fnum, io); + status = pvfs_open_setup_eas_acl(pvfs, req, name, -1, f, io); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; } @@ -361,7 +344,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* form the lock context used for opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, f->fnum); return status; } @@ -371,7 +353,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, name->full_name)); /* we were supposed to do a blocking lock, so something is badly wrong! */ - idr_remove(pvfs->files.idtree, fnum); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -396,15 +377,17 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } if (!name->exists) { - idr_remove(pvfs->files.idtree, fnum); return NT_STATUS_OBJECT_NAME_NOT_FOUND; } /* the open succeeded, keep this handle permanently */ - talloc_steal(pvfs, f); + status = ntvfs_handle_set_backend_data(h, pvfs->ntvfs, f); + if (!NT_STATUS_IS_OK(status)) { + goto cleanup_delete; + } io->generic.out.oplock_level = OPLOCK_NONE; - io->generic.out.file.fnum = f->fnum; + io->generic.out.file.ntvfs = h; io->generic.out.create_action = create_action; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; @@ -420,7 +403,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_OK; cleanup_delete: - idr_remove(pvfs->files.idtree, fnum); rmdir(name->full_name); return status; } @@ -510,11 +492,11 @@ static int pvfs_handle_destructor(void *p) */ static int pvfs_fnum_destructor(void *p) { - struct pvfs_file *f = p; + struct pvfs_file *f = talloc_get_type(p, struct pvfs_file); DLIST_REMOVE(f->pvfs->files.list, f); pvfs_lock_close(f->pvfs, f); - idr_remove(f->pvfs->files.idtree, f->fnum); + ntvfs_handle_remove_backend_data(f->ntvfs, f->pvfs->ntvfs); return 0; } @@ -527,8 +509,8 @@ static int pvfs_fnum_destructor(void *p) locking space) */ static NTSTATUS pvfs_brl_locking_handle(TALLOC_CTX *mem_ctx, - struct pvfs_filename *name, - uint16_t fnum, + struct pvfs_filename *name, + struct ntvfs_handle *ntvfs, struct brl_handle **_h) { DATA_BLOB odb_key, key; @@ -550,7 +532,7 @@ static NTSTATUS pvfs_brl_locking_handle(TALLOC_CTX *mem_ctx, data_blob_free(&odb_key); } - h = brl_create_handle(mem_ctx, &key, fnum); + h = brl_create_handle(mem_ctx, ntvfs, &key); NT_STATUS_HAVE_NO_MEMORY(h); *_h = h; @@ -567,7 +549,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, { struct pvfs_file *f; NTSTATUS status; - int flags, fnum, fd; + struct ntvfs_handle *h; + int flags, fd; struct odb_lock *lck; uint32_t create_options = io->generic.in.create_options; uint32_t share_access = io->generic.in.share_access; @@ -606,20 +589,14 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, flags = O_RDONLY; } - f = talloc(req, struct pvfs_file); - if (f == NULL) { - return NT_STATUS_NO_MEMORY; - } + status = ntvfs_handle_new(pvfs->ntvfs, req, &h); + NT_STATUS_NOT_OK_RETURN(status); - f->handle = talloc(f, struct pvfs_file_handle); - if (f->handle == NULL) { - return NT_STATUS_NO_MEMORY; - } + f = talloc(h, struct pvfs_file); + NT_STATUS_HAVE_NO_MEMORY(f); - fnum = idr_get_new_above(pvfs->files.idtree, f, PVFS_MIN_NEW_FNUM, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; - } + f->handle = talloc(f, struct pvfs_file_handle); + NT_STATUS_HAVE_NO_MEMORY(f->handle); attrib = io->ntcreatex.in.file_attr | FILE_ATTRIBUTE_ARCHIVE; mode = pvfs_fileperms(pvfs, attrib); @@ -627,7 +604,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* create the file */ fd = open(name->full_name, flags | O_CREAT | O_EXCL, mode); if (fd == -1) { - idr_remove(pvfs->files.idtree, fnum); return pvfs_map_errno(pvfs, errno); } @@ -637,7 +613,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, if (name->stream_name) { status = pvfs_stream_create(pvfs, name, fd); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, fnum); close(fd); return status; } @@ -646,7 +621,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* re-resolve the open fd */ status = pvfs_resolve_name_fd(pvfs, fd, name); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, fnum); close(fd); return status; } @@ -658,7 +632,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } - status = pvfs_open_setup_eas_acl(pvfs, req, name, fd, fnum, io); + status = pvfs_open_setup_eas_acl(pvfs, req, name, fd, f, io); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; } @@ -670,7 +644,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, goto cleanup_delete; } - status = pvfs_brl_locking_handle(f, name, fnum, &f->brl_handle); + status = pvfs_brl_locking_handle(f, name, h, &f->brl_handle); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; } @@ -708,7 +682,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, /* bad news, we must have hit a race - we don't delete the file here as the most likely scenario is that someone else created the file at the same time */ - idr_remove(pvfs->files.idtree, fnum); close(fd); return status; } @@ -717,7 +690,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, oplock_granted = OPLOCK_BATCH; } - f->fnum = fnum; + f->ntvfs = h; f->session_info = req->session_info; f->smbpid = req->smbpid; f->pvfs = pvfs; @@ -746,7 +719,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, talloc_set_destructor(f->handle, pvfs_handle_destructor); io->generic.out.oplock_level = oplock_granted; - io->generic.out.file.fnum = f->fnum; + io->generic.out.file.ntvfs = f->ntvfs; io->generic.out.create_action = NTCREATEX_ACTION_CREATED; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; @@ -760,7 +733,10 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, io->generic.out.is_directory = 0; /* success - keep the file handle */ - talloc_steal(pvfs, f); + status = ntvfs_handle_set_backend_data(h, pvfs->ntvfs, f); + if (!NT_STATUS_IS_OK(status)) { + goto cleanup_delete; + } notify_trigger(pvfs->notify_context, NOTIFY_ACTION_ADDED, @@ -770,7 +746,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return NT_STATUS_OK; cleanup_delete: - idr_remove(pvfs->files.idtree, fnum); close(fd); unlink(name->full_name); return status; @@ -873,6 +848,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f2; struct pvfs_filename *name; + NTSTATUS status; /* search for an existing open with the right parameters. Note the magic ntcreatex options flag, which is set in the @@ -919,7 +895,7 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, name = f->handle->name; io->generic.out.oplock_level = OPLOCK_NONE; - io->generic.out.file.fnum = f->fnum; + io->generic.out.file.ntvfs = f->ntvfs; io->generic.out.create_action = NTCREATEX_ACTION_EXISTED; io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; @@ -931,8 +907,9 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, io->generic.out.file_type = FILE_TYPE_DISK; io->generic.out.ipc_state = 0; io->generic.out.is_directory = 0; - - talloc_steal(f->pvfs, f); + + status = ntvfs_handle_set_backend_data(f->ntvfs, ntvfs, f); + NT_STATUS_NOT_OK_RETURN(status); return NT_STATUS_OK; } @@ -1009,8 +986,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, int flags; struct pvfs_filename *name; struct pvfs_file *f; + struct ntvfs_handle *h; NTSTATUS status; - int fnum, fd; + int fd; struct odb_lock *lck; uint32_t create_options; uint32_t share_access; @@ -1128,7 +1106,10 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } - f = talloc(req, struct pvfs_file); + status = ntvfs_handle_new(pvfs->ntvfs, req, &h); + NT_STATUS_NOT_OK_RETURN(status); + + f = talloc(h, struct pvfs_file); if (f == NULL) { return NT_STATUS_NO_MEMORY; } @@ -1138,13 +1119,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_NO_MEMORY; } - /* allocate a fnum */ - fnum = idr_get_new_above(pvfs->files.idtree, f, PVFS_MIN_FILE_FNUM, UINT16_MAX); - if (fnum == -1) { - return NT_STATUS_TOO_MANY_OPENED_FILES; - } - - f->fnum = fnum; + f->ntvfs = h; f->session_info = req->session_info; f->smbpid = req->smbpid; f->pvfs = pvfs; @@ -1169,13 +1144,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, f->fnum); return status; } - status = pvfs_brl_locking_handle(f, name, f->fnum, &f->brl_handle); + status = pvfs_brl_locking_handle(f, name, h, &f->brl_handle); if (!NT_STATUS_IS_OK(status)) { - idr_remove(pvfs->files.idtree, f->fnum); return status; } @@ -1186,7 +1159,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, name->full_name)); /* we were supposed to do a blocking lock, so something is badly wrong! */ - idr_remove(pvfs->files.idtree, fnum); return NT_STATUS_INTERNAL_DB_CORRUPTION; } @@ -1288,8 +1260,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, talloc_free(lck); + status = ntvfs_handle_set_backend_data(h, ntvfs, f); + NT_STATUS_NOT_OK_RETURN(status); + io->generic.out.oplock_level = oplock_granted; - io->generic.out.file.fnum = f->fnum; + io->generic.out.file.ntvfs = h; io->generic.out.create_action = stream_existed? NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED; io->generic.out.create_time = name->dos.create_time; @@ -1303,9 +1278,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, io->generic.out.ipc_state = 0; io->generic.out.is_directory = 0; - /* success - keep the file handle */ - talloc_steal(f->pvfs, f); - return NT_STATUS_OK; } @@ -1328,7 +1300,7 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return ntvfs_map_close(ntvfs, req, io); } - f = pvfs_find_fd(pvfs, req, io->close.in.file.fnum); + f = pvfs_find_fd(pvfs, req, io->close.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } -- cgit From d8223e4b94afe04f6b2fcf1a8ee4ba2d5cf16d22 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 23 May 2006 06:19:35 +0000 Subject: r15833: fixed two delete on close memory leaks (This used to be commit f3274e8f78f28a51313e98934b208c2deb9ae9ea) --- source4/ntvfs/posix/pvfs_open.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index fd382ba1d9..2102de29f5 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -58,7 +58,7 @@ static int pvfs_dir_handle_destructor(void *p) { struct pvfs_file_handle *h = p; int open_count; - char *path; + char *path = NULL; if (h->name->stream_name == NULL && pvfs_delete_on_close_set(h->pvfs, h, &open_count, &path) && @@ -75,6 +75,8 @@ static int pvfs_dir_handle_destructor(void *p) } } + talloc_free(path); + if (h->have_opendb_entry) { struct odb_lock *lck; NTSTATUS status; @@ -414,7 +416,7 @@ static int pvfs_handle_destructor(void *p) { struct pvfs_file_handle *h = p; int open_count; - char *path; + char *path = NULL; /* the write time is no longer sticky */ if (h->sticky_write_time) { @@ -464,6 +466,8 @@ static int pvfs_handle_destructor(void *p) } } + talloc_free(path); + if (h->have_opendb_entry) { struct odb_lock *lck; NTSTATUS status; -- cgit From 971d30bb201f5c3faff5f575d26882eb79f7955a Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 24 May 2006 07:34:11 +0000 Subject: r15854: more talloc_set_destructor() typesafe fixes (This used to be commit 61c6100617589ac6df4f527877241464cacbf8b3) --- source4/ntvfs/posix/pvfs_open.c | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 2102de29f5..74f9b44c5c 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -54,9 +54,8 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, /* cleanup a open directory handle */ -static int pvfs_dir_handle_destructor(void *p) +static int pvfs_dir_handle_destructor(struct pvfs_file_handle *h) { - struct pvfs_file_handle *h = p; int open_count; char *path = NULL; @@ -102,10 +101,8 @@ static int pvfs_dir_handle_destructor(void *p) /* cleanup a open directory fnum */ -static int pvfs_dir_fnum_destructor(void *p) +static int pvfs_dir_fnum_destructor(struct pvfs_file *f) { - struct pvfs_file *f = p; - DLIST_REMOVE(f->pvfs->files.list, f); ntvfs_handle_remove_backend_data(f->ntvfs, f->pvfs->ntvfs); @@ -412,9 +409,8 @@ cleanup_delete: /* destroy a struct pvfs_file_handle */ -static int pvfs_handle_destructor(void *p) +static int pvfs_handle_destructor(struct pvfs_file_handle *h) { - struct pvfs_file_handle *h = p; int open_count; char *path = NULL; @@ -494,10 +490,8 @@ static int pvfs_handle_destructor(void *p) /* destroy a struct pvfs_file */ -static int pvfs_fnum_destructor(void *p) +static int pvfs_fnum_destructor(struct pvfs_file *f) { - struct pvfs_file *f = talloc_get_type(p, struct pvfs_file); - DLIST_REMOVE(f->pvfs->files.list, f); pvfs_lock_close(f->pvfs, f); ntvfs_handle_remove_backend_data(f->ntvfs, f->pvfs->ntvfs); @@ -768,9 +762,8 @@ struct pvfs_open_retry { }; /* destroy a pending open request */ -static int pvfs_retry_destructor(void *ptr) +static int pvfs_retry_destructor(struct pvfs_open_retry *r) { - struct pvfs_open_retry *r = ptr; struct pvfs_state *pvfs = r->ntvfs->private_data; if (r->odb_locking_key.data) { struct odb_lock *lck; -- cgit From 42248766d410f7a5725b81e20c37c682db847b37 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 8 Jul 2006 12:35:37 +0000 Subject: r16876: implement SMB2 Find in the posix ntvfs backend metze (This used to be commit 4f1afda488f2fb5cfcf98ef6a56157f954fdccfc) --- source4/ntvfs/posix/pvfs_open.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 74f9b44c5c..5482bb3562 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -266,6 +266,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->access_mask = access_mask; f->brl_handle = NULL; f->notify_buffer = NULL; + f->search = NULL; f->handle->pvfs = pvfs; f->handle->name = talloc_steal(f->handle, name); @@ -698,6 +699,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->access_mask = access_mask; f->impersonation = io->generic.in.impersonation; f->notify_buffer = NULL; + f->search = NULL; f->handle->pvfs = pvfs; f->handle->name = talloc_steal(f->handle, name); @@ -1126,6 +1128,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->access_mask = access_mask; f->impersonation = io->generic.in.impersonation; f->notify_buffer = NULL; + f->search = NULL; f->handle->pvfs = pvfs; f->handle->fd = -1; -- cgit From 4c499cb45fa2452756642ab7017c1a9f321b73f6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 13 Jul 2006 13:51:54 +0000 Subject: r17008: on SMB2 Create the delete_on_close flag isn't ignored for existing opened files as it is for SMB. metze (This used to be commit bcf09a769e241de36abed17f22aa0534d87cf4ff) --- source4/ntvfs/posix/pvfs_open.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 5482bb3562..b0d0348240 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -992,6 +992,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, uint32_t create_options; uint32_t share_access; uint32_t access_mask; + BOOL del_on_close; BOOL stream_existed, stream_truncate=False; uint32_t oplock_level = OPLOCK_NONE, oplock_granted; @@ -1169,6 +1170,17 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, talloc_set_destructor(f, pvfs_fnum_destructor); talloc_set_destructor(f->handle, pvfs_handle_destructor); + /* + * Only SMB2 takes care of the delete_on_close, + * on existing files + */ + if (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE && + req->ctx->protocol == PROTOCOL_SMB2) { + del_on_close = True; + } else { + del_on_close = False; + } + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { oplock_level = OPLOCK_NONE; } else if (io->ntcreatex.in.flags & NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK) { @@ -1179,8 +1191,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* see if we are allowed to open at the same time as existing opens */ status = odb_open_file(lck, f->handle, f->handle->name->stream_id, - share_access, access_mask, False, name->full_name, - oplock_level, &oplock_granted); + share_access, access_mask, del_on_close, + name->full_name, oplock_level, &oplock_granted); /* on a sharing violation we need to retry when the file is closed by the other user, or after 1 second */ -- cgit From 529c5dae51c1e782e095bf96b7ab2ca95ccbb856 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 1 Aug 2006 10:58:01 +0000 Subject: r17362: session_info and smbpid are available from the ntvfs_handle so we don't need them on the pvfs_file struct. also we don't need to check is the handle has the correct session as this is job of the frontend server metze (This used to be commit c83501335f245ac73b9d53c12efee3d46b8c5b05) --- source4/ntvfs/posix/pvfs_open.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index b0d0348240..d8f30476ac 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -43,11 +43,6 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, f = talloc_get_type(p, struct pvfs_file); if (!f) return NULL; - if (req->session_info != f->session_info) { - DEBUG(2,("pvfs_find_fd: attempt to use wrong session for handle %p\n",h)); - return NULL; - } - return f; } @@ -256,8 +251,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } f->ntvfs = h; - f->session_info = req->session_info; - f->smbpid = req->smbpid; f->pvfs = pvfs; f->pending_list = NULL; f->lock_count = 0; @@ -690,8 +683,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } f->ntvfs = h; - f->session_info = req->session_info; - f->smbpid = req->smbpid; f->pvfs = pvfs; f->pending_list = NULL; f->lock_count = 0; @@ -861,8 +852,8 @@ static NTSTATUS pvfs_open_deny_dos(struct ntvfs_module_context *ntvfs, */ for (f2=pvfs->files.list;f2;f2=f2->next) { if (f2 != f && - f2->session_info == req->session_info && - f2->smbpid == req->smbpid && + f2->ntvfs->session_info == req->session_info && + f2->ntvfs->smbpid == req->smbpid && (f2->handle->create_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) && @@ -1120,8 +1111,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } f->ntvfs = h; - f->session_info = req->session_info; - f->smbpid = req->smbpid; f->pvfs = pvfs; f->pending_list = NULL; f->lock_count = 0; @@ -1344,7 +1333,7 @@ NTSTATUS pvfs_logoff(struct ntvfs_module_context *ntvfs, for (f=pvfs->files.list;f;f=next) { next = f->next; - if (f->session_info == req->session_info) { + if (f->ntvfs->session_info == req->session_info) { talloc_free(f); } } @@ -1364,8 +1353,8 @@ NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs, for (f=pvfs->files.list;f;f=next) { next = f->next; - if (f->session_info == req->session_info && - f->smbpid == req->smbpid) { + if (f->ntvfs->session_info == req->session_info && + f->ntvfs->smbpid == req->smbpid) { talloc_free(f); } } -- cgit From 0329d755a7611ba3897fc1ee9bdce410cc33d7f8 Mon Sep 17 00:00:00 2001 From: Jelmer Vernooij Date: Wed, 30 Aug 2006 11:29:34 +0000 Subject: r17930: Merge noinclude branch: * Move dlinklist.h, smb.h to subsystem-specific directories * Clean up ads.h and move what is left of it to dsdb/ (only place where it's used) (This used to be commit f7afa1cb77f3cfa7020b57de12e6003db7cfcc42) --- source4/ntvfs/posix/pvfs_open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index d8f30476ac..a0ef77b0ff 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -24,7 +24,7 @@ #include "vfs_posix.h" #include "system/dir.h" #include "system/time.h" -#include "dlinklist.h" +#include "lib/util/dlinklist.h" #include "messaging/messaging.h" #include "librpc/gen_ndr/xattr.h" -- cgit From e3036006fe99893eb6c4f69ca2e70e48d35e8f24 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Sun, 20 May 2007 08:01:02 +0000 Subject: r23017: fixed the warning we have been getting for a long time: pvfs_close: failed to delete XXX during the BASE-DELETE test. It was a real bug, and could result in a delete on close triggering for a handle that had never fully opened. (This used to be commit 398c3724b4cd8c8073c8a77f8b0568d6b3ce1e7d) --- source4/ntvfs/posix/pvfs_open.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index a0ef77b0ff..b737fa328a 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -270,6 +270,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->handle->position = 0; f->handle->mode = 0; f->handle->sticky_write_time = False; + f->handle->open_completed = False; if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && pvfs_directory_empty(pvfs, f->handle->name)) { @@ -379,6 +380,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, goto cleanup_delete; } + f->handle->open_completed = True; + io->generic.out.oplock_level = OPLOCK_NONE; io->generic.out.file.ntvfs = h; io->generic.out.create_action = create_action; @@ -437,6 +440,7 @@ static int pvfs_handle_destructor(struct pvfs_file_handle *h) } if (h->name->stream_name == NULL && + h->open_completed && pvfs_delete_on_close_set(h->pvfs, h, &open_count, &path) && open_count == 1) { NTSTATUS status; @@ -701,6 +705,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->handle->mode = 0; f->handle->have_opendb_entry = True; f->handle->sticky_write_time = False; + f->handle->open_completed = False; DLIST_ADD(pvfs->files.list, f); @@ -729,6 +734,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, goto cleanup_delete; } + f->handle->open_completed = True; + notify_trigger(pvfs->notify_context, NOTIFY_ACTION_ADDED, FILE_NOTIFY_CHANGE_FILE_NAME, @@ -1129,6 +1136,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->handle->mode = 0; f->handle->have_opendb_entry = False; f->handle->sticky_write_time = False; + f->handle->open_completed = False; /* form the lock context used for byte range locking and opendb locking */ @@ -1264,6 +1272,10 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, status = ntvfs_handle_set_backend_data(h, ntvfs, f); NT_STATUS_NOT_OK_RETURN(status); + /* mark the open as having completed fully, so delete on close + can now be used */ + f->handle->open_completed = True; + io->generic.out.oplock_level = oplock_granted; io->generic.out.file.ntvfs = h; io->generic.out.create_action = stream_existed? -- 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_open.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index b737fa328a..269df13069 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.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 . */ #include "includes.h" -- 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_open.c | 60 ++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 30 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 269df13069..8558f0476a 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -186,7 +186,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, uint32_t create_action; uint32_t access_mask = io->generic.in.access_mask; struct odb_lock *lck; - BOOL del_on_close; + bool del_on_close; uint32_t create_options; uint32_t share_access; @@ -268,14 +268,14 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->handle->seek_offset = 0; f->handle->position = 0; f->handle->mode = 0; - f->handle->sticky_write_time = False; - f->handle->open_completed = False; + f->handle->sticky_write_time = false; + f->handle->open_completed = false; if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && pvfs_directory_empty(pvfs, f->handle->name)) { - del_on_close = True; + del_on_close = true; } else { - del_on_close = False; + del_on_close = false; } if (name->exists) { @@ -305,7 +305,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return status; } - f->handle->have_opendb_entry = True; + f->handle->have_opendb_entry = true; } DLIST_ADD(pvfs->files.list, f); @@ -357,7 +357,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, goto cleanup_delete; } - f->handle->have_opendb_entry = True; + f->handle->have_opendb_entry = true; create_action = NTCREATEX_ACTION_CREATED; @@ -379,7 +379,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, goto cleanup_delete; } - f->handle->open_completed = True; + f->handle->open_completed = true; io->generic.out.oplock_level = OPLOCK_NONE; io->generic.out.file.ntvfs = h; @@ -552,7 +552,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, uint32_t access_mask = io->generic.in.access_mask; mode_t mode; uint32_t attrib; - BOOL del_on_close; + bool del_on_close; struct pvfs_filename *parent; uint32_t oplock_level = OPLOCK_NONE, oplock_granted; @@ -656,9 +656,9 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } if (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) { - del_on_close = True; + del_on_close = true; } else { - del_on_close = False; + del_on_close = false; } if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { @@ -702,9 +702,9 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->handle->seek_offset = 0; f->handle->position = 0; f->handle->mode = 0; - f->handle->have_opendb_entry = True; - f->handle->sticky_write_time = False; - f->handle->open_completed = False; + f->handle->have_opendb_entry = true; + f->handle->sticky_write_time = false; + f->handle->open_completed = false; DLIST_ADD(pvfs->files.list, f); @@ -733,7 +733,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, goto cleanup_delete; } - f->handle->open_completed = True; + f->handle->open_completed = true; notify_trigger(pvfs->notify_context, NOTIFY_ACTION_ADDED, @@ -989,8 +989,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, uint32_t create_options; uint32_t share_access; uint32_t access_mask; - BOOL del_on_close; - BOOL stream_existed, stream_truncate=False; + bool del_on_close; + bool stream_existed, stream_truncate=false; uint32_t oplock_level = OPLOCK_NONE, oplock_granted; /* use the generic mapping code to avoid implementing all the @@ -1035,7 +1035,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, if (name->stream_name == NULL) { flags = O_TRUNC; } else { - stream_truncate = True; + stream_truncate = true; } break; @@ -1053,7 +1053,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, if (name->stream_name == NULL) { flags = O_TRUNC; } else { - stream_truncate = True; + stream_truncate = true; } break; @@ -1133,9 +1133,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->handle->seek_offset = 0; f->handle->position = 0; f->handle->mode = 0; - f->handle->have_opendb_entry = False; - f->handle->sticky_write_time = False; - f->handle->open_completed = False; + f->handle->have_opendb_entry = false; + f->handle->sticky_write_time = false; + f->handle->open_completed = false; /* form the lock context used for byte range locking and opendb locking */ @@ -1172,9 +1172,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, */ if (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE && req->ctx->protocol == PROTOCOL_SMB2) { - del_on_close = True; + del_on_close = true; } else { - del_on_close = False; + del_on_close = false; } if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { @@ -1206,7 +1206,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, oplock_granted = OPLOCK_BATCH; } - f->handle->have_opendb_entry = True; + f->handle->have_opendb_entry = true; if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) { flags |= O_RDWR; @@ -1273,7 +1273,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* mark the open as having completed fully, so delete on close can now be used */ - f->handle->open_completed = True; + f->handle->open_completed = true; io->generic.out.oplock_level = oplock_granted; io->generic.out.file.ntvfs = h; @@ -1379,7 +1379,7 @@ NTSTATUS pvfs_exit(struct ntvfs_module_context *ntvfs, */ NTSTATUS pvfs_set_delete_on_close(struct pvfs_state *pvfs, struct ntvfs_request *req, - struct pvfs_file *f, BOOL del_on_close) + struct pvfs_file *f, bool del_on_close) { struct odb_lock *lck; NTSTATUS status; @@ -1532,17 +1532,17 @@ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, /* determine if delete on close is set on */ -BOOL pvfs_delete_on_close_set(struct pvfs_state *pvfs, struct pvfs_file_handle *h, +bool pvfs_delete_on_close_set(struct pvfs_state *pvfs, struct pvfs_file_handle *h, int *open_count, char **path) { NTSTATUS status; - BOOL del_on_close; + bool del_on_close; status = odb_get_delete_on_close(pvfs->odb_context, &h->odb_locking_key, &del_on_close, open_count, path); if (!NT_STATUS_IS_OK(status)) { DEBUG(1,("WARNING: unable to determine delete on close status for open file\n")); - return False; + return false; } return del_on_close; -- cgit From a0a0d4a5d0c24729a26a37ff54caa665de9149a2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Feb 2008 09:02:17 +0100 Subject: pvfs_wait: use struct pvfs_wait * instead of void * metze (This used to be commit 3b70331536d2402814db13a9f1f226a39373313a) --- source4/ntvfs/posix/pvfs_open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 8558f0476a..3ccd239523 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -756,7 +756,7 @@ struct pvfs_open_retry { struct ntvfs_module_context *ntvfs; struct ntvfs_request *req; union smb_open *io; - void *wait_handle; + struct pvfs_wait *wait_handle; DATA_BLOB odb_locking_key; }; -- cgit From f56ff422a525fc6fdf04de8e2ce5c5fa4c097629 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Feb 2008 20:01:25 +0100 Subject: pvfs: handle SHARING_VIOLATION and OPLOCK_NOT_GRANTED in pvfs_can_delete/rename() If the caller asks for the odb_lock return it also if we return NT_STATUS_SHARING_VIOLATION or NT_STATUS_OPLOCK_NOT_GRANTED so that the caller can add the pending notification. metze (This used to be commit daab9cb11eb540fae7ec3c024a586f5fd02cfc71) --- source4/ntvfs/posix/pvfs_open.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 3ccd239523..0d97b3d629 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1447,7 +1447,19 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, status = pvfs_access_check_simple(pvfs, req, name, SEC_STD_DELETE); } - if (!NT_STATUS_IS_OK(status)) { + /* + * if it's a sharing violation or we got no oplock + * only keep the lock if the caller requested access + * to the lock + */ + if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) || + NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) { + if (lckp) { + *lckp = lck; + } else { + talloc_free(lck); + } + } else if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); *lckp = lck; } else if (lckp != NULL) { @@ -1487,7 +1499,19 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, 0, SEC_STD_DELETE); - if (!NT_STATUS_IS_OK(status)) { + /* + * if it's a sharing violation or we got no oplock + * only keep the lock if the caller requested access + * to the lock + */ + if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) || + NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) { + if (lckp) { + *lckp = lck; + } else { + talloc_free(lck); + } + } else if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); *lckp = lck; } else if (lckp != NULL) { -- cgit From 6f077d4017e6df9e070b1c3ea85b7afacf3437cd Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Feb 2008 19:56:36 +0100 Subject: pvfs_open: unify talloc behavior in pvfs_can_delete/rename/stat() And also handle NULL for lckp in the error path without crashing. metze (This used to be commit 04eb1be0c67317067ee0ca70c731fef958cd513c) --- source4/ntvfs/posix/pvfs_open.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 0d97b3d629..3a8b17ab16 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1461,8 +1461,10 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, } } else if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); - *lckp = lck; - } else if (lckp != NULL) { + if (lckp) { + *lckp = NULL; + } + } else if (lckp) { *lckp = lck; } @@ -1513,8 +1515,10 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, } } else if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); - *lckp = lck; - } else if (lckp != NULL) { + if (lckp) { + *lckp = NULL; + } + } else if (lckp) { *lckp = lck; } @@ -1549,6 +1553,10 @@ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, NTCREATEX_SHARE_ACCESS_WRITE, 0, 0); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + } + return status; } -- cgit From 9852e0d31582f669179c2a8c8ebdb263fef611f2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 25 Feb 2008 16:49:40 +0100 Subject: pvfs_open: pass down open_disposition and break_to_none to odb_open_file() metze (This used to be commit 46500983fe2f63540a67e2e963ab264fa8a090d0) --- source4/ntvfs/posix/pvfs_open.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 3a8b17ab16..1b5ea56d64 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -296,9 +296,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } /* see if we are allowed to open at the same time as existing opens */ - status = odb_open_file(lck, f->handle, f->handle->name->stream_id, + status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, share_access, access_mask, del_on_close, - name->full_name, OPLOCK_NONE, NULL); + io->generic.in.open_disposition, + false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); @@ -349,9 +350,10 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - status = odb_open_file(lck, f->handle, f->handle->name->stream_id, + status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, share_access, access_mask, del_on_close, - name->full_name, OPLOCK_NONE, NULL); + io->generic.in.open_disposition, + false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; @@ -669,9 +671,10 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, oplock_level = OPLOCK_EXCLUSIVE; } - status = odb_open_file(lck, f->handle, name->stream_id, + status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, share_access, access_mask, del_on_close, - name->full_name, oplock_level, &oplock_granted); + io->generic.in.open_disposition, + false, oplock_level, &oplock_granted); talloc_free(lck); if (!NT_STATUS_IS_OK(status)) { /* bad news, we must have hit a race - we don't delete the file @@ -1186,9 +1189,10 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } /* see if we are allowed to open at the same time as existing opens */ - status = odb_open_file(lck, f->handle, f->handle->name->stream_id, + status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, share_access, access_mask, del_on_close, - name->full_name, oplock_level, &oplock_granted); + io->generic.in.open_disposition, + false, oplock_level, &oplock_granted); /* on a sharing violation we need to retry when the file is closed by the other user, or after 1 second */ -- cgit From c93cf42d9fe4f1e382a762e7c1eafef0dff122c1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 25 Feb 2008 17:50:22 +0100 Subject: pvfs_open: fix odb_can_open() callers after prototype change metze (This used to be commit 904159327b3cb80fbec6aa5a4feaa141190a3f3a) --- source4/ntvfs/posix/pvfs_open.c | 51 ++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 16 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 1b5ea56d64..bbfe4ac733 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1428,6 +1428,9 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, NTSTATUS status; DATA_BLOB key; struct odb_lock *lck; + uint32_t share_access; + uint32_t access_mask; + bool delete_on_close; status = pvfs_locking_key(name, name, &key); if (!NT_STATUS_IS_OK(status)) { @@ -1440,15 +1443,18 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - status = odb_can_open(lck, - NTCREATEX_SHARE_ACCESS_READ | - NTCREATEX_SHARE_ACCESS_WRITE | - NTCREATEX_SHARE_ACCESS_DELETE, - NTCREATEX_OPTIONS_DELETE_ON_CLOSE, - SEC_STD_DELETE); + share_access = NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE | + NTCREATEX_SHARE_ACCESS_DELETE; + access_mask = SEC_STD_DELETE; + delete_on_close = true; + + status = odb_can_open(lck, name->stream_id, + share_access, access_mask, delete_on_close, + 0, false); if (NT_STATUS_IS_OK(status)) { - status = pvfs_access_check_simple(pvfs, req, name, SEC_STD_DELETE); + status = pvfs_access_check_simple(pvfs, req, name, access_mask); } /* @@ -1487,6 +1493,9 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, NTSTATUS status; DATA_BLOB key; struct odb_lock *lck; + uint32_t share_access; + uint32_t access_mask; + bool delete_on_close; status = pvfs_locking_key(name, name, &key); if (!NT_STATUS_IS_OK(status)) { @@ -1499,11 +1508,14 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - status = odb_can_open(lck, - NTCREATEX_SHARE_ACCESS_READ | - NTCREATEX_SHARE_ACCESS_WRITE, - 0, - SEC_STD_DELETE); + share_access = NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE; + access_mask = SEC_STD_DELETE; + delete_on_close = false; + + status = odb_can_open(lck, name->stream_id, + share_access, access_mask, delete_on_close, + 0, false); /* * if it's a sharing violation or we got no oplock @@ -1540,6 +1552,9 @@ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, NTSTATUS status; DATA_BLOB key; struct odb_lock *lck; + uint32_t share_access; + uint32_t access_mask; + bool delete_on_close; status = pvfs_locking_key(name, name, &key); if (!NT_STATUS_IS_OK(status)) { @@ -1552,10 +1567,14 @@ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - status = odb_can_open(lck, - NTCREATEX_SHARE_ACCESS_READ | - NTCREATEX_SHARE_ACCESS_WRITE, - 0, 0); + share_access = NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE; + access_mask = 0; + delete_on_close = false; + + status = odb_can_open(lck, name->stream_id, + share_access, access_mask, delete_on_close, + 0, false); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); -- cgit From d7ea52e9a3cd920f7c8a3b00f7cd28a7f605a993 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 21 Feb 2008 17:48:13 +0100 Subject: pvfs_open: make the retry logic indepdendent from open and sharing violations metze (This used to be commit 56bd63a4236ebf360d3e805c8560df86759573f7) --- source4/ntvfs/posix/pvfs_open.c | 149 ++++++++++++++++++++++++++-------------- 1 file changed, 99 insertions(+), 50 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index bbfe4ac733..8e1870fa70 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -751,20 +751,25 @@ cleanup_delete: return status; } - /* - state of a pending open retry + state of a pending retry */ -struct pvfs_open_retry { +struct pvfs_odb_retry { struct ntvfs_module_context *ntvfs; struct ntvfs_request *req; - union smb_open *io; - struct pvfs_wait *wait_handle; DATA_BLOB odb_locking_key; + void *io; + void *private_data; + void (*callback)(struct pvfs_odb_retry *r, + struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + void *io, + void *private_data, + enum pvfs_wait_notice reason); }; -/* destroy a pending open request */ -static int pvfs_retry_destructor(struct pvfs_open_retry *r) +/* destroy a pending request */ +static int pvfs_odb_retry_destructor(struct pvfs_odb_retry *r) { struct pvfs_state *pvfs = r->ntvfs->private_data; if (r->odb_locking_key.data) { @@ -778,15 +783,92 @@ static int pvfs_retry_destructor(struct pvfs_open_retry *r) return 0; } +static void pvfs_odb_retry_callback(void *_r, enum pvfs_wait_notice reason) +{ + struct pvfs_odb_retry *r = talloc_get_type(_r, struct pvfs_odb_retry); + + if (reason == PVFS_WAIT_EVENT) { + /* + * The pending odb entry is already removed. + * We use a null locking key to indicate this + * to the destructor. + */ + data_blob_free(&r->odb_locking_key); + } + + r->callback(r, r->ntvfs, r->req, r->io, r->private_data, reason); +} + /* - retry an open + setup for a retry of a request that was rejected + by odb_open_file() or odb_can_open() */ -static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason) +NTSTATUS pvfs_odb_retry_setup(struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + struct odb_lock *lck, + struct timeval end_time, + void *io, + void *private_data, + void (*callback)(struct pvfs_odb_retry *r, + struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + void *io, + void *private_data, + enum pvfs_wait_notice reason)) { - struct pvfs_open_retry *r = private; - struct ntvfs_module_context *ntvfs = r->ntvfs; - struct ntvfs_request *req = r->req; - union smb_open *io = r->io; + struct pvfs_state *pvfs = ntvfs->private_data; + struct pvfs_odb_retry *r; + struct pvfs_wait *wait_handle; + NTSTATUS status; + + r = talloc(req, struct pvfs_odb_retry); + NT_STATUS_HAVE_NO_MEMORY(r); + + r->ntvfs = ntvfs; + r->req = req; + r->io = io; + r->private_data = private_data; + r->callback = callback; + r->odb_locking_key = odb_get_key(r, lck); + if (r->odb_locking_key.data == NULL) { + return NT_STATUS_NO_MEMORY; + } + + /* setup a pending lock */ + status = odb_open_file_pending(lck, r); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + talloc_free(lck); + + talloc_set_destructor(r, pvfs_odb_retry_destructor); + + wait_handle = pvfs_wait_message(pvfs, req, + MSG_PVFS_RETRY_OPEN, end_time, + pvfs_odb_retry_callback, r); + if (wait_handle == NULL) { + return NT_STATUS_NO_MEMORY; + } + + talloc_steal(r, wait_handle); + + talloc_steal(pvfs, r); + + return NT_STATUS_OK; +} + +/* + retry an open after a sharing violation +*/ +static void pvfs_retry_open_sharing(struct pvfs_odb_retry *r, + struct ntvfs_module_context *ntvfs, + struct ntvfs_request *req, + void *_io, + void *private_data, + enum pvfs_wait_notice reason) +{ + union smb_open *io = talloc_get_type(_io, union smb_open); NTSTATUS status; /* w2k3 ignores SMBntcancel for outstanding open requests. It's probably @@ -795,8 +877,6 @@ static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason) return; } - talloc_free(r->wait_handle); - if (reason == PVFS_WAIT_TIMEOUT) { /* if it timed out, then give the failure immediately */ @@ -806,9 +886,6 @@ static void pvfs_open_retry(void *private, enum pvfs_wait_notice reason) return; } - /* the pending odb entry is already removed. We use a null locking - key to indicate this */ - data_blob_free(&r->odb_locking_key); talloc_free(r); /* try the open again, which could trigger another retry setup @@ -925,7 +1002,6 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, struct odb_lock *lck) { struct pvfs_state *pvfs = ntvfs->private_data; - struct pvfs_open_retry *r; NTSTATUS status; struct timeval end_time; @@ -939,40 +1015,13 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, } } - r = talloc(req, struct pvfs_open_retry); - if (r == NULL) { - return NT_STATUS_NO_MEMORY; - } - - r->ntvfs = ntvfs; - r->req = req; - r->io = io; - r->odb_locking_key = data_blob_talloc(r, - f->handle->odb_locking_key.data, - f->handle->odb_locking_key.length); - - end_time = timeval_add(&req->statistics.request_time, 0, pvfs->sharing_violation_delay); - - /* setup a pending lock */ - status = odb_open_file_pending(lck, r); - if (!NT_STATUS_IS_OK(status)) { - return status; - } - - talloc_free(lck); + /* the retry should allocate a new file handle */ talloc_free(f); - talloc_set_destructor(r, pvfs_retry_destructor); - - r->wait_handle = pvfs_wait_message(pvfs, req, MSG_PVFS_RETRY_OPEN, end_time, - pvfs_open_retry, r); - if (r->wait_handle == NULL) { - return NT_STATUS_NO_MEMORY; - } - - talloc_steal(pvfs, r); + end_time = timeval_add(&req->statistics.request_time, 0, pvfs->sharing_violation_delay); - return NT_STATUS_OK; + return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io, NULL, + pvfs_retry_open_sharing); } /* -- cgit From be1ba5b63164e7dab4bf067bc1aac4ed9cece2bc Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 25 Feb 2008 08:39:13 +0100 Subject: pvfs_open: call pvfs_setup_oplock() if an oplock was granted This is needed to receive oplock breaks from other "processes" metze (This used to be commit dd56f55afdc0d114a0b0bceb0e4feb022919323a) --- source4/ntvfs/posix/pvfs_open.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 8e1870fa70..8429c14d1b 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -268,6 +268,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->handle->seek_offset = 0; f->handle->position = 0; f->handle->mode = 0; + f->handle->oplock = NULL; f->handle->sticky_write_time = false; f->handle->open_completed = false; @@ -684,9 +685,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return status; } - if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { - oplock_granted = OPLOCK_BATCH; - } f->ntvfs = h; f->pvfs = pvfs; @@ -705,12 +703,23 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->handle->seek_offset = 0; f->handle->position = 0; f->handle->mode = 0; + f->handle->oplock = NULL; f->handle->have_opendb_entry = true; f->handle->sticky_write_time = false; f->handle->open_completed = false; DLIST_ADD(pvfs->files.list, f); + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { + oplock_granted = OPLOCK_BATCH; + } else if (oplock_granted != OPLOCK_NONE) { + status = pvfs_setup_oplock(f, oplock_granted); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + return status; + } + } + /* setup a destructor to avoid file descriptor leaks on abnormal termination */ talloc_set_destructor(f, pvfs_fnum_destructor); @@ -1185,6 +1194,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->handle->seek_offset = 0; f->handle->position = 0; f->handle->mode = 0; + f->handle->oplock = NULL; f->handle->have_opendb_entry = false; f->handle->sticky_write_time = false; f->handle->open_completed = false; @@ -1257,6 +1267,12 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { oplock_granted = OPLOCK_BATCH; + } else if (oplock_granted != OPLOCK_NONE) { + status = pvfs_setup_oplock(f, oplock_granted); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + return status; + } } f->handle->have_opendb_entry = true; -- cgit From 61e17794c394d2c070ce7df9cee6c53d846e7b75 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 22 Feb 2008 11:52:17 +0100 Subject: pvfs_unlink: retry unlink after oplock not granted metze (This used to be commit 746e89ce2e74dbd2cea8f5575c403e4c61f82cb8) --- source4/ntvfs/posix/pvfs_open.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 8429c14d1b..4110df292d 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1008,7 +1008,8 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_open *io, struct pvfs_file *f, - struct odb_lock *lck) + struct odb_lock *lck, + NTSTATUS parent_status) { struct pvfs_state *pvfs = ntvfs->private_data; NTSTATUS status; @@ -1027,7 +1028,15 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, /* the retry should allocate a new file handle */ talloc_free(f); - end_time = timeval_add(&req->statistics.request_time, 0, pvfs->sharing_violation_delay); + if (NT_STATUS_EQUAL(parent_status, NT_STATUS_SHARING_VIOLATION)) { + end_time = timeval_add(&req->statistics.request_time, + 0, pvfs->sharing_violation_delay); + } else if (NT_STATUS_EQUAL(parent_status, NT_STATUS_OPLOCK_NOT_GRANTED)) { + end_time = timeval_add(&req->statistics.request_time, + pvfs->oplock_break_timeout, 0); + } else { + return NT_STATUS_INTERNAL_ERROR; + } return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io, NULL, pvfs_retry_open_sharing); @@ -1253,11 +1262,16 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, io->generic.in.open_disposition, false, oplock_level, &oplock_granted); - /* on a sharing violation we need to retry when the file is closed by - the other user, or after 1 second */ - if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) && + /* + * on a sharing violation we need to retry when the file is closed by + * the other user, or after 1 second + * on a non granted oplock we need to retry when the file is closed by + * the other user, or after 30 seconds + */ + if ((NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) || + NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) && (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { - return pvfs_open_setup_retry(ntvfs, req, io, f, lck); + return pvfs_open_setup_retry(ntvfs, req, io, f, lck, status); } if (!NT_STATUS_IS_OK(status)) { -- cgit From 4eb0fcc5173ddf50305fa5094ec0d87d53d71a33 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 23 Feb 2008 11:49:39 +0100 Subject: pvfs_open: add pvfs_can_update_file_size() TODO: this is not complete, we need more tests to trigger this metze (This used to be commit 66ad1081f2be8a0caa16fb0d614b857a5bde751c) --- source4/ntvfs/posix/pvfs_open.c | 62 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 4110df292d..12b70c00fd 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1620,6 +1620,68 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, return status; } +/* + determine if the file size of a file can be changed, + or if it is prevented by an already open file +*/ +NTSTATUS pvfs_can_update_file_size(struct pvfs_state *pvfs, + struct ntvfs_request *req, + struct pvfs_filename *name, + struct odb_lock **lckp) +{ + NTSTATUS status; + DATA_BLOB key; + struct odb_lock *lck; + uint32_t share_access; + uint32_t access_mask; + bool break_to_none; + bool delete_on_close; + + status = pvfs_locking_key(name, name, &key); + if (!NT_STATUS_IS_OK(status)) { + return NT_STATUS_NO_MEMORY; + } + + lck = odb_lock(req, pvfs->odb_context, &key); + if (lck == NULL) { + DEBUG(0,("Unable to lock opendb for can_stat\n")); + return NT_STATUS_INTERNAL_DB_CORRUPTION; + } + + /* TODO: this may needs some more flags */ + share_access = NTCREATEX_SHARE_ACCESS_WRITE; + access_mask = 0; + delete_on_close = false; + break_to_none = true; + + status = odb_can_open(lck, name->stream_id, + share_access, access_mask, delete_on_close, + 0, break_to_none); + + /* + * if it's a sharing violation or we got no oplock + * only keep the lock if the caller requested access + * to the lock + */ + if (NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION) || + NT_STATUS_EQUAL(status, NT_STATUS_OPLOCK_NOT_GRANTED)) { + if (lckp) { + *lckp = lck; + } else { + talloc_free(lck); + } + } else if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + if (lckp) { + *lckp = NULL; + } + } else if (lckp) { + *lckp = lck; + } + + return status; +} + /* determine if file meta data can be accessed, or if it is prevented by an already open file -- cgit From 9f8fc29ea418c7ed2e2f206eb4789080ec9ab3f1 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Feb 2008 10:21:39 +0100 Subject: pvfs_open: pass NTCREATEX_DISP_OPEN to odb_can_open() As 0 is NTCREATEX_DISP_SUPERSEDE and that's not what we want here. metze (This used to be commit 10c42e3d4ab71a71dfe620b40841dfe98f458c1a) --- source4/ntvfs/posix/pvfs_open.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 12b70c00fd..ef05db5eac 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1530,7 +1530,7 @@ NTSTATUS pvfs_can_delete(struct pvfs_state *pvfs, status = odb_can_open(lck, name->stream_id, share_access, access_mask, delete_on_close, - 0, false); + NTCREATEX_DISP_OPEN, false); if (NT_STATUS_IS_OK(status)) { status = pvfs_access_check_simple(pvfs, req, name, access_mask); @@ -1594,7 +1594,7 @@ NTSTATUS pvfs_can_rename(struct pvfs_state *pvfs, status = odb_can_open(lck, name->stream_id, share_access, access_mask, delete_on_close, - 0, false); + NTCREATEX_DISP_OPEN, false); /* * if it's a sharing violation or we got no oplock @@ -1656,7 +1656,7 @@ NTSTATUS pvfs_can_update_file_size(struct pvfs_state *pvfs, status = odb_can_open(lck, name->stream_id, share_access, access_mask, delete_on_close, - 0, break_to_none); + NTCREATEX_DISP_OPEN, break_to_none); /* * if it's a sharing violation or we got no oplock @@ -1715,7 +1715,7 @@ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, status = odb_can_open(lck, name->stream_id, share_access, access_mask, delete_on_close, - 0, false); + NTCREATEX_DISP_OPEN, false); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); -- cgit From b40be554e7775687a01704b9af0aa272cc9019d0 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Feb 2008 10:28:07 +0100 Subject: pvfs_open: pass down an access mask in pvfs_can_stat() metze (This used to be commit 6c34c7bc6801e470e5ec50aa93d0a07f7ad59314) --- source4/ntvfs/posix/pvfs_open.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index ef05db5eac..0e4250d744 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1710,7 +1710,7 @@ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE; - access_mask = 0; + access_mask = SEC_FILE_READ_ATTRIBUTE; delete_on_close = false; status = odb_can_open(lck, name->stream_id, -- cgit From 55377f0352d73fa354e8abcf3e644c63c78d0ca6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 26 Feb 2008 10:26:33 +0100 Subject: pvfs_open: pass down an access mask to pvfs_can_update_file_size() You just need SEC_FILE_WRITE_ATTRIBUTE to change the filesize... metze (This used to be commit 27e39063a0b759c7bced1cc9d7a6cb9192820c70) --- source4/ntvfs/posix/pvfs_open.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 0e4250d744..a01352f60c 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1648,9 +1648,19 @@ NTSTATUS pvfs_can_update_file_size(struct pvfs_state *pvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } - /* TODO: this may needs some more flags */ - share_access = NTCREATEX_SHARE_ACCESS_WRITE; - access_mask = 0; + share_access = NTCREATEX_SHARE_ACCESS_READ | + NTCREATEX_SHARE_ACCESS_WRITE | + NTCREATEX_SHARE_ACCESS_DELETE; + /* + * I would have thought that we would need to pass + * SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA here too + * + * But you only need SEC_FILE_WRITE_ATTRIBUTE permissions + * to set the filesize. + * + * --metze + */ + access_mask = SEC_FILE_WRITE_ATTRIBUTE; delete_on_close = false; break_to_none = true; -- cgit From 03660b240c74eedc7d767acac08cc2504c60515e Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 27 Feb 2008 21:52:52 +0100 Subject: pvfs_open: use the delete_path of odb_close_file() metze (This used to be commit c78451ce0618de92321430d2b50f9a8172d283f4) --- source4/ntvfs/posix/pvfs_open.c | 84 +++++++++++++++++------------------------ 1 file changed, 35 insertions(+), 49 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index a01352f60c..6f2f587212 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -50,29 +50,10 @@ struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, */ static int pvfs_dir_handle_destructor(struct pvfs_file_handle *h) { - int open_count; - char *path = NULL; - - if (h->name->stream_name == NULL && - pvfs_delete_on_close_set(h->pvfs, h, &open_count, &path) && - open_count == 1) { - NTSTATUS status; - status = pvfs_xattr_unlink_hook(h->pvfs, path); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n", - path, nt_errstr(status))); - } - if (rmdir(path) != 0) { - DEBUG(0,("pvfs_dir_handle_destructor: failed to rmdir '%s' - %s\n", - path, strerror(errno))); - } - } - - talloc_free(path); - if (h->have_opendb_entry) { struct odb_lock *lck; NTSTATUS status; + const char *delete_path = NULL; lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key); if (lck == NULL) { @@ -80,12 +61,24 @@ static int pvfs_dir_handle_destructor(struct pvfs_file_handle *h) return 0; } - status = odb_close_file(lck, h); + status = odb_close_file(lck, h, &delete_path); if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n", + DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n", h->name->full_name, nt_errstr(status))); } + if (h->name->stream_name == NULL && delete_path) { + status = pvfs_xattr_unlink_hook(h->pvfs, delete_path); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n", + delete_path, nt_errstr(status))); + } + if (rmdir(delete_path) != 0) { + DEBUG(0,("pvfs_dir_handle_destructor: failed to rmdir '%s' - %s\n", + delete_path, strerror(errno))); + } + } + talloc_free(lck); } @@ -410,9 +403,6 @@ cleanup_delete: */ static int pvfs_handle_destructor(struct pvfs_file_handle *h) { - int open_count; - char *path = NULL; - /* the write time is no longer sticky */ if (h->sticky_write_time) { NTSTATUS status; @@ -441,32 +431,10 @@ static int pvfs_handle_destructor(struct pvfs_file_handle *h) h->fd = -1; } - if (h->name->stream_name == NULL && - h->open_completed && - pvfs_delete_on_close_set(h->pvfs, h, &open_count, &path) && - open_count == 1) { - NTSTATUS status; - status = pvfs_xattr_unlink_hook(h->pvfs, path); - if (!NT_STATUS_IS_OK(status)) { - DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n", - path, nt_errstr(status))); - } - if (unlink(path) != 0) { - DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n", - path, strerror(errno))); - } else { - notify_trigger(h->pvfs->notify_context, - NOTIFY_ACTION_REMOVED, - FILE_NOTIFY_CHANGE_FILE_NAME, - path); - } - } - - talloc_free(path); - if (h->have_opendb_entry) { struct odb_lock *lck; NTSTATUS status; + const char *delete_path = NULL; lck = odb_lock(h, h->pvfs->odb_context, &h->odb_locking_key); if (lck == NULL) { @@ -474,12 +442,30 @@ static int pvfs_handle_destructor(struct pvfs_file_handle *h) return 0; } - status = odb_close_file(lck, h); + status = odb_close_file(lck, h, &delete_path); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n", h->name->full_name, nt_errstr(status))); } + if (h->name->stream_name == NULL && + h->open_completed && delete_path) { + status = pvfs_xattr_unlink_hook(h->pvfs, delete_path); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Warning: xattr unlink hook failed for '%s' - %s\n", + delete_path, nt_errstr(status))); + } + if (unlink(delete_path) != 0) { + DEBUG(0,("pvfs_close: failed to delete '%s' - %s\n", + delete_path, strerror(errno))); + } else { + notify_trigger(h->pvfs->notify_context, + NOTIFY_ACTION_REMOVED, + FILE_NOTIFY_CHANGE_FILE_NAME, + delete_path); + } + } + talloc_free(lck); } -- cgit From 9028ecca22713d4069e6f610b546fd8d60756b81 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 27 Feb 2008 22:22:10 +0100 Subject: pvfs: remove unused args from pvfs_delete_on_close_set() metze (This used to be commit 73f12be7c6a648d4d5336328a340510ac7b1d6de) --- source4/ntvfs/posix/pvfs_open.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 6f2f587212..3c2fa73df8 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1724,8 +1724,7 @@ NTSTATUS pvfs_can_stat(struct pvfs_state *pvfs, /* determine if delete on close is set on */ -bool pvfs_delete_on_close_set(struct pvfs_state *pvfs, struct pvfs_file_handle *h, - int *open_count, char **path) +bool pvfs_delete_on_close_set(struct pvfs_state *pvfs, struct pvfs_file_handle *h) { NTSTATUS status; bool del_on_close; -- cgit From c3ce0a0b95b6051a356c72424c2d62b77a0e81df Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 27 Feb 2008 22:22:56 +0100 Subject: pvfs_open: fix callers of odb_get_delete_on_close() metze (This used to be commit 608e5cd881d64b8db9146dfc4b3a1778a93a0f8e) --- source4/ntvfs/posix/pvfs_open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 3c2fa73df8..740a0a9d13 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -560,7 +560,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, status = pvfs_locking_key(parent, req, &locking_key); NT_STATUS_NOT_OK_RETURN(status); status = odb_get_delete_on_close(pvfs->odb_context, &locking_key, - &del_on_close, NULL, NULL); + &del_on_close); NT_STATUS_NOT_OK_RETURN(status); if (del_on_close) { return NT_STATUS_DELETE_PENDING; @@ -1730,7 +1730,7 @@ bool pvfs_delete_on_close_set(struct pvfs_state *pvfs, struct pvfs_file_handle * bool del_on_close; status = odb_get_delete_on_close(pvfs->odb_context, &h->odb_locking_key, - &del_on_close, open_count, path); + &del_on_close); if (!NT_STATUS_IS_OK(status)) { DEBUG(1,("WARNING: unable to determine delete on close status for open file\n")); return false; -- cgit From 48270181bac1a640d085ce5f5a58329d69c7a1ac Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 28 Feb 2008 12:18:29 +0100 Subject: pvfs_open: make pvfs_locking_key() non static metze (This used to be commit 587373b97b95a8e562c3a5a59a62abade4dfed2f) --- source4/ntvfs/posix/pvfs_open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 740a0a9d13..adf4c1ac18 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -144,8 +144,8 @@ static NTSTATUS pvfs_open_setup_eas_acl(struct pvfs_state *pvfs, form the lock context used for opendb locking. Note that we must zero here to take account of possible padding on some architectures */ -static NTSTATUS pvfs_locking_key(struct pvfs_filename *name, - TALLOC_CTX *mem_ctx, DATA_BLOB *key) +NTSTATUS pvfs_locking_key(struct pvfs_filename *name, + TALLOC_CTX *mem_ctx, DATA_BLOB *key) { struct { dev_t device; -- cgit From 0339ae5ad82c248b43afa9431b13cda536b18fd6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 6 Mar 2008 15:34:37 +0100 Subject: pvfs_open: fix crash/leak in case pvfs_setup_oplock() fails metze (This used to be commit 5563238782e825f64a22b5f9e0a7deb687f50b19) --- source4/ntvfs/posix/pvfs_open.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index adf4c1ac18..792e35cd14 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -696,21 +696,20 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, DLIST_ADD(pvfs->files.list, f); + /* setup a destructor to avoid file descriptor leaks on + abnormal termination */ + talloc_set_destructor(f, pvfs_fnum_destructor); + talloc_set_destructor(f->handle, pvfs_handle_destructor); + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { oplock_granted = OPLOCK_BATCH; } else if (oplock_granted != OPLOCK_NONE) { status = pvfs_setup_oplock(f, oplock_granted); if (!NT_STATUS_IS_OK(status)) { - talloc_free(lck); return status; } } - /* setup a destructor to avoid file descriptor leaks on - abnormal termination */ - talloc_set_destructor(f, pvfs_fnum_destructor); - talloc_set_destructor(f->handle, pvfs_handle_destructor); - io->generic.out.oplock_level = oplock_granted; io->generic.out.file.ntvfs = f->ntvfs; io->generic.out.create_action = NTCREATEX_ACTION_CREATED; -- cgit From ef4ae2597d0c198f42a5144ccd49716f0cb5796b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 6 Mar 2008 15:48:31 +0100 Subject: pvfs_open: pass down allow_level_II_oplock to odb_open_file() metze (This used to be commit 7c9b269b0742d435055e21f7e6cc945c21c7e332) --- source4/ntvfs/posix/pvfs_open.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 792e35cd14..47b44b9634 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -293,7 +293,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, share_access, access_mask, del_on_close, io->generic.in.open_disposition, - false, OPLOCK_NONE, NULL); + false, false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); @@ -347,7 +347,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, share_access, access_mask, del_on_close, io->generic.in.open_disposition, - false, OPLOCK_NONE, NULL); + false, false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; @@ -544,6 +544,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, bool del_on_close; struct pvfs_filename *parent; uint32_t oplock_level = OPLOCK_NONE, oplock_granted; + bool allow_level_II_oplock = false; if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) && (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { @@ -658,10 +659,15 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, oplock_level = OPLOCK_EXCLUSIVE; } + if (req->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS) { + allow_level_II_oplock = true; + } + status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, share_access, access_mask, del_on_close, io->generic.in.open_disposition, - false, oplock_level, &oplock_granted); + false, allow_level_II_oplock, + oplock_level, &oplock_granted); talloc_free(lck); if (!NT_STATUS_IS_OK(status)) { /* bad news, we must have hit a race - we don't delete the file @@ -1047,6 +1053,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, bool del_on_close; bool stream_existed, stream_truncate=false; uint32_t oplock_level = OPLOCK_NONE, oplock_granted; + bool allow_level_II_oplock = false; /* use the generic mapping code to avoid implementing all the different open calls. */ @@ -1241,11 +1248,16 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, oplock_level = OPLOCK_EXCLUSIVE; } + if (req->client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS) { + allow_level_II_oplock = true; + } + /* see if we are allowed to open at the same time as existing opens */ status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, share_access, access_mask, del_on_close, io->generic.in.open_disposition, - false, oplock_level, &oplock_granted); + false, allow_level_II_oplock, + oplock_level, &oplock_granted); /* * on a sharing violation we need to retry when the file is closed by -- cgit From 75a412a46975754e75679f5d072e6ce688fee894 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 7 Mar 2008 17:50:17 +0100 Subject: pvfs_open: always call odb_can_open() before odb_open_file() odb_open_file() will later change to not redo the logic of odb_can_open(). metze (This used to be commit b09a1461ac595be1b6530221b7df5211084884cc) --- source4/ntvfs/posix/pvfs_open.c | 51 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 6 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 47b44b9634..1ed517c719 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -290,6 +290,15 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } /* see if we are allowed to open at the same time as existing opens */ + status = odb_can_open(lck, name->stream_id, + share_access, access_mask, del_on_close, + io->generic.in.open_disposition, false); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + return status; + } + + /* now really mark the file as open */ status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, share_access, access_mask, del_on_close, io->generic.in.open_disposition, @@ -344,6 +353,14 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_INTERNAL_DB_CORRUPTION; } + status = odb_can_open(lck, name->stream_id, + share_access, access_mask, del_on_close, + io->generic.in.open_disposition, false); + + if (!NT_STATUS_IS_OK(status)) { + goto cleanup_delete; + } + status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, share_access, access_mask, del_on_close, io->generic.in.open_disposition, @@ -663,6 +680,18 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, allow_level_II_oplock = true; } + status = odb_can_open(lck, name->stream_id, + share_access, access_mask, del_on_close, + io->generic.in.open_disposition, false); + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + /* bad news, we must have hit a race - we don't delete the file + here as the most likely scenario is that someone else created + the file at the same time */ + close(fd); + return status; + } + status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, share_access, access_mask, del_on_close, io->generic.in.open_disposition, @@ -801,7 +830,7 @@ static void pvfs_odb_retry_callback(void *_r, enum pvfs_wait_notice reason) /* setup for a retry of a request that was rejected - by odb_open_file() or odb_can_open() + by odb_can_open() */ NTSTATUS pvfs_odb_retry_setup(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, @@ -1253,11 +1282,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } /* see if we are allowed to open at the same time as existing opens */ - status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, - share_access, access_mask, del_on_close, - io->generic.in.open_disposition, - false, allow_level_II_oplock, - oplock_level, &oplock_granted); + status = odb_can_open(lck, name->stream_id, + share_access, access_mask, del_on_close, + io->generic.in.open_disposition, false); /* * on a sharing violation we need to retry when the file is closed by @@ -1276,6 +1303,18 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } + /* now really mark the file as open */ + status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, + share_access, access_mask, del_on_close, + io->generic.in.open_disposition, + false, allow_level_II_oplock, + oplock_level, &oplock_granted); + + if (!NT_STATUS_IS_OK(status)) { + talloc_free(lck); + return status; + } + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { oplock_granted = OPLOCK_BATCH; } else if (oplock_granted != OPLOCK_NONE) { -- cgit From db669e1eb13effb08b1111405587c8c6dde95954 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 7 Mar 2008 18:28:48 +0100 Subject: pvfs_open: fix the odb_open_file() callers metze (This used to be commit 5fdca988c687f58fe2fddd3c8eff5f461207065b) --- source4/ntvfs/posix/pvfs_open.c | 24 ++++++++---------------- 1 file changed, 8 insertions(+), 16 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 1ed517c719..2e757e1742 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -299,10 +299,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } /* now really mark the file as open */ - status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, - share_access, access_mask, del_on_close, - io->generic.in.open_disposition, - false, false, OPLOCK_NONE, NULL); + status = odb_open_file(lck, f->handle, name->full_name, + false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); @@ -361,10 +359,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, goto cleanup_delete; } - status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, - share_access, access_mask, del_on_close, - io->generic.in.open_disposition, - false, false, OPLOCK_NONE, NULL); + status = odb_open_file(lck, f->handle, name->full_name, + false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; @@ -692,10 +688,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return status; } - status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, - share_access, access_mask, del_on_close, - io->generic.in.open_disposition, - false, allow_level_II_oplock, + status = odb_open_file(lck, f->handle, name->full_name, + allow_level_II_oplock, oplock_level, &oplock_granted); talloc_free(lck); if (!NT_STATUS_IS_OK(status)) { @@ -1304,10 +1298,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } /* now really mark the file as open */ - status = odb_open_file(lck, f->handle, name->full_name, name->stream_id, - share_access, access_mask, del_on_close, - io->generic.in.open_disposition, - false, allow_level_II_oplock, + status = odb_open_file(lck, f->handle, name->full_name, + allow_level_II_oplock, oplock_level, &oplock_granted); if (!NT_STATUS_IS_OK(status)) { -- cgit From 7ba236d78e02fb8413db8c6ac74b9e89e64e847b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 8 Mar 2008 09:20:08 +0100 Subject: pvfs_open: pass down &f->handle->fd to odb_open_file() metze (This used to be commit 80f5f9362100b971fa12ffee33705b745131770e) --- source4/ntvfs/posix/pvfs_open.c | 61 ++++++++++++++++++++--------------------- 1 file changed, 30 insertions(+), 31 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 2e757e1742..ceda3a6da0 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -300,7 +300,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* now really mark the file as open */ status = odb_open_file(lck, f->handle, name->full_name, - false, OPLOCK_NONE, NULL); + NULL, false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); @@ -360,7 +360,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } status = odb_open_file(lck, f->handle, name->full_name, - false, OPLOCK_NONE, NULL); + NULL, false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; @@ -688,19 +688,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return status; } - status = odb_open_file(lck, f->handle, name->full_name, - allow_level_II_oplock, - oplock_level, &oplock_granted); - talloc_free(lck); - if (!NT_STATUS_IS_OK(status)) { - /* bad news, we must have hit a race - we don't delete the file - here as the most likely scenario is that someone else created - the file at the same time */ - close(fd); - return status; - } - - f->ntvfs = h; f->pvfs = pvfs; f->pending_list = NULL; @@ -723,6 +710,18 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->handle->sticky_write_time = false; f->handle->open_completed = false; + status = odb_open_file(lck, f->handle, name->full_name, + &f->handle->fd, allow_level_II_oplock, + oplock_level, &oplock_granted); + talloc_free(lck); + if (!NT_STATUS_IS_OK(status)) { + /* bad news, we must have hit a race - we don't delete the file + here as the most likely scenario is that someone else created + the file at the same time */ + close(fd); + return status; + } + DLIST_ADD(pvfs->files.list, f); /* setup a destructor to avoid file descriptor leaks on @@ -1297,9 +1296,24 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } + if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) { + flags |= O_RDWR; + } else { + flags |= O_RDONLY; + } + + /* do the actual open */ + fd = open(f->handle->name->full_name, flags); + if (fd == -1) { + talloc_free(lck); + return pvfs_map_errno(f->pvfs, errno); + } + + f->handle->fd = fd; + /* now really mark the file as open */ status = odb_open_file(lck, f->handle, name->full_name, - allow_level_II_oplock, + &f->handle->fd, allow_level_II_oplock, oplock_level, &oplock_granted); if (!NT_STATUS_IS_OK(status)) { @@ -1319,21 +1333,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->handle->have_opendb_entry = true; - if (access_mask & (SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA)) { - flags |= O_RDWR; - } else { - flags |= O_RDONLY; - } - - /* do the actual open */ - fd = open(f->handle->name->full_name, flags); - if (fd == -1) { - talloc_free(lck); - return pvfs_map_errno(f->pvfs, errno); - } - - f->handle->fd = fd; - stream_existed = name->stream_exists; /* if this was a stream create then create the stream as well */ -- cgit From 454e9bed04011bcb184f20c2dd82f37255403227 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Mon, 10 Mar 2008 12:48:02 +0100 Subject: pvfs_open: pass O_NONBLOCK to open() so that we'll not block with kernel oplocks metze (This used to be commit eeb0b8c349552517b521f1b8d7d9341e0ef630f2) --- source4/ntvfs/posix/pvfs_open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index ceda3a6da0..8a949daa87 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -600,7 +600,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, mode = pvfs_fileperms(pvfs, attrib); /* create the file */ - fd = open(name->full_name, flags | O_CREAT | O_EXCL, mode); + fd = open(name->full_name, flags | O_CREAT | O_EXCL| O_NONBLOCK, mode); if (fd == -1) { return pvfs_map_errno(pvfs, errno); } @@ -1303,7 +1303,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } /* do the actual open */ - fd = open(f->handle->name->full_name, flags); + fd = open(f->handle->name->full_name, flags | O_NONBLOCK); if (fd == -1) { talloc_free(lck); return pvfs_map_errno(f->pvfs, errno); -- cgit From 50243cdbbda8a1f14e56c684281a93614aab0103 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 12 Mar 2008 14:02:11 +0100 Subject: pvfs_open: retry pvfs_open() after an EGAIN or EWOULDBLOCK from open() In case a unix application as an oplock or share mode on a file we need to retry periodicly as there's no way to get a notification from the kernel when the oplock is released. metze (This used to be commit 4d40f3a02643b4cdacee31f0b7bc9fc77cc9869a) --- source4/ntvfs/posix/pvfs_open.c | 58 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 54 insertions(+), 4 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 8a949daa87..1399f120a7 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -858,7 +858,13 @@ NTSTATUS pvfs_odb_retry_setup(struct ntvfs_module_context *ntvfs, /* setup a pending lock */ status = odb_open_file_pending(lck, r); - if (!NT_STATUS_IS_OK(status)) { + if (NT_STATUS_EQUAL(NT_STATUS_OBJECT_NAME_NOT_FOUND,status)) { + /* + * maybe only a unix application + * has the file open + */ + data_blob_free(&r->odb_locking_key); + } else if (!NT_STATUS_IS_OK(status)) { return status; } @@ -891,8 +897,14 @@ static void pvfs_retry_open_sharing(struct pvfs_odb_retry *r, enum pvfs_wait_notice reason) { union smb_open *io = talloc_get_type(_io, union smb_open); + struct timeval *final_timeout = NULL; NTSTATUS status; + if (private_data) { + final_timeout = talloc_get_type(private_data, + struct timeval); + } + /* w2k3 ignores SMBntcancel for outstanding open requests. It's probably just a bug in their server, but we better do the same */ if (reason == PVFS_WAIT_CANCEL) { @@ -900,6 +912,16 @@ static void pvfs_retry_open_sharing(struct pvfs_odb_retry *r, } if (reason == PVFS_WAIT_TIMEOUT) { + if (final_timeout && + !timeval_expired(final_timeout)) { + /* + * we need to retry periodictly + * after an EAGAIN as there's + * no way the kernel tell us + * an oplock is released. + */ + goto retry; + } /* if it timed out, then give the failure immediately */ talloc_free(r); @@ -908,6 +930,7 @@ static void pvfs_retry_open_sharing(struct pvfs_odb_retry *r, return; } +retry: talloc_free(r); /* try the open again, which could trigger another retry setup @@ -1027,6 +1050,7 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, struct pvfs_state *pvfs = ntvfs->private_data; NTSTATUS status; struct timeval end_time; + struct timeval *final_timeout = NULL; if (io->generic.in.create_options & (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS | NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { @@ -1047,12 +1071,28 @@ static NTSTATUS pvfs_open_setup_retry(struct ntvfs_module_context *ntvfs, } else if (NT_STATUS_EQUAL(parent_status, NT_STATUS_OPLOCK_NOT_GRANTED)) { end_time = timeval_add(&req->statistics.request_time, pvfs->oplock_break_timeout, 0); + } else if (NT_STATUS_EQUAL(parent_status, STATUS_MORE_ENTRIES)) { + /* + * we got EAGAIN which means a unix application + * has an oplock or share mode + * + * we retry every 4/5 of the sharing violation delay + * to see if the unix application + * has released the oplock or share mode. + */ + final_timeout = talloc(req, struct timeval); + NT_STATUS_HAVE_NO_MEMORY(final_timeout); + *final_timeout = timeval_add(&req->statistics.request_time, + pvfs->oplock_break_timeout, + 0); + end_time = timeval_current_ofs(0, (pvfs->sharing_violation_delay*4)/5); + end_time = timeval_min(final_timeout, &end_time); } else { return NT_STATUS_INTERNAL_ERROR; } - return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io, NULL, - pvfs_retry_open_sharing); + return pvfs_odb_retry_setup(ntvfs, req, lck, end_time, io, + final_timeout, pvfs_retry_open_sharing); } /* @@ -1305,8 +1345,18 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* do the actual open */ fd = open(f->handle->name->full_name, flags | O_NONBLOCK); if (fd == -1) { + status = pvfs_map_errno(f->pvfs, errno); + + /* + * STATUS_MORE_ENTRIES is EAGAIN or EWOULDBLOCK + */ + if (NT_STATUS_EQUAL(status, STATUS_MORE_ENTRIES) && + (req->async_states->state & NTVFS_ASYNC_STATE_MAY_ASYNC)) { + return pvfs_open_setup_retry(ntvfs, req, io, f, lck, status); + } + talloc_free(lck); - return pvfs_map_errno(f->pvfs, errno); + return status; } f->handle->fd = fd; -- cgit From 74d940ca5742a021a01e8820be40a69366f67ee6 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 15 Mar 2008 12:35:04 +0100 Subject: pvfs_open: the pvfs_odb_retry structs need to be children of the request Otherwise they're not cleaned up when the request is finished. metze (This used to be commit 055760f0f4aadd2079b0a4999b59ac3dbe5edf8a) --- source4/ntvfs/posix/pvfs_open.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 1399f120a7..d1cb0eb603 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -881,8 +881,6 @@ NTSTATUS pvfs_odb_retry_setup(struct ntvfs_module_context *ntvfs, talloc_steal(r, wait_handle); - talloc_steal(pvfs, r); - return NT_STATUS_OK; } -- cgit From e76c8aa097d9865f97b254be7477f2097ea86e7d Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Sat, 15 Mar 2008 12:36:20 +0100 Subject: pvfs_open: set h->have_opendb_entry directly after odb_open_file() Otherwise we may not clean up in the destructor. metze (This used to be commit 218ec98a1694080748d1ac12baa90ffcda364833) --- source4/ntvfs/posix/pvfs_open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index d1cb0eb603..6e77cb7c75 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1369,6 +1369,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } + f->handle->have_opendb_entry = true; + if (pvfs->flags & PVFS_FLAG_FAKE_OPLOCKS) { oplock_granted = OPLOCK_BATCH; } else if (oplock_granted != OPLOCK_NONE) { @@ -1379,8 +1381,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } } - f->handle->have_opendb_entry = true; - stream_existed = name->stream_exists; /* if this was a stream create then create the stream as well */ -- cgit From 3e80085fb09a89957991780f79f5726029b8a26f Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Wed, 7 May 2008 15:46:22 +0200 Subject: pvfs: remove XATTR_ATTRIB_FLAG_STICKY_WRITE_TIME code I'll fix this more correctly very soon, so that we'll pass the BASE-DELAYWRITE test. metze (This used to be commit b09dd6b65d533832a025a51509dcc84f84b048aa) --- source4/ntvfs/posix/pvfs_open.c | 17 ----------------- 1 file changed, 17 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 6e77cb7c75..c9c1c56f14 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -262,7 +262,6 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->handle->position = 0; f->handle->mode = 0; f->handle->oplock = NULL; - f->handle->sticky_write_time = false; f->handle->open_completed = false; if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && @@ -416,16 +415,6 @@ cleanup_delete: */ static int pvfs_handle_destructor(struct pvfs_file_handle *h) { - /* the write time is no longer sticky */ - if (h->sticky_write_time) { - NTSTATUS status; - status = pvfs_dosattrib_load(h->pvfs, h->name, h->fd); - if (NT_STATUS_IS_OK(status)) { - h->name->dos.flags &= ~XATTR_ATTRIB_FLAG_STICKY_WRITE_TIME; - pvfs_dosattrib_save(h->pvfs, h->name, h->fd); - } - } - if ((h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && h->name->stream_name) { NTSTATUS status; @@ -707,7 +696,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->handle->mode = 0; f->handle->oplock = NULL; f->handle->have_opendb_entry = true; - f->handle->sticky_write_time = false; f->handle->open_completed = false; status = odb_open_file(lck, f->handle, name->full_name, @@ -1257,7 +1245,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->handle->mode = 0; f->handle->oplock = NULL; f->handle->have_opendb_entry = false; - f->handle->sticky_write_time = false; f->handle->open_completed = false; /* form the lock context used for byte range locking and @@ -1479,10 +1466,6 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, unix_times.actime = 0; unix_times.modtime = io->close.in.write_time; utime(f->handle->name->full_name, &unix_times); - } else if (f->handle->sticky_write_time) { - unix_times.actime = 0; - unix_times.modtime = nt_time_to_unix(f->handle->name->dos.write_time); - utime(f->handle->name->full_name, &unix_times); } talloc_free(f); -- cgit From 2352602a57989ac1572151cba1da1e78b9410860 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 20 May 2008 11:58:47 +1000 Subject: check the creation options where the client can require a path to be a file or a directory (This used to be commit c05b58940f06b01b9770c218eb0708cb621215ef) --- source4/ntvfs/posix/pvfs_open.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index c9c1c56f14..67937324cc 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1117,6 +1117,20 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return status; } + /* if the client specified that it must not be a directory then + check that it isn't */ + if (name->exists && (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) && + (io->generic.in.create_options & NTCREATEX_OPTIONS_NON_DIRECTORY_FILE)) { + return NT_STATUS_FILE_IS_A_DIRECTORY; + } + + /* if the client specified that it must be a directory then + check that it is */ + if (name->exists && !(name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) && + (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)) { + return NT_STATUS_NOT_A_DIRECTORY; + } + /* directory opens are handled separately */ if ((name->exists && (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) || (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)) { -- cgit From 7a9ffeca21666935ba08cd909b63fc063f7607f7 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 22 May 2008 17:53:50 +1000 Subject: check for invalid file attribute values in create (This used to be commit dd21e3d9d788a67d4673625ed4892a875f4600dc) --- source4/ntvfs/posix/pvfs_open.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 67937324cc..cc4f0add27 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -548,6 +548,10 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, uint32_t oplock_level = OPLOCK_NONE, oplock_granted; bool allow_level_II_oplock = false; + if (io->ntcreatex.in.file_attr & ~FILE_ATTRIBUTE_ALL_MASK) { + return NT_STATUS_INVALID_PARAMETER; + } + if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) && (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { return NT_STATUS_CANNOT_DELETE; -- cgit From 5d648b4aa5540e91fa7ea77668965eefd8926b1a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Fri, 23 May 2008 09:47:59 +0200 Subject: pvfs_open: return FILE_IS_A_DIRECTORY when opening a stream on a directory metze (This used to be commit 1421b1cc0c442be839be702647009ed5295f34a3) --- source4/ntvfs/posix/pvfs_open.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index cc4f0add27..926c99d37e 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -182,12 +182,19 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, bool del_on_close; uint32_t create_options; uint32_t share_access; + bool forced; create_options = io->generic.in.create_options; share_access = io->generic.in.share_access; + forced = (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY)?true:false; + if (name->stream_name) { - return NT_STATUS_NOT_A_DIRECTORY; + if (forced) { + return NT_STATUS_NOT_A_DIRECTORY; + } else { + return NT_STATUS_FILE_IS_A_DIRECTORY; + } } /* if the client says it must be a directory, and it isn't, -- cgit From 2ad2bdda89c07c0b8ce754c3b0cd4664eefc697d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Mon, 26 May 2008 15:02:43 +1000 Subject: stricter checks for valid inputs in SMB2 open and lock (This used to be commit a7b5689a73adde59de28770aa3949660441291ea) --- source4/ntvfs/posix/pvfs_open.c | 38 +++++++++++++++++++++++++++----------- 1 file changed, 27 insertions(+), 11 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 926c99d37e..59b42fe751 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -203,6 +203,13 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, return NT_STATUS_NOT_A_DIRECTORY; } + /* found with gentest */ + if (io->ntcreatex.in.access_mask == SEC_FLAG_MAXIMUM_ALLOWED && + (io->ntcreatex.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) && + (io->ntcreatex.in.create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { + return NT_STATUS_INVALID_PARAMETER; + } + switch (io->generic.in.open_disposition) { case NTCREATEX_DISP_OPEN_IF: break; @@ -563,7 +570,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { return NT_STATUS_CANNOT_DELETE; } - + status = pvfs_access_check_create(pvfs, req, name, &access_mask); NT_STATUS_NOT_OK_RETURN(status); @@ -1121,6 +1128,25 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return ntvfs_map_open(ntvfs, req, io); } + create_options = io->generic.in.create_options; + share_access = io->generic.in.share_access; + access_mask = io->generic.in.access_mask; + + if (share_access & ~NTCREATEX_SHARE_ACCESS_MASK) { + return NT_STATUS_INVALID_PARAMETER; + } + + /* some create options are not supported */ + if (create_options & NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK) { + return NT_STATUS_NOT_SUPPORTED; + } + + /* other create options are not allowed */ + if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && + !(access_mask & SEC_STD_DELETE)) { + return NT_STATUS_INVALID_PARAMETER; + } + /* resolve the cifs name to a posix name */ status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, PVFS_RESOLVE_STREAMS, &name); @@ -1152,16 +1178,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, open doesn't match */ io->generic.in.file_attr &= ~FILE_ATTRIBUTE_DIRECTORY; - create_options = io->generic.in.create_options; - share_access = io->generic.in.share_access; - access_mask = io->generic.in.access_mask; - - /* certain create options are not allowed */ - if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && - !(access_mask & SEC_STD_DELETE)) { - return NT_STATUS_INVALID_PARAMETER; - } - flags = 0; switch (io->generic.in.open_disposition) { -- cgit From f0b4b15f64259fcdb18f21657434f592bb2f157e Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 14:07:11 +1000 Subject: check for some more invalid bits in smb2 create (This used to be commit dcdaa9f5fd9150b16fb277213e864e5c39d831d6) --- source4/ntvfs/posix/pvfs_open.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 59b42fe751..328f064a57 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1147,6 +1147,15 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } + if (access_mask & (SEC_MASK_INVALID | SEC_STD_SYNCHRONIZE)) { + return NT_STATUS_ACCESS_DENIED; + } + + if (io->ntcreatex.in.file_attr & (FILE_ATTRIBUTE_DEVICE| + FILE_ATTRIBUTE_VOLUME)) { + return NT_STATUS_INVALID_PARAMETER; + } + /* resolve the cifs name to a posix name */ status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, PVFS_RESOLVE_STREAMS, &name); -- cgit From 6e265867ff8869254820e8af954c8f1316b05d39 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 14:30:42 +1000 Subject: SEC_STD_SYNCHRONIZE is only invalid on SMB2 (This used to be commit 067f1271adaa13d537bbc92b19fe8d633cbaaf50) --- source4/ntvfs/posix/pvfs_open.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 328f064a57..739c127b98 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -565,6 +565,10 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, if (io->ntcreatex.in.file_attr & ~FILE_ATTRIBUTE_ALL_MASK) { return NT_STATUS_INVALID_PARAMETER; } + + if (io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_ENCRYPTED) { + return NT_STATUS_ACCESS_DENIED; + } if ((io->ntcreatex.in.file_attr & FILE_ATTRIBUTE_READONLY) && (create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE)) { @@ -1147,7 +1151,12 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } - if (access_mask & (SEC_MASK_INVALID | SEC_STD_SYNCHRONIZE)) { + if (access_mask & SEC_MASK_INVALID) { + return NT_STATUS_ACCESS_DENIED; + } + + if (req->ctx->protocol == PROTOCOL_SMB2 && + (access_mask & SEC_STD_SYNCHRONIZE)) { return NT_STATUS_ACCESS_DENIED; } -- cgit From 65e31a965ee6514610ec0d4ca52a5cd8772c5254 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 14:59:55 +1000 Subject: make the SEC_STD_SYNCHRONIZE test more specific (This used to be commit 8c263f91bda97eb910c8589b6cd987ec4a62d770) --- source4/ntvfs/posix/pvfs_open.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 739c127b98..cfa88b6baa 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1155,13 +1155,16 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_ACCESS_DENIED; } + /* what does this bit really mean?? */ if (req->ctx->protocol == PROTOCOL_SMB2 && - (access_mask & SEC_STD_SYNCHRONIZE)) { + (access_mask & SEC_STD_SYNCHRONIZE) && + !(access_mask & SEC_STD_READ_CONTROL)) { return NT_STATUS_ACCESS_DENIED; } if (io->ntcreatex.in.file_attr & (FILE_ATTRIBUTE_DEVICE| - FILE_ATTRIBUTE_VOLUME)) { + FILE_ATTRIBUTE_VOLUME| + (~FILE_ATTRIBUTE_ALL_MASK))) { return NT_STATUS_INVALID_PARAMETER; } -- cgit From cf274201b4e987faa822a137bb67fa191dabc5e8 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 15:27:25 +1000 Subject: disable the SEC_STD_SYNCHRONIZE test until we know what it means (This used to be commit 897f4582bee72e319874e8a2d064ba442415571d) --- source4/ntvfs/posix/pvfs_open.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index cfa88b6baa..adcdeb1f2b 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1155,12 +1155,14 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_ACCESS_DENIED; } +#if 0 /* what does this bit really mean?? */ if (req->ctx->protocol == PROTOCOL_SMB2 && (access_mask & SEC_STD_SYNCHRONIZE) && !(access_mask & SEC_STD_READ_CONTROL)) { return NT_STATUS_ACCESS_DENIED; } +#endif if (io->ntcreatex.in.file_attr & (FILE_ATTRIBUTE_DEVICE| FILE_ATTRIBUTE_VOLUME| -- cgit From 46e64417a3b14d1c33ca7e97080c64f8e67efec2 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 16:02:27 +1000 Subject: another attempt at the damn SEC_STD_SYNCHRONIZE flag (This used to be commit 2ac27bfffa557d6c0f71c443b43a8d1967edb177) --- source4/ntvfs/posix/pvfs_open.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index adcdeb1f2b..908dd449af 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1155,14 +1155,11 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_ACCESS_DENIED; } -#if 0 /* what does this bit really mean?? */ if (req->ctx->protocol == PROTOCOL_SMB2 && - (access_mask & SEC_STD_SYNCHRONIZE) && - !(access_mask & SEC_STD_READ_CONTROL)) { + access_mask == SEC_STD_SYNCHRONIZE) { return NT_STATUS_ACCESS_DENIED; } -#endif if (io->ntcreatex.in.file_attr & (FILE_ATTRIBUTE_DEVICE| FILE_ATTRIBUTE_VOLUME| -- cgit From cb36437db2d75e7facc91cf0089f2caa20bf0ca0 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Tue, 27 May 2008 16:43:36 +1000 Subject: added support for the output fields of SMB2 close (This used to be commit 2633bc749792c224acc73a2e4ca723404331c19c) --- source4/ntvfs/posix/pvfs_open.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 908dd449af..49710806c7 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1514,21 +1514,44 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, return NT_STATUS_DOS(ERRSRV, ERRerror); } - if (io->generic.level != RAW_CLOSE_CLOSE) { + if (io->generic.level != RAW_CLOSE_GENERIC) { return ntvfs_map_close(ntvfs, req, io); } - f = pvfs_find_fd(pvfs, req, io->close.in.file.ntvfs); + f = pvfs_find_fd(pvfs, req, io->generic.in.file.ntvfs); if (!f) { return NT_STATUS_INVALID_HANDLE; } - if (!null_time(io->close.in.write_time)) { + if (!null_time(io->generic.in.write_time)) { unix_times.actime = 0; unix_times.modtime = io->close.in.write_time; utime(f->handle->name->full_name, &unix_times); } + if (io->generic.in.flags & SMB2_CLOSE_FLAGS_FULL_INFORMATION) { + struct pvfs_filename *name; + NTSTATUS status; + struct pvfs_file_handle *h = f->handle; + + status = pvfs_resolve_name_handle(pvfs, h); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + name = h->name; + + io->generic.out.flags = SMB2_CLOSE_FLAGS_FULL_INFORMATION; + io->generic.out.create_time = name->dos.create_time; + io->generic.out.access_time = name->dos.access_time; + io->generic.out.write_time = name->dos.write_time; + io->generic.out.change_time = name->dos.change_time; + io->generic.out.alloc_size = name->dos.alloc_size; + io->generic.out.size = name->st.st_size; + io->generic.out.file_attr = name->dos.attrib; + } else { + ZERO_STRUCT(io->generic.out); + } + talloc_free(f); return NT_STATUS_OK; -- cgit From 6b707263058ec69f12a6235890005a226c8671de Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 28 May 2008 16:28:37 +1000 Subject: implement the documented SMB2 create blobs in the server Not all of them are honoured yet, but they are all parsed and the ones that have SMB equivalents are honoured (This used to be commit 9fc70e2ed6a54f6d9a0530f4d37c0f8acadb6778) --- source4/ntvfs/posix/pvfs_open.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 49710806c7..0f08136a79 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -634,6 +634,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, return status; } + /* support initial alloc sizes */ + name->dos.alloc_size = io->ntcreatex.in.alloc_size; name->dos.attrib = attrib; status = pvfs_dosattrib_save(pvfs, name, fd); if (!NT_STATUS_IS_OK(status)) { @@ -1464,6 +1466,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, talloc_free(lck); return pvfs_map_errno(pvfs, errno); } + name->dos.alloc_size = io->ntcreatex.in.alloc_size; name->dos.attrib = attrib; status = pvfs_dosattrib_save(pvfs, name, fd); if (!NT_STATUS_IS_OK(status)) { -- cgit From 67226f054b57961ac00b419761014d4a92e8c18d Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Wed, 28 May 2008 22:44:20 +1000 Subject: fixed create_action for truncated files (This used to be commit 884c32fcef48244bd260026a61790332bd706eb4) --- source4/ntvfs/posix/pvfs_open.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 0f08136a79..a1c5571258 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1122,6 +1122,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, uint32_t create_options; uint32_t share_access; uint32_t access_mask; + uint32_t create_action = NTCREATEX_ACTION_EXISTED; bool del_on_close; bool stream_existed, stream_truncate=false; uint32_t oplock_level = OPLOCK_NONE, oplock_granted; @@ -1169,6 +1170,13 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } + /* we ignore some file_attr bits */ + io->ntcreatex.in.file_attr &= ~(FILE_ATTRIBUTE_NONINDEXED | + FILE_ATTRIBUTE_COMPRESSED | + FILE_ATTRIBUTE_REPARSE_POINT | + FILE_ATTRIBUTE_SPARSE | + FILE_ATTRIBUTE_NORMAL); + /* resolve the cifs name to a posix name */ status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname, PVFS_RESOLVE_STREAMS, &name); @@ -1210,6 +1218,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } else { stream_truncate = true; } + create_action = NTCREATEX_ACTION_TRUNCATED; break; case NTCREATEX_DISP_OPEN: @@ -1228,6 +1237,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } else { stream_truncate = true; } + create_action = NTCREATEX_ACTION_TRUNCATED; break; case NTCREATEX_DISP_CREATE: @@ -1487,7 +1497,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, io->generic.out.oplock_level = oplock_granted; io->generic.out.file.ntvfs = h; io->generic.out.create_action = stream_existed? - NTCREATEX_ACTION_EXISTED:NTCREATEX_ACTION_CREATED; + create_action:NTCREATEX_ACTION_CREATED; + io->generic.out.create_time = name->dos.create_time; io->generic.out.access_time = name->dos.access_time; io->generic.out.write_time = name->dos.write_time; -- cgit From c86dc11be6e626fa81f025d7ec78226fb4249cdc Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 29 May 2008 19:16:26 +1000 Subject: added support for returning the maximal access MXAC tag in SMB2 create (This used to be commit 4eb49335d5f0319f9aa47ded5215a2977d3336bf) --- source4/ntvfs/posix/pvfs_open.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index a1c5571258..dada9f503f 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -252,8 +252,12 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } else { status = pvfs_access_check_create(pvfs, req, name, &access_mask); } - if (!NT_STATUS_IS_OK(status)) { - return status; + NT_STATUS_NOT_OK_RETURN(status); + + if (io->generic.in.query_maximal_access) { + status = pvfs_access_maximal_allowed(pvfs, req, name, + &io->generic.out.maximal_access); + NT_STATUS_NOT_OK_RETURN(status); } f->ntvfs = h; @@ -578,6 +582,12 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, status = pvfs_access_check_create(pvfs, req, name, &access_mask); NT_STATUS_NOT_OK_RETURN(status); + if (io->generic.in.query_maximal_access) { + status = pvfs_access_maximal_allowed(pvfs, req, name, + &io->generic.out.maximal_access); + NT_STATUS_NOT_OK_RETURN(status); + } + /* check that the parent isn't opened with delete on close set */ status = pvfs_resolve_parent(pvfs, req, name, &parent); if (NT_STATUS_IS_OK(status)) { @@ -1135,6 +1145,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return ntvfs_map_open(ntvfs, req, io); } + ZERO_STRUCT(io->generic.out); + create_options = io->generic.in.create_options; share_access = io->generic.in.share_access; access_mask = io->generic.in.access_mask; @@ -1282,8 +1294,12 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* check the security descriptor */ status = pvfs_access_check(pvfs, req, name, &access_mask); - if (!NT_STATUS_IS_OK(status)) { - return status; + NT_STATUS_NOT_OK_RETURN(status); + + if (io->generic.in.query_maximal_access) { + status = pvfs_access_maximal_allowed(pvfs, req, name, + &io->generic.out.maximal_access); + NT_STATUS_NOT_OK_RETURN(status); } status = ntvfs_handle_new(pvfs->ntvfs, req, &h); -- cgit From 0827b08a433b7dec91be7ca7406804087f3fef07 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 15 Apr 2008 16:00:42 +0200 Subject: opendb: add write time handling metze (This used to be commit 3868d8ce630c71e2c70aae442fcdbd68ba1eb708) --- source4/ntvfs/posix/pvfs_open.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index dada9f503f..bdb6c9bad0 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -280,6 +280,7 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, f->handle->position = 0; f->handle->mode = 0; f->handle->oplock = NULL; + ZERO_STRUCT(f->handle->write_time); f->handle->open_completed = false; if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && @@ -317,7 +318,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, /* now really mark the file as open */ status = odb_open_file(lck, f->handle, name->full_name, - NULL, false, OPLOCK_NONE, NULL); + NULL, name->dos.write_time, + false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); @@ -377,7 +379,8 @@ static NTSTATUS pvfs_open_directory(struct pvfs_state *pvfs, } status = odb_open_file(lck, f->handle, name->full_name, - NULL, false, OPLOCK_NONE, NULL); + NULL, name->dos.write_time, + false, OPLOCK_NONE, NULL); if (!NT_STATUS_IS_OK(status)) { goto cleanup_delete; @@ -594,8 +597,8 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, DATA_BLOB locking_key; status = pvfs_locking_key(parent, req, &locking_key); NT_STATUS_NOT_OK_RETURN(status); - status = odb_get_delete_on_close(pvfs->odb_context, &locking_key, - &del_on_close); + status = odb_get_file_infos(pvfs->odb_context, &locking_key, + &del_on_close, NULL); NT_STATUS_NOT_OK_RETURN(status); if (del_on_close) { return NT_STATUS_DELETE_PENDING; @@ -730,10 +733,12 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, f->handle->mode = 0; f->handle->oplock = NULL; f->handle->have_opendb_entry = true; + ZERO_STRUCT(f->handle->write_time); f->handle->open_completed = false; status = odb_open_file(lck, f->handle, name->full_name, - &f->handle->fd, allow_level_II_oplock, + &f->handle->fd, name->dos.write_time, + allow_level_II_oplock, oplock_level, &oplock_granted); talloc_free(lck); if (!NT_STATUS_IS_OK(status)) { @@ -1334,6 +1339,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, f->handle->mode = 0; f->handle->oplock = NULL; f->handle->have_opendb_entry = false; + ZERO_STRUCT(f->handle->write_time); f->handle->open_completed = false; /* form the lock context used for byte range locking and @@ -1437,7 +1443,8 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* now really mark the file as open */ status = odb_open_file(lck, f->handle, name->full_name, - &f->handle->fd, allow_level_II_oplock, + &f->handle->fd, name->dos.write_time, + allow_level_II_oplock, oplock_level, &oplock_granted); if (!NT_STATUS_IS_OK(status)) { @@ -1915,8 +1922,8 @@ bool pvfs_delete_on_close_set(struct pvfs_state *pvfs, struct pvfs_file_handle * NTSTATUS status; bool del_on_close; - status = odb_get_delete_on_close(pvfs->odb_context, &h->odb_locking_key, - &del_on_close); + status = odb_get_file_infos(pvfs->odb_context, &h->odb_locking_key, + &del_on_close, NULL); if (!NT_STATUS_IS_OK(status)) { DEBUG(1,("WARNING: unable to determine delete on close status for open file\n")); return false; -- 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_open.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index bdb6c9bad0..94480df6b7 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -641,7 +641,7 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, } /* re-resolve the open fd */ - status = pvfs_resolve_name_fd(pvfs, fd, name); + status = pvfs_resolve_name_fd(pvfs, fd, name, 0); if (!NT_STATUS_IS_OK(status)) { close(fd); return status; @@ -1483,7 +1483,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, } /* re-resolve the open fd */ - status = pvfs_resolve_name_fd(f->pvfs, fd, f->handle->name); + status = pvfs_resolve_name_fd(f->pvfs, fd, f->handle->name, PVFS_RESOLVE_NO_OPENDB); if (!NT_STATUS_IS_OK(status)) { talloc_free(lck); return status; -- cgit From 60759b64a7508b161de795e42c46c2bd62e0728a Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 3 Jun 2008 11:54:21 +0200 Subject: pvfs: correctly set the write time in the handle destructor metze (This used to be commit 58c118ab4d2b76c4ea68d79b711b81900634f767) --- source4/ntvfs/posix/pvfs_open.c | 46 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 94480df6b7..c7f93fb0d8 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -436,6 +436,9 @@ cleanup_delete: */ static int pvfs_handle_destructor(struct pvfs_file_handle *h) { + talloc_free(h->write_time.update_event); + h->write_time.update_event = NULL; + if ((h->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && h->name->stream_name) { NTSTATUS status; @@ -454,6 +457,14 @@ static int pvfs_handle_destructor(struct pvfs_file_handle *h) h->fd = -1; } + if (!h->write_time.update_forced && + h->write_time.update_on_close && + h->write_time.close_time == 0) { + struct timeval tv; + tv = timeval_current(); + h->write_time.close_time = timeval_to_nttime(&tv); + } + if (h->have_opendb_entry) { struct odb_lock *lck; NTSTATUS status; @@ -465,6 +476,26 @@ static int pvfs_handle_destructor(struct pvfs_file_handle *h) return 0; } + if (h->write_time.update_forced) { + status = odb_get_file_infos(h->pvfs->odb_context, + &h->odb_locking_key, + NULL, + &h->write_time.close_time); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable get write time for '%s' - %s\n", + h->name->full_name, nt_errstr(status))); + } + + h->write_time.update_forced = false; + h->write_time.update_on_close = true; + } else if (h->write_time.update_on_close) { + status = odb_set_write_time(lck, h->write_time.close_time, true); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("Unable set write time for '%s' - %s\n", + h->name->full_name, nt_errstr(status))); + } + } + status = odb_close_file(lck, h, &delete_path); if (!NT_STATUS_IS_OK(status)) { DEBUG(0,("Unable to remove opendb entry for '%s' - %s\n", @@ -487,11 +518,26 @@ static int pvfs_handle_destructor(struct pvfs_file_handle *h) FILE_NOTIFY_CHANGE_FILE_NAME, delete_path); } + h->write_time.update_on_close = false; } talloc_free(lck); } + if (h->write_time.update_on_close) { + struct utimbuf unix_times; + + unix_times.actime = nt_time_to_unix(h->name->dos.access_time); + unix_times.modtime = nt_time_to_unix(h->write_time.close_time); + + if (unix_times.actime != 0 || unix_times.modtime != 0) { + if (utime(h->name->full_name, &unix_times) == -1) { + DEBUG(0,("pvfs_close: utime() failed '%s' - %s\n", + h->name->full_name, strerror(errno))); + } + } + } + return 0; } -- 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_open.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index c7f93fb0d8..a78d0a79c7 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1591,7 +1591,6 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, { struct pvfs_state *pvfs = ntvfs->private_data; struct pvfs_file *f; - struct utimbuf unix_times; if (io->generic.level == RAW_CLOSE_SPLCLOSE) { return NT_STATUS_DOS(ERRSRV, ERRerror); @@ -1607,9 +1606,9 @@ NTSTATUS pvfs_close(struct ntvfs_module_context *ntvfs, } if (!null_time(io->generic.in.write_time)) { - unix_times.actime = 0; - unix_times.modtime = io->close.in.write_time; - utime(f->handle->name->full_name, &unix_times); + f->handle->write_time.update_forced = false; + f->handle->write_time.update_on_close = true; + unix_to_nt_time(&f->handle->write_time.close_time, io->generic.in.write_time); } if (io->generic.in.flags & SMB2_CLOSE_FLAGS_FULL_INFORMATION) { -- cgit From b800af662cd1135432c835643e2736921e173998 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 3 Jun 2008 13:32:04 +0200 Subject: pvfs: use utimes() instead of utime() to get better timestamp resolution Note: that libreplace always provides utimes() metze (This used to be commit 61bad69e2d7f84e2c6d6fb82917cfa86b17f54b0) --- source4/ntvfs/posix/pvfs_open.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index a78d0a79c7..43203086f8 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -525,14 +525,14 @@ static int pvfs_handle_destructor(struct pvfs_file_handle *h) } if (h->write_time.update_on_close) { - struct utimbuf unix_times; + struct timeval tv[2]; - unix_times.actime = nt_time_to_unix(h->name->dos.access_time); - unix_times.modtime = nt_time_to_unix(h->write_time.close_time); + nttime_to_timeval(&tv[0], h->name->dos.access_time); + nttime_to_timeval(&tv[1], h->write_time.close_time); - if (unix_times.actime != 0 || unix_times.modtime != 0) { - if (utime(h->name->full_name, &unix_times) == -1) { - DEBUG(0,("pvfs_close: utime() failed '%s' - %s\n", + if (!timeval_is_zero(&tv[0]) || !timeval_is_zero(&tv[1])) { + if (utimes(h->name->full_name, tv) == -1) { + DEBUG(0,("pvfs_handle_destructor: utimes() failed '%s' - %s\n", h->name->full_name, strerror(errno))); } } -- cgit From e92125e6319d49185a3d0456a8a0e5c1b8d364e7 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 16 Jul 2008 14:00:18 +1000 Subject: Ignore and handle more NT Create & X options. The MS-SMB document explains that some of these options should be ignored. The test proves it. /* Must be ignored by the server, per MS-SMB 2.2.8 */ /* Must be ignored by the server, per MS-SMB 2.2.8 */ If we implement HSM in samba4 (likely) we should honour this bit. /* Don't pull this file off tape in a HSM system */ Andrew Bartlett (This used to be commit 502739ff90d56d2c9aabe8e224317f6ceb175c17) --- source4/ntvfs/posix/pvfs_open.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 43203086f8..5302fc3f50 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1206,11 +1206,22 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } - /* some create options are not supported */ if (create_options & NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK) { return NT_STATUS_NOT_SUPPORTED; } + /* TODO: When we implement HSM, add a hook here not to pull + * the actual file off tape, when this option is passed from + * the client */ + if (create_options & NTCREATEX_OPTIONS_NO_RECALL) { + /* no-op */ + } + + /* These options are ignored */ + if (create_options & (NTCREATEX_OPTIONS_FREE_SPACE_QUERY | NTCREATEX_OPTIONS_OPFILTER)) { + /* no-op */ + } + /* other create options are not allowed */ if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && !(access_mask & SEC_STD_DELETE)) { -- cgit From 853194c308a0f2171808b78b17aed50c5fab1b3b Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 18 Jul 2008 18:40:19 +1000 Subject: More 'must be ignored' options from the MS-SMB doc. Also in particular the 'sync' flags (which Samba has traditionally ignored). Thanks to Olivier Salamin for pointing out more flags that needed to be handled. Andrew Bartlett (This used to be commit 370bb39cd79fe49efd36a1ceb3e896d386e6d3ce) --- source4/ntvfs/posix/pvfs_open.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 5302fc3f50..01a249ceb7 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1173,7 +1173,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, struct ntvfs_request *req, union smb_open *io) { struct pvfs_state *pvfs = ntvfs->private_data; - int flags; + int flags = 0; struct pvfs_filename *name; struct pvfs_file *f; struct ntvfs_handle *h; @@ -1206,6 +1206,9 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } + /* These options are ignored */ + create_options &= ~NTCREATEX_OPTIONS_MUST_IGNORE_MASK; + if (create_options & NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK) { return NT_STATUS_NOT_SUPPORTED; } @@ -1217,11 +1220,23 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, /* no-op */ } - /* These options are ignored */ - if (create_options & (NTCREATEX_OPTIONS_FREE_SPACE_QUERY | NTCREATEX_OPTIONS_OPFILTER)) { + /* TODO: If (unlikely) Linux does a good compressed + * filesystem, we might need an ioctl call for this */ + if (create_options & NTCREATEX_OPTIONS_NO_COMPRESSION) { /* no-op */ } + if (create_options & NTCREATEX_OPTIONS_NO_INTERMEDIATE_BUFFERING) { + create_options |= NTCREATEX_OPTIONS_WRITE_THROUGH; + } + + /* Open the file with sync, if they asked for it, but + 'strict sync = no' turns this client request into a no-op */ + if (create_options & (NTCREATEX_OPTIONS_WRITE_THROUGH) && !(pvfs->flags | PVFS_FLAG_STRICT_SYNC)) { + flags |= O_SYNC; + } + + /* other create options are not allowed */ if ((create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) && !(access_mask & SEC_STD_DELETE)) { @@ -1282,8 +1297,6 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, open doesn't match */ io->generic.in.file_attr &= ~FILE_ATTRIBUTE_DIRECTORY; - flags = 0; - switch (io->generic.in.open_disposition) { case NTCREATEX_DISP_SUPERSEDE: case NTCREATEX_DISP_OVERWRITE_IF: -- cgit From 2ecda9fde4aa00aecd6df6ebeb162d173853d146 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Thu, 24 Jul 2008 14:21:52 +1000 Subject: we can't query the ACL on a new file till it exists! (This used to be commit 4f6646f06988b1fb8be9e0c8ae833bb9792184af) --- source4/ntvfs/posix/pvfs_open.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 01a249ceb7..6114b2052c 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -631,12 +631,6 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, status = pvfs_access_check_create(pvfs, req, name, &access_mask); NT_STATUS_NOT_OK_RETURN(status); - if (io->generic.in.query_maximal_access) { - status = pvfs_access_maximal_allowed(pvfs, req, name, - &io->generic.out.maximal_access); - NT_STATUS_NOT_OK_RETURN(status); - } - /* check that the parent isn't opened with delete on close set */ status = pvfs_resolve_parent(pvfs, req, name, &parent); if (NT_STATUS_IS_OK(status)) { @@ -707,6 +701,12 @@ static NTSTATUS pvfs_create_file(struct pvfs_state *pvfs, goto cleanup_delete; } + if (io->generic.in.query_maximal_access) { + status = pvfs_access_maximal_allowed(pvfs, req, name, + &io->generic.out.maximal_access); + NT_STATUS_NOT_OK_RETURN(status); + } + /* form the lock context used for byte range locking and opendb locking */ status = pvfs_locking_key(name, f->handle, &f->handle->odb_locking_key); -- cgit From cc60d5a0320f824f7dc7b8abbe9cb0ccd668dda2 Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Thu, 14 Aug 2008 12:37:31 +0200 Subject: pvfs: fix handling of create_option flags metze (This used to be commit 3c6cadf76861d6522c5ec41953df1ba2fac4910d) --- source4/ntvfs/posix/pvfs_open.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'source4/ntvfs/posix/pvfs_open.c') diff --git a/source4/ntvfs/posix/pvfs_open.c b/source4/ntvfs/posix/pvfs_open.c index 6114b2052c..c127885a68 100644 --- a/source4/ntvfs/posix/pvfs_open.c +++ b/source4/ntvfs/posix/pvfs_open.c @@ -1181,6 +1181,7 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, int fd; struct odb_lock *lck; uint32_t create_options; + uint32_t create_options_must_ignore_mask; uint32_t share_access; uint32_t access_mask; uint32_t create_action = NTCREATEX_ACTION_EXISTED; @@ -1206,13 +1207,22 @@ NTSTATUS pvfs_open(struct ntvfs_module_context *ntvfs, return NT_STATUS_INVALID_PARAMETER; } - /* These options are ignored */ - create_options &= ~NTCREATEX_OPTIONS_MUST_IGNORE_MASK; + /* + * These options are ignored, + * but we reuse some of them as private values for the generic mapping + */ + create_options_must_ignore_mask = NTCREATEX_OPTIONS_MUST_IGNORE_MASK; + create_options_must_ignore_mask &= ~NTCREATEX_OPTIONS_PRIVATE_MASK; + create_options &= ~create_options_must_ignore_mask; if (create_options & NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK) { return NT_STATUS_NOT_SUPPORTED; } + if (create_options & NTCREATEX_OPTIONS_INVALID_PARAM_MASK) { + return NT_STATUS_INVALID_PARAMETER; + } + /* TODO: When we implement HSM, add a hook here not to pull * the actual file off tape, when this option is passed from * the client */ -- cgit