2004-09-20 11:28:43 +04:00
/*
Unix SMB / CIFS implementation .
POSIX NTVFS backend - mkdir and rmdir
Copyright ( C ) Andrew Tridgell 2004
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
2004-11-05 10:24:25 +03:00
# include "includes.h"
2005-06-24 02:30:26 +04:00
# include "system/dir.h"
2004-09-20 11:28:43 +04:00
# include "vfs_posix.h"
2006-03-16 03:23:11 +03:00
# include "librpc/gen_ndr/security.h"
2004-09-20 11:28:43 +04:00
2004-12-14 02:57:59 +03:00
/*
create a directory with EAs
*/
static NTSTATUS pvfs_t2mkdir ( struct pvfs_state * pvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_mkdir * md )
2004-12-14 02:57:59 +03:00
{
NTSTATUS status ;
struct pvfs_filename * name ;
mode_t mode ;
/* resolve the cifs name to a posix name */
status = pvfs_resolve_name ( pvfs , req , md - > t2mkdir . in . path , 0 , & name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( name - > exists ) {
return NT_STATUS_OBJECT_NAME_COLLISION ;
}
2005-01-09 11:27:35 +03:00
status = pvfs_access_check_parent ( pvfs , req , name , SEC_DIR_ADD_FILE ) ;
2004-12-30 08:50:23 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-12-14 02:57:59 +03:00
mode = pvfs_fileperms ( pvfs , FILE_ATTRIBUTE_DIRECTORY ) ;
if ( mkdir ( name - > full_name , mode ) = = - 1 ) {
return pvfs_map_errno ( pvfs , errno ) ;
}
2004-12-17 08:03:57 +03:00
pvfs_xattr_unlink_hook ( pvfs , name - > full_name ) ;
2004-12-14 02:57:59 +03:00
status = pvfs_resolve_name ( pvfs , req , md - > t2mkdir . in . path , 0 , & name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( ! name - > exists | |
! ( name - > dos . attrib & FILE_ATTRIBUTE_DIRECTORY ) ) {
return NT_STATUS_INTERNAL_ERROR ;
}
2004-12-30 05:38:44 +03:00
/* setup an inherited acl from the parent */
status = pvfs_acl_inherit ( pvfs , req , name , - 1 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
rmdir ( name - > full_name ) ;
return status ;
}
2004-12-14 02:57:59 +03:00
/* setup any EAs that were asked for */
2004-12-17 07:51:23 +03:00
status = pvfs_setfileinfo_ea_set ( pvfs , name , - 1 ,
md - > t2mkdir . in . num_eas ,
md - > t2mkdir . in . eas ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
rmdir ( name - > full_name ) ;
return status ;
2004-12-14 02:57:59 +03:00
}
2006-03-30 07:51:49 +04:00
notify_trigger ( pvfs - > notify_context ,
NOTIFY_ACTION_ADDED ,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME ,
name - > full_name ) ;
2006-03-29 17:31:30 +04:00
2004-12-14 02:57:59 +03:00
return NT_STATUS_OK ;
}
2004-09-20 11:28:43 +04:00
/*
create a directory
*/
2004-09-29 17:17:09 +04:00
NTSTATUS pvfs_mkdir ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , union smb_mkdir * md )
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
NTSTATUS status ;
struct pvfs_filename * name ;
2004-10-30 01:51:36 +04:00
mode_t mode ;
2004-09-20 11:28:43 +04:00
2004-12-14 02:57:59 +03:00
if ( md - > generic . level = = RAW_MKDIR_T2MKDIR ) {
return pvfs_t2mkdir ( pvfs , req , md ) ;
}
2004-09-20 11:28:43 +04:00
if ( md - > generic . level ! = RAW_MKDIR_MKDIR ) {
return NT_STATUS_INVALID_LEVEL ;
}
/* resolve the cifs name to a posix name */
2004-11-15 09:57:26 +03:00
status = pvfs_resolve_name ( pvfs , req , md - > mkdir . in . path , 0 , & name ) ;
2004-09-20 11:28:43 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( name - > exists ) {
return NT_STATUS_OBJECT_NAME_COLLISION ;
}
2005-01-09 11:27:35 +03:00
status = pvfs_access_check_parent ( pvfs , req , name , SEC_DIR_ADD_FILE ) ;
2004-12-30 08:50:23 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-10-30 01:51:36 +04:00
mode = pvfs_fileperms ( pvfs , FILE_ATTRIBUTE_DIRECTORY ) ;
2004-09-20 11:28:43 +04:00
2004-10-30 01:51:36 +04:00
if ( mkdir ( name - > full_name , mode ) = = - 1 ) {
2004-09-20 11:28:43 +04:00
return pvfs_map_errno ( pvfs , errno ) ;
}
2004-12-17 08:03:57 +03:00
pvfs_xattr_unlink_hook ( pvfs , name - > full_name ) ;
2004-12-30 05:38:44 +03:00
/* setup an inherited acl from the parent */
status = pvfs_acl_inherit ( pvfs , req , name , - 1 ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
rmdir ( name - > full_name ) ;
return status ;
}
2006-03-30 07:51:49 +04:00
notify_trigger ( pvfs - > notify_context ,
NOTIFY_ACTION_ADDED ,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME ,
name - > full_name ) ;
2006-03-29 17:31:30 +04:00
2004-09-20 11:28:43 +04:00
return NT_STATUS_OK ;
}
/*
remove a directory
*/
2004-09-29 17:17:09 +04:00
NTSTATUS pvfs_rmdir ( struct ntvfs_module_context * ntvfs ,
2006-03-10 17:31:17 +03:00
struct ntvfs_request * req , struct smb_rmdir * rd )
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
NTSTATUS status ;
struct pvfs_filename * name ;
/* resolve the cifs name to a posix name */
2004-11-15 09:57:26 +03:00
status = pvfs_resolve_name ( pvfs , req , rd - > in . path , 0 , & name ) ;
2004-09-20 11:28:43 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( ! name - > exists ) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
2004-12-30 08:50:23 +03:00
status = pvfs_access_check_simple ( pvfs , req , name , SEC_STD_DELETE ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-12-17 07:51:23 +03:00
status = pvfs_xattr_unlink_hook ( pvfs , name - > full_name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-09-20 11:28:43 +04:00
if ( rmdir ( name - > full_name ) = = - 1 ) {
return pvfs_map_errno ( pvfs , errno ) ;
}
2006-03-30 07:51:49 +04:00
notify_trigger ( pvfs - > notify_context ,
NOTIFY_ACTION_REMOVED ,
FILE_NOTIFY_CHANGE_FILE_NAME | FILE_NOTIFY_CHANGE_DIR_NAME ,
name - > full_name ) ;
2006-03-29 17:31:30 +04:00
2004-09-20 11:28:43 +04:00
return NT_STATUS_OK ;
}