(root)/
glibc-2.38/
hurd/
path-lookup.c
       1  /* Filename lookup using a search path
       2     Copyright (C) 1995-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <string.h>
      20  #include <hurd.h>
      21  #include <hurd/lookup.h>
      22  
      23  /* If FILE_NAME contains a '/', or PATH is NULL, call FUN with FILE_NAME, and
      24     return the result (if PREFIXED_NAME is non-NULL, setting *PREFIXED_NAME to
      25     NULL).  Otherwise, call FUN repeatedly with FILE_NAME prefixed with each
      26     successive `:' separated element of PATH, returning whenever FUN returns
      27     0 (if PREFIXED_NAME is non-NULL, setting *PREFIXED_NAME to the resulting
      28     prefixed path).  If FUN never returns 0, return the first non-ENOENT
      29     return value, or ENOENT if there is none.  */
      30  error_t
      31  file_name_path_scan (const char *file_name, const char *path,
      32  		     error_t (*fun)(const char *name),
      33  		     char **prefixed_name)
      34  {
      35    if (path == NULL || strchr (file_name, '/'))
      36      {
      37        if (prefixed_name)
      38  	*prefixed_name = 0;
      39        return (*fun)(file_name);
      40      }
      41    else
      42      {
      43        error_t real_err = 0;
      44        size_t file_name_len = strlen (file_name);
      45  
      46        for (;;)
      47  	{
      48  	  error_t err;
      49  	  const char *next = strchr (path, ':') ?: path + strlen (path);
      50  	  size_t pfx_len = next - path;
      51  	  char pfxed_name[pfx_len + 2 + file_name_len + 1];
      52  
      53  	  if (pfx_len == 0)
      54  	    pfxed_name[pfx_len++] = '.';
      55  	  else
      56  	    memcpy (pfxed_name, path, pfx_len);
      57  	  if (pfxed_name[pfx_len - 1] != '/')
      58  	    pfxed_name[pfx_len++] = '/';
      59  	  memcpy (pfxed_name + pfx_len, file_name, file_name_len + 1);
      60  
      61  	  err = (*fun)(pfxed_name);
      62  	  if (err == 0)
      63  	    {
      64  	      if (prefixed_name)
      65  		*prefixed_name = __strdup (pfxed_name);
      66  	      return 0;
      67  	    }
      68  	  if (!real_err && err != ENOENT)
      69  	    real_err = err;
      70  
      71  	  if (*next == '\0')
      72  	    return real_err ?: ENOENT;
      73  	  else
      74  	    path = next + 1;
      75  	}
      76      }
      77  }
      78  
      79  /* Lookup FILE_NAME and return the node opened with FLAGS & MODE in result
      80     (see hurd_file_name_lookup for details), but a simple filename (without
      81     any directory prefixes) will be consecutively prefixed with the pathnames
      82     in the `:' separated list PATH until one succeeds in a successful lookup.
      83     If none succeed, then the first error that wasn't ENOENT is returned, or
      84     ENOENT if no other errors were returned.  If PREFIXED_NAME is non-NULL,
      85     then if RESULT is looked up directly, *PREFIXED_NAME is set to NULL, and
      86     if it is looked up using a prefix from PATH, *PREFIXED_NAME is set to
      87     malloced storage containing the prefixed name.  */
      88  error_t
      89  __hurd_file_name_path_lookup (error_t (*use_init_port)
      90  			        (int which, error_t (*operate) (mach_port_t)),
      91  			      file_t (*get_dtable_port) (int fd),
      92  			      error_t (*lookup)
      93  			        (file_t dir, const char *name, int flags, mode_t mode,
      94  			         retry_type *do_retry, string_t retry_name,
      95  			         mach_port_t *result),
      96  			      const char *file_name, const char *path,
      97  			      int flags, mode_t mode,
      98  			      file_t *result, char **prefixed_name)
      99  {
     100    error_t scan_lookup (const char *name)
     101      {
     102        return
     103  	__hurd_file_name_lookup (use_init_port, get_dtable_port, lookup,
     104  				 name, flags, mode, result);
     105      }
     106    return file_name_path_scan (file_name, path, scan_lookup, prefixed_name);
     107  }
     108  strong_alias (__hurd_file_name_path_lookup, hurd_file_name_path_lookup)
     109  
     110  file_t
     111  file_name_path_lookup (const char *file_name, const char *path,
     112  		       int flags, mode_t mode, char **prefixed_name)
     113  {
     114    error_t err;
     115    file_t result;
     116  
     117    err = __hurd_file_name_path_lookup (&_hurd_ports_use, &__getdport, 0,
     118  				      file_name, path, flags, mode,
     119  				      &result, prefixed_name);
     120  
     121    return err ? (__hurd_fail (err), MACH_PORT_NULL) : result;
     122  }