2 Unix SMB/CIFS implementation.
3 Filename utility functions.
4 Copyright (C) Tim Prouty 2009
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.
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.
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/>.
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.
27 NTSTATUS
get_full_smb_filename(TALLOC_CTX
*ctx
,
28 const struct smb_filename
*smb_fname
,
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');
35 *full_name
= talloc_asprintf(ctx
, "%s%s", smb_fname
->base_name
,
36 smb_fname
->stream_name
);
38 *full_name
= talloc_strdup(ctx
, smb_fname
->base_name
);
42 return NT_STATUS_NO_MEMORY
;
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.
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
,
60 /* Setup the base_name/stream_name. */
62 struct smb_filename smb_fname_loc
= {
63 .base_name
= discard_const_p(char, base_name
),
64 .stream_name
= discard_const_p(char, stream_name
),
69 /* Copy the psbuf if one was given. */
71 smb_fname_loc
.st
= *psbuf
;
73 /* Let cp_smb_filename() do the heavy lifting. */
74 return cp_smb_filename(mem_ctx
, &smb_fname_loc
);
78 * Utility function used by VFS calls that must *NOT* operate
79 * on a stream filename, only the base_name.
81 struct smb_filename
*cp_smb_filename_nostream(TALLOC_CTX
*mem_ctx
,
82 const struct smb_filename
*smb_fname_in
)
84 struct smb_filename smb_fname_loc
= *smb_fname_in
;
85 struct smb_filename
*smb_fname
= NULL
;
87 smb_fname_loc
.stream_name
= NULL
;
89 smb_fname
= cp_smb_filename(mem_ctx
, &smb_fname_loc
);
94 * There are a few legitimate users of this.
96 struct smb_filename
*synthetic_smb_fname_split(TALLOC_CTX
*ctx
,
100 char *stream_name
= NULL
;
101 char *base_name
= NULL
;
102 struct smb_filename
*ret
;
106 /* No stream name looked for. */
107 return synthetic_smb_fname(ctx
,
112 SMB_FILENAME_POSIX_PATH
);
115 ok
= split_stream_filename(ctx
,
123 ret
= synthetic_smb_fname(ctx
,
129 TALLOC_FREE(base_name
);
130 TALLOC_FREE(stream_name
);
135 * Return a string using the talloc_tos()
137 const char *smb_fname_str_dbg(const struct smb_filename
*smb_fname
)
142 struct tm
*ptm
= NULL
;
147 if (smb_fname
== NULL
) {
150 status
= get_full_smb_filename(talloc_tos(), smb_fname
, &fname
);
151 if (!NT_STATUS_IS_OK(status
)) {
154 if (smb_fname
->twrp
== 0) {
158 t
= nt_time_to_unix(smb_fname
->twrp
);
159 ptm
= gmtime_r(&t
, &tm
);
164 slen
= strftime(tstr
, sizeof(tstr
), GMT_FORMAT
, &tm
);
169 fname
= talloc_asprintf_append_buffer(
170 fname
, " {%s}", tstr
);
178 * Return a debug string of the path name of an fsp using the talloc_tos().
180 const char *fsp_str_dbg(const struct files_struct
*fsp
)
182 const char *name
= NULL
;
184 name
= smb_fname_str_dbg(fsp
->fsp_name
);
193 * Create a debug string for the fnum of an fsp.
195 * This is allocated to talloc_tos() or a string constant
196 * in certain corner cases. The returned string should
197 * hence not be free'd directly but only via the talloc stack.
199 const char *fsp_fnum_dbg(const struct files_struct
*fsp
)
204 return "fnum [fsp is NULL]";
207 if (fsp
->fnum
== FNUM_FIELD_INVALID
) {
208 return "fnum [invalid value]";
211 str
= talloc_asprintf(talloc_tos(), "fnum %"PRIu64
, fsp
->fnum
);
213 DEBUG(1, ("%s: talloc_asprintf failed\n", __FUNCTION__
));
214 return "fnum [talloc failed!]";
220 struct smb_filename
*cp_smb_filename(TALLOC_CTX
*mem_ctx
,
221 const struct smb_filename
*in
)
223 struct smb_filename
*out
;
225 size_t stream_len
= 0;
228 /* stream_name must always be NULL if there is no stream. */
229 if (in
->stream_name
) {
230 SMB_ASSERT(in
->stream_name
[0] != '\0');
233 if (in
->base_name
!= NULL
) {
234 base_len
= strlen(in
->base_name
) + 1;
237 if (in
->stream_name
!= NULL
) {
238 stream_len
= strlen(in
->stream_name
) + 1;
242 out
= talloc_pooled_object(mem_ctx
, struct smb_filename
,
243 num
, stream_len
+ base_len
);
250 * The following allocations cannot fail as we
251 * pre-allocated space for them in the out pooled
254 if (in
->base_name
!= NULL
) {
255 out
->base_name
= talloc_memdup(
256 out
, in
->base_name
, base_len
);
257 talloc_set_name_const(out
->base_name
,
260 if (in
->stream_name
!= NULL
) {
261 out
->stream_name
= talloc_memdup(
262 out
, in
->stream_name
, stream_len
);
263 talloc_set_name_const(out
->stream_name
,
266 out
->flags
= in
->flags
;
268 out
->twrp
= in
->twrp
;
272 static void assert_valid_stream_smb_fname(const struct smb_filename
*smb_fname
)
274 /* stream_name must always be NULL if there is no stream. */
275 if (smb_fname
->stream_name
) {
276 SMB_ASSERT(smb_fname
->stream_name
[0] != '\0');
279 if (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
) {
280 SMB_ASSERT(smb_fname
->stream_name
== NULL
);
284 /****************************************************************************
285 Simple check to determine if a smb_fname is a real named stream or the
287 ***************************************************************************/
289 bool is_ntfs_stream_smb_fname(const struct smb_filename
*smb_fname
)
291 assert_valid_stream_smb_fname(smb_fname
);
293 return (smb_fname
->stream_name
!= NULL
);
296 /****************************************************************************
297 Simple check to determine if a smb_fname is pointing to a normal file or
298 a named stream that is not the default stream "::$DATA".
303 foo:bar:$DATA -> true
305 ***************************************************************************/
307 bool is_named_stream(const struct smb_filename
*smb_fname
)
309 assert_valid_stream_smb_fname(smb_fname
);
311 if (smb_fname
->stream_name
== NULL
) {
315 if (strequal_m(smb_fname
->stream_name
, "::$DATA")) {
322 /****************************************************************************
323 Returns true if the filename's stream == "::$DATA"
324 ***************************************************************************/
325 bool is_ntfs_default_stream_smb_fname(const struct smb_filename
*smb_fname
)
327 assert_valid_stream_smb_fname(smb_fname
);
329 if (smb_fname
->stream_name
== NULL
) {
333 return strequal_m(smb_fname
->stream_name
, "::$DATA");
336 /****************************************************************************
337 Filter out Windows invalid EA names (list probed from Windows 2012).
338 ****************************************************************************/
340 static const char bad_ea_name_chars
[] = "\"*+,/:;<=>?[\\]|";
342 bool is_invalid_windows_ea_name(const char *name
)
345 /* EA name is pulled as ascii so we can examine
346 individual bytes here. */
347 for (i
= 0; name
[i
] != 0; i
++) {
348 int val
= (name
[i
] & 0xff);
349 if (val
< ' ' || strchr(bad_ea_name_chars
, val
)) {
356 bool ea_list_has_invalid_name(struct ea_list
*ea_list
)
358 for (;ea_list
; ea_list
= ea_list
->next
) {
359 if (is_invalid_windows_ea_name(ea_list
->ea
.name
)) {
366 /****************************************************************************
367 Split an incoming name into tallocd filename and stream components.
368 Returns true on success, false on out of memory.
369 ****************************************************************************/
371 bool split_stream_filename(TALLOC_CTX
*ctx
,
372 const char *filename_in
,
374 char **streamname_out
)
376 const char *stream_name
= NULL
;
377 char *stream_out
= NULL
;
378 char *file_out
= NULL
;
380 stream_name
= strchr_m(filename_in
, ':');
383 stream_out
= talloc_strdup(ctx
, stream_name
);
384 if (stream_out
== NULL
) {
387 file_out
= talloc_strndup(ctx
,
389 PTR_DIFF(stream_name
, filename_in
));
391 file_out
= talloc_strdup(ctx
, filename_in
);
394 if (file_out
== NULL
) {
395 TALLOC_FREE(stream_out
);
400 *filename_out
= file_out
;
402 if (streamname_out
) {
403 *streamname_out
= stream_out
;