2004-09-20 07:28:43 +00: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
2007-07-10 02:07:03 +00:00
the Free Software Foundation ; either version 3 of the License , or
2004-09-20 07:28:43 +00: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 02:07:03 +00:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2004-09-20 07:28:43 +00:00
*/
2004-11-05 07:24:25 +00:00
# include "includes.h"
2005-06-23 22:30:26 +00:00
# include "system/dir.h"
2004-09-20 07:28:43 +00:00
# include "vfs_posix.h"
2006-03-16 00:23:11 +00:00
# include "librpc/gen_ndr/security.h"
2004-09-20 07:28:43 +00:00
2004-12-13 23:57:59 +00:00
/*
create a directory with EAs
*/
static NTSTATUS pvfs_t2mkdir ( struct pvfs_state * pvfs ,
2006-03-10 14:31:17 +00:00
struct ntvfs_request * req , union smb_mkdir * md )
2004-12-13 23:57:59 +00: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 08:27:35 +00:00
status = pvfs_access_check_parent ( pvfs , req , name , SEC_DIR_ADD_FILE ) ;
2004-12-30 05:50:23 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-12-13 23:57:59 +00:00
mode = pvfs_fileperms ( pvfs , FILE_ATTRIBUTE_DIRECTORY ) ;
if ( mkdir ( name - > full_name , mode ) = = - 1 ) {
return pvfs_map_errno ( pvfs , errno ) ;
}
2004-12-17 05:03:57 +00:00
pvfs_xattr_unlink_hook ( pvfs , name - > full_name ) ;
2004-12-13 23:57:59 +00: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 02:38:44 +00: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-13 23:57:59 +00:00
/* setup any EAs that were asked for */
2004-12-17 04:51:23 +00: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-13 23:57:59 +00:00
}
2006-03-30 03:51:49 +00:00
notify_trigger ( pvfs - > notify_context ,
NOTIFY_ACTION_ADDED ,
2006-04-06 01:56:04 +00:00
FILE_NOTIFY_CHANGE_DIR_NAME ,
2006-03-30 03:51:49 +00:00
name - > full_name ) ;
2006-03-29 13:31:30 +00:00
2004-12-13 23:57:59 +00:00
return NT_STATUS_OK ;
}
2004-09-20 07:28:43 +00:00
/*
create a directory
*/
2004-09-29 13:17:09 +00:00
NTSTATUS pvfs_mkdir ( struct ntvfs_module_context * ntvfs ,
2006-03-10 14:31:17 +00:00
struct ntvfs_request * req , union smb_mkdir * md )
2004-09-20 07:28:43 +00:00
{
2009-02-04 08:52:41 +01:00
struct pvfs_state * pvfs = talloc_get_type ( ntvfs - > private_data ,
struct pvfs_state ) ;
2004-09-20 07:28:43 +00:00
NTSTATUS status ;
struct pvfs_filename * name ;
2004-10-29 21:51:36 +00:00
mode_t mode ;
2004-09-20 07:28:43 +00:00
2004-12-13 23:57:59 +00:00
if ( md - > generic . level = = RAW_MKDIR_T2MKDIR ) {
return pvfs_t2mkdir ( pvfs , req , md ) ;
}
2004-09-20 07:28:43 +00:00
if ( md - > generic . level ! = RAW_MKDIR_MKDIR ) {
return NT_STATUS_INVALID_LEVEL ;
}
/* resolve the cifs name to a posix name */
2004-11-15 06:57:26 +00:00
status = pvfs_resolve_name ( pvfs , req , md - > mkdir . in . path , 0 , & name ) ;
2004-09-20 07:28:43 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( name - > exists ) {
return NT_STATUS_OBJECT_NAME_COLLISION ;
}
2005-01-09 08:27:35 +00:00
status = pvfs_access_check_parent ( pvfs , req , name , SEC_DIR_ADD_FILE ) ;
2004-12-30 05:50:23 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-10-29 21:51:36 +00:00
mode = pvfs_fileperms ( pvfs , FILE_ATTRIBUTE_DIRECTORY ) ;
2004-09-20 07:28:43 +00:00
2004-10-29 21:51:36 +00:00
if ( mkdir ( name - > full_name , mode ) = = - 1 ) {
2004-09-20 07:28:43 +00:00
return pvfs_map_errno ( pvfs , errno ) ;
}
2004-12-17 05:03:57 +00:00
pvfs_xattr_unlink_hook ( pvfs , name - > full_name ) ;
2004-12-30 02:38:44 +00: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 03:51:49 +00:00
notify_trigger ( pvfs - > notify_context ,
NOTIFY_ACTION_ADDED ,
2006-04-06 01:56:04 +00:00
FILE_NOTIFY_CHANGE_DIR_NAME ,
2006-03-30 03:51:49 +00:00
name - > full_name ) ;
2006-03-29 13:31:30 +00:00
2004-09-20 07:28:43 +00:00
return NT_STATUS_OK ;
}
/*
remove a directory
*/
2004-09-29 13:17:09 +00:00
NTSTATUS pvfs_rmdir ( struct ntvfs_module_context * ntvfs ,
2006-03-10 14:31:17 +00:00
struct ntvfs_request * req , struct smb_rmdir * rd )
2004-09-20 07:28:43 +00:00
{
2009-02-04 08:52:41 +01:00
struct pvfs_state * pvfs = talloc_get_type ( ntvfs - > private_data ,
struct pvfs_state ) ;
2004-09-20 07:28:43 +00:00
NTSTATUS status ;
struct pvfs_filename * name ;
/* resolve the cifs name to a posix name */
2004-11-15 06:57:26 +00:00
status = pvfs_resolve_name ( pvfs , req , rd - > in . path , 0 , & name ) ;
2004-09-20 07:28:43 +00:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
if ( ! name - > exists ) {
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
}
2004-12-30 05:50:23 +00:00
status = pvfs_access_check_simple ( pvfs , req , name , SEC_STD_DELETE ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-12-17 04:51:23 +00:00
status = pvfs_xattr_unlink_hook ( pvfs , name - > full_name ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-09-20 07:28:43 +00:00
if ( rmdir ( name - > full_name ) = = - 1 ) {
2006-08-21 06:06:02 +00:00
/* some olders systems don't return ENOTEMPTY to rmdir() */
if ( errno = = EEXIST ) {
return NT_STATUS_DIRECTORY_NOT_EMPTY ;
}
2004-09-20 07:28:43 +00:00
return pvfs_map_errno ( pvfs , errno ) ;
}
2006-03-30 03:51:49 +00:00
notify_trigger ( pvfs - > notify_context ,
NOTIFY_ACTION_REMOVED ,
2006-04-06 01:56:04 +00:00
FILE_NOTIFY_CHANGE_DIR_NAME ,
2006-03-30 03:51:49 +00:00
name - > full_name ) ;
2006-03-29 13:31:30 +00:00
2004-09-20 07:28:43 +00:00
return NT_STATUS_OK ;
}