]> git.ipfire.org Git - thirdparty/glibc.git/blame - hurd/path-lookup.c
posix/glob.c: update from gnulib
[thirdparty/glibc.git] / hurd / path-lookup.c
CommitLineData
8f0c527e 1/* Filename lookup using a search path
581c785b 2 Copyright (C) 1995-2022 Free Software Foundation, Inc.
478b92f0 3 This file is part of the GNU C Library.
8f0c527e 4
478b92f0 5 The GNU C Library is free software; you can redistribute it and/or
41bdb6e2
AJ
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.
8f0c527e 9
478b92f0
UD
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
8f0c527e 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
8f0c527e 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6 16 License along with the GNU C Library; if not, see
5a82c748 17 <https://www.gnu.org/licenses/>. */
8f0c527e
RM
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. */
30error_t
31file_name_path_scan (const char *file_name, const char *path,
32 error_t (*fun)(const char *name),
33 char **prefixed_name)
34{
c7a37ad3 35 if (path == NULL || strchr (file_name, '/'))
8f0c527e
RM
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;
c7a37ad3 49 const char *next = strchr (path, ':') ?: path + strlen (path);
8f0c527e
RM
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
9596d0dd 56 memcpy (pfxed_name, path, pfx_len);
8f0c527e
RM
57 if (pfxed_name[pfx_len - 1] != '/')
58 pfxed_name[pfx_len++] = '/';
9596d0dd 59 memcpy (pfxed_name + pfx_len, file_name, file_name_len + 1);
8f0c527e
RM
60
61 err = (*fun)(pfxed_name);
62 if (err == 0)
63 {
64 if (prefixed_name)
dba2bdbe 65 *prefixed_name = __strdup (pfxed_name);
8f0c527e
RM
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
6d52618b 81 any directory prefixes) will be consecutively prefixed with the pathnames
8f0c527e
RM
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. */
88error_t
7a8f45e3
ST
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)
8f0c527e 99{
bf0f4720 100 error_t scan_lookup (const char *name)
8f0c527e
RM
101 {
102 return
bf0f4720 103 __hurd_file_name_lookup (use_init_port, get_dtable_port, lookup,
8f0c527e
RM
104 name, flags, mode, result);
105 }
bf0f4720 106 return file_name_path_scan (file_name, path, scan_lookup, prefixed_name);
8f0c527e 107}
7a8f45e3 108strong_alias (__hurd_file_name_path_lookup, hurd_file_name_path_lookup)
8f0c527e
RM
109
110file_t
111file_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
7a8f45e3
ST
117 err = __hurd_file_name_path_lookup (&_hurd_ports_use, &__getdport, 0,
118 file_name, path, flags, mode,
119 &result, prefixed_name);
8f0c527e
RM
120
121 return err ? (__hurd_fail (err), MACH_PORT_NULL) : result;
122}