| 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 | NTSTATUS 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 | */
|
|---|
| 78 | NTSTATUS 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 | */
|
|---|
| 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 using the talloc_tos(). This can only be called from
|
|---|
| 129 | * DEBUG() macros due to the debut_ctx().
|
|---|
| 130 | */
|
|---|
| 131 | const char *fsp_str_dbg(const struct files_struct *fsp)
|
|---|
| 132 | {
|
|---|
| 133 | return smb_fname_str_dbg(fsp->fsp_name);
|
|---|
| 134 | }
|
|---|
| 135 |
|
|---|
| 136 | NTSTATUS 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 | ***************************************************************************/
|
|---|
| 182 | bool 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 | ***************************************************************************/
|
|---|
| 199 | bool 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 | }
|
|---|