/usr/src/lib/libgen/common/rmdirp.c

https://github.com/richlowe/illumos-gate · C · 141 lines · 67 code · 25 blank · 49 comment · 27 complexity · a03e2a97070cb927392d6bcdbb0d4aea MD5 · raw file

  1. /*
  2. * CDDL HEADER START
  3. *
  4. * The contents of this file are subject to the terms of the
  5. * Common Development and Distribution License (the "License").
  6. * You may not use this file except in compliance with the License.
  7. *
  8. * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  9. * or http://www.opensolaris.org/os/licensing.
  10. * See the License for the specific language governing permissions
  11. * and limitations under the License.
  12. *
  13. * When distributing Covered Code, include this CDDL HEADER in each
  14. * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15. * If applicable, add the following below this CDDL HEADER, with the
  16. * fields enclosed by brackets "[]" replaced with your own identifying
  17. * information: Portions Copyright [yyyy] [name of copyright owner]
  18. *
  19. * CDDL HEADER END
  20. */
  21. /*
  22. * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
  23. * Use is subject to license terms.
  24. */
  25. /* Copyright (c) 1988 AT&T */
  26. /* All Rights Reserved */
  27. #pragma ident "%Z%%M% %I% %E% SMI"
  28. /*
  29. * rmdirp() removes directories in path "d". Removal starts from the
  30. * right most directory in the path and goes backward as far as possible.
  31. * The remaining path, which is not removed for some reason, is stored in "d1".
  32. * If nothing remains, "d1" is empty.
  33. *
  34. * rmdirp()
  35. * returns 0 only if it succeeds in removing every directory in d.
  36. * returns -1 if removal stops because of errors other than the following.
  37. * returns -2 if removal stops when "." or ".." is encountered in path.
  38. * returns -3 if removal stops because it's the current directory.
  39. */
  40. #include <sys/types.h>
  41. #include <libgen.h>
  42. #include <sys/stat.h>
  43. #include <string.h>
  44. #include <unistd.h>
  45. static int dotdot(char *);
  46. int
  47. rmdirp(char *d, char *d1)
  48. {
  49. struct stat64 st, cst;
  50. int currstat;
  51. char *slash;
  52. slash = strrchr(d, '/');
  53. currstat = stat64(".", &cst);
  54. /* Starts from right most element */
  55. while (d) {
  56. /* If it's under current directory */
  57. if (slash == NULL) {
  58. /* Stop if it's . or .. */
  59. if (dotdot(d)) {
  60. (void) strcpy(d1, d);
  61. return (-2);
  62. }
  63. /* Stop if can not stat it */
  64. } else { /* If there's a slash before it */
  65. /* If extra / in the end */
  66. if (slash != d) {
  67. if (++slash == strrchr(d, '\0')) {
  68. *(--slash) = '\0';
  69. slash = strrchr(d, '/');
  70. continue;
  71. } else {
  72. slash--;
  73. }
  74. }
  75. /* Stop if it's . or .. */
  76. if (dotdot(++slash)) {
  77. (void) strcpy(d1, d);
  78. return (-2);
  79. }
  80. slash--;
  81. /* Stop if can not stat it */
  82. if (stat64(d, &st) < 0) {
  83. (void) strcpy(d1, d);
  84. return (-1);
  85. }
  86. if (currstat == 0) {
  87. /* Stop if it's current directory */
  88. if ((st.st_ino == cst.st_ino) &&
  89. (st.st_dev == cst.st_dev)) {
  90. (void) strcpy(d1, d);
  91. return (-3);
  92. }
  93. }
  94. } /* End of else */
  95. /* Remove it */
  96. if (rmdir(d) != 0) {
  97. (void) strcpy(d1, d);
  98. return (-1);
  99. }
  100. /* Have reached left end, break */
  101. if (slash == NULL || slash == d)
  102. break;
  103. /* Go backward to next directory */
  104. *slash = '\0';
  105. slash = strrchr(d, '/');
  106. }
  107. *d1 = '\0';
  108. return (0);
  109. }
  110. static int
  111. dotdot(char *dir)
  112. {
  113. if (strcmp(dir, ".") == 0 || strcmp(dir, "..") == 0)
  114. return (-1);
  115. return (0);
  116. }