Back to index

glibc  2.9
path-lookup.c
Go to the documentation of this file.
00001 /* Filename lookup using a search path
00002    Copyright (C) 1995, 1996, 1997 Free Software Foundation, Inc.
00003    This file is part of the GNU C Library.
00004    Written by Miles Bader <miles@gnu.ai.mit.edu>
00005 
00006    The GNU C Library is free software; you can redistribute it and/or
00007    modify it under the terms of the GNU Lesser General Public
00008    License as published by the Free Software Foundation; either
00009    version 2.1 of the License, or (at your option) any later version.
00010 
00011    The GNU C Library is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Lesser General Public License for more details.
00015 
00016    You should have received a copy of the GNU Lesser General Public
00017    License along with the GNU C Library; if not, write to the Free
00018    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019    02111-1307 USA.  */
00020 
00021 #include <string.h>
00022 #include <hurd.h>
00023 #include <hurd/lookup.h>
00024 
00025 /* If FILE_NAME contains a '/', or PATH is NULL, call FUN with FILE_NAME, and
00026    return the result (if PREFIXED_NAME is non-NULL, setting *PREFIXED_NAME to
00027    NULL).  Otherwise, call FUN repeatedly with FILE_NAME prefixed with each
00028    successive `:' separated element of PATH, returning whenever FUN returns
00029    0 (if PREFIXED_NAME is non-NULL, setting *PREFIXED_NAME to the resulting
00030    prefixed path).  If FUN never returns 0, return the first non-ENOENT
00031    return value, or ENOENT if there is none.  */
00032 error_t
00033 file_name_path_scan (const char *file_name, const char *path,
00034                    error_t (*fun)(const char *name),
00035                    char **prefixed_name)
00036 {
00037   if (path == NULL || index (file_name, '/'))
00038     {
00039       if (prefixed_name)
00040        *prefixed_name = 0;
00041       return (*fun)(file_name);
00042     }
00043   else
00044     {
00045       error_t real_err = 0;
00046       size_t file_name_len = strlen (file_name);
00047 
00048       for (;;)
00049        {
00050          error_t err;
00051          const char *next = index (path, ':') ?: path + strlen (path);
00052          size_t pfx_len = next - path;
00053          char pfxed_name[pfx_len + 2 + file_name_len + 1];
00054 
00055          if (pfx_len == 0)
00056            pfxed_name[pfx_len++] = '.';
00057          else
00058            memcpy (pfxed_name, path, pfx_len);
00059          if (pfxed_name[pfx_len - 1] != '/')
00060            pfxed_name[pfx_len++] = '/';
00061          memcpy (pfxed_name + pfx_len, file_name, file_name_len + 1);
00062 
00063          err = (*fun)(pfxed_name);
00064          if (err == 0)
00065            {
00066              if (prefixed_name)
00067               *prefixed_name = strdup (pfxed_name);
00068              return 0;
00069            }
00070          if (!real_err && err != ENOENT)
00071            real_err = err;
00072 
00073          if (*next == '\0')
00074            return real_err ?: ENOENT;
00075          else
00076            path = next + 1;
00077        }
00078     }
00079 }
00080 
00081 /* Lookup FILE_NAME and return the node opened with FLAGS & MODE in result
00082    (see hurd_file_name_lookup for details), but a simple filename (without
00083    any directory prefixes) will be consecutively prefixed with the pathnames
00084    in the `:' separated list PATH until one succeeds in a successful lookup.
00085    If none succeed, then the first error that wasn't ENOENT is returned, or
00086    ENOENT if no other errors were returned.  If PREFIXED_NAME is non-NULL,
00087    then if RESULT is looked up directly, *PREFIXED_NAME is set to NULL, and
00088    if it is looked up using a prefix from PATH, *PREFIXED_NAME is set to
00089    malloced storage containing the prefixed name.  */
00090 error_t
00091 hurd_file_name_path_lookup (error_t (*use_init_port)
00092                            (int which, error_t (*operate) (mach_port_t)),
00093                          file_t (*get_dtable_port) (int fd),
00094                          error_t (*lookup)
00095                            (file_t dir, char *name, int flags, mode_t mode,
00096                             retry_type *do_retry, string_t retry_name,
00097                             mach_port_t *result),
00098                          const char *file_name, const char *path,
00099                          int flags, mode_t mode,
00100                          file_t *result, char **prefixed_name)
00101 {
00102   error_t scan_lookup (const char *name)
00103     {
00104       return
00105        __hurd_file_name_lookup (use_init_port, get_dtable_port, lookup,
00106                              name, flags, mode, result);
00107     }
00108   return file_name_path_scan (file_name, path, scan_lookup, prefixed_name);
00109 }
00110 
00111 file_t
00112 file_name_path_lookup (const char *file_name, const char *path,
00113                      int flags, mode_t mode, char **prefixed_name)
00114 {
00115   error_t err;
00116   file_t result;
00117 
00118   err = hurd_file_name_path_lookup (&_hurd_ports_use, &__getdport, 0,
00119                                 file_name, path, flags, mode,
00120                                 &result, prefixed_name);
00121 
00122   return err ? (__hurd_fail (err), MACH_PORT_NULL) : result;
00123 }