153469Sobrien/* savedir.c -- save the list of files in a directory in a string 2131554Stjr Copyright (C) 1990, 1997, 1998, 1999, 2000, 2001 Free Software Foundation, Inc. 353469Sobrien 453469Sobrien This program is free software; you can redistribute it and/or modify 553469Sobrien it under the terms of the GNU General Public License as published by 653469Sobrien the Free Software Foundation; either version 2, or (at your option) 753469Sobrien any later version. 853469Sobrien 953469Sobrien This program is distributed in the hope that it will be useful, 1053469Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 1153469Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1253469Sobrien GNU General Public License for more details. 1353469Sobrien 1453469Sobrien You should have received a copy of the GNU General Public License 1553469Sobrien along with this program; if not, write to the Free Software Foundation, 1653469Sobrien Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ 1753469Sobrien 1853469Sobrien/* Written by David MacKenzie <djm@gnu.ai.mit.edu>. */ 1953469Sobrien 20187907Sobrien#include <sys/cdefs.h> 21187907Sobrien__FBSDID("$FreeBSD$"); 22187907Sobrien 2353469Sobrien#if HAVE_CONFIG_H 2453469Sobrien# include <config.h> 2553469Sobrien#endif 2653469Sobrien 2753469Sobrien#include <sys/types.h> 2853469Sobrien 2953469Sobrien#if HAVE_UNISTD_H 3053469Sobrien# include <unistd.h> 3153469Sobrien#endif 3253469Sobrien 3353469Sobrien#if HAVE_DIRENT_H 3453469Sobrien# include <dirent.h> 3553469Sobrien# define NAMLEN(dirent) strlen((dirent)->d_name) 3653469Sobrien#else 3753469Sobrien# define dirent direct 3853469Sobrien# define NAMLEN(dirent) (dirent)->d_namlen 3953469Sobrien# if HAVE_SYS_NDIR_H 4053469Sobrien# include <sys/ndir.h> 4153469Sobrien# endif 4253469Sobrien# if HAVE_SYS_DIR_H 4353469Sobrien# include <sys/dir.h> 4453469Sobrien# endif 4553469Sobrien# if HAVE_NDIR_H 4653469Sobrien# include <ndir.h> 4753469Sobrien# endif 4853469Sobrien#endif 4953469Sobrien 5053469Sobrien#ifdef CLOSEDIR_VOID 5153469Sobrien/* Fake a return value. */ 5253469Sobrien# define CLOSEDIR(d) (closedir (d), 0) 5353469Sobrien#else 5453469Sobrien# define CLOSEDIR(d) closedir (d) 5553469Sobrien#endif 5653469Sobrien 5753469Sobrien#ifdef STDC_HEADERS 5853469Sobrien# include <stdlib.h> 5953469Sobrien# include <string.h> 6053469Sobrien#else 6153469Sobrienchar *malloc (); 6253469Sobrienchar *realloc (); 6353469Sobrien#endif 6453469Sobrien#ifndef NULL 6553469Sobrien# define NULL 0 6653469Sobrien#endif 6753469Sobrien 6853469Sobrien#ifndef stpcpy 6953469Sobrienchar *stpcpy (); 7053469Sobrien#endif 7153469Sobrien 72131554Stjr#include <fnmatch.h> 7353469Sobrien#include "savedir.h" 7453469Sobrien 75131554Stjrchar *path; 76131554Stjrsize_t pathlen; 77131554Stjr 78131554Stjrstatic int 79131554Stjrisdir1 (const char *dir, const char *file) 80131554Stjr{ 81131554Stjr int status; 82131554Stjr int slash; 83131554Stjr size_t dirlen = strlen (dir); 84131554Stjr size_t filelen = strlen (file); 85131554Stjr if ((dirlen + filelen + 2) > pathlen) 86131554Stjr { 87131554Stjr path = calloc (dirlen + 1 + filelen + 1, sizeof (*path)); 88131554Stjr pathlen = dirlen + filelen + 2; 89131554Stjr } 90131554Stjr strcpy (path, dir); 91131554Stjr slash = (path[dirlen] != '/'); 92131554Stjr path[dirlen] = '/'; 93131554Stjr strcpy (path + dirlen + slash , file); 94131554Stjr status = isdir (path); 95131554Stjr return status; 96131554Stjr} 97131554Stjr 9853469Sobrien/* Return a freshly allocated string containing the filenames 9953469Sobrien in directory DIR, separated by '\0' characters; 10053469Sobrien the end is marked by two '\0' characters in a row. 10153469Sobrien NAME_SIZE is the number of bytes to initially allocate 10253469Sobrien for the string; it will be enlarged as needed. 10353469Sobrien Return NULL if DIR cannot be opened or if out of memory. */ 10453469Sobrienchar * 105131554Stjrsavedir (const char *dir, off_t name_size, struct exclude *included_patterns, 106131554Stjr struct exclude *excluded_patterns) 10753469Sobrien{ 10853469Sobrien DIR *dirp; 10953469Sobrien struct dirent *dp; 11053469Sobrien char *name_space; 11153469Sobrien char *namep; 11253469Sobrien 11353469Sobrien dirp = opendir (dir); 11453469Sobrien if (dirp == NULL) 11553469Sobrien return NULL; 11653469Sobrien 11756230Sru /* Be sure name_size is at least `1' so there's room for 11856230Sru the final NUL byte. */ 119126432Sache if (name_size <= 0) 120126432Sache name_size = 1; 12156230Sru 12253469Sobrien name_space = (char *) malloc (name_size); 12353469Sobrien if (name_space == NULL) 12453469Sobrien { 12553469Sobrien closedir (dirp); 12653469Sobrien return NULL; 12753469Sobrien } 12853469Sobrien namep = name_space; 12953469Sobrien 13053469Sobrien while ((dp = readdir (dirp)) != NULL) 13153469Sobrien { 13253469Sobrien /* Skip "." and ".." (some NFS filesystems' directories lack them). */ 13353469Sobrien if (dp->d_name[0] != '.' 13453469Sobrien || (dp->d_name[1] != '\0' 13553469Sobrien && (dp->d_name[1] != '.' || dp->d_name[2] != '\0'))) 13653469Sobrien { 13756915Sru off_t size_needed = (namep - name_space) + NAMLEN (dp) + 2; 13853469Sobrien 139131554Stjr if ((included_patterns || excluded_patterns) 140131554Stjr && !isdir1 (dir, dp->d_name)) 141131554Stjr { 142131554Stjr if (included_patterns 143187907Sobrien && !excluded_filename (included_patterns, path, 0)) 144131554Stjr continue; 145131554Stjr if (excluded_patterns 146187907Sobrien && excluded_filename (excluded_patterns, path, 0)) 147131554Stjr continue; 148131554Stjr } 149131554Stjr 15053469Sobrien if (size_needed > name_size) 15153469Sobrien { 15253469Sobrien char *new_name_space; 15353469Sobrien 15453469Sobrien while (size_needed > name_size) 15553469Sobrien name_size += 1024; 15653469Sobrien 15753469Sobrien new_name_space = realloc (name_space, name_size); 15853469Sobrien if (new_name_space == NULL) 15953469Sobrien { 16053469Sobrien closedir (dirp); 16153469Sobrien return NULL; 16253469Sobrien } 16353469Sobrien namep += new_name_space - name_space; 16453469Sobrien name_space = new_name_space; 16553469Sobrien } 16653469Sobrien namep = stpcpy (namep, dp->d_name) + 1; 16753469Sobrien } 16853469Sobrien } 16953469Sobrien *namep = '\0'; 17053469Sobrien if (CLOSEDIR (dirp)) 17153469Sobrien { 17253469Sobrien free (name_space); 17353469Sobrien return NULL; 17453469Sobrien } 175131554Stjr if (path) 176131554Stjr { 177131554Stjr free (path); 178131554Stjr path = NULL; 179131554Stjr pathlen = 0; 180131554Stjr } 18153469Sobrien return name_space; 18253469Sobrien} 183