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 */ 27NTSTATUS 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 SMB_VFS_STREAMINFO interface and then want to 51 * operate on each stream. 52 */ 53NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name, 54 const char *stream_name, 55 const SMB_STRUCT_STAT *psbuf, 56 struct smb_filename **smb_fname_out) 57{ 58 struct smb_filename smb_fname_loc; 59 60 ZERO_STRUCT(smb_fname_loc); 61 62 /* Setup the base_name/stream_name. */ 63 smb_fname_loc.base_name = CONST_DISCARD(char *, base_name); 64 smb_fname_loc.stream_name = CONST_DISCARD(char *, stream_name); 65 66 /* Copy the psbuf if one was given. */ 67 if (psbuf) 68 smb_fname_loc.st = *psbuf; 69 70 /* Let copy_smb_filename() do the heavy lifting. */ 71 return copy_smb_filename(ctx, &smb_fname_loc, smb_fname_out); 72} 73 74/** 75 * XXX: This is temporary and there should be no callers of this once 76 * smb_filename is plumbed through all path based operations. 77 */ 78NTSTATUS create_synthetic_smb_fname_split(TALLOC_CTX *ctx, 79 const char *fname, 80 const SMB_STRUCT_STAT *psbuf, 81 struct smb_filename **smb_fname_out) 82{ 83 NTSTATUS status; 84 const char *stream_name = NULL; 85 char *base_name = NULL; 86 87 if (!lp_posix_pathnames()) { 88 stream_name = strchr_m(fname, ':'); 89 } 90 91 /* Setup the base_name/stream_name. */ 92 if (stream_name) { 93 base_name = talloc_strndup(ctx, fname, 94 PTR_DIFF(stream_name, fname)); 95 } else { 96 base_name = talloc_strdup(ctx, fname); 97 } 98 99 if (!base_name) { 100 return NT_STATUS_NO_MEMORY; 101 } 102 103 status = create_synthetic_smb_fname(ctx, base_name, stream_name, psbuf, 104 smb_fname_out); 105 TALLOC_FREE(base_name); 106 return status; 107} 108 109/** 110 * Return a string using the talloc_tos() 111 */ 112const 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 using the talloc_tos(). This can only be called from 129 * DEBUG() macros due to the debut_ctx(). 130 */ 131const char *fsp_str_dbg(const struct files_struct *fsp) 132{ 133 return smb_fname_str_dbg(fsp->fsp_name); 134} 135 136NTSTATUS copy_smb_filename(TALLOC_CTX *ctx, 137 const struct smb_filename *smb_fname_in, 138 struct smb_filename **smb_fname_out) 139{ 140 /* stream_name must always be NULL if there is no stream. */ 141 if (smb_fname_in->stream_name) { 142 SMB_ASSERT(smb_fname_in->stream_name[0] != '\0'); 143 } 144 145 *smb_fname_out = talloc_zero(ctx, struct smb_filename); 146 if (*smb_fname_out == NULL) { 147 return NT_STATUS_NO_MEMORY; 148 } 149 150 if (smb_fname_in->base_name) { 151 (*smb_fname_out)->base_name = 152 talloc_strdup(*smb_fname_out, smb_fname_in->base_name); 153 if (!(*smb_fname_out)->base_name) 154 goto no_mem_err; 155 } 156 157 if (smb_fname_in->stream_name) { 158 (*smb_fname_out)->stream_name = 159 talloc_strdup(*smb_fname_out, smb_fname_in->stream_name); 160 if (!(*smb_fname_out)->stream_name) 161 goto no_mem_err; 162 } 163 164 if (smb_fname_in->original_lcomp) { 165 (*smb_fname_out)->original_lcomp = 166 talloc_strdup(*smb_fname_out, smb_fname_in->original_lcomp); 167 if (!(*smb_fname_out)->original_lcomp) 168 goto no_mem_err; 169 } 170 171 (*smb_fname_out)->st = smb_fname_in->st; 172 return NT_STATUS_OK; 173 174 no_mem_err: 175 TALLOC_FREE(*smb_fname_out); 176 return NT_STATUS_NO_MEMORY; 177} 178 179/**************************************************************************** 180 Simple check to determine if the filename is a stream. 181 ***************************************************************************/ 182bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname) 183{ 184 /* stream_name must always be NULL if there is no stream. */ 185 if (smb_fname->stream_name) { 186 SMB_ASSERT(smb_fname->stream_name[0] != '\0'); 187 } 188 189 if (lp_posix_pathnames()) { 190 return false; 191 } 192 193 return smb_fname->stream_name != NULL; 194} 195 196/**************************************************************************** 197 Returns true if the filename's stream == "::$DATA" 198 ***************************************************************************/ 199bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname) 200{ 201 if (!is_ntfs_stream_smb_fname(smb_fname)) { 202 return false; 203 } 204 205 return StrCaseCmp(smb_fname->stream_name, "::$DATA") == 0; 206} 207