LCOV - code coverage report
Current view: top level - source3/lib - util_path.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 51 75 68.0 %
Date: 2024-06-13 04:01:37 Functions: 6 6 100.0 %

          Line data    Source code
       1             : /*
       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
       9             :  *
      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.
      14             :  *
      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.
      19             :  *
      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/>.
      22             :  */
      23             : 
      24             : #include "replace.h"
      25             : #include <talloc.h>
      26             : #include "lib/util/debug.h"
      27             : #include "lib/util/samba_util.h"
      28             : #include "lib/util_path.h"
      29             : 
      30             : struct loadparm_substitution;
      31             : struct share_params;
      32             : #include "source3/param/param_proto.h"
      33             : 
      34             : /**
      35             :  * @brief Returns an absolute path to a file concatenating the provided
      36             :  * @a rootpath and @a basename
      37             :  *
      38             :  * @param name Filename, relative to @a rootpath
      39             :  *
      40             :  * @retval Pointer to a string containing the full path.
      41             :  **/
      42             : 
      43       21548 : static char *xx_path(TALLOC_CTX *mem_ctx,
      44             :                      const char *name,
      45             :                      const char *rootpath)
      46             : {
      47       21548 :         char *fname = NULL;
      48             : 
      49       21548 :         fname = talloc_strdup(mem_ctx, rootpath);
      50       21548 :         if (!fname) {
      51           0 :                 return NULL;
      52             :         }
      53       21548 :         trim_string(fname,"","/");
      54             : 
      55       21548 :         if (!directory_create_or_exist(fname, 0755)) {
      56           0 :                 return NULL;
      57             :         }
      58             : 
      59       21548 :         return talloc_asprintf_append(fname, "/%s", name);
      60             : }
      61             : 
      62             : /**
      63             :  * @brief Returns an absolute path to a file in the Samba lock directory.
      64             :  *
      65             :  * @param name File to find, relative to LOCKDIR.
      66             :  *
      67             :  * @retval Pointer to a talloc'ed string containing the full path.
      68             :  **/
      69             : 
      70        9859 : char *lock_path(TALLOC_CTX *mem_ctx, const char *name)
      71             : {
      72        9859 :         return xx_path(mem_ctx, name, lp_lock_directory());
      73             : }
      74             : 
      75             : /**
      76             :  * @brief Returns an absolute path to a file in the Samba state directory.
      77             :  *
      78             :  * @param name File to find, relative to STATEDIR.
      79             :  *
      80             :  * @retval Pointer to a talloc'ed string containing the full path.
      81             :  **/
      82             : 
      83       11437 : char *state_path(TALLOC_CTX *mem_ctx, const char *name)
      84             : {
      85       11437 :         return xx_path(mem_ctx, name, lp_state_directory());
      86             : }
      87             : 
      88             : /**
      89             :  * @brief Returns an absolute path to a file in the Samba cache directory.
      90             :  *
      91             :  * @param name File to find, relative to CACHEDIR.
      92             :  *
      93             :  * @retval Pointer to a talloc'ed string containing the full path.
      94             :  **/
      95             : 
      96         252 : char *cache_path(TALLOC_CTX *mem_ctx, const char *name)
      97             : {
      98         252 :         return xx_path(mem_ctx, name, lp_cache_directory());
      99             : }
     100             : 
     101             : /**
     102             :  * @brief Removes any invalid path components in an absolute POSIX path.
     103             :  *
     104             :  * @param ctx Talloc context to return string.
     105             :  *
     106             :  * @param abs_path Absolute path string to process.
     107             :  *
     108             :  * @retval Pointer to a talloc'ed string containing the absolute full path.
     109             :  **/
     110             : 
     111       25007 : char *canonicalize_absolute_path(TALLOC_CTX *ctx, const char *pathname_in)
     112             : {
     113             :         /*
     114             :          * Note we use +2 here so if pathname_in=="" then we
     115             :          * have space to return "/".
     116             :          */
     117       25007 :         char *pathname = talloc_array(ctx, char, strlen(pathname_in)+2);
     118       25007 :         const char *s = pathname_in;
     119       25007 :         char *p = pathname;
     120             : 
     121       25007 :         if (pathname == NULL) {
     122           0 :                 return NULL;
     123             :         }
     124             : 
     125             :         /* Always start with a '/'. */
     126       25007 :         *p++ = '/';
     127             : 
     128     1416989 :         while (*s) {
     129             :                 /* Deal with '/' or multiples of '/'. */
     130     1375366 :                 if (s[0] == '/') {
     131      522144 :                         while (s[0] == '/') {
     132             :                                 /* Eat trailing '/' */
     133      200632 :                                 s++;
     134             :                         }
     135             :                         /* Update target with one '/' */
     136      200624 :                         if (p[-1] != '/') {
     137      175617 :                                 *p++ = '/';
     138             :                         }
     139      200624 :                         continue;
     140             :                 }
     141     1174742 :                 if (p[-1] == '/') {
     142             :                         /* Deal with "./" or ".\0" */
     143      197590 :                         if (s[0] == '.' &&
     144          12 :                                         (s[1] == '/' || s[1] == '\0')) {
     145             :                                 /* Eat the dot. */
     146           8 :                                 s++;
     147          12 :                                 while (s[0] == '/') {
     148             :                                         /* Eat any trailing '/' */
     149           0 :                                         s++;
     150             :                                 }
     151             :                                 /* Don't write anything to target. */
     152           8 :                                 continue;
     153             :                         }
     154             :                         /* Deal with "../" or "..\0" */
     155      197578 :                         if (s[0] == '.' && s[1] == '.' &&
     156           0 :                                         (s[2] == '/' || s[2] == '\0')) {
     157             :                                 /* Eat the dot dot. */
     158           0 :                                 s += 2;
     159           0 :                                 while (s[0] == '/') {
     160             :                                         /* Eat any trailing '/' */
     161           0 :                                         s++;
     162             :                                 }
     163             :                                 /*
     164             :                                  * As we're on the slash, we go back
     165             :                                  * one character to point p at the
     166             :                                  * slash we just saw.
     167             :                                  */
     168           0 :                                 if (p > pathname) {
     169           0 :                                         p--;
     170             :                                 }
     171             :                                 /*
     172             :                                  * Now go back to the slash
     173             :                                  * before the one that p currently points to.
     174             :                                  */
     175           0 :                                 while (p > pathname) {
     176           0 :                                         p--;
     177           0 :                                         if (p[0] == '/') {
     178           0 :                                                 break;
     179             :                                         }
     180             :                                 }
     181             :                                 /*
     182             :                                  * Step forward one to leave the
     183             :                                  * last written '/' alone.
     184             :                                  */
     185           0 :                                 p++;
     186             : 
     187             :                                 /* Don't write anything to target. */
     188           0 :                                 continue;
     189             :                         }
     190             :                 }
     191             :                 /* Non-separator character, just copy. */
     192     1174734 :                 *p++ = *s++;
     193             :         }
     194       25007 :         if (p[-1] == '/') {
     195             :                 /*
     196             :                  * We finished on a '/'.
     197             :                  * Remove the trailing '/', but not if it's
     198             :                  * the sole character in the path.
     199             :                  */
     200        3046 :                 if (p > pathname + 1) {
     201           0 :                         p--;
     202             :                 }
     203             :         }
     204             :         /* Terminate and we're done ! */
     205       25007 :         *p++ = '\0';
     206       25007 :         return pathname;
     207             : }
     208             : 
     209             : /*
     210             :  * Take two absolute paths, figure out if "subdir" is a proper
     211             :  * subdirectory of "parent". Return the component relative to the
     212             :  * "parent" without the potential "/". Take care of "parent"
     213             :  * possibly ending in "/".
     214             :  */
     215        3444 : bool subdir_of(const char *parent,
     216             :                size_t parent_len,
     217             :                const char *subdir,
     218             :                const char **_relative)
     219             : {
     220        3444 :         const char *relative = NULL;
     221             :         bool matched;
     222             : 
     223        3444 :         SMB_ASSERT(parent[0] == '/');
     224        3444 :         SMB_ASSERT(subdir[0] == '/');
     225             : 
     226        3444 :         if (parent_len == 1) {
     227             :                 /*
     228             :                  * Everything is below "/"
     229             :                  */
     230           0 :                 *_relative = subdir+1;
     231           0 :                 return true;
     232             :         }
     233             : 
     234        3444 :         if (parent[parent_len-1] == '/') {
     235           0 :                 parent_len -= 1;
     236             :         }
     237             : 
     238        3444 :         matched = (strncmp(subdir, parent, parent_len) == 0);
     239        3444 :         if (!matched) {
     240           0 :                 return false;
     241             :         }
     242             : 
     243        3444 :         relative = &subdir[parent_len];
     244             : 
     245        3444 :         if (relative[0] == '\0') {
     246           0 :                 *_relative = relative; /* nothing left */
     247           0 :                 return true;
     248             :         }
     249             : 
     250        3444 :         if (relative[0] == '/') {
     251             :                 /* End of parent must match a '/' in subdir. */
     252        3444 :                 *_relative = relative+1;
     253        3444 :                 return true;
     254             :         }
     255             : 
     256           0 :         return false;
     257             : }

Generated by: LCOV version 1.13