(root)/
glibc-2.38/
sysdeps/
unix/
sysv/
linux/
dl-origin.c
       1  /* Find path of executable.
       2     Copyright (C) 1998-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 <assert.h>
      20  #include <dl-dst.h>
      21  #include <fcntl.h>
      22  #include <ldsodefs.h>
      23  #include <sysdep.h>
      24  
      25  /* On Linux >= 2.1 systems which have the dcache implementation we can get
      26     the path of the application from the /proc/self/exe symlink.  Try this
      27     first and fall back on the generic method if necessary.  */
      28  
      29  const char *
      30  _dl_get_origin (void)
      31  {
      32    char linkval[PATH_MAX];
      33    char *result;
      34    int len;
      35  
      36    len = INTERNAL_SYSCALL_CALL (readlinkat, AT_FDCWD, "/proc/self/exe",
      37  			       linkval, sizeof (linkval));
      38    if (len > 0 && linkval[0] != '[')
      39      {
      40        /* We can use this value.  */
      41        assert (linkval[0] == '/');
      42        while (len > 1 && linkval[len - 1] != '/')
      43  	--len;
      44        result = (char *) malloc (len + 1);
      45        if (result == NULL)
      46  	result = (char *) -1;
      47        else if (len == 1)
      48  	memcpy (result, "/", 2);
      49        else
      50  	*((char *) __mempcpy (result, linkval, len - 1)) = '\0';
      51      }
      52    else
      53      {
      54        result = (char *) -1;
      55        /* We use the environment variable LD_ORIGIN_PATH.  If it is set make
      56  	 a copy and strip out trailing slashes.  */
      57        if (GLRO(dl_origin_path) != NULL)
      58  	{
      59  	  size_t len = strlen (GLRO(dl_origin_path));
      60  	  result = (char *) malloc (len + 1);
      61  	  if (result == NULL)
      62  	    result = (char *) -1;
      63  	  else
      64  	    {
      65  	      char *cp = __mempcpy (result, GLRO(dl_origin_path), len);
      66  	      while (cp > result + 1 && cp[-1] == '/')
      67  		--cp;
      68  	      *cp = '\0';
      69  	    }
      70  	}
      71      }
      72  
      73    return result;
      74  }