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