(root)/
glibc-2.38/
misc/
dirname.c
       1  /* dirname - return directory part of PATH.
       2     Copyright (C) 1996-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 <libgen.h>
      20  #include <string.h>
      21  
      22  
      23  char *
      24  dirname (char *path)
      25  {
      26    static const char dot[] = ".";
      27    char *last_slash;
      28  
      29    /* Find last '/'.  */
      30    last_slash = path != NULL ? strrchr (path, '/') : NULL;
      31  
      32    if (last_slash != NULL && last_slash != path && last_slash[1] == '\0')
      33      {
      34        /* Determine whether all remaining characters are slashes.  */
      35        char *runp;
      36  
      37        for (runp = last_slash; runp != path; --runp)
      38  	if (runp[-1] != '/')
      39  	  break;
      40  
      41        /* The '/' is the last character, we have to look further.  */
      42        if (runp != path)
      43  	last_slash = __memrchr (path, '/', runp - path);
      44      }
      45  
      46    if (last_slash != NULL)
      47      {
      48        /* Determine whether all remaining characters are slashes.  */
      49        char *runp;
      50  
      51        for (runp = last_slash; runp != path; --runp)
      52  	if (runp[-1] != '/')
      53  	  break;
      54  
      55        /* Terminate the path.  */
      56        if (runp == path)
      57  	{
      58  	  /* The last slash is the first character in the string.  We have to
      59  	     return "/".  As a special case we have to return "//" if there
      60  	     are exactly two slashes at the beginning of the string.  See
      61  	     XBD 4.10 Path Name Resolution for more information.  */
      62  	  if (last_slash == path + 1)
      63  	    ++last_slash;
      64  	  else
      65  	    last_slash = path + 1;
      66  	}
      67        else
      68  	last_slash = runp;
      69  
      70        last_slash[0] = '\0';
      71      }
      72    else
      73      /* This assignment is ill-designed but the XPG specs require to
      74         return a string containing "." in any case no directory part is
      75         found and so a static and constant string is required.  */
      76      path = (char *) dot;
      77  
      78    return path;
      79  }