lib: Make create_synthetic_smb_fname use synthetic_smb_fname
[garming/samba-autobuild/.git] / source3 / lib / filename_util.c
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 static NTSTATUS copy_smb_filename(TALLOC_CTX *ctx,
22                                   const struct smb_filename *smb_fname_in,
23                                   struct smb_filename **smb_fname_out);
24
25 /**
26  * XXX: This is temporary and there should be no callers of this outside of
27  * this file once smb_filename is plumbed through all path based operations.
28  * The one legitimate caller currently is smb_fname_str_dbg(), which this
29  * could be made static for.
30  */
31 NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx,
32                                const struct smb_filename *smb_fname,
33                                char **full_name)
34 {
35         if (smb_fname->stream_name) {
36                 /* stream_name must always be NULL if there is no stream. */
37                 SMB_ASSERT(smb_fname->stream_name[0] != '\0');
38
39                 *full_name = talloc_asprintf(ctx, "%s%s", smb_fname->base_name,
40                                              smb_fname->stream_name);
41         } else {
42                 *full_name = talloc_strdup(ctx, smb_fname->base_name);
43         }
44
45         if (!*full_name) {
46                 return NT_STATUS_NO_MEMORY;
47         }
48
49         return NT_STATUS_OK;
50 }
51
52 /**
53  * There are actually legitimate callers of this such as functions that
54  * enumerate streams using the vfs_streaminfo interface and then want to
55  * operate on each stream.
56  */
57 NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name,
58                                     const char *stream_name,
59                                     const SMB_STRUCT_STAT *psbuf,
60                                     struct smb_filename **smb_fname_out)
61 {
62         *smb_fname_out = synthetic_smb_fname(ctx, base_name, stream_name,
63                                              psbuf);
64         if (*smb_fname_out == NULL) {
65                 return NT_STATUS_NO_MEMORY;
66         }
67         return NT_STATUS_OK;
68 }
69
70 struct smb_filename *synthetic_smb_fname(TALLOC_CTX *mem_ctx,
71                                          const char *base_name,
72                                          const char *stream_name,
73                                          const SMB_STRUCT_STAT *psbuf)
74 {
75         struct smb_filename smb_fname_loc = { 0, };
76
77         /* Setup the base_name/stream_name. */
78         smb_fname_loc.base_name = discard_const_p(char, base_name);
79         smb_fname_loc.stream_name = discard_const_p(char, stream_name);
80
81         /* Copy the psbuf if one was given. */
82         if (psbuf)
83                 smb_fname_loc.st = *psbuf;
84
85         /* Let cp_smb_filename() do the heavy lifting. */
86         return cp_smb_filename(mem_ctx, &smb_fname_loc);
87 }
88
89 /**
90  * XXX: This is temporary and there should be no callers of this once
91  * smb_filename is plumbed through all path based operations.
92  */
93 NTSTATUS create_synthetic_smb_fname_split(TALLOC_CTX *ctx,
94                                           const char *fname,
95                                           const SMB_STRUCT_STAT *psbuf,
96                                           struct smb_filename **smb_fname_out)
97 {
98         NTSTATUS status;
99         const char *stream_name = NULL;
100         char *base_name = NULL;
101
102         if (!lp_posix_pathnames()) {
103                 stream_name = strchr_m(fname, ':');
104         }
105
106         /* Setup the base_name/stream_name. */
107         if (stream_name) {
108                 base_name = talloc_strndup(ctx, fname,
109                                            PTR_DIFF(stream_name, fname));
110         } else {
111                 base_name = talloc_strdup(ctx, fname);
112         }
113
114         if (!base_name) {
115                 return NT_STATUS_NO_MEMORY;
116         }
117
118         status = create_synthetic_smb_fname(ctx, base_name, stream_name, psbuf,
119                                             smb_fname_out);
120         TALLOC_FREE(base_name);
121         return status;
122 }
123
124 /**
125  * Return a string using the talloc_tos()
126  */
127 const char *smb_fname_str_dbg(const struct smb_filename *smb_fname)
128 {
129         char *fname = NULL;
130         NTSTATUS status;
131
132         if (smb_fname == NULL) {
133                 return "";
134         }
135         status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
136         if (!NT_STATUS_IS_OK(status)) {
137                 return "";
138         }
139         return fname;
140 }
141
142 /**
143  * Return a debug string of the path name of an fsp using the talloc_tos().
144  */
145 const char *fsp_str_dbg(const struct files_struct *fsp)
146 {
147         return smb_fname_str_dbg(fsp->fsp_name);
148 }
149
150 /**
151  * Create a debug string for the fnum of an fsp.
152  *
153  * This is allocated to talloc_tos() or a string constant
154  * in certain corner cases. The returned string should
155  * hence not be free'd directly but only via the talloc stack.
156  */
157 const char *fsp_fnum_dbg(const struct files_struct *fsp)
158 {
159         char *str;
160
161         if (fsp == NULL) {
162                 return "fnum [fsp is NULL]";
163         }
164
165         if (fsp->fnum == FNUM_FIELD_INVALID) {
166                 return "fnum [invalid value]";
167         }
168
169         str = talloc_asprintf(talloc_tos(), "fnum %llu",
170                               (unsigned long long)fsp->fnum);
171         if (str == NULL) {
172                 DEBUG(1, ("%s: talloc_asprintf failed\n", __FUNCTION__));
173                 return "fnum [talloc failed!]";
174         }
175
176         return str;
177 }
178
179 struct smb_filename *cp_smb_filename(TALLOC_CTX *mem_ctx,
180                                      const struct smb_filename *in)
181 {
182         struct smb_filename *out;
183
184         /* stream_name must always be NULL if there is no stream. */
185         if (in->stream_name) {
186                 SMB_ASSERT(in->stream_name[0] != '\0');
187         }
188
189         out = talloc_zero(mem_ctx, struct smb_filename);
190         if (out == NULL) {
191                 return NULL;
192         }
193         if (in->base_name != NULL) {
194                 out->base_name = talloc_strdup(out, in->base_name);
195                 if (out->base_name == NULL) {
196                         goto fail;
197                 }
198         }
199         if (in->stream_name != NULL) {
200                 out->stream_name = talloc_strdup(out, in->stream_name);
201                 if (out->stream_name == NULL) {
202                         goto fail;
203                 }
204         }
205         if (in->original_lcomp != NULL) {
206                 out->original_lcomp = talloc_strdup(out, in->original_lcomp);
207                 if (out->original_lcomp == NULL) {
208                         goto fail;
209                 }
210         }
211         out->st = in->st;
212         return out;
213 fail:
214         TALLOC_FREE(out);
215         return NULL;
216 }
217
218 static NTSTATUS copy_smb_filename(TALLOC_CTX *ctx,
219                                   const struct smb_filename *smb_fname_in,
220                                   struct smb_filename **smb_fname_out)
221 {
222         *smb_fname_out = cp_smb_filename(ctx, smb_fname_in);
223         if (*smb_fname_out == NULL) {
224                 return NT_STATUS_NO_MEMORY;
225         }
226         return NT_STATUS_OK;
227 }
228
229 /****************************************************************************
230  Simple check to determine if the filename is a stream.
231  ***************************************************************************/
232 bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname)
233 {
234         /* stream_name must always be NULL if there is no stream. */
235         if (smb_fname->stream_name) {
236                 SMB_ASSERT(smb_fname->stream_name[0] != '\0');
237         }
238
239         if (lp_posix_pathnames()) {
240                 return false;
241         }
242
243         return smb_fname->stream_name != NULL;
244 }
245
246 /****************************************************************************
247  Returns true if the filename's stream == "::$DATA"
248  ***************************************************************************/
249 bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname)
250 {
251         if (!is_ntfs_stream_smb_fname(smb_fname)) {
252                 return false;
253         }
254
255         return strcasecmp_m(smb_fname->stream_name, "::$DATA") == 0;
256 }