/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- smb2_util_close
- smb2_util_unlink
- smb2_util_rmdir
- smb2_util_mkdir
- smb2_util_setatr
- smb2_deltree
1 /*
2 Unix SMB/CIFS implementation.
3
4 SMB2 client utility functions
5
6 Copyright (C) Andrew Tridgell 2005
7
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.
12
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.
17
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/>.
20 */
21
22 #include "includes.h"
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
29 /*
30 simple close wrapper with SMB2
31 */
32 NTSTATUS smb2_util_close(struct smb2_tree *tree, struct smb2_handle h)
/* [<][>][^][v][top][bottom][index][help] */
33 {
34 struct smb2_close c;
35
36 ZERO_STRUCT(c);
37 c.in.file.handle = h;
38
39 return smb2_close(tree, &c);
40 }
41
42 /*
43 unlink a file with SMB2
44 */
45 NTSTATUS smb2_util_unlink(struct smb2_tree *tree, const char *fname)
/* [<][>][^][v][top][bottom][index][help] */
46 {
47 union smb_unlink io;
48
49 ZERO_STRUCT(io);
50 io.unlink.in.pattern = fname;
51
52 return smb2_composite_unlink(tree, &io);
53 }
54
55
56 /*
57 rmdir with SMB2
58 */
59 NTSTATUS smb2_util_rmdir(struct smb2_tree *tree, const char *dname)
/* [<][>][^][v][top][bottom][index][help] */
60 {
61 struct smb_rmdir io;
62
63 ZERO_STRUCT(io);
64 io.in.path = dname;
65
66 return smb2_composite_rmdir(tree, &io);
67 }
68
69
70 /*
71 mkdir with SMB2
72 */
73 NTSTATUS smb2_util_mkdir(struct smb2_tree *tree, const char *dname)
/* [<][>][^][v][top][bottom][index][help] */
74 {
75 union smb_mkdir io;
76
77 ZERO_STRUCT(io);
78 io.mkdir.level = RAW_MKDIR_MKDIR;
79 io.mkdir.in.path = dname;
80
81 return smb2_composite_mkdir(tree, &io);
82 }
83
84
85 /*
86 set file attribute with SMB2
87 */
88 NTSTATUS smb2_util_setatr(struct smb2_tree *tree, const char *name, uint32_t attrib)
/* [<][>][^][v][top][bottom][index][help] */
89 {
90 union smb_setfileinfo io;
91
92 ZERO_STRUCT(io);
93 io.basic_info.level = RAW_SFILEINFO_BASIC_INFORMATION;
94 io.basic_info.in.file.path = name;
95 io.basic_info.in.attrib = attrib;
96
97 return smb2_composite_setpathinfo(tree, &io);
98 }
99
100
101
102
103 /*
104 recursively descend a tree deleting all files
105 returns the number of files deleted, or -1 on error
106 */
107 int smb2_deltree(struct smb2_tree *tree, const char *dname)
/* [<][>][^][v][top][bottom][index][help] */
108 {
109 NTSTATUS status;
110 uint32_t total_deleted = 0;
111 uint_t count, i;
112 union smb_search_data *list;
113 TALLOC_CTX *tmp_ctx = talloc_new(tree);
114 struct smb2_find f;
115 struct smb2_create create_parm;
116
117 /* it might be a file */
118 status = smb2_util_unlink(tree, dname);
119 if (NT_STATUS_IS_OK(status)) {
120 talloc_free(tmp_ctx);
121 return 1;
122 }
123 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND) ||
124 NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_PATH_NOT_FOUND) ||
125 NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_FILE)) {
126 talloc_free(tmp_ctx);
127 return 0;
128 }
129
130 if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
131 /* it could be read-only */
132 status = smb2_util_setatr(tree, dname, FILE_ATTRIBUTE_NORMAL);
133 status = smb2_util_unlink(tree, dname);
134 }
135 if (NT_STATUS_IS_OK(status)) {
136 talloc_free(tmp_ctx);
137 return 1;
138 }
139
140 ZERO_STRUCT(create_parm);
141 create_parm.in.desired_access = SEC_FILE_READ_DATA;
142 create_parm.in.share_access =
143 NTCREATEX_SHARE_ACCESS_READ|
144 NTCREATEX_SHARE_ACCESS_WRITE;
145 create_parm.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
146 create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
147 create_parm.in.fname = dname;
148
149 status = smb2_create(tree, tmp_ctx, &create_parm);
150 if (NT_STATUS_IS_ERR(status)) {
151 DEBUG(2,("Failed to open %s - %s\n", dname, nt_errstr(status)));
152 talloc_free(tmp_ctx);
153 return -1;
154 }
155
156
157 ZERO_STRUCT(f);
158 f.in.file.handle = create_parm.out.file.handle;
159 f.in.max_response_size = 0x10000;
160 f.in.level = SMB2_FIND_NAME_INFO;
161 f.in.pattern = "*";
162
163 status = smb2_find_level(tree, tmp_ctx, &f, &count, &list);
164 if (NT_STATUS_IS_ERR(status)) {
165 DEBUG(2,("Failed to list %s - %s\n",
166 dname, nt_errstr(status)));
167 smb2_util_close(tree, create_parm.out.file.handle);
168 talloc_free(tmp_ctx);
169 return -1;
170 }
171
172 for (i=0;i<count;i++) {
173 char *name;
174 if (strcmp(".", list[i].name_info.name.s) == 0 ||
175 strcmp("..", list[i].name_info.name.s) == 0) {
176 continue;
177 }
178 name = talloc_asprintf(tmp_ctx, "%s\\%s", dname, list[i].name_info.name.s);
179 status = smb2_util_unlink(tree, name);
180 if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
181 /* it could be read-only */
182 status = smb2_util_setatr(tree, name, FILE_ATTRIBUTE_NORMAL);
183 status = smb2_util_unlink(tree, name);
184 }
185
186 if (NT_STATUS_EQUAL(status, NT_STATUS_FILE_IS_A_DIRECTORY)) {
187 int ret;
188 ret = smb2_deltree(tree, name);
189 if (ret > 0) total_deleted += ret;
190 }
191 talloc_free(name);
192 if (NT_STATUS_IS_OK(status)) {
193 total_deleted++;
194 }
195 }
196
197 smb2_util_close(tree, create_parm.out.file.handle);
198
199 status = smb2_util_rmdir(tree, dname);
200 if (NT_STATUS_EQUAL(status, NT_STATUS_CANNOT_DELETE)) {
201 /* it could be read-only */
202 status = smb2_util_setatr(tree, dname, FILE_ATTRIBUTE_NORMAL);
203 status = smb2_util_rmdir(tree, dname);
204 }
205
206 if (NT_STATUS_IS_ERR(status)) {
207 DEBUG(2,("Failed to delete %s - %s\n",
208 dname, nt_errstr(status)));
209 talloc_free(tmp_ctx);
210 return -1;
211 }
212
213 talloc_free(tmp_ctx);
214
215 return total_deleted;
216 }