path-lookup.c 4.2 KB

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