linux: Fix fstat64 on alpha and sparc64
[glibc.git] / hurd / path-lookup.c
blob1922dfc85a04a1a97d057f5781756e0d8c566f56
1 /* Filename lookup using a search path
2 Copyright (C) 1995-2024 Free Software Foundation, Inc.
3 This file is part of the GNU C Library.
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.
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.
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/>. */
19 #include <string.h>
20 #include <hurd.h>
21 #include <hurd/lookup.h>
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)
35 if (path == NULL || strchr (file_name, '/'))
37 if (prefixed_name)
38 *prefixed_name = 0;
39 return (*fun)(file_name);
41 else
43 error_t real_err = 0;
44 size_t file_name_len = strlen (file_name);
46 for (;;)
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];
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);
61 err = (*fun)(pfxed_name);
62 if (err == 0)
64 if (prefixed_name)
65 *prefixed_name = __strdup (pfxed_name);
66 return 0;
68 if (!real_err && err != ENOENT)
69 real_err = err;
71 if (*next == '\0')
72 return real_err ?: ENOENT;
73 else
74 path = next + 1;
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)
100 error_t scan_lookup (const char *name)
102 return
103 __hurd_file_name_lookup (use_init_port, get_dtable_port, lookup,
104 name, flags, mode, result);
106 return file_name_path_scan (file_name, path, scan_lookup, prefixed_name);
108 strong_alias (__hurd_file_name_path_lookup, hurd_file_name_path_lookup)
110 file_t
111 file_name_path_lookup (const char *file_name, const char *path,
112 int flags, mode_t mode, char **prefixed_name)
114 error_t err;
115 file_t result;
117 err = __hurd_file_name_path_lookup (&_hurd_ports_use, &__getdport, 0,
118 file_name, path, flags, mode,
119 &result, prefixed_name);
121 return err ? (__hurd_fail (err), MACH_PORT_NULL) : result;