2 Unix SMB/CIFS implementation.
4 POSIX NTVFS backend - mkdir and rmdir
6 Copyright (C) Andrew Tridgell 2004
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "system/dir.h"
24 #include "vfs_posix.h"
25 #include "librpc/gen_ndr/security.h"
28 create a directory with EAs
30 static NTSTATUS
pvfs_t2mkdir(struct pvfs_state
*pvfs
,
31 struct ntvfs_request
*req
, union smb_mkdir
*md
)
34 struct pvfs_filename
*name
;
37 /* resolve the cifs name to a posix name */
38 status
= pvfs_resolve_name(pvfs
, req
, md
->t2mkdir
.in
.path
, 0, &name
);
39 if (!NT_STATUS_IS_OK(status
)) {
44 return NT_STATUS_OBJECT_NAME_COLLISION
;
47 status
= pvfs_access_check_parent(pvfs
, req
, name
, SEC_DIR_ADD_FILE
);
48 if (!NT_STATUS_IS_OK(status
)) {
52 mode
= pvfs_fileperms(pvfs
, FILE_ATTRIBUTE_DIRECTORY
);
54 if (pvfs_sys_mkdir(pvfs
, name
->full_name
, mode
, name
->allow_override
) == -1) {
55 return pvfs_map_errno(pvfs
, errno
);
58 pvfs_xattr_unlink_hook(pvfs
, name
->full_name
);
60 status
= pvfs_resolve_name(pvfs
, req
, md
->t2mkdir
.in
.path
, 0, &name
);
61 if (!NT_STATUS_IS_OK(status
)) {
65 !(name
->dos
.attrib
& FILE_ATTRIBUTE_DIRECTORY
)) {
66 return NT_STATUS_INTERNAL_ERROR
;
69 /* setup an inherited acl from the parent */
70 status
= pvfs_acl_inherit(pvfs
, req
, name
, -1);
71 if (!NT_STATUS_IS_OK(status
)) {
72 pvfs_sys_rmdir(pvfs
, name
->full_name
, name
->allow_override
);
76 /* setup any EAs that were asked for */
77 status
= pvfs_setfileinfo_ea_set(pvfs
, name
, -1,
78 md
->t2mkdir
.in
.num_eas
,
80 if (!NT_STATUS_IS_OK(status
)) {
81 pvfs_sys_rmdir(pvfs
, name
->full_name
, name
->allow_override
);
85 notify_trigger(pvfs
->notify_context
,
87 FILE_NOTIFY_CHANGE_DIR_NAME
,
96 NTSTATUS
pvfs_mkdir(struct ntvfs_module_context
*ntvfs
,
97 struct ntvfs_request
*req
, union smb_mkdir
*md
)
99 struct pvfs_state
*pvfs
= talloc_get_type(ntvfs
->private_data
,
102 struct pvfs_filename
*name
;
105 if (md
->generic
.level
== RAW_MKDIR_T2MKDIR
) {
106 return pvfs_t2mkdir(pvfs
, req
, md
);
109 if (md
->generic
.level
!= RAW_MKDIR_MKDIR
) {
110 return NT_STATUS_INVALID_LEVEL
;
113 /* resolve the cifs name to a posix name */
114 status
= pvfs_resolve_name(pvfs
, req
, md
->mkdir
.in
.path
, 0, &name
);
115 if (!NT_STATUS_IS_OK(status
)) {
120 return NT_STATUS_OBJECT_NAME_COLLISION
;
123 status
= pvfs_access_check_parent(pvfs
, req
, name
, SEC_DIR_ADD_FILE
);
124 if (!NT_STATUS_IS_OK(status
)) {
128 mode
= pvfs_fileperms(pvfs
, FILE_ATTRIBUTE_DIRECTORY
);
130 if (pvfs_sys_mkdir(pvfs
, name
->full_name
, mode
, name
->allow_override
) == -1) {
131 return pvfs_map_errno(pvfs
, errno
);
134 pvfs_xattr_unlink_hook(pvfs
, name
->full_name
);
136 /* setup an inherited acl from the parent */
137 status
= pvfs_acl_inherit(pvfs
, req
, name
, -1);
138 if (!NT_STATUS_IS_OK(status
)) {
139 pvfs_sys_rmdir(pvfs
, name
->full_name
, name
->allow_override
);
143 notify_trigger(pvfs
->notify_context
,
145 FILE_NOTIFY_CHANGE_DIR_NAME
,
154 NTSTATUS
pvfs_rmdir(struct ntvfs_module_context
*ntvfs
,
155 struct ntvfs_request
*req
, struct smb_rmdir
*rd
)
157 struct pvfs_state
*pvfs
= talloc_get_type(ntvfs
->private_data
,
160 struct pvfs_filename
*name
;
162 /* resolve the cifs name to a posix name */
163 status
= pvfs_resolve_name(pvfs
, req
, rd
->in
.path
, 0, &name
);
164 if (!NT_STATUS_IS_OK(status
)) {
169 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
172 status
= pvfs_access_check_simple(pvfs
, req
, name
, SEC_STD_DELETE
);
173 if (!NT_STATUS_IS_OK(status
)) {
177 status
= pvfs_xattr_unlink_hook(pvfs
, name
->full_name
);
178 if (!NT_STATUS_IS_OK(status
)) {
182 if (pvfs_sys_rmdir(pvfs
, name
->full_name
, name
->allow_override
) == -1) {
183 /* some olders systems don't return ENOTEMPTY to rmdir() */
184 if (errno
== EEXIST
) {
185 return NT_STATUS_DIRECTORY_NOT_EMPTY
;
187 return pvfs_map_errno(pvfs
, errno
);
190 notify_trigger(pvfs
->notify_context
,
191 NOTIFY_ACTION_REMOVED
,
192 FILE_NOTIFY_CHANGE_DIR_NAME
,