2004-09-20 11:28:43 +04:00
/*
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
2007-07-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2004-09-20 11:28:43 +04:00
( 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
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2004-09-20 11:28:43 +04:00
*/
2004-11-05 10:29:02 +03:00
# include "includes.h"
2004-09-20 11:28:43 +04:00
# include "vfs_posix.h"
2005-06-24 02:30:26 +04:00
# include "system/dir.h"
2004-11-02 03:24:21 +03:00
# include "system/time.h"
2006-08-30 15:29:34 +04:00
# include "lib/util/dlinklist.h"
2006-01-03 18:40:05 +03:00
# include "messaging/messaging.h"
2006-03-16 03:23:11 +03:00
# include "librpc/gen_ndr/xattr.h"
2004-09-20 11:28:43 +04:00
/*
find open file handle given fnum
*/
2004-09-29 17:17:09 +04:00
struct pvfs_file * pvfs_find_fd ( struct pvfs_state * pvfs ,
2006-05-20 12:15:22 +04:00
struct ntvfs_request * req , struct ntvfs_handle * h )
2004-09-20 11:28:43 +04:00
{
2006-05-20 12:15:22 +04:00
void * p ;
2004-09-20 11:28:43 +04:00
struct pvfs_file * f ;
2004-10-19 10:39:51 +04:00
2006-05-20 12:15:22 +04:00
p = ntvfs_handle_get_backend_data ( h , pvfs - > ntvfs ) ;
if ( ! p ) return NULL ;
2004-10-19 10:39:51 +04:00
2006-05-20 12:15:22 +04:00
f = talloc_get_type ( p , struct pvfs_file ) ;
if ( ! f ) return NULL ;
2004-11-08 06:54:12 +03:00
2004-10-19 10:39:51 +04:00
return f ;
2004-09-20 11:28:43 +04:00
}
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)
2004-10-20 12:28:31 +04:00
/*
cleanup a open directory handle
*/
2006-05-24 11:34:11 +04:00
static int pvfs_dir_handle_destructor ( struct pvfs_file_handle * h )
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)
2004-10-20 12:28:31 +04:00
{
2006-02-28 06:47:02 +03:00
if ( h - > have_opendb_entry ) {
struct odb_lock * lck ;
NTSTATUS status ;
2008-02-27 23:52:52 +03:00
const char * delete_path = NULL ;
2006-02-28 06:47:02 +03:00
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 ;
2004-12-17 07:51:23 +03:00
}
2006-02-28 06:47:02 +03:00
2008-02-27 23:52:52 +03:00
status = odb_close_file ( lck , h , & delete_path ) ;
2006-02-28 06:47:02 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2008-02-27 23:52:52 +03:00
DEBUG ( 0 , ( " Unable to remove opendb entry for '%s' - %s \n " ,
2006-02-28 06:47:02 +03:00
h - > name - > full_name , nt_errstr ( status ) ) ) ;
2004-10-24 16:39:15 +04:00
}
2006-02-28 06:47:02 +03:00
2008-02-27 23:52:52 +03:00
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 ) ) ) ;
}
}
2006-02-28 06:47:02 +03:00
talloc_free ( lck ) ;
2004-10-24 16:39:15 +04:00
}
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)
2004-10-20 12:28:31 +04:00
return 0 ;
}
2004-11-08 06:54:12 +03:00
/*
cleanup a open directory fnum
*/
2006-05-24 11:34:11 +04:00
static int pvfs_dir_fnum_destructor ( struct pvfs_file * f )
2004-11-08 06:54:12 +03:00
{
2006-03-18 13:38:38 +03:00
DLIST_REMOVE ( f - > pvfs - > files . list , f ) ;
2006-05-20 12:15:22 +04:00
ntvfs_handle_remove_backend_data ( f - > ntvfs , f - > pvfs - > ntvfs ) ;
2004-11-08 06:54:12 +03:00
return 0 ;
}
2004-12-30 05:25:20 +03:00
/*
setup any EAs and the ACL on newly created files / directories
*/
static NTSTATUS pvfs_open_setup_eas_acl ( struct pvfs_state * pvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req ,
2004-12-30 05:25:20 +03:00
struct pvfs_filename * name ,
2006-05-20 12:15:22 +04:00
int fd , struct pvfs_file * f ,
2004-12-30 05:25:20 +03:00
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 ;
2006-04-18 12:07:35 +04:00
/*
* 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
*/
2006-05-20 12:15:22 +04:00
set . set_secdesc . in . file . ntvfs = f - > ntvfs ;
2004-12-30 05:25:20 +03:00
set . set_secdesc . in . secinfo_flags = SECINFO_DACL ;
set . set_secdesc . in . sd = io - > ntcreatex . in . sec_desc ;
2004-12-31 11:56:32 +03:00
status = pvfs_acl_set ( pvfs , req , name , fd , SEC_STD_WRITE_DAC , & set ) ;
2004-12-30 05:25:20 +03:00
} else {
/* otherwise setup an inherited acl from the parent */
status = pvfs_acl_inherit ( pvfs , req , name , fd ) ;
}
return status ;
}
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)
2004-10-20 12:28:31 +04:00
2006-02-28 06:47:02 +03:00
/*
form the lock context used for opendb locking . Note that we must
zero here to take account of possible padding on some architectures
*/
2008-02-28 14:18:29 +03:00
NTSTATUS pvfs_locking_key ( struct pvfs_filename * name ,
TALLOC_CTX * mem_ctx , DATA_BLOB * key )
2006-02-28 06:47:02 +03:00
{
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 ;
}
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)
2004-10-20 12:28:31 +04:00
/*
open a directory
*/
static NTSTATUS pvfs_open_directory ( struct pvfs_state * pvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req ,
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)
2004-10-20 12:28:31 +04:00
struct pvfs_filename * name ,
union smb_open * io )
{
struct pvfs_file * f ;
2006-05-20 12:15:22 +04:00
struct ntvfs_handle * h ;
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)
2004-10-20 12:28:31 +04:00
NTSTATUS status ;
2004-10-23 10:22:57 +04:00
uint32_t create_action ;
2004-12-04 15:42:40 +03:00
uint32_t access_mask = io - > generic . in . access_mask ;
2006-02-28 06:47:02 +03:00
struct odb_lock * lck ;
2007-10-07 02:28:14 +04:00
bool del_on_close ;
2006-02-28 06:47:02 +03:00
uint32_t create_options ;
uint32_t share_access ;
2008-05-23 11:47:59 +04:00
bool forced ;
2006-02-28 06:47:02 +03:00
create_options = io - > generic . in . create_options ;
share_access = io - > generic . in . share_access ;
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)
2004-10-20 12:28:31 +04:00
2008-05-23 11:47:59 +04:00
forced = ( io - > generic . in . create_options & NTCREATEX_OPTIONS_DIRECTORY ) ? true : false ;
2004-11-15 09:57:26 +03:00
if ( name - > stream_name ) {
2008-05-23 11:47:59 +04:00
if ( forced ) {
return NT_STATUS_NOT_A_DIRECTORY ;
} else {
return NT_STATUS_FILE_IS_A_DIRECTORY ;
}
2004-11-15 09:57:26 +03:00
}
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)
2004-10-20 12:28:31 +04:00
/* 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 ;
}
2008-05-26 09:02:43 +04:00
/* 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 ;
}
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)
2004-10-20 12:28:31 +04:00
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 ;
}
2006-05-20 12:15:22 +04:00
status = ntvfs_handle_new ( pvfs - > ntvfs , req , & h ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
f = talloc ( h , struct pvfs_file ) ;
2004-10-24 12:31:41 +04:00
if ( f = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2005-01-27 10:08:20 +03:00
f - > handle = talloc ( f , struct pvfs_file_handle ) ;
2004-11-08 06:54:12 +03:00
if ( f - > handle = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2004-12-04 15:42:40 +03:00
if ( name - > exists ) {
/* check the security descriptor */
status = pvfs_access_check ( pvfs , req , name , & access_mask ) ;
2004-12-30 08:50:23 +03:00
} else {
2005-01-07 05:14:34 +03:00
status = pvfs_access_check_create ( pvfs , req , name , & access_mask ) ;
2004-12-30 08:50:23 +03:00
}
2008-05-29 13:16:26 +04:00
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 ) ;
2004-12-04 15:42:40 +03:00
}
2006-05-20 12:15:22 +04:00
f - > ntvfs = h ;
2004-11-08 14:35:49 +03:00
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 ;
2004-12-04 15:42:40 +03:00
f - > access_mask = access_mask ;
2006-05-15 16:22:00 +04:00
f - > brl_handle = NULL ;
2006-03-21 14:47:24 +03:00
f - > notify_buffer = NULL ;
2006-07-08 16:35:37 +04:00
f - > search = NULL ;
2004-11-08 06:54:12 +03:00
2004-11-24 09:09:14 +03:00
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 - > create_options = io - > generic . in . create_options ;
f - > handle - > seek_offset = 0 ;
f - > handle - > position = 0 ;
f - > handle - > mode = 0 ;
2008-02-25 10:39:13 +03:00
f - > handle - > oplock = NULL ;
2008-04-15 18:00:42 +04:00
ZERO_STRUCT ( f - > handle - > write_time ) ;
2007-10-07 02:28:14 +04:00
f - > handle - > open_completed = false ;
2004-10-24 12:31:41 +04:00
2006-02-28 06:47:02 +03:00
if ( ( create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE ) & &
pvfs_directory_empty ( pvfs , f - > handle - > name ) ) {
2007-10-07 02:28:14 +04:00
del_on_close = true ;
2006-02-28 06:47:02 +03:00
} else {
2007-10-07 02:28:14 +04:00
del_on_close = false ;
2006-02-28 06:47:02 +03:00
}
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 ) ) {
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 ! */
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
/* see if we are allowed to open at the same time as existing opens */
2008-03-07 19:50:17 +03:00
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 */
2008-03-07 20:28:48 +03:00
status = odb_open_file ( lck , f - > handle , name - > full_name ,
2008-04-15 18:00:42 +04:00
NULL , name - > dos . write_time ,
false , OPLOCK_NONE , NULL ) ;
2006-02-28 06:47:02 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( lck ) ;
return status ;
}
2007-10-07 02:28:14 +04:00
f - > handle - > have_opendb_entry = true ;
2006-02-28 06:47:02 +03:00
}
2004-10-24 12:31:41 +04:00
2006-03-18 13:38:38 +03:00
DLIST_ADD ( pvfs - > files . list , f ) ;
2004-10-24 12:31:41 +04:00
2004-11-08 06:54:12 +03:00
/* 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 ) ;
2004-10-24 12:31:41 +04:00
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)
2004-10-20 12:28:31 +04:00
if ( ! name - > exists ) {
2004-10-25 09:27:49 +04:00
uint32_t attrib = io - > generic . in . file_attr | FILE_ATTRIBUTE_DIRECTORY ;
mode_t mode = pvfs_fileperms ( pvfs , attrib ) ;
2006-02-28 06:47:02 +03:00
2004-10-25 09:27:49 +04:00
if ( mkdir ( name - > full_name , mode ) = = - 1 ) {
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)
2004-10-20 12:28:31 +04:00
return pvfs_map_errno ( pvfs , errno ) ;
}
2004-12-17 09:35:11 +03:00
pvfs_xattr_unlink_hook ( pvfs , name - > full_name ) ;
2004-11-15 09:57:26 +03:00
status = pvfs_resolve_name ( pvfs , req , io - > ntcreatex . in . fname , 0 , & name ) ;
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)
2004-10-20 12:28:31 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-12-30 05:25:20 +03:00
goto cleanup_delete ;
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)
2004-10-20 12:28:31 +04:00
}
2004-12-30 05:25:20 +03:00
2006-05-20 12:15:22 +04:00
status = pvfs_open_setup_eas_acl ( pvfs , req , name , - 1 , f , io ) ;
2004-12-30 05:25:20 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto cleanup_delete ;
}
2006-02-28 06:47:02 +03:00
/* 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 ) ) {
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 ! */
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2008-03-07 19:50:17 +03:00
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 ;
}
2008-03-07 20:28:48 +03:00
status = odb_open_file ( lck , f - > handle , name - > full_name ,
2008-04-15 18:00:42 +04:00
NULL , name - > dos . write_time ,
false , OPLOCK_NONE , NULL ) ;
2006-02-28 06:47:02 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto cleanup_delete ;
}
2007-10-07 02:28:14 +04:00
f - > handle - > have_opendb_entry = true ;
2006-02-28 06:47:02 +03:00
2004-10-23 10:22:57 +04:00
create_action = NTCREATEX_ACTION_CREATED ;
2006-03-30 07:51:49 +04:00
notify_trigger ( pvfs - > notify_context ,
2006-04-06 05:56:04 +04:00
NOTIFY_ACTION_ADDED ,
FILE_NOTIFY_CHANGE_DIR_NAME ,
2006-03-30 07:51:49 +04:00
name - > full_name ) ;
2004-10-23 10:22:57 +04:00
} else {
create_action = NTCREATEX_ACTION_EXISTED ;
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)
2004-10-20 12:28:31 +04:00
}
if ( ! name - > exists ) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
/* the open succeeded, keep this handle permanently */
2006-05-20 12:15:22 +04:00
status = ntvfs_handle_set_backend_data ( h , pvfs - > ntvfs , f ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto cleanup_delete ;
}
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)
2004-10-20 12:28:31 +04:00
2007-10-07 02:28:14 +04:00
f - > handle - > open_completed = true ;
2007-05-20 12:01:02 +04:00
2004-11-24 09:09:14 +03:00
io - > generic . out . oplock_level = OPLOCK_NONE ;
2006-05-20 12:15:22 +04:00
io - > generic . out . file . ntvfs = h ;
2004-10-23 10:22:57 +04:00
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 ;
2004-10-25 11:03:15 +04:00
io - > generic . out . alloc_size = name - > dos . alloc_size ;
io - > generic . out . size = name - > st . st_size ;
2004-10-23 10:22:57 +04:00
io - > generic . out . file_type = FILE_TYPE_DISK ;
io - > generic . out . ipc_state = 0 ;
io - > generic . out . is_directory = 1 ;
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)
2004-10-20 12:28:31 +04:00
return NT_STATUS_OK ;
2004-12-30 05:25:20 +03:00
cleanup_delete :
rmdir ( name - > full_name ) ;
return status ;
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)
2004-10-20 12:28:31 +04:00
}
2004-09-25 08:45:52 +04:00
/*
2004-11-08 06:54:12 +03:00
destroy a struct pvfs_file_handle
2004-09-25 08:45:52 +04:00
*/
2006-05-24 11:34:11 +04:00
static int pvfs_handle_destructor ( struct pvfs_file_handle * h )
2004-09-25 08:45:52 +04:00
{
2008-06-03 13:54:21 +04:00
talloc_free ( h - > write_time . update_event ) ;
h - > write_time . update_event = NULL ;
2004-11-17 09:44:50 +03:00
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 ) ) ;
}
}
2004-11-08 06:54:12 +03:00
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 ;
2004-09-25 08:45:52 +04:00
}
2004-10-19 10:39:51 +04:00
2008-06-03 13:54:21 +04:00
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 ) ;
}
2004-11-08 06:54:12 +03:00
if ( h - > have_opendb_entry ) {
struct odb_lock * lck ;
NTSTATUS status ;
2008-02-27 23:52:52 +03:00
const char * delete_path = NULL ;
2004-10-24 12:31:41 +04:00
2004-11-17 08:58:04 +03:00
lck = odb_lock ( h , h - > pvfs - > odb_context , & h - > odb_locking_key ) ;
2004-11-08 06:54:12 +03:00
if ( lck = = NULL ) {
DEBUG ( 0 , ( " Unable to lock opendb for close \n " ) ) ;
return 0 ;
}
2008-06-03 13:54:21 +04:00
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 ) ) ) ;
}
}
2008-02-27 23:52:52 +03:00
status = odb_close_file ( lck , h , & delete_path ) ;
2004-11-03 13:09:48 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 0 , ( " Unable to remove opendb entry for '%s' - %s \n " ,
2004-11-08 06:54:12 +03:00
h - > name - > full_name , nt_errstr ( status ) ) ) ;
2004-11-03 13:09:48 +03:00
}
2004-11-08 06:54:12 +03:00
2008-02-27 23:52:52 +03:00
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 ) ;
}
2008-06-03 13:54:21 +04:00
h - > write_time . update_on_close = false ;
2008-02-27 23:52:52 +03:00
}
2004-11-08 06:54:12 +03:00
talloc_free ( lck ) ;
2004-10-24 12:31:41 +04:00
}
2008-06-03 13:54:21 +04:00
if ( h - > write_time . update_on_close ) {
2008-06-03 15:32:04 +04:00
struct timeval tv [ 2 ] ;
2008-06-03 13:54:21 +04:00
2008-06-03 15:32:04 +04:00
nttime_to_timeval ( & tv [ 0 ] , h - > name - > dos . access_time ) ;
nttime_to_timeval ( & tv [ 1 ] , h - > write_time . close_time ) ;
2008-06-03 13:54:21 +04:00
2008-06-03 15:32:04 +04:00
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 " ,
2008-06-03 13:54:21 +04:00
h - > name - > full_name , strerror ( errno ) ) ) ;
}
}
}
2004-11-08 06:54:12 +03:00
return 0 ;
}
/*
destroy a struct pvfs_file
*/
2006-05-24 11:34:11 +04:00
static int pvfs_fnum_destructor ( struct pvfs_file * f )
2004-11-08 06:54:12 +03:00
{
2006-03-18 13:38:38 +03:00
DLIST_REMOVE ( f - > pvfs - > files . list , f ) ;
2004-11-08 06:54:12 +03:00
pvfs_lock_close ( f - > pvfs , f ) ;
2006-05-20 12:15:22 +04:00
ntvfs_handle_remove_backend_data ( f - > ntvfs , f - > pvfs - > ntvfs ) ;
2004-10-24 16:39:15 +04:00
2004-09-25 08:45:52 +04:00
return 0 ;
}
2004-10-22 11:01:32 +04:00
2004-11-17 08:58:04 +03:00
/*
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 )
*/
2006-05-15 16:22:00 +04:00
static NTSTATUS pvfs_brl_locking_handle ( TALLOC_CTX * mem_ctx ,
2006-05-20 12:15:22 +04:00
struct pvfs_filename * name ,
struct ntvfs_handle * ntvfs ,
2006-05-15 16:22:00 +04:00
struct brl_handle * * _h )
2004-11-17 08:58:04 +03:00
{
2006-05-15 16:22:00 +04:00
DATA_BLOB odb_key , key ;
2004-11-17 08:58:04 +03:00
NTSTATUS status ;
2006-05-15 16:22:00 +04:00
struct brl_handle * h ;
2004-11-17 08:58:04 +03:00
status = pvfs_locking_key ( name , mem_ctx , & odb_key ) ;
2006-05-15 16:22:00 +04:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
2004-11-17 08:58:04 +03:00
if ( name - > stream_name = = NULL ) {
2006-05-15 16:22:00 +04:00
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 ) ;
2004-11-17 08:58:04 +03:00
}
2006-05-15 16:22:00 +04:00
2006-05-20 12:15:22 +04:00
h = brl_create_handle ( mem_ctx , ntvfs , & key ) ;
2006-05-15 16:22:00 +04:00
NT_STATUS_HAVE_NO_MEMORY ( h ) ;
* _h = h ;
2004-11-17 08:58:04 +03:00
return NT_STATUS_OK ;
}
2004-10-22 11:01:32 +04:00
/*
create a new file
*/
static NTSTATUS pvfs_create_file ( struct pvfs_state * pvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req ,
2004-10-22 11:01:32 +04:00
struct pvfs_filename * name ,
union smb_open * io )
{
struct pvfs_file * f ;
NTSTATUS status ;
2006-05-20 12:15:22 +04:00
struct ntvfs_handle * h ;
int flags , fd ;
2004-10-22 11:01:32 +04:00
struct odb_lock * lck ;
2004-10-24 12:31:41 +04:00
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 ;
2004-10-24 16:53:13 +04:00
mode_t mode ;
2004-11-05 14:49:37 +03:00
uint32_t attrib ;
2007-10-07 02:28:14 +04:00
bool del_on_close ;
2006-02-28 06:47:02 +03:00
struct pvfs_filename * parent ;
2006-04-12 08:42:40 +04:00
uint32_t oplock_level = OPLOCK_NONE , oplock_granted ;
2008-03-06 17:48:31 +03:00
bool allow_level_II_oplock = false ;
2004-10-24 16:53:13 +04:00
2008-05-22 11:53:50 +04:00
if ( io - > ntcreatex . in . file_attr & ~ FILE_ATTRIBUTE_ALL_MASK ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2008-05-27 08:30:42 +04:00
if ( io - > ntcreatex . in . file_attr & FILE_ATTRIBUTE_ENCRYPTED ) {
return NT_STATUS_ACCESS_DENIED ;
}
2008-05-22 11:53:50 +04:00
2004-10-24 16:53:13 +04:00
if ( ( io - > ntcreatex . in . file_attr & FILE_ATTRIBUTE_READONLY ) & &
( create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE ) ) {
return NT_STATUS_CANNOT_DELETE ;
}
2008-05-26 09:02:43 +04:00
2005-01-07 05:14:34 +03:00
status = pvfs_access_check_create ( pvfs , req , name , & access_mask ) ;
2006-02-28 06:47:02 +03:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
2008-05-29 13:16:26 +04:00
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 ) ;
}
2006-02-28 06:47:02 +03:00
/* 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 ) ;
2008-04-15 18:00:42 +04:00
status = odb_get_file_infos ( pvfs - > odb_context , & locking_key ,
& del_on_close , NULL ) ;
2006-02-28 06:47:02 +03:00
NT_STATUS_NOT_OK_RETURN ( status ) ;
if ( del_on_close ) {
return NT_STATUS_DELETE_PENDING ;
}
2004-10-25 06:36:12 +04:00
}
2004-11-30 07:33:27 +03:00
if ( access_mask & ( SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA ) ) {
2004-10-25 09:27:49 +04:00
flags = O_RDWR ;
2004-10-29 13:28:35 +04:00
} else {
flags = O_RDONLY ;
2004-10-25 09:27:49 +04:00
}
2004-10-22 11:01:32 +04:00
2006-05-20 12:15:22 +04:00
status = ntvfs_handle_new ( pvfs - > ntvfs , req , & h ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
2004-10-22 11:01:32 +04:00
2006-05-20 12:15:22 +04:00
f = talloc ( h , struct pvfs_file ) ;
NT_STATUS_HAVE_NO_MEMORY ( f ) ;
2004-11-08 06:54:12 +03:00
2006-05-20 12:15:22 +04:00
f - > handle = talloc ( f , struct pvfs_file_handle ) ;
NT_STATUS_HAVE_NO_MEMORY ( f - > handle ) ;
2004-10-22 11:01:32 +04:00
2004-11-05 14:49:37 +03:00
attrib = io - > ntcreatex . in . file_attr | FILE_ATTRIBUTE_ARCHIVE ;
mode = pvfs_fileperms ( pvfs , attrib ) ;
2004-10-24 16:53:13 +04:00
2004-10-22 11:01:32 +04:00
/* create the file */
2008-03-10 14:48:02 +03:00
fd = open ( name - > full_name , flags | O_CREAT | O_EXCL | O_NONBLOCK , mode ) ;
2004-10-22 11:01:32 +04:00
if ( fd = = - 1 ) {
return pvfs_map_errno ( pvfs , errno ) ;
}
2004-12-17 09:35:11 +03:00
pvfs_xattr_unlink_hook ( pvfs , name - > full_name ) ;
2004-11-17 08:58:04 +03:00
/* 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 ) ) {
close ( fd ) ;
return status ;
}
}
2004-10-22 11:01:32 +04:00
/* re-resolve the open fd */
2008-05-05 14:18:47 +04:00
status = pvfs_resolve_name_fd ( pvfs , fd , name , 0 ) ;
2004-10-22 11:01:32 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-10-24 12:31:41 +04:00
close ( fd ) ;
2004-10-22 11:01:32 +04:00
return status ;
}
2008-05-28 10:28:37 +04:00
/* support initial alloc sizes */
name - > dos . alloc_size = io - > ntcreatex . in . alloc_size ;
2004-11-05 14:49:37 +03:00
name - > dos . attrib = attrib ;
2004-11-05 14:31:35 +03:00
status = pvfs_dosattrib_save ( pvfs , name , fd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-12-30 05:25:20 +03:00
goto cleanup_delete ;
2004-11-05 10:29:02 +03:00
}
2004-11-17 15:36:14 +03:00
2006-05-20 12:15:22 +04:00
status = pvfs_open_setup_eas_acl ( pvfs , req , name , fd , f , io ) ;
2004-12-30 05:25:20 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto cleanup_delete ;
2004-11-18 06:59:24 +03:00
}
2004-10-22 11:01:32 +04:00
/* form the lock context used for byte range locking and
opendb locking */
2004-11-17 08:58:04 +03:00
status = pvfs_locking_key ( name , f - > handle , & f - > handle - > odb_locking_key ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-12-30 05:25:20 +03:00
goto cleanup_delete ;
2004-11-17 08:58:04 +03:00
}
2006-05-20 12:15:22 +04:00
status = pvfs_brl_locking_handle ( f , name , h , & f - > brl_handle ) ;
2004-10-22 11:01:32 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-12-30 05:25:20 +03:00
goto cleanup_delete ;
2004-10-22 11:01:32 +04:00
}
/* grab a lock on the open file record */
2004-11-17 08:58:04 +03:00
lck = odb_lock ( req , pvfs - > odb_context , & f - > handle - > odb_locking_key ) ;
2004-10-22 11:01:32 +04:00
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 ! */
2004-12-30 05:25:20 +03:00
status = NT_STATUS_INTERNAL_DB_CORRUPTION ;
goto cleanup_delete ;
2004-10-22 11:01:32 +04:00
}
2006-02-28 06:47:02 +03:00
if ( create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE ) {
2007-10-07 02:28:14 +04:00
del_on_close = true ;
2006-02-28 06:47:02 +03:00
} else {
2007-10-07 02:28:14 +04:00
del_on_close = false ;
2006-02-28 06:47:02 +03:00
}
2006-04-12 08:42:40 +04:00
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 ;
}
2008-03-06 17:48:31 +03:00
if ( req - > client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS ) {
allow_level_II_oplock = true ;
}
2008-03-07 19:50:17 +03:00
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 ;
}
2006-05-20 12:15:22 +04:00
f - > ntvfs = h ;
2004-11-08 14:35:49 +03:00
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 ;
2006-03-21 14:47:24 +03:00
f - > notify_buffer = NULL ;
2006-07-08 16:35:37 +04:00
f - > search = NULL ;
2004-11-08 06:54:12 +03:00
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 - > seek_offset = 0 ;
f - > handle - > position = 0 ;
f - > handle - > mode = 0 ;
2008-02-25 10:39:13 +03:00
f - > handle - > oplock = NULL ;
2007-10-07 02:28:14 +04:00
f - > handle - > have_opendb_entry = true ;
2008-04-15 18:00:42 +04:00
ZERO_STRUCT ( f - > handle - > write_time ) ;
2007-10-07 02:28:14 +04:00
f - > handle - > open_completed = false ;
2004-10-22 11:01:32 +04:00
2008-03-08 11:20:08 +03:00
status = odb_open_file ( lck , f - > handle , name - > full_name ,
2008-04-15 18:00:42 +04:00
& f - > handle - > fd , name - > dos . write_time ,
allow_level_II_oplock ,
2008-03-08 11:20:08 +03:00
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 ;
}
2006-03-18 13:38:38 +03:00
DLIST_ADD ( pvfs - > files . list , f ) ;
2004-10-22 11:01:32 +04:00
2008-03-06 17:34:37 +03:00
/* 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 ) ;
2008-02-25 10:39:13 +03:00
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 ) ) {
return status ;
}
}
2006-04-12 08:42:40 +04:00
io - > generic . out . oplock_level = oplock_granted ;
2006-05-20 12:15:22 +04:00
io - > generic . out . file . ntvfs = f - > ntvfs ;
2004-10-22 11:01:32 +04:00
io - > generic . out . create_action = NTCREATEX_ACTION_CREATED ;
2004-10-23 10:22:57 +04:00
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 ;
2004-10-22 11:01:32 +04:00
/* success - keep the file handle */
2006-05-20 12:15:22 +04:00
status = ntvfs_handle_set_backend_data ( h , pvfs - > ntvfs , f ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
goto cleanup_delete ;
}
2006-03-30 06:06:06 +04:00
2007-10-07 02:28:14 +04:00
f - > handle - > open_completed = true ;
2007-05-20 12:01:02 +04:00
2006-03-30 07:51:49 +04:00
notify_trigger ( pvfs - > notify_context ,
NOTIFY_ACTION_ADDED ,
FILE_NOTIFY_CHANGE_FILE_NAME ,
name - > full_name ) ;
2004-10-22 11:01:32 +04:00
return NT_STATUS_OK ;
2004-12-30 05:25:20 +03:00
cleanup_delete :
close ( fd ) ;
unlink ( name - > full_name ) ;
return status ;
2004-10-22 11:01:32 +04:00
}
2004-11-03 13:09:48 +03:00
/*
2008-02-21 19:48:13 +03:00
state of a pending retry
2004-11-03 13:09:48 +03:00
*/
2008-02-21 19:48:13 +03:00
struct pvfs_odb_retry {
2004-11-05 04:14:06 +03:00
struct ntvfs_module_context * ntvfs ;
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req ;
2004-11-17 08:58:04 +03:00
DATA_BLOB odb_locking_key ;
2008-02-21 19:48:13 +03:00
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 ) ;
2004-11-03 13:09:48 +03:00
} ;
2008-02-21 19:48:13 +03:00
/* destroy a pending request */
static int pvfs_odb_retry_destructor ( struct pvfs_odb_retry * r )
2004-11-03 13:09:48 +03:00
{
2004-11-05 04:14:06 +03:00
struct pvfs_state * pvfs = r - > ntvfs - > private_data ;
2004-11-17 08:58:04 +03:00
if ( r - > odb_locking_key . data ) {
2004-11-05 04:14:06 +03:00
struct odb_lock * lck ;
2004-11-17 08:58:04 +03:00
lck = odb_lock ( r - > req , pvfs - > odb_context , & r - > odb_locking_key ) ;
2004-11-05 04:14:06 +03:00
if ( lck ! = NULL ) {
odb_remove_pending ( lck , r ) ;
}
2004-11-07 13:05:35 +03:00
talloc_free ( lck ) ;
2004-11-03 13:09:48 +03:00
}
return 0 ;
}
2008-02-21 19:48:13 +03:00
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 ) ;
}
2004-11-03 13:09:48 +03:00
/*
2008-02-21 19:48:13 +03:00
setup for a retry of a request that was rejected
2008-03-07 19:50:17 +03:00
by odb_can_open ( )
2004-11-03 13:09:48 +03:00
*/
2008-02-21 19:48:13 +03:00
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 ) )
2004-11-03 13:09:48 +03:00
{
2008-02-21 19:48:13 +03:00
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 ) ;
2008-03-12 16:02:11 +03:00
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 ) ) {
2008-02-21 19:48:13 +03:00
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 ) ;
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 ) ;
2008-03-12 16:02:11 +03:00
struct timeval * final_timeout = NULL ;
2004-11-03 13:09:48 +03:00
NTSTATUS status ;
2008-03-12 16:02:11 +03:00
if ( private_data ) {
final_timeout = talloc_get_type ( private_data ,
struct timeval ) ;
}
2004-11-05 05:22:07 +03:00
/* 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 ;
}
if ( reason = = PVFS_WAIT_TIMEOUT ) {
2008-03-12 16:02:11 +03:00
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 ;
}
2004-11-05 04:14:06 +03:00
/* if it timed out, then give the failure
immediately */
talloc_free ( r ) ;
req - > async_states - > status = NT_STATUS_SHARING_VIOLATION ;
2004-11-03 13:09:48 +03:00
req - > async_states - > send_fn ( req ) ;
return ;
}
2008-03-12 16:02:11 +03:00
retry :
2004-11-05 04:14:06 +03:00
talloc_free ( r ) ;
2004-11-03 13:09:48 +03:00
2004-11-05 04:14:06 +03:00
/* 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 ;
2004-11-03 13:09:48 +03:00
2004-11-05 04:14:06 +03:00
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 ;
2004-11-03 13:09:48 +03:00
}
2004-11-05 10:29:02 +03:00
/* re-mark it async, just in case someone up the chain does
paranoid checking */
req - > async_states - > state | = NTVFS_ASYNC_STATE_ASYNC ;
2004-11-05 04:14:06 +03:00
/* send the reply up the chain */
2004-11-03 13:09:48 +03:00
req - > async_states - > status = status ;
req - > async_states - > send_fn ( req ) ;
}
2004-11-05 04:14:06 +03:00
2004-11-08 14:35:49 +03:00
/*
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 ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_open * io ,
2004-11-08 14:35:49 +03:00
struct pvfs_file * f , struct odb_lock * lck )
{
struct pvfs_state * pvfs = ntvfs - > private_data ;
struct pvfs_file * f2 ;
struct pvfs_filename * name ;
2006-05-20 12:15:22 +04:00
NTSTATUS status ;
2004-11-08 14:35:49 +03:00
/* 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 .
*/
2006-03-18 13:38:38 +03:00
for ( f2 = pvfs - > files . list ; f2 ; f2 = f2 - > next ) {
2004-11-08 14:35:49 +03:00
if ( f2 ! = f & &
2006-08-01 14:58:01 +04:00
f2 - > ntvfs - > session_info = = req - > session_info & &
f2 - > ntvfs - > smbpid = = req - > smbpid & &
2004-11-08 14:35:49 +03:00
( f2 - > handle - > create_options &
( NTCREATEX_OPTIONS_PRIVATE_DENY_DOS |
NTCREATEX_OPTIONS_PRIVATE_DENY_FCB ) ) & &
2004-11-30 07:33:27 +03:00
( f2 - > access_mask & SEC_FILE_WRITE_DATA ) & &
2005-08-30 15:55:05 +04:00
strcasecmp_m ( f2 - > handle - > name - > original_name ,
2004-11-08 14:35:49 +03:00
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 ;
2004-11-24 09:09:14 +03:00
io - > generic . out . oplock_level = OPLOCK_NONE ;
2006-05-20 12:15:22 +04:00
io - > generic . out . file . ntvfs = f - > ntvfs ;
2004-11-08 14:35:49 +03:00
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 ;
2006-05-20 12:15:22 +04:00
status = ntvfs_handle_set_backend_data ( f - > ntvfs , ntvfs , f ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
2004-11-08 14:35:49 +03:00
return NT_STATUS_OK ;
}
2004-11-03 13:09:48 +03:00
/*
setup for a open retry after a sharing violation
*/
2004-11-05 04:14:06 +03:00
static NTSTATUS pvfs_open_setup_retry ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req ,
2004-11-03 13:09:48 +03:00
union smb_open * io ,
2004-11-05 04:14:06 +03:00
struct pvfs_file * f ,
2008-02-22 13:52:17 +03:00
struct odb_lock * lck ,
NTSTATUS parent_status )
2004-11-03 13:09:48 +03:00
{
2004-11-05 04:14:06 +03:00
struct pvfs_state * pvfs = ntvfs - > private_data ;
2004-11-03 13:09:48 +03:00
NTSTATUS status ;
2004-11-05 04:14:06 +03:00
struct timeval end_time ;
2008-03-12 16:02:11 +03:00
struct timeval * final_timeout = NULL ;
2004-11-03 13:09:48 +03:00
2004-11-08 14:35:49 +03:00
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 ;
}
}
2008-02-21 19:48:13 +03:00
/* the retry should allocate a new file handle */
2004-11-05 04:14:06 +03:00
talloc_free ( f ) ;
2008-02-22 13:52:17 +03:00
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 ) ;
2008-03-12 16:02:11 +03:00
} 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 ) ;
2008-02-22 13:52:17 +03:00
} else {
return NT_STATUS_INTERNAL_ERROR ;
}
2004-11-09 05:12:57 +03:00
2008-03-12 16:02:11 +03:00
return pvfs_odb_retry_setup ( ntvfs , req , lck , end_time , io ,
final_timeout , pvfs_retry_open_sharing ) ;
2004-11-03 13:09:48 +03:00
}
2004-09-20 11:28:43 +04:00
/*
open a file
*/
2004-09-29 17:17:09 +04:00
NTSTATUS pvfs_open ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_open * io )
2004-09-20 11:28:43 +04:00
{
2004-09-29 17:17:09 +04:00
struct pvfs_state * pvfs = ntvfs - > private_data ;
2008-07-18 12:40:19 +04:00
int flags = 0 ;
2004-09-20 11:28:43 +04:00
struct pvfs_filename * name ;
struct pvfs_file * f ;
2006-05-20 12:15:22 +04:00
struct ntvfs_handle * h ;
2004-09-20 11:28:43 +04:00
NTSTATUS status ;
2006-05-20 12:15:22 +04:00
int fd ;
2004-10-22 11:01:32 +04:00
struct odb_lock * lck ;
2004-10-24 12:31:41 +04:00
uint32_t create_options ;
uint32_t share_access ;
uint32_t access_mask ;
2008-05-28 16:44:20 +04:00
uint32_t create_action = NTCREATEX_ACTION_EXISTED ;
2007-10-07 02:28:14 +04:00
bool del_on_close ;
bool stream_existed , stream_truncate = false ;
2006-04-12 08:42:40 +04:00
uint32_t oplock_level = OPLOCK_NONE , oplock_granted ;
2008-03-06 17:48:31 +03:00
bool allow_level_II_oplock = false ;
2004-09-20 11:28:43 +04:00
2004-10-22 11:01:32 +04:00
/* use the generic mapping code to avoid implementing all the
2004-11-08 14:35:49 +03:00
different open calls . */
2004-11-17 15:36:14 +03:00
if ( io - > generic . level ! = RAW_OPEN_GENERIC & &
io - > generic . level ! = RAW_OPEN_NTTRANS_CREATE ) {
2006-03-10 17:31:17 +03:00
return ntvfs_map_open ( ntvfs , req , io ) ;
2004-09-20 11:28:43 +04:00
}
2008-05-29 13:16:26 +04:00
ZERO_STRUCT ( io - > generic . out ) ;
2008-05-26 09:02:43 +04:00
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 ;
}
2008-07-18 12:40:19 +04:00
/* These options are ignored */
create_options & = ~ NTCREATEX_OPTIONS_MUST_IGNORE_MASK ;
2008-05-26 09:02:43 +04:00
if ( create_options & NTCREATEX_OPTIONS_NOT_SUPPORTED_MASK ) {
return NT_STATUS_NOT_SUPPORTED ;
}
2008-07-16 08:00:18 +04:00
/* 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 */
}
2008-07-18 12:40:19 +04:00
/* TODO: If (unlikely) Linux does a good compressed
* filesystem , we might need an ioctl call for this */
if ( create_options & NTCREATEX_OPTIONS_NO_COMPRESSION ) {
2008-07-16 08:00:18 +04:00
/* no-op */
}
2008-07-18 12:40:19 +04:00
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 ;
}
2008-05-26 09:02:43 +04:00
/* other create options are not allowed */
if ( ( create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE ) & &
! ( access_mask & SEC_STD_DELETE ) ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2008-05-27 08:30:42 +04:00
if ( access_mask & SEC_MASK_INVALID ) {
return NT_STATUS_ACCESS_DENIED ;
}
2008-05-27 08:59:55 +04:00
/* what does this bit really mean?? */
2008-05-27 08:30:42 +04:00
if ( req - > ctx - > protocol = = PROTOCOL_SMB2 & &
2008-05-27 10:02:27 +04:00
access_mask = = SEC_STD_SYNCHRONIZE ) {
2008-05-27 08:07:11 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
if ( io - > ntcreatex . in . file_attr & ( FILE_ATTRIBUTE_DEVICE |
2008-05-27 08:59:55 +04:00
FILE_ATTRIBUTE_VOLUME |
( ~ FILE_ATTRIBUTE_ALL_MASK ) ) ) {
2008-05-27 08:07:11 +04:00
return NT_STATUS_INVALID_PARAMETER ;
}
2008-05-28 16:44:20 +04:00
/* 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 ) ;
2004-09-20 11:28:43 +04:00
/* resolve the cifs name to a posix name */
2004-11-15 09:57:26 +03:00
status = pvfs_resolve_name ( pvfs , req , io - > ntcreatex . in . fname ,
PVFS_RESOLVE_STREAMS , & name ) ;
2004-09-20 11:28:43 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2008-05-20 05:58:47 +04:00
/* 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 ;
}
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)
2004-10-20 12:28:31 +04:00
/* 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 ) ;
}
2004-12-30 05:25:20 +03:00
/* FILE_ATTRIBUTE_DIRECTORY is ignored if the above test for directory
open doesn ' t match */
io - > generic . in . file_attr & = ~ FILE_ATTRIBUTE_DIRECTORY ;
2004-09-20 11:28:43 +04:00
switch ( io - > generic . in . open_disposition ) {
case NTCREATEX_DISP_SUPERSEDE :
case NTCREATEX_DISP_OVERWRITE_IF :
2005-05-02 19:59:34 +04:00
if ( name - > stream_name = = NULL ) {
flags = O_TRUNC ;
} else {
2007-10-07 02:28:14 +04:00
stream_truncate = true ;
2005-05-02 19:59:34 +04:00
}
2008-05-28 16:44:20 +04:00
create_action = NTCREATEX_ACTION_TRUNCATED ;
2004-09-20 11:28:43 +04:00
break ;
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)
2004-10-20 12:28:31 +04:00
2004-09-20 11:28:43 +04:00
case NTCREATEX_DISP_OPEN :
2004-11-17 08:58:04 +03:00
if ( ! name - > stream_exists ) {
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)
2004-10-20 12:28:31 +04:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
2004-09-20 11:28:43 +04:00
flags = 0 ;
break ;
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)
2004-10-20 12:28:31 +04:00
2004-10-18 11:40:17 +04:00
case NTCREATEX_DISP_OVERWRITE :
2004-11-17 08:58:04 +03:00
if ( ! name - > stream_exists ) {
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)
2004-10-20 12:28:31 +04:00
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
2005-05-02 19:59:34 +04:00
if ( name - > stream_name = = NULL ) {
flags = O_TRUNC ;
} else {
2007-10-07 02:28:14 +04:00
stream_truncate = true ;
2005-05-02 19:59:34 +04:00
}
2008-05-28 16:44:20 +04:00
create_action = NTCREATEX_ACTION_TRUNCATED ;
2004-10-18 11:40:17 +04:00
break ;
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)
2004-10-20 12:28:31 +04:00
2004-09-20 11:28:43 +04:00
case NTCREATEX_DISP_CREATE :
2004-11-17 08:58:04 +03:00
if ( name - > stream_exists ) {
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)
2004-10-20 12:28:31 +04:00
return NT_STATUS_OBJECT_NAME_COLLISION ;
}
2004-10-22 11:01:32 +04:00
flags = 0 ;
2004-09-20 11:28:43 +04:00
break ;
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)
2004-10-20 12:28:31 +04:00
2004-09-20 11:28:43 +04:00
case NTCREATEX_DISP_OPEN_IF :
2004-10-22 11:01:32 +04:00
flags = 0 ;
2004-09-20 11:28:43 +04:00
break ;
2004-09-20 12:53:45 +04:00
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)
2004-10-20 12:28:31 +04:00
default :
return NT_STATUS_INVALID_PARAMETER ;
2004-10-11 18:35:54 +04:00
}
2004-10-22 11:01:32 +04:00
/* 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 */
2004-11-15 09:57:26 +03:00
status = pvfs_resolve_name ( pvfs , req , io - > ntcreatex . in . fname , 0 , & name ) ;
2004-10-22 11:01:32 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
/* fall through to a normal open */
}
2004-10-24 16:53:13 +04:00
if ( ( name - > dos . attrib & FILE_ATTRIBUTE_READONLY ) & &
( create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE ) ) {
return NT_STATUS_CANNOT_DELETE ;
}
2004-12-01 14:35:01 +03:00
/* check the security descriptor */
status = pvfs_access_check ( pvfs , req , name , & access_mask ) ;
2008-05-29 13:16:26 +04:00
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 ) ;
2004-12-01 14:35:01 +03:00
}
2006-05-20 12:15:22 +04:00
status = ntvfs_handle_new ( pvfs - > ntvfs , req , & h ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
f = talloc ( h , struct pvfs_file ) ;
2004-10-19 10:39:51 +04:00
if ( f = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2005-01-27 10:08:20 +03:00
f - > handle = talloc ( f , struct pvfs_file_handle ) ;
2004-11-08 06:54:12 +03:00
if ( f - > handle = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2006-05-20 12:15:22 +04:00
f - > ntvfs = h ;
2004-11-08 14:35:49 +03:00
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 ;
2006-03-21 14:47:24 +03:00
f - > notify_buffer = NULL ;
2006-07-08 16:35:37 +04:00
f - > search = NULL ;
2004-11-08 06:54:12 +03:00
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 ;
2004-11-24 09:09:14 +03:00
f - > handle - > mode = 0 ;
2008-02-25 10:39:13 +03:00
f - > handle - > oplock = NULL ;
2007-10-07 02:28:14 +04:00
f - > handle - > have_opendb_entry = false ;
2008-04-15 18:00:42 +04:00
ZERO_STRUCT ( f - > handle - > write_time ) ;
2007-10-07 02:28:14 +04:00
f - > handle - > open_completed = false ;
2004-11-03 13:09:48 +03:00
2004-10-22 11:01:32 +04:00
/* form the lock context used for byte range locking and
opendb locking */
2004-11-17 08:58:04 +03:00
status = pvfs_locking_key ( name , f - > handle , & f - > handle - > odb_locking_key ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2006-05-20 12:15:22 +04:00
status = pvfs_brl_locking_handle ( f , name , h , & f - > brl_handle ) ;
2004-10-22 11:01:32 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2004-10-19 10:39:51 +04:00
}
2004-10-22 11:01:32 +04:00
/* get a lock on this file before the actual open */
2004-11-17 08:58:04 +03:00
lck = odb_lock ( req , pvfs - > odb_context , & f - > handle - > odb_locking_key ) ;
2004-10-22 11:01:32 +04:00
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 ;
}
2006-03-18 13:38:38 +03:00
DLIST_ADD ( pvfs - > files . list , f ) ;
2004-09-20 11:28:43 +04:00
2004-09-25 08:45:52 +04:00
/* setup a destructor to avoid file descriptor leaks on
abnormal termination */
2004-11-08 06:54:12 +03:00
talloc_set_destructor ( f , pvfs_fnum_destructor ) ;
talloc_set_destructor ( f - > handle , pvfs_handle_destructor ) ;
2004-09-25 08:45:52 +04:00
2006-07-13 17:51:54 +04:00
/*
* 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 ) {
2007-10-07 02:28:14 +04:00
del_on_close = true ;
2006-07-13 17:51:54 +04:00
} else {
2007-10-07 02:28:14 +04:00
del_on_close = false ;
2006-07-13 17:51:54 +04:00
}
2006-04-12 08:42:40 +04:00
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 ;
}
2008-03-06 17:48:31 +03:00
if ( req - > client_caps & NTVFS_CLIENT_CAP_LEVEL_II_OPLOCKS ) {
allow_level_II_oplock = true ;
}
2004-11-03 13:09:48 +03:00
/* see if we are allowed to open at the same time as existing opens */
2008-03-07 19:50:17 +03:00
status = odb_can_open ( lck , name - > stream_id ,
share_access , access_mask , del_on_close ,
io - > generic . in . open_disposition , false ) ;
2004-11-03 13:09:48 +03:00
2008-02-22 13:52:17 +03:00
/*
* 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 ) ) & &
2004-11-03 13:09:48 +03:00
( req - > async_states - > state & NTVFS_ASYNC_STATE_MAY_ASYNC ) ) {
2008-02-22 13:52:17 +03:00
return pvfs_open_setup_retry ( ntvfs , req , io , f , lck , status ) ;
2004-11-03 13:09:48 +03:00
}
2004-10-24 16:39:15 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-11-07 13:05:35 +03:00
talloc_free ( lck ) ;
2004-10-24 16:39:15 +04:00
return status ;
}
2008-03-08 11:20:08 +03:00
if ( access_mask & ( SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA ) ) {
flags | = O_RDWR ;
} else {
flags | = O_RDONLY ;
}
/* do the actual open */
2008-03-10 14:48:02 +03:00
fd = open ( f - > handle - > name - > full_name , flags | O_NONBLOCK ) ;
2008-03-08 11:20:08 +03:00
if ( fd = = - 1 ) {
2008-03-12 16:02:11 +03:00
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 ) ;
}
2008-03-08 11:20:08 +03:00
talloc_free ( lck ) ;
2008-03-12 16:02:11 +03:00
return status ;
2008-03-08 11:20:08 +03:00
}
f - > handle - > fd = fd ;
2008-03-07 19:50:17 +03:00
/* now really mark the file as open */
2008-03-07 20:28:48 +03:00
status = odb_open_file ( lck , f - > handle , name - > full_name ,
2008-04-15 18:00:42 +04:00
& f - > handle - > fd , name - > dos . write_time ,
allow_level_II_oplock ,
2008-03-07 19:50:17 +03:00
oplock_level , & oplock_granted ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( lck ) ;
return status ;
}
2008-03-15 14:36:20 +03:00
f - > handle - > have_opendb_entry = true ;
2006-04-12 08:42:40 +04:00
if ( pvfs - > flags & PVFS_FLAG_FAKE_OPLOCKS ) {
oplock_granted = OPLOCK_BATCH ;
2008-02-25 10:39:13 +03:00
} else if ( oplock_granted ! = OPLOCK_NONE ) {
status = pvfs_setup_oplock ( f , oplock_granted ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( lck ) ;
return status ;
}
2006-04-12 08:42:40 +04:00
}
2004-11-17 08:58:04 +03:00
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 ;
}
2005-05-02 19:59:34 +04:00
if ( stream_truncate ) {
status = pvfs_stream_truncate ( pvfs , f - > handle - > name , fd , 0 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( lck ) ;
return status ;
}
}
2004-11-17 08:58:04 +03:00
}
2004-11-05 04:14:06 +03:00
/* re-resolve the open fd */
2008-05-05 14:18:47 +04:00
status = pvfs_resolve_name_fd ( f - > pvfs , fd , f - > handle - > name , PVFS_RESOLVE_NO_OPENDB ) ;
2004-11-05 04:14:06 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-11-07 13:05:35 +03:00
talloc_free ( lck ) ;
2004-11-05 04:14:06 +03:00
return status ;
}
2004-11-17 08:58:04 +03:00
if ( f - > handle - > name - > stream_id = = 0 & &
( io - > generic . in . open_disposition = = NTCREATEX_DISP_OVERWRITE | |
io - > generic . in . open_disposition = = NTCREATEX_DISP_OVERWRITE_IF ) ) {
2004-11-06 15:35:31 +03:00
/* 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 ) {
2004-11-07 13:05:35 +03:00
talloc_free ( lck ) ;
2004-11-13 08:47:27 +03:00
return pvfs_map_errno ( pvfs , errno ) ;
2004-11-06 15:35:31 +03:00
}
2008-05-28 10:28:37 +04:00
name - > dos . alloc_size = io - > ntcreatex . in . alloc_size ;
2004-11-06 15:35:31 +03:00
name - > dos . attrib = attrib ;
status = pvfs_dosattrib_save ( pvfs , name , fd ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-11-07 13:05:35 +03:00
talloc_free ( lck ) ;
2004-11-06 15:35:31 +03:00
return status ;
}
}
2004-11-07 13:05:35 +03:00
talloc_free ( lck ) ;
2004-11-06 15:35:31 +03:00
2006-05-20 12:15:22 +04:00
status = ntvfs_handle_set_backend_data ( h , ntvfs , f ) ;
NT_STATUS_NOT_OK_RETURN ( status ) ;
2007-05-20 12:01:02 +04:00
/* mark the open as having completed fully, so delete on close
can now be used */
2007-10-07 02:28:14 +04:00
f - > handle - > open_completed = true ;
2007-05-20 12:01:02 +04:00
2006-04-12 08:42:40 +04:00
io - > generic . out . oplock_level = oplock_granted ;
2006-05-20 12:15:22 +04:00
io - > generic . out . file . ntvfs = h ;
2004-11-17 08:58:04 +03:00
io - > generic . out . create_action = stream_existed ?
2008-05-28 16:44:20 +04:00
create_action : NTCREATEX_ACTION_CREATED ;
2004-11-08 06:54:12 +03:00
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 ;
2004-11-05 04:14:06 +03:00
io - > generic . out . file_type = FILE_TYPE_DISK ;
io - > generic . out . ipc_state = 0 ;
io - > generic . out . is_directory = 0 ;
return NT_STATUS_OK ;
2004-09-20 11:28:43 +04:00
}
/*
close a file
*/
2004-09-29 17:17:09 +04:00
NTSTATUS pvfs_close ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_close * io )
2004-09-20 11:28:43 +04:00
{
2004-09-29 17:17:09 +04:00
struct pvfs_state * pvfs = ntvfs - > private_data ;
2004-09-20 11:28:43 +04:00
struct pvfs_file * f ;
2004-10-26 11:11:49 +04:00
if ( io - > generic . level = = RAW_CLOSE_SPLCLOSE ) {
2005-07-04 09:24:39 +04:00
return NT_STATUS_DOS ( ERRSRV , ERRerror ) ;
2004-10-26 11:11:49 +04:00
}
2008-05-27 10:43:36 +04:00
if ( io - > generic . level ! = RAW_CLOSE_GENERIC ) {
2006-03-10 17:31:17 +03:00
return ntvfs_map_close ( ntvfs , req , io ) ;
2004-09-20 11:28:43 +04:00
}
2008-05-27 10:43:36 +04:00
f = pvfs_find_fd ( pvfs , req , io - > generic . in . file . ntvfs ) ;
2004-09-20 11:28:43 +04:00
if ( ! f ) {
return NT_STATUS_INVALID_HANDLE ;
}
2008-05-27 10:43:36 +04:00
if ( ! null_time ( io - > generic . in . write_time ) ) {
2008-05-09 00:16:55 +04:00
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 ) ;
2004-10-26 09:39:54 +04:00
}
2004-11-24 09:09:14 +03:00
2008-05-27 10:43:36 +04:00
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 ) ;
}
2004-09-20 11:28:43 +04:00
talloc_free ( f ) ;
2004-11-08 06:54:12 +03:00
return NT_STATUS_OK ;
2004-09-20 11:28:43 +04:00
}
2004-09-26 15:30:20 +04:00
/*
logoff - close all file descriptors open by a vuid
*/
2004-09-29 17:17:09 +04:00
NTSTATUS pvfs_logoff ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req )
2004-09-26 15:30:20 +04:00
{
2004-09-29 17:17:09 +04:00
struct pvfs_state * pvfs = ntvfs - > private_data ;
2004-09-26 15:30:20 +04:00
struct pvfs_file * f , * next ;
2006-03-18 13:38:38 +03:00
for ( f = pvfs - > files . list ; f ; f = next ) {
2004-09-26 15:30:20 +04:00
next = f - > next ;
2006-08-01 14:58:01 +04:00
if ( f - > ntvfs - > session_info = = req - > session_info ) {
2004-09-26 15:30:20 +04:00
talloc_free ( f ) ;
}
}
return NT_STATUS_OK ;
}
/*
exit - close files for the current pid
*/
2004-09-29 17:17:09 +04:00
NTSTATUS pvfs_exit ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req )
2004-09-26 15:30:20 +04:00
{
2004-09-29 17:17:09 +04:00
struct pvfs_state * pvfs = ntvfs - > private_data ;
2004-09-26 15:30:20 +04:00
struct pvfs_file * f , * next ;
2006-03-18 13:38:38 +03:00
for ( f = pvfs - > files . list ; f ; f = next ) {
2004-09-26 15:30:20 +04:00
next = f - > next ;
2006-08-01 14:58:01 +04:00
if ( f - > ntvfs - > session_info = = req - > session_info & &
f - > ntvfs - > smbpid = = req - > smbpid ) {
2004-09-26 15:30:20 +04:00
talloc_free ( f ) ;
}
}
return NT_STATUS_OK ;
}
2004-10-24 16:39:15 +04:00
/*
2006-02-28 06:47:02 +03:00
change the delete on close flag on an already open file
2004-10-24 16:39:15 +04:00
*/
2006-02-28 06:47:02 +03:00
NTSTATUS pvfs_set_delete_on_close ( struct pvfs_state * pvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req ,
2007-10-07 02:28:14 +04:00
struct pvfs_file * f , bool del_on_close )
2004-10-24 16:39:15 +04:00
{
struct odb_lock * lck ;
NTSTATUS status ;
2006-02-28 06:47:02 +03:00
if ( ( f - > handle - > name - > dos . attrib & FILE_ATTRIBUTE_READONLY ) & & del_on_close ) {
2004-10-24 16:53:13 +04:00
return NT_STATUS_CANNOT_DELETE ;
}
2006-02-28 06:47:02 +03:00
if ( ( f - > handle - > name - > dos . attrib & FILE_ATTRIBUTE_DIRECTORY ) & &
! pvfs_directory_empty ( pvfs , f - > handle - > name ) ) {
return NT_STATUS_DIRECTORY_NOT_EMPTY ;
2005-07-01 16:59:23 +04:00
}
2006-02-28 06:47:02 +03:00
if ( del_on_close ) {
f - > handle - > create_options | = NTCREATEX_OPTIONS_DELETE_ON_CLOSE ;
} else {
f - > handle - > create_options & = ~ NTCREATEX_OPTIONS_DELETE_ON_CLOSE ;
}
2004-11-17 08:58:04 +03:00
lck = odb_lock ( req , pvfs - > odb_context , & f - > handle - > odb_locking_key ) ;
2004-10-24 16:39:15 +04:00
if ( lck = = NULL ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2006-02-28 06:47:02 +03:00
status = odb_set_delete_on_close ( lck , del_on_close ) ;
2004-10-24 16:39:15 +04:00
2005-07-09 15:06:33 +04:00
talloc_free ( lck ) ;
2004-10-24 16:39:15 +04:00
return status ;
}
2004-10-25 05:29:31 +04:00
/*
2004-10-25 08:24:58 +04:00
determine if a file can be deleted , or if it is prevented by an
already open file
2004-10-25 05:29:31 +04:00
*/
2004-12-21 14:44:32 +03:00
NTSTATUS pvfs_can_delete ( struct pvfs_state * pvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req ,
2006-02-28 06:47:02 +03:00
struct pvfs_filename * name ,
struct odb_lock * * lckp )
2004-10-25 05:29:31 +04:00
{
NTSTATUS status ;
DATA_BLOB key ;
2006-02-28 06:47:02 +03:00
struct odb_lock * lck ;
2008-02-25 19:50:22 +03:00
uint32_t share_access ;
uint32_t access_mask ;
bool delete_on_close ;
2004-10-25 05:29:31 +04:00
status = pvfs_locking_key ( name , name , & key ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-10-25 08:24:58 +04:00
return NT_STATUS_NO_MEMORY ;
2004-10-25 05:29:31 +04:00
}
2006-02-28 06:47:02 +03:00
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 ;
}
2008-02-25 19:50:22 +03:00
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 ,
2008-02-26 12:21:39 +03:00
NTCREATEX_DISP_OPEN , false ) ;
2004-11-06 12:12:53 +03:00
2004-12-21 14:44:32 +03:00
if ( NT_STATUS_IS_OK ( status ) ) {
2008-02-25 19:50:22 +03:00
status = pvfs_access_check_simple ( pvfs , req , name , access_mask ) ;
2004-12-21 14:44:32 +03:00
}
2008-02-21 22:01:25 +03:00
/*
* 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 ) ) {
2006-02-28 06:47:02 +03:00
talloc_free ( lck ) ;
2008-02-21 21:56:36 +03:00
if ( lckp ) {
* lckp = NULL ;
}
} else if ( lckp ) {
2006-02-28 06:47:02 +03:00
* lckp = lck ;
}
2004-11-06 12:12:53 +03:00
return status ;
}
/*
determine if a file can be renamed , or if it is prevented by an
already open file
*/
2006-02-28 06:47:02 +03:00
NTSTATUS pvfs_can_rename ( struct pvfs_state * pvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req ,
2006-02-28 06:47:02 +03:00
struct pvfs_filename * name ,
struct odb_lock * * lckp )
2004-11-06 12:12:53 +03:00
{
NTSTATUS status ;
DATA_BLOB key ;
2006-02-28 06:47:02 +03:00
struct odb_lock * lck ;
2008-02-25 19:50:22 +03:00
uint32_t share_access ;
uint32_t access_mask ;
bool delete_on_close ;
2004-11-06 12:12:53 +03:00
status = pvfs_locking_key ( name , name , & key ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return NT_STATUS_NO_MEMORY ;
}
2006-02-28 06:47:02 +03:00
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 ;
}
2008-02-25 19:50:22 +03:00
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 ,
2008-02-26 12:21:39 +03:00
NTCREATEX_DISP_OPEN , false ) ;
2004-10-25 08:24:58 +04:00
2008-02-21 22:01:25 +03:00
/*
* 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 ) ) {
2006-02-28 06:47:02 +03:00
talloc_free ( lck ) ;
2008-02-21 21:56:36 +03:00
if ( lckp ) {
* lckp = NULL ;
}
} else if ( lckp ) {
2006-02-28 06:47:02 +03:00
* lckp = lck ;
}
2004-10-25 08:24:58 +04:00
return status ;
2004-10-25 05:29:31 +04:00
}
2006-02-28 06:47:02 +03:00
2008-02-23 13:49:39 +03:00
/*
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 ;
}
2008-02-26 12:26:33 +03:00
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 ;
2008-02-23 13:49:39 +03:00
delete_on_close = false ;
break_to_none = true ;
status = odb_can_open ( lck , name - > stream_id ,
share_access , access_mask , delete_on_close ,
2008-02-26 12:21:39 +03:00
NTCREATEX_DISP_OPEN , break_to_none ) ;
2008-02-23 13:49:39 +03:00
/*
* 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 ;
}
2006-02-28 06:47:02 +03:00
/*
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 ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req ,
2006-02-28 06:47:02 +03:00
struct pvfs_filename * name )
{
NTSTATUS status ;
DATA_BLOB key ;
struct odb_lock * lck ;
2008-02-25 19:50:22 +03:00
uint32_t share_access ;
uint32_t access_mask ;
bool delete_on_close ;
2006-02-28 06:47:02 +03:00
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 ;
}
2008-02-25 19:50:22 +03:00
share_access = NTCREATEX_SHARE_ACCESS_READ |
NTCREATEX_SHARE_ACCESS_WRITE ;
2008-02-26 12:28:07 +03:00
access_mask = SEC_FILE_READ_ATTRIBUTE ;
2008-02-25 19:50:22 +03:00
delete_on_close = false ;
status = odb_can_open ( lck , name - > stream_id ,
share_access , access_mask , delete_on_close ,
2008-02-26 12:21:39 +03:00
NTCREATEX_DISP_OPEN , false ) ;
2006-02-28 06:47:02 +03:00
2008-02-21 21:56:36 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( lck ) ;
}
2006-02-28 06:47:02 +03:00
return status ;
}
/*
determine if delete on close is set on
*/
2008-02-28 00:22:10 +03:00
bool pvfs_delete_on_close_set ( struct pvfs_state * pvfs , struct pvfs_file_handle * h )
2006-02-28 06:47:02 +03:00
{
NTSTATUS status ;
2007-10-07 02:28:14 +04:00
bool del_on_close ;
2006-02-28 06:47:02 +03:00
2008-04-15 18:00:42 +04:00
status = odb_get_file_infos ( pvfs - > odb_context , & h - > odb_locking_key ,
& del_on_close , NULL ) ;
2006-02-28 06:47:02 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
DEBUG ( 1 , ( " WARNING: unable to determine delete on close status for open file \n " ) ) ;
2007-10-07 02:28:14 +04:00
return false ;
2006-02-28 06:47:02 +03:00
}
return del_on_close ;
}