recursive_action.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. /* vi: set sw=4 ts=4: */
  2. /*
  3. * Utility routines.
  4. *
  5. * Copyright (C) 1999-2004 by Erik Andersen <andersen@codepoet.org>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  15. * General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  20. */
  21. #include <stdio.h>
  22. #include <string.h>
  23. #include <dirent.h>
  24. #include <sys/stat.h>
  25. #include <stdlib.h> /* free() */
  26. #include "libbb.h"
  27. #undef DEBUG_RECURS_ACTION
  28. /*
  29. * Walk down all the directories under the specified
  30. * location, and do something (something specified
  31. * by the fileAction and dirAction function pointers).
  32. *
  33. * Unfortunately, while nftw(3) could replace this and reduce
  34. * code size a bit, nftw() wasn't supported before GNU libc 2.1,
  35. * and so isn't sufficiently portable to take over since glibc2.1
  36. * is so stinking huge.
  37. */
  38. int recursive_action(const char *fileName,
  39. int recurse, int followLinks, int depthFirst,
  40. int (*fileAction) (const char *fileName,
  41. struct stat * statbuf,
  42. void* userData),
  43. int (*dirAction) (const char *fileName,
  44. struct stat * statbuf,
  45. void* userData),
  46. void* userData)
  47. {
  48. int status;
  49. struct stat statbuf;
  50. struct dirent *next;
  51. if (followLinks)
  52. status = stat(fileName, &statbuf);
  53. else
  54. status = lstat(fileName, &statbuf);
  55. if (status < 0) {
  56. #ifdef DEBUG_RECURS_ACTION
  57. bb_error_msg("status=%d followLinks=%d TRUE=%d",
  58. status, followLinks, TRUE);
  59. #endif
  60. bb_perror_msg("%s", fileName);
  61. return FALSE;
  62. }
  63. if (! followLinks && (S_ISLNK(statbuf.st_mode))) {
  64. if (fileAction == NULL)
  65. return TRUE;
  66. else
  67. return fileAction(fileName, &statbuf, userData);
  68. }
  69. if (! recurse) {
  70. if (S_ISDIR(statbuf.st_mode)) {
  71. if (dirAction != NULL)
  72. return (dirAction(fileName, &statbuf, userData));
  73. else
  74. return TRUE;
  75. }
  76. }
  77. if (S_ISDIR(statbuf.st_mode)) {
  78. DIR *dir;
  79. if (dirAction != NULL && ! depthFirst) {
  80. status = dirAction(fileName, &statbuf, userData);
  81. if (! status) {
  82. bb_perror_msg("%s", fileName);
  83. return FALSE;
  84. } else if (status == SKIP)
  85. return TRUE;
  86. }
  87. dir = opendir(fileName);
  88. if (!dir) {
  89. bb_perror_msg("%s", fileName);
  90. return FALSE;
  91. }
  92. status = TRUE;
  93. while ((next = readdir(dir)) != NULL) {
  94. char *nextFile;
  95. nextFile = concat_subpath_file(fileName, next->d_name);
  96. if(nextFile == NULL)
  97. continue;
  98. if (! recursive_action(nextFile, TRUE, followLinks, depthFirst,
  99. fileAction, dirAction, userData)) {
  100. status = FALSE;
  101. }
  102. free(nextFile);
  103. }
  104. closedir(dir);
  105. if (dirAction != NULL && depthFirst) {
  106. if (! dirAction(fileName, &statbuf, userData)) {
  107. bb_perror_msg("%s", fileName);
  108. return FALSE;
  109. }
  110. }
  111. if (! status)
  112. return FALSE;
  113. } else {
  114. if (fileAction == NULL)
  115. return TRUE;
  116. else
  117. return fileAction(fileName, &statbuf, userData);
  118. }
  119. return TRUE;
  120. }
  121. /* END CODE */
  122. /*
  123. Local Variables:
  124. c-file-style: "linux"
  125. c-basic-offset: 4
  126. tab-width: 4
  127. End:
  128. */