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
;
273 * Return allocated parent directory and basename of path
275 * Note: if requesting name, it is returned as talloc child of the
276 * parent. Freeing the parent is thus sufficient to free both.
278 bool parent_smb_fname(TALLOC_CTX
*mem_ctx
,
279 const struct smb_filename
*path
,
280 struct smb_filename
**_parent
,
281 struct smb_filename
**_name
)
283 TALLOC_CTX
*frame
= talloc_stackframe();
284 struct smb_filename
*parent
= NULL
;
285 struct smb_filename
*name
= NULL
;
288 parent
= cp_smb_filename(frame
, path
);
289 if (parent
== NULL
) {
293 TALLOC_FREE(parent
->stream_name
);
294 SET_STAT_INVALID(parent
->st
);
296 p
= strrchr_m(parent
->base_name
, '/'); /* Find final '/', if any */
298 TALLOC_FREE(parent
->base_name
);
299 parent
->base_name
= talloc_strdup(parent
, ".");
300 if (parent
->base_name
== NULL
) {
311 *_parent
= talloc_move(mem_ctx
, &parent
);
316 name
= cp_smb_filename(frame
, path
);
321 TALLOC_FREE(name
->base_name
);
323 name
->base_name
= talloc_strdup(mem_ctx
, p
);
329 *_parent
= talloc_move(mem_ctx
, &parent
);
330 *_name
= talloc_move(*_parent
, &name
);
335 static void assert_valid_stream_smb_fname(const struct smb_filename
*smb_fname
)
337 /* stream_name must always be NULL if there is no stream. */
338 if (smb_fname
->stream_name
) {
339 SMB_ASSERT(smb_fname
->stream_name
[0] != '\0');
342 if (smb_fname
->flags
& SMB_FILENAME_POSIX_PATH
) {
343 SMB_ASSERT(smb_fname
->stream_name
== NULL
);
347 /****************************************************************************
348 Simple check to determine if a smb_fname is a real named stream or the
350 ***************************************************************************/
352 bool is_ntfs_stream_smb_fname(const struct smb_filename
*smb_fname
)
354 assert_valid_stream_smb_fname(smb_fname
);
356 if (smb_fname
->stream_name
== NULL
) {
363 /****************************************************************************
364 Simple check to determine if a smb_fname is pointing to a normal file or
365 a named stream that is not the default stream "::$DATA".
370 foo:bar:$DATA -> true
372 ***************************************************************************/
374 bool is_named_stream(const struct smb_filename
*smb_fname
)
376 assert_valid_stream_smb_fname(smb_fname
);
378 if (smb_fname
->stream_name
== NULL
) {
382 if (strequal_m(smb_fname
->stream_name
, "::$DATA")) {
389 /****************************************************************************
390 Returns true if the filename's stream == "::$DATA"
391 ***************************************************************************/
392 bool is_ntfs_default_stream_smb_fname(const struct smb_filename
*smb_fname
)
394 assert_valid_stream_smb_fname(smb_fname
);
396 if (smb_fname
->stream_name
== NULL
) {
400 return strequal_m(smb_fname
->stream_name
, "::$DATA");
403 /****************************************************************************
404 Filter out Windows invalid EA names (list probed from Windows 2012).
405 ****************************************************************************/
407 static char bad_ea_name_chars
[] = "\"*+,/:;<=>?[\\]|";
409 bool is_invalid_windows_ea_name(const char *name
)
412 /* EA name is pulled as ascii so we can examine
413 individual bytes here. */
414 for (i
= 0; name
[i
] != 0; i
++) {
415 int val
= (name
[i
] & 0xff);
416 if (val
< ' ' || strchr(bad_ea_name_chars
, val
)) {
423 bool ea_list_has_invalid_name(struct ea_list
*ea_list
)
425 for (;ea_list
; ea_list
= ea_list
->next
) {
426 if (is_invalid_windows_ea_name(ea_list
->ea
.name
)) {
433 /****************************************************************************
434 Split an incoming name into tallocd filename and stream components.
435 Returns true on success, false on out of memory.
436 ****************************************************************************/
438 bool split_stream_filename(TALLOC_CTX
*ctx
,
439 const char *filename_in
,
441 char **streamname_out
)
443 const char *stream_name
= NULL
;
444 char *stream_out
= NULL
;
445 char *file_out
= NULL
;
447 stream_name
= strchr_m(filename_in
, ':');
450 stream_out
= talloc_strdup(ctx
, stream_name
);
451 if (stream_out
== NULL
) {
454 file_out
= talloc_strndup(ctx
,
456 PTR_DIFF(stream_name
, filename_in
));
458 file_out
= talloc_strdup(ctx
, filename_in
);
461 if (file_out
== NULL
) {
462 TALLOC_FREE(stream_out
);
467 *filename_out
= file_out
;
469 if (streamname_out
) {
470 *streamname_out
= stream_out
;