dirname.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /*
  2. * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. * 3. The name of the author may not be used to endorse or promote products
  14. * derived from this software without specific prior written permission.
  15. *
  16. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
  17. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
  18. * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
  19. * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
  20. * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
  21. * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
  22. * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
  23. * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  24. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
  25. * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  26. */
  27. #include <errno.h>
  28. #include <libgen.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <memdebug.h>
  32. #if !defined(MAXPATHLEN)
  33. #define MAXPATHLEN 256
  34. #endif
  35. /*!
  36. * \file fs/dirname.c
  37. * \brief Extracts the directory part of a pathname.
  38. *
  39. * \verbatim
  40. *
  41. * $Log$
  42. * Revision 1.2 2009/02/13 14:52:05 haraldkipp
  43. * Include memdebug.h for heap management debugging support.
  44. *
  45. * Revision 1.1 2006/08/01 07:42:56 haraldkipp
  46. * New functions extract last component and parent directory from pathnames.
  47. *
  48. *
  49. * \endverbatim
  50. */
  51. /*!
  52. * \brief Extract the directory part of a given pathname.
  53. *
  54. * This is the converse of basename().
  55. *
  56. * \param path Pointer to the pathname.
  57. *
  58. * \return A pointer to the parent directory of the pathname. Any
  59. * trailing slash is not counted as part of the directory
  60. * name. If the specified pathname is a null pointer, an
  61. * empty string, or contains no slash character, then a
  62. * single dot is returned. On failures, a NULL pointer
  63. * is returned and the global variable errno is set to
  64. * indicate the error.
  65. */
  66. char *dirname(const char *path)
  67. {
  68. static char *bname;
  69. const char *endp;
  70. if (bname == NULL) {
  71. bname = (char *) malloc(MAXPATHLEN);
  72. if (bname == NULL)
  73. return (NULL);
  74. }
  75. /* Empty or NULL string gets treated as "." */
  76. if (path == NULL || *path == '\0') {
  77. strncpy(bname, ".", MAXPATHLEN);
  78. return (bname);
  79. }
  80. /* Strip trailing slashes */
  81. endp = path + strlen(path) - 1;
  82. while (endp > path && *endp == '/')
  83. endp--;
  84. /* Find the start of the dir */
  85. while (endp > path && *endp != '/')
  86. endp--;
  87. /* Either the dir is "/" or there are no slashes */
  88. if (endp == path) {
  89. strncpy(bname, *endp == '/' ? "/" : ".", MAXPATHLEN);
  90. return (bname);
  91. }
  92. do {
  93. endp--;
  94. } while (endp > path && *endp == '/');
  95. if (endp - path + 2 > MAXPATHLEN) {
  96. errno = ENAMETOOLONG;
  97. return (NULL);
  98. }
  99. strcpy(bname, path);
  100. bname[(endp - path) + 1] = 0;
  101. return (bname);
  102. }