savedir.c revision 131555
1/* savedir.c -- save the list of files in a directory in a string 2 Copyright (C) 1990, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. 3 4 This program is free software; you can redistribute it and/or modify 5 it under the terms of the GNU General Public License as published by 6 the Free Software Foundation; either version 2, or (at your option) 7 any later version. 8 9 This program is distributed in the hope that it will be useful, 10 but WITHOUT ANY WARRANTY; without even the implied warranty of 11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 GNU General Public License for more details. 13 14 You should have received a copy of the GNU General Public License 15 along with this program; if not, write to the Free Software Foundation, 16 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 17 18/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */ 19 20#if HAVE_CONFIG_H 21# include <config.h> 22#endif 23 24#include <sys/types.h> 25 26#if HAVE_UNISTD_H 27# include <unistd.h> 28#endif 29 30#if HAVE_DIRENT_H 31# include <dirent.h> 32# define NAMLEN(dirent) strlen((dirent)->d_name) 33#else 34# define dirent direct 35# define NAMLEN(dirent) (dirent)->d_namlen 36# if HAVE_SYS_NDIR_H 37# include <sys/ndir.h> 38# endif 39# if HAVE_SYS_DIR_H 40# include <sys/dir.h> 41# endif 42# if HAVE_NDIR_H 43# include <ndir.h> 44# endif 45#endif 46 47#ifdef CLOSEDIR_VOID 48/* Fake a return value. */ 49# define CLOSEDIR(d) (closedir (d), 0) 50#else 51# define CLOSEDIR(d) closedir (d) 52#endif 53 54#ifdef STDC_HEADERS 55# include <stdlib.h> 56# include <string.h> 57#else 58char *malloc (); 59char *realloc (); 60#endif 61#ifndef NULL 62# define NULL 0 63#endif 64 65#ifndef stpcpy 66char *stpcpy (); 67#endif 68 69#include <fnmatch.h> 70#include "savedir.h" 71 72char *path; 73size_t pathlen; 74 75static int 76isdir1 (const char *dir, const char *file) 77{ 78 int status; 79 int slash; 80 size_t dirlen = strlen (dir); 81 size_t filelen = strlen (file); 82 if ((dirlen + filelen + 2) > pathlen) 83 { 84 path = calloc (dirlen + 1 + filelen + 1, sizeof (*path)); 85 pathlen = dirlen + filelen + 2; 86 } 87 strcpy (path, dir); 88 slash = (path[dirlen] != '/'); 89 path[dirlen] = '/'; 90 strcpy (path + dirlen + slash , file); 91 status = isdir (path); 92 return status; 93} 94 95/* Return a freshly allocated string containing the filenames 96 in directory DIR, separated by '\0' characters; 97 the end is marked by two '\0' characters in a row. 98 NAME_SIZE is the number of bytes to initially allocate 99 for the string; it will be enlarged as needed. 100 Return NULL if DIR cannot be opened or if out of memory. */ 101char * 102savedir (const char *dir, off_t name_size, struct exclude *included_patterns, 103 struct exclude *excluded_patterns) 104{ 105 DIR *dirp; 106 struct dirent *dp; 107 char *name_space; 108 char *namep; 109 110 dirp = opendir (dir); 111 if (dirp == NULL) 112 return NULL; 113 114 /* Be sure name_size is at least `1' so there's room for 115 the final NUL byte. */ 116 if (name_size <= 0) 117 name_size = 1; 118 119 name_space = (char *) malloc (name_size); 120 if (name_space == NULL) 121 { 122 closedir (dirp); 123 return NULL; 124 } 125 namep = name_space; 126 127 while ((dp = readdir (dirp)) != NULL) 128 { 129 /* Skip "." and ".." (some NFS filesystems' directories lack them). */ 130 if (dp->d_name[0] != '.' 131 || (dp->d_name[1] != '\0' 132 && (dp->d_name[1] != '.' || dp->d_name[2] != '\0'))) 133 { 134 off_t size_needed = (namep - name_space) + NAMLEN (dp) + 2; 135 136 if ((included_patterns || excluded_patterns) 137 && !isdir1 (dir, dp->d_name)) 138 { 139 if (included_patterns 140 && !excluded_filename (included_patterns, dp->d_name, 0)) 141 continue; 142 if (excluded_patterns 143 && excluded_filename (excluded_patterns, dp->d_name, 0)) 144 continue; 145 } 146 147 if (size_needed > name_size) 148 { 149 char *new_name_space; 150 151 while (size_needed > name_size) 152 name_size += 1024; 153 154 new_name_space = realloc (name_space, name_size); 155 if (new_name_space == NULL) 156 { 157 closedir (dirp); 158 return NULL; 159 } 160 namep += new_name_space - name_space; 161 name_space = new_name_space; 162 } 163 namep = stpcpy (namep, dp->d_name) + 1; 164 } 165 } 166 *namep = '\0'; 167 if (CLOSEDIR (dirp)) 168 { 169 free (name_space); 170 return NULL; 171 } 172 if (path) 173 { 174 free (path); 175 path = NULL; 176 pathlen = 0; 177 } 178 return name_space; 179} 180