s3: include smbd/smbd.h where needed.
[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 #include "smbd/smbd.h"
21
22 /**
23  * XXX: This is temporary and there should be no callers of this outside of
24  * this file once smb_filename is plumbed through all path based operations.
25  * The one legitimate caller currently is smb_fname_str_dbg(), which this
26  * could be made static for.
27  */
28 NTSTATUS get_full_smb_filename(TALLOC_CTX *ctx,
29                                const struct smb_filename *smb_fname,
30                                char **full_name)
31 {
32         if (smb_fname->stream_name) {
33                 /* stream_name must always be NULL if there is no stream. */
34                 SMB_ASSERT(smb_fname->stream_name[0] != '\0');
35
36                 *full_name = talloc_asprintf(ctx, "%s%s", smb_fname->base_name,
37                                              smb_fname->stream_name);
38         } else {
39                 *full_name = talloc_strdup(ctx, smb_fname->base_name);
40         }
41
42         if (!*full_name) {
43                 return NT_STATUS_NO_MEMORY;
44         }
45
46         return NT_STATUS_OK;
47 }
48
49 /**
50  * There are actually legitimate callers of this such as functions that
51  * enumerate streams using the SMB_VFS_STREAMINFO interface and then want to
52  * operate on each stream.
53  */
54 NTSTATUS create_synthetic_smb_fname(TALLOC_CTX *ctx, const char *base_name,
55                                     const char *stream_name,
56                                     const SMB_STRUCT_STAT *psbuf,
57                                     struct smb_filename **smb_fname_out)
58 {
59         struct smb_filename smb_fname_loc;
60
61         ZERO_STRUCT(smb_fname_loc);
62
63         /* Setup the base_name/stream_name. */
64         smb_fname_loc.base_name = CONST_DISCARD(char *, base_name);
65         smb_fname_loc.stream_name = CONST_DISCARD(char *, stream_name);
66
67         /* Copy the psbuf if one was given. */
68         if (psbuf)
69                 smb_fname_loc.st = *psbuf;
70
71         /* Let copy_smb_filename() do the heavy lifting. */
72         return copy_smb_filename(ctx, &smb_fname_loc, smb_fname_out);
73 }
74
75 /**
76  * XXX: This is temporary and there should be no callers of this once
77  * smb_filename is plumbed through all path based operations.
78  */
79 NTSTATUS create_synthetic_smb_fname_split(TALLOC_CTX *ctx,
80                                           const char *fname,
81                                           const SMB_STRUCT_STAT *psbuf,
82                                           struct smb_filename **smb_fname_out)
83 {
84         NTSTATUS status;
85         const char *stream_name = NULL;
86         char *base_name = NULL;
87
88         if (!lp_posix_pathnames()) {
89                 stream_name = strchr_m(fname, ':');
90         }
91
92         /* Setup the base_name/stream_name. */
93         if (stream_name) {
94                 base_name = talloc_strndup(ctx, fname,
95                                            PTR_DIFF(stream_name, fname));
96         } else {
97                 base_name = talloc_strdup(ctx, fname);
98         }
99
100         if (!base_name) {
101                 return NT_STATUS_NO_MEMORY;
102         }
103
104         status = create_synthetic_smb_fname(ctx, base_name, stream_name, psbuf,
105                                             smb_fname_out);
106         TALLOC_FREE(base_name);
107         return status;
108 }
109
110 /**
111  * Return a string using the talloc_tos()
112  */
113 const char *smb_fname_str_dbg(const struct smb_filename *smb_fname)
114 {
115         char *fname = NULL;
116         NTSTATUS status;
117
118         if (smb_fname == NULL) {
119                 return "";
120         }
121         status = get_full_smb_filename(talloc_tos(), smb_fname, &fname);
122         if (!NT_STATUS_IS_OK(status)) {
123                 return "";
124         }
125         return fname;
126 }
127
128 /**
129  * Return a debug string using the talloc_tos().  This can only be called from
130  * DEBUG() macros due to the debut_ctx().
131  */
132 const char *fsp_str_dbg(const struct files_struct *fsp)
133 {
134         return smb_fname_str_dbg(fsp->fsp_name);
135 }
136
137 NTSTATUS copy_smb_filename(TALLOC_CTX *ctx,
138                            const struct smb_filename *smb_fname_in,
139                            struct smb_filename **smb_fname_out)
140 {
141         /* stream_name must always be NULL if there is no stream. */
142         if (smb_fname_in->stream_name) {
143                 SMB_ASSERT(smb_fname_in->stream_name[0] != '\0');
144         }
145
146         *smb_fname_out = talloc_zero(ctx, struct smb_filename);
147         if (*smb_fname_out == NULL) {
148                 return NT_STATUS_NO_MEMORY;
149         }
150
151         if (smb_fname_in->base_name) {
152                 (*smb_fname_out)->base_name =
153                     talloc_strdup(*smb_fname_out, smb_fname_in->base_name);
154                 if (!(*smb_fname_out)->base_name)
155                         goto no_mem_err;
156         }
157
158         if (smb_fname_in->stream_name) {
159                 (*smb_fname_out)->stream_name =
160                     talloc_strdup(*smb_fname_out, smb_fname_in->stream_name);
161                 if (!(*smb_fname_out)->stream_name)
162                         goto no_mem_err;
163         }
164
165         if (smb_fname_in->original_lcomp) {
166                 (*smb_fname_out)->original_lcomp =
167                     talloc_strdup(*smb_fname_out, smb_fname_in->original_lcomp);
168                 if (!(*smb_fname_out)->original_lcomp)
169                         goto no_mem_err;
170         }
171
172         (*smb_fname_out)->st = smb_fname_in->st;
173         return NT_STATUS_OK;
174
175  no_mem_err:
176         TALLOC_FREE(*smb_fname_out);
177         return NT_STATUS_NO_MEMORY;
178 }
179
180 /****************************************************************************
181  Simple check to determine if the filename is a stream.
182  ***************************************************************************/
183 bool is_ntfs_stream_smb_fname(const struct smb_filename *smb_fname)
184 {
185         /* stream_name must always be NULL if there is no stream. */
186         if (smb_fname->stream_name) {
187                 SMB_ASSERT(smb_fname->stream_name[0] != '\0');
188         }
189
190         if (lp_posix_pathnames()) {
191                 return false;
192         }
193
194         return smb_fname->stream_name != NULL;
195 }
196
197 /****************************************************************************
198  Returns true if the filename's stream == "::$DATA"
199  ***************************************************************************/
200 bool is_ntfs_default_stream_smb_fname(const struct smb_filename *smb_fname)
201 {
202         if (!is_ntfs_stream_smb_fname(smb_fname)) {
203                 return false;
204         }
205
206         return StrCaseCmp(smb_fname->stream_name, "::$DATA") == 0;
207 }