2 Unix SMB/CIFS implementation.
4 SMB2 client utility functions
6 Copyright (C) Andrew Tridgell 2005
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 "libcli/raw/libcliraw.h"
24 #include "libcli/raw/raw_proto.h"
25 #include "libcli/smb2/smb2.h"
26 #include "libcli/smb2/smb2_calls.h"
27 #include "libcli/smb_composite/smb_composite.h"
28 #include "librpc/gen_ndr/ndr_security.h"
31 simple close wrapper with SMB2
33 NTSTATUS
smb2_util_close(struct smb2_tree
*tree
, struct smb2_handle h
)
40 return smb2_close(tree
, &c
);
44 unlink a file with SMB2
46 NTSTATUS
smb2_util_unlink(struct smb2_tree
*tree
, const char *fname
)
51 io
.unlink
.in
.pattern
= fname
;
53 return smb2_composite_unlink(tree
, &io
);
60 NTSTATUS
smb2_util_rmdir(struct smb2_tree
*tree
, const char *dname
)
67 return smb2_composite_rmdir(tree
, &io
);
74 NTSTATUS
smb2_util_mkdir(struct smb2_tree
*tree
, const char *dname
)
79 io
.mkdir
.level
= RAW_MKDIR_MKDIR
;
80 io
.mkdir
.in
.path
= dname
;
82 return smb2_composite_mkdir(tree
, &io
);
87 set file attribute with SMB2
89 NTSTATUS
smb2_util_setatr(struct smb2_tree
*tree
, const char *name
, uint32_t attrib
)
91 union smb_setfileinfo io
;
94 io
.basic_info
.level
= RAW_SFILEINFO_BASIC_INFORMATION
;
95 io
.basic_info
.in
.file
.path
= name
;
96 io
.basic_info
.in
.attrib
= attrib
;
98 return smb2_composite_setpathinfo(tree
, &io
);
105 recursively descend a tree deleting all files
106 returns the number of files deleted, or -1 on error
108 int smb2_deltree(struct smb2_tree
*tree
, const char *dname
)
111 uint32_t total_deleted
= 0;
112 unsigned int count
, i
;
113 union smb_search_data
*list
;
114 TALLOC_CTX
*tmp_ctx
= talloc_new(tree
);
116 struct smb2_create create_parm
;
119 /* it might be a file */
120 status
= smb2_util_unlink(tree
, dname
);
121 if (NT_STATUS_IS_OK(status
)) {
122 talloc_free(tmp_ctx
);
125 if (NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_NAME_NOT_FOUND
) ||
126 NT_STATUS_EQUAL(status
, NT_STATUS_OBJECT_PATH_NOT_FOUND
) ||
127 NT_STATUS_EQUAL(status
, NT_STATUS_NO_SUCH_FILE
)) {
128 talloc_free(tmp_ctx
);
132 if (NT_STATUS_EQUAL(status
, NT_STATUS_CANNOT_DELETE
)) {
133 /* it could be read-only */
134 status
= smb2_util_setatr(tree
, dname
, FILE_ATTRIBUTE_NORMAL
);
135 status
= smb2_util_unlink(tree
, dname
);
137 if (NT_STATUS_IS_OK(status
)) {
138 talloc_free(tmp_ctx
);
142 ZERO_STRUCT(create_parm
);
143 create_parm
.in
.desired_access
= SEC_FILE_READ_DATA
;
144 create_parm
.in
.share_access
=
145 NTCREATEX_SHARE_ACCESS_READ
|
146 NTCREATEX_SHARE_ACCESS_WRITE
;
147 create_parm
.in
.create_options
= NTCREATEX_OPTIONS_DIRECTORY
;
148 create_parm
.in
.create_disposition
= NTCREATEX_DISP_OPEN
;
149 create_parm
.in
.fname
= dname
;
151 status
= smb2_create(tree
, tmp_ctx
, &create_parm
);
152 if (NT_STATUS_IS_ERR(status
)) {
153 DEBUG(2,("Failed to open %s - %s\n", dname
, nt_errstr(status
)));
154 talloc_free(tmp_ctx
);
163 f
.in
.file
.handle
= create_parm
.out
.file
.handle
;
164 f
.in
.max_response_size
= 0x10000;
165 f
.in
.level
= SMB2_FIND_NAME_INFO
;
168 status
= smb2_find_level(tree
, tmp_ctx
, &f
, &count
, &list
);
169 if (NT_STATUS_IS_ERR(status
)) {
170 DEBUG(2,("Failed to list %s - %s\n",
171 dname
, nt_errstr(status
)));
172 smb2_util_close(tree
, create_parm
.out
.file
.handle
);
173 talloc_free(tmp_ctx
);
177 for (i
=0;i
<count
;i
++) {
179 if (strcmp(".", list
[i
].name_info
.name
.s
) == 0 ||
180 strcmp("..", list
[i
].name_info
.name
.s
) == 0) {
183 name
= talloc_asprintf(tmp_ctx
, "%s\\%s", dname
, list
[i
].name_info
.name
.s
);
184 status
= smb2_util_unlink(tree
, name
);
185 if (NT_STATUS_EQUAL(status
, NT_STATUS_CANNOT_DELETE
)) {
186 /* it could be read-only */
187 status
= smb2_util_setatr(tree
, name
, FILE_ATTRIBUTE_NORMAL
);
188 status
= smb2_util_unlink(tree
, name
);
191 if (NT_STATUS_EQUAL(status
, NT_STATUS_FILE_IS_A_DIRECTORY
)) {
193 ret
= smb2_deltree(tree
, name
);
194 if (ret
> 0) total_deleted
+= ret
;
197 if (NT_STATUS_IS_OK(status
)) {
202 } while (did_delete
);
204 smb2_util_close(tree
, create_parm
.out
.file
.handle
);
206 status
= smb2_util_rmdir(tree
, dname
);
207 if (NT_STATUS_EQUAL(status
, NT_STATUS_CANNOT_DELETE
)) {
208 /* it could be read-only */
209 status
= smb2_util_setatr(tree
, dname
, FILE_ATTRIBUTE_NORMAL
);
210 status
= smb2_util_rmdir(tree
, dname
);
213 if (NT_STATUS_IS_ERR(status
)) {
214 DEBUG(2,("Failed to delete %s - %s\n",
215 dname
, nt_errstr(status
)));
216 talloc_free(tmp_ctx
);
220 talloc_free(tmp_ctx
);
222 return total_deleted
;
226 check if two SMB2 file handles are the same
228 bool smb2_util_handle_equal(const struct smb2_handle h1
,
229 const struct smb2_handle h2
)
231 return (h1
.data
[0] == h2
.data
[0]) && (h1
.data
[1] == h2
.data
[1]);
234 bool smb2_util_handle_empty(const struct smb2_handle h
)
236 struct smb2_handle empty
;
240 return smb2_util_handle_equal(h
, empty
);