2 * Unix SMB/CIFS implementation.
3 * Samba utility functions
4 * Copyright (C) Andrew Tridgell 1992-1998
5 * Copyright (C) Jeremy Allison 2001-2007
6 * Copyright (C) Simo Sorce 2001
7 * Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003
8 * Copyright (C) James Peach 2006
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 3 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program. If not, see <http://www.gnu.org/licenses/>.
26 #include "lib/util/samba_util.h"
27 #include "lib/util_path.h"
30 #include "source3/param/param_proto.h"
33 * @brief Returns an absolute path to a file concatenating the provided
34 * @a rootpath and @a basename
36 * @param name Filename, relative to @a rootpath
38 * @retval Pointer to a string containing the full path.
41 static char *xx_path(const char *name
, const char *rootpath
)
45 fname
= talloc_strdup(talloc_tos(), rootpath
);
49 trim_string(fname
,"","/");
51 if (!directory_create_or_exist(fname
, 0755)) {
55 return talloc_asprintf_append(fname
, "/%s", name
);
59 * @brief Returns an absolute path to a file in the Samba lock directory.
61 * @param name File to find, relative to LOCKDIR.
63 * @retval Pointer to a talloc'ed string containing the full path.
66 char *lock_path(const char *name
)
68 return xx_path(name
, lp_lock_directory());
72 * @brief Returns an absolute path to a file in the Samba state directory.
74 * @param name File to find, relative to STATEDIR.
76 * @retval Pointer to a talloc'ed string containing the full path.
79 char *state_path(const char *name
)
81 return xx_path(name
, lp_state_directory());
85 * @brief Returns an absolute path to a file in the Samba cache directory.
87 * @param name File to find, relative to CACHEDIR.
89 * @retval Pointer to a talloc'ed string containing the full path.
92 char *cache_path(const char *name
)
94 return xx_path(name
, lp_cache_directory());
98 * @brief Removes any invalid path components in an absolute POSIX path.
100 * @param ctx Talloc context to return string.
102 * @param abs_path Absolute path string to process.
104 * @retval Pointer to a talloc'ed string containing the absolute full path.
107 char *canonicalize_absolute_path(TALLOC_CTX
*ctx
, const char *abs_path
)
111 const char *s
= abs_path
;
112 bool start_of_name_component
= true;
114 /* Allocate for strlen + '\0' + possible leading '/' */
115 destname
= (char *)talloc_size(ctx
, strlen(abs_path
) + 2);
116 if (destname
== NULL
) {
121 *d
++ = '/'; /* Always start with root. */
125 /* Eat multiple '/' */
129 if ((d
> destname
+ 1) && (*s
!= '\0')) {
132 start_of_name_component
= true;
136 if (start_of_name_component
) {
137 if ((s
[0] == '.') && (s
[1] == '.') &&
138 (s
[2] == '/' || s
[2] == '\0')) {
139 /* Uh oh - "/../" or "/..\0" ! */
141 /* Go past the .. leaving us on the / or '\0' */
144 /* If we just added a '/' - delete it */
145 if ((d
> destname
) && (*(d
-1) == '/')) {
151 * Are we at the start ?
152 * Can't go back further if so.
155 *d
++ = '/'; /* Can't delete root */
158 /* Go back one level... */
160 * Decrement d first as d points to
161 * the *next* char to write into.
163 for (d
--; d
> destname
; d
--) {
170 * Are we at the start ?
171 * Can't go back further if so.
174 *d
++ = '/'; /* Can't delete root */
179 * We're still at the start of a name
180 * component, just the previous one.
183 } else if ((s
[0] == '.') &&
184 ((s
[1] == '\0') || s
[1] == '/')) {
186 * Component of pathname can't be "." only.
202 /* Get the size of the next MB character. */
203 next_codepoint(s
,&siz
);
224 start_of_name_component
= false;
228 /* And must not end in '/' */
229 if (d
> destname
+ 1 && (*(d
-1) == '/')) {