pthreadpool: Use detached threads
[kai/samba-autobuild/.git] / source3 / lib / filename_util.c
1 /*
2    Unix SMB/CIFS implementation.
3    Filename utility functions.
4    Copyright (C) Tim Prouty 2009
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 */
19 #include "includes.h"
20
21 /**
22  * XXX: This is temporary and there should be no callers of this outside of
23  * this file once smb_filename is plumbed through all path based operations.
24  * The one legitimate caller currently is smb_fname_str_dbg(), which this
25  * could be made static for.
26  */
27 NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx,
28                                const struct smb_filename *smb_fname,
29                                char **full_name)
30 {
31         if (smb_fname->stream_name) {
32                 /* stream_name must always be NULL if there is no stream. */
33                 SMB_ASSERT(smb_fname->stream_name[0] != '\0');
34
35                 *full_name = talloc_asprintf(ctx, "%s%s", smb_fname->base_name,
36                                              smb_fname->stream_name);
37         } else {
38                 *full_name = talloc_strdup(ctx, smb_fname->base_name);
39         }
40
41         if (!*full_name) {
42                 return NT_STATUS_NO_MEMORY;
43         }
44
45         return NT_STATUS_OK;
46 }
47
48 /**
49  * There are actually legitimate callers of this such as functions that
50  * enumerate streams using the vfs_streaminfo interface and then want to
51  * operate on each stream.
52  */
53 struct smb_filename *synthetic_smb_fname(TALLOC_CTX *mem_ctx,
54                                          const char *base_name,
55                                          const char *stream_name,
56                                          const SMB_STRUCT_STAT *psbuf,
57                                          uint32_t flags)
58 {
59         struct smb_filename smb_fname_loc = { 0, };
60
61         /* Setup the base_name/stream_name. */
62         smb_fname_loc.base_name = discard_const_p(char, base_name);
63         smb_fname_loc.stream_name = discard_const_p(char, stream_name);
64         smb_fname_loc.flags = flags;
65
66         /* Copy the psbuf if one was given. */
67         if (psbuf)
68                 smb_fname_loc.st = *psbuf;
69
70         /* Let cp_smb_filename() do the heavy lifting. */
71         return cp_smb_filename(mem_ctx, &smb_fname_loc);
72 }
73
74 /**
75  * There are a few legitimate users of this.
76  */
77 struct smb_filename *synthetic_smb_fname_split(TALLOC_CTX *ctx,
78                                                 const char *fname,
79                                                 bool posix_path)
80 {
81         char *stream_name = NULL;
82         char *base_name = NULL;
83         struct smb_filename *ret;
84         bool ok;
85
86         if (posix_path) {
87                 /* No stream name looked for. */
88                 return synthetic_smb_fname(ctx,
89                                 fname,
90                                 NULL,
91                                 NULL,
92                                 SMB_FILENAME_POSIX_PATH);
93         }
94
95         ok = split_stream_filename(ctx,
96                                 fname,
97                                 &base_name,
98                                 &stream_name);
99         if (!ok) {
100                 return NULL;
101         }
102
103         ret = synthetic_smb_fname(ctx, base_name, stream_name, NULL, 0);
104         TALLOC_FREE(base_name);
105         TALLOC_FREE(stream_name);
106         return ret;
107 }
108
109 /**
110  * Return a string using the talloc_tos()
111  */
112 const char *smb_fname_str_dbg(const struct smb_filename *smb_fname)
113 {
114         char *fname = NULL;
115         NTSTATUS status;
116
117         if (smb_fname == NULL) {
118                 return "";
119         }
120         status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
121         if (!NT_STATUS_IS_OK(status)) {
122                 return "";
123         }
124         return fname;
125 }
126
127 /**
128  * Return a debug string of the path name of an fsp using the talloc_tos().
129  */
130 const char *fsp_str_dbg(const struct files_struct *fsp)
131 {
132         return smb_fname_str_dbg(fsp->fsp_name);
133 }
134
135 /**
136  * Create a debug string for the fnum of an fsp.
137  *
138  * This is allocated to talloc_tos() or a string constant
139  * in certain corner cases. The returned string should
140  * hence not be free'd directly but only via the talloc stack.
141  */
142 const char *fsp_fnum_dbg(const struct files_struct *fsp)
143 {
144         char *str;
145
146         if (fsp == NULL) {
147                 return "fnum [fsp is NULL]";
148         }
149
150         if (fsp->fnum == FNUM_FIELD_INVALID) {
151                 return "fnum [invalid value]";
152         }
153
154         str = talloc_asprintf(talloc_tos(), "fnum %llu",
155                               (unsigned long long)fsp->fnum);
156         if (str == NULL) {
157                 DEBUG(1, ("%s: talloc_asprintf failed\n", __FUNCTION__));
158                 return "fnum [talloc failed!]";
159         }
160
161         return str;
162 }
163
164 struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx,
165                                      const struct smb_filename *in)
166 {
167         struct smb_filename *out;
168         size_t base_len = 0;
169         size_t stream_len = 0;
170         size_t lcomp_len = 0;
171         int num = 0;
172
173         /* stream_name must always be NULL if there is no stream. */
174         if (in->stream_name) {
175                 SMB_ASSERT(in->stream_name[0] != '\0');
176         }
177
178         if (in->base_name != NULL) {
179                 base_len = strlen(in->base_name) + 1;
180                 num += 1;
181         }
182         if (in->stream_name != NULL) {
183                 stream_len = strlen(in->stream_name) + 1;
184                 num += 1;
185         }
186         if (in->original_lcomp != NULL) {
187                 lcomp_len = strlen(in->original_lcomp) + 1;
188                 num += 1;
189         }
190
191         out = talloc_pooled_object(mem_ctx, struct smb_filename,
192                                 num, stream_len + base_len + lcomp_len);
193         if (out == NULL) {
194                 return NULL;
195         }
196         ZERO_STRUCTP(out);
197
198         /*
199          * The following allocations cannot fail as we
200          * pre-allocated space for them in the out pooled
201          * object.
202          */
203         if (in->base_name != NULL) {
204                 out->base_name = talloc_memdup(
205                                 out, in->base_name, base_len);
206                 talloc_set_name_const(out->base_name,
207                                       out->base_name);
208         }
209         if (in->stream_name != NULL) {
210                 out->stream_name = talloc_memdup(
211                                 out, in->stream_name, stream_len);
212                 talloc_set_name_const(out->stream_name,
213                                       out->stream_name);
214         }
215         if (in->original_lcomp != NULL) {
216                 out->original_lcomp = talloc_memdup(
217                                 out, in->original_lcomp, lcomp_len);
218                 talloc_set_name_const(out->original_lcomp,
219                                       out->original_lcomp);
220         }
221         out->flags = in->flags;
222         out->st = in->st;
223         return out;
224 }
225
226 /****************************************************************************
227  Simple check to determine if the filename is a stream.
228  ***************************************************************************/
229 bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname)
230 {
231         /* stream_name must always be NULL if there is no stream. */
232         if (smb_fname->stream_name) {
233                 SMB_ASSERT(smb_fname->stream_name[0] != '\0');
234         }
235
236         if (smb_fname->flags & SMB_FILENAME_POSIX_PATH) {
237                 return false;
238         }
239
240         return smb_fname->stream_name != NULL;
241 }
242
243 /****************************************************************************
244  Returns true if the filename's stream == "::$DATA"
245  ***************************************************************************/
246 bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname)
247 {
248         if (!is_ntfs_stream_smb_fname(smb_fname)) {
249                 return false;
250         }
251
252         return strcasecmp_m(smb_fname->stream_name, "::$DATA") == 0;
253 }
254
255 /****************************************************************************
256  Filter out Windows invalid EA names (list probed from Windows 2012).
257 ****************************************************************************/
258
259 static char bad_ea_name_chars[] = "\"*+,/:;<=>?[\\]|";
260
261 bool is_invalid_windows_ea_name(const char *name)
262 {
263         int i;
264         /* EA name is pulled as ascii so we can examine
265            individual bytes here. */
266         for (i = 0; name[i] != 0; i++) {
267                 int val = (name[i] & 0xff);
268                 if (val < ' ' || strchr(bad_ea_name_chars, val)) {
269                         return true;
270                 }
271         }
272         return false;
273 }
274
275 bool ea_list_has_invalid_name(struct ea_list *ea_list)
276 {
277         for (;ea_list; ea_list = ea_list->next) {
278                 if (is_invalid_windows_ea_name(ea_list->ea.name)) {
279                         return true;
280                 }
281         }
282         return false;
283 }
284
285 /****************************************************************************
286  Split an incoming name into tallocd filename and stream components.
287  Returns true on success, false on out of memory.
288 ****************************************************************************/
289
290 bool split_stream_filename(TALLOC_CTX *ctx,
291                                 const char *filename_in,
292                                 char **filename_out,
293                                 char **streamname_out)
294 {
295         const char *stream_name = NULL;
296         char *stream_out = NULL;
297         char *file_out = NULL;
298
299         stream_name = strchr_m(filename_in, ':');
300
301         if (stream_name) {
302                 stream_out = talloc_strdup(ctx, stream_name);
303                 if (stream_out == NULL) {
304                         return false;
305                 }
306                 file_out = talloc_strndup(ctx,
307                                         filename_in,
308                                         PTR_DIFF(stream_name, filename_in));
309         } else {
310                 file_out = talloc_strdup(ctx, filename_in);
311         }
312
313         if (file_out == NULL) {
314                 TALLOC_FREE(stream_out);
315                 return false;
316         }
317
318         if (filename_out) {
319                 *filename_out = file_out;
320         }
321         if (streamname_out) {
322                 *streamname_out = stream_out;
323         }
324         return true;
325 }