(root)/
glibc-2.38/
hurd/
lookup-at.c
       1  /* Lookup helper function for Hurd implementation of *at functions.
       2     Copyright (C) 2006-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 <hurd.h>
      20  #include <hurd/lookup.h>
      21  #include <hurd/fd.h>
      22  #include <string.h>
      23  #include <fcntl.h>
      24  
      25  file_t
      26  __file_name_lookup_at (int fd, int at_flags,
      27  		       const char *file_name, int flags, mode_t mode)
      28  {
      29    error_t err;
      30    file_t result;
      31    int empty = at_flags & AT_EMPTY_PATH;
      32    int orig_flags;
      33  
      34    at_flags &= ~AT_EMPTY_PATH;
      35  
      36    err = __hurd_at_flags (&at_flags, &flags);
      37    if (err)
      38      return (__hurd_fail (err), MACH_PORT_NULL);
      39  
      40    if (empty != 0 && file_name[0] == '\0')
      41      {
      42        enum retry_type doretry;
      43        char retryname[1024];	/* XXX string_t LOSES! */
      44  
      45        err = HURD_DPORT_USE (fd, __dir_lookup (port, "", flags, mode,
      46  					      &doretry, retryname,
      47  					      &result));
      48  
      49        if (! err)
      50  	err = __hurd_file_name_lookup_retry (&_hurd_ports_use, &__getdport,
      51  					     NULL, doretry, retryname,
      52  					     flags, mode, &result);
      53  
      54        return err ? (__hurd_dfail (fd, err), MACH_PORT_NULL) : result;
      55      }
      56  
      57    orig_flags = flags;
      58    if (flags & O_TMPFILE)
      59      flags = O_DIRECTORY;
      60  
      61    if (fd == AT_FDCWD || file_name[0] == '/')
      62      {
      63        err = __hurd_file_name_lookup (&_hurd_ports_use, &__getdport, 0,
      64                                       file_name, flags, mode & ~_hurd_umask,
      65                                       &result);
      66        if (err)
      67          {
      68            __hurd_fail (err);
      69            return MACH_PORT_NULL;
      70          }
      71      }
      72    else
      73      {
      74        file_t startdir;
      75        /* We need to look the file up relative to the given directory (and
      76           not our cwd).  For this to work, we supply our own wrapper for
      77           _hurd_ports_use, which replaces cwd with our startdir.  */
      78        error_t use_init_port (int which, error_t (*operate) (mach_port_t))
      79          {
      80            return (which == INIT_PORT_CWDIR ? (*operate) (startdir)
      81  	          : _hurd_ports_use (which, operate));
      82          }
      83  
      84        err = HURD_DPORT_USE (fd, (startdir = port,
      85                                   __hurd_file_name_lookup (&use_init_port,
      86                                                            &__getdport, NULL,
      87                                                            file_name,
      88                                                            flags,
      89                                                            mode & ~_hurd_umask,
      90                                                            &result)));
      91        if (err)
      92          {
      93            __hurd_dfail (fd, err);
      94            return MACH_PORT_NULL;
      95          }
      96      }
      97  
      98    if (orig_flags & O_TMPFILE)
      99      {
     100        /* What we have looked up is not the file itself, but actually
     101           the directory to create the file in.  Do that now.  */
     102        file_t dir = result;
     103  
     104        err = __dir_mkfile (dir, orig_flags & ~(O_TMPFILE | O_DIRECTORY),
     105                            mode, &result);
     106        __mach_port_deallocate (__mach_task_self (), dir);
     107        if (err)
     108          {
     109            __hurd_fail (err);
     110            return MACH_PORT_NULL;
     111          }
     112      }
     113  
     114    return result;
     115  }
     116  
     117  file_t
     118  __file_name_split_at (int fd, const char *file_name, char **name)
     119  {
     120    error_t err;
     121    file_t result;
     122  
     123    if (fd == AT_FDCWD || file_name[0] == '/')
     124      return __file_name_split (file_name, name);
     125  
     126    err = __hurd_file_name_split (&_hurd_ports_use, &__getdport, 0,
     127  				file_name, &result, name);
     128  
     129    file_t startdir;
     130    error_t use_init_port (int which, error_t (*operate) (mach_port_t))
     131    {
     132      return (which == INIT_PORT_CWDIR ? (*operate) (startdir)
     133  	    : _hurd_ports_use (which, operate));
     134    }
     135  
     136    err = HURD_DPORT_USE (fd, (startdir = port,
     137  			     __hurd_file_name_split (&use_init_port,
     138  						     &__getdport, 0,
     139  						     file_name,
     140  						     &result, name)));
     141  
     142    return err ? (__hurd_dfail (fd, err), MACH_PORT_NULL) : result;
     143  }
     144  
     145  file_t
     146  __directory_name_split_at (int fd, const char *directory_name, char **name)
     147  {
     148    error_t err;
     149    file_t result;
     150  
     151    if (fd == AT_FDCWD || directory_name[0] == '/')
     152      return __directory_name_split (directory_name, name);
     153  
     154    file_t startdir;
     155    error_t use_init_port (int which, error_t (*operate) (mach_port_t))
     156      {
     157        return (which == INIT_PORT_CWDIR ? (*operate) (startdir)
     158  	      : _hurd_ports_use (which, operate));
     159      }
     160  
     161    err = HURD_DPORT_USE (fd, (startdir = port,
     162  			     __hurd_directory_name_split (&use_init_port,
     163  							  &__getdport, 0,
     164  							  directory_name,
     165  							  &result, name)));
     166  
     167    return err ? (__hurd_dfail (fd, err), MACH_PORT_NULL) : result;
     168  }