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