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 struct smb_filename smb_fname_loc
= { 0, };
62 /* Setup the base_name/stream_name. */
63 smb_fname_loc
.base_name
= discard_const_p(char, base_name
);
64 smb_fname_loc
.stream_name
= discard_const_p(char, stream_name
);
65 smb_fname_loc
.flags
= flags
;
66 smb_fname_loc
.twrp
= twrp
;
68 /* Copy the psbuf if one was given. */
70 smb_fname_loc
.st
= *psbuf
;
72 /* Let cp_smb_filename() do the heavy lifting. */
73 return cp_smb_filename(mem_ctx
, &smb_fname_loc
);
77 * Utility function used by VFS calls that must *NOT* operate
78 * on a stream filename, only the base_name.
80 struct smb_filename
*cp_smb_filename_nostream(TALLOC_CTX
*mem_ctx
,
81 const struct smb_filename
*smb_fname_in
)
83 struct smb_filename
*smb_fname
= cp_smb_filename(mem_ctx
,
85 if (smb_fname
== NULL
) {
88 TALLOC_FREE(smb_fname
->stream_name
);
93 * There are a few legitimate users of this.
95 struct smb_filename
*synthetic_smb_fname_split(TALLOC_CTX
*ctx
,
99 char *stream_name
= NULL
;
100 char *base_name
= NULL
;
101 struct smb_filename
*ret
;
105 /* No stream name looked for. */
106 return synthetic_smb_fname(ctx
,
111 SMB_FILENAME_POSIX_PATH
);
114 ok
= split_stream_filename(ctx
,
122 ret
= synthetic_smb_fname(ctx
,
128 TALLOC_FREE(base_name
);
129 TALLOC_FREE(stream_name
);
134 * Return a string using the talloc_tos()
136 const char *smb_fname_str_dbg(const struct smb_filename
*smb_fname
)
141 struct tm
*ptm
= NULL
;
146 if (smb_fname
== NULL
) {
149 status
= get_full_smb_filename(talloc_tos(), smb_fname
, &fname
);
150 if (!NT_STATUS_IS_OK(status
)) {
153 if (smb_fname
->twrp
== 0) {
157 t
= nt_time_to_unix(smb_fname
->twrp
);
158 ptm
= gmtime_r(&t
, &tm
);
163 slen
= strftime(tstr
, sizeof(tstr
), GMT_FORMAT
, &tm
);
168 fname
= talloc_asprintf_append_buffer(
169 fname
, " {%s}", tstr
);
177 * Return a debug string of the path name of an fsp using the talloc_tos().
179 const char *fsp_str_dbg(const struct files_struct
*fsp
)
181 const char *name
= NULL
;
183 name
= smb_fname_str_dbg(fsp
->fsp_name
);
192 * Create a debug string for the fnum of an fsp.
194 * This is allocated to talloc_tos() or a string constant
195 * in certain corner cases. The returned string should
196 * hence not be free'd directly but only via the talloc stack.
198 const char *fsp_fnum_dbg(const struct files_struct
*fsp
)
203 return "fnum [fsp is NULL]";
206 if (fsp
->fnum
== FNUM_FIELD_INVALID
) {
207 return "fnum [invalid value]";
210 str
= talloc_asprintf(talloc_tos(), "fnum %llu",
211 (unsigned long long)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 if (smb_fname
->stream_name
== NULL
) {
300 /****************************************************************************
301 Simple check to determine if a smb_fname is pointing to a normal file or
302 a named stream that is not the default stream "::$DATA".
307 foo:bar:$DATA -> true
309 ***************************************************************************/
311 bool is_named_stream(const struct smb_filename
*smb_fname
)
313 assert_valid_stream_smb_fname(smb_fname
);
315 if (smb_fname
->stream_name
== NULL
) {
319 if (strequal_m(smb_fname
->stream_name
, "::$DATA")) {
326 /****************************************************************************
327 Returns true if the filename's stream == "::$DATA"
328 ***************************************************************************/
329 bool is_ntfs_default_stream_smb_fname(const struct smb_filename
*smb_fname
)
331 assert_valid_stream_smb_fname(smb_fname
);
333 if (smb_fname
->stream_name
== NULL
) {
337 return strequal_m(smb_fname
->stream_name
, "::$DATA");
340 /****************************************************************************
341 Filter out Windows invalid EA names (list probed from Windows 2012).
342 ****************************************************************************/
344 static char bad_ea_name_chars
[] = "\"*+,/:;<=>?[\\]|";
346 bool is_invalid_windows_ea_name(const char *name
)
349 /* EA name is pulled as ascii so we can examine
350 individual bytes here. */
351 for (i
= 0; name
[i
] != 0; i
++) {
352 int val
= (name
[i
] & 0xff);
353 if (val
< ' ' || strchr(bad_ea_name_chars
, val
)) {
360 bool ea_list_has_invalid_name(struct ea_list
*ea_list
)
362 for (;ea_list
; ea_list
= ea_list
->next
) {
363 if (is_invalid_windows_ea_name(ea_list
->ea
.name
)) {
370 /****************************************************************************
371 Split an incoming name into tallocd filename and stream components.
372 Returns true on success, false on out of memory.
373 ****************************************************************************/
375 bool split_stream_filename(TALLOC_CTX
*ctx
,
376 const char *filename_in
,
378 char **streamname_out
)
380 const char *stream_name
= NULL
;
381 char *stream_out
= NULL
;
382 char *file_out
= NULL
;
384 stream_name
= strchr_m(filename_in
, ':');
387 stream_out
= talloc_strdup(ctx
, stream_name
);
388 if (stream_out
== NULL
) {
391 file_out
= talloc_strndup(ctx
,
393 PTR_DIFF(stream_name
, filename_in
));
395 file_out
= talloc_strdup(ctx
, filename_in
);
398 if (file_out
== NULL
) {
399 TALLOC_FREE(stream_out
);
404 *filename_out
= file_out
;
406 if (streamname_out
) {
407 *streamname_out
= stream_out
;