x->baselen = baselen;
if (which->nr == which->alloc) {
which->alloc = alloc_nr(which->alloc);
- which->excludes = realloc(which->excludes,
- which->alloc * sizeof(x));
+ which->excludes = xrealloc(which->excludes,
+ which->alloc * sizeof(x));
}
which->excludes[which->nr++] = x;
}
int baselen,
struct exclude_list *which)
{
+ struct stat st;
int fd, i;
long size;
char *buf, *entry;
fd = open(fname, O_RDONLY);
- if (fd < 0)
+ if (fd < 0 || fstat(fd, &st) < 0)
goto err;
- size = lseek(fd, 0, SEEK_END);
- if (size < 0)
- goto err;
- lseek(fd, 0, SEEK_SET);
+ size = st.st_size;
if (size == 0) {
close(fd);
return 0;
* Also, we ignore the name ".git" (even if it is not a directory).
* That likely will not change.
*/
-static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen)
+static int read_directory_recursive(struct dir_struct *dir, const char *path, const char *base, int baselen, int check_only)
{
DIR *fdir = opendir(path);
int contents = 0;
if (fdir) {
int exclude_stk;
struct dirent *de;
- char fullname[MAXPATHLEN + 1];
+ char fullname[PATH_MAX + 1];
memcpy(fullname, base, baselen);
exclude_stk = push_exclude_per_directory(dir, base, baselen);
switch (DTYPE(de)) {
struct stat st;
- int subdir, rewind_base;
default:
continue;
case DT_UNKNOWN:
case DT_DIR:
memcpy(fullname + baselen + len, "/", 2);
len++;
- rewind_base = dir->nr;
- subdir = read_directory_recursive(dir, fullname, fullname,
- baselen + len);
if (dir->show_other_directories &&
- (subdir || !dir->hide_empty_directories) &&
!dir_exists(fullname, baselen + len)) {
- /* Rewind the read subdirectory */
- while (dir->nr > rewind_base)
- free(dir->entries[--dir->nr]);
+ if (dir->hide_empty_directories &&
+ !read_directory_recursive(dir,
+ fullname, fullname,
+ baselen + len, 1))
+ continue;
break;
}
- contents += subdir;
+
+ contents += read_directory_recursive(dir,
+ fullname, fullname, baselen + len, 0);
continue;
case DT_REG:
case DT_LNK:
break;
}
- add_name(dir, fullname, baselen + len);
contents++;
+ if (check_only)
+ goto exit_early;
+ else
+ add_name(dir, fullname, baselen + len);
}
+exit_early:
closedir(fdir);
pop_exclude_per_directory(dir, exclude_stk);
}
}
- read_directory_recursive(dir, path, base, baselen);
+ read_directory_recursive(dir, path, base, baselen, 0);
qsort(dir->entries, dir->nr, sizeof(struct dir_entry *), cmp_name);
return dir->nr;
}
+
+int
+file_exists(const char *f)
+{
+ struct stat sb;
+ return stat(f, &sb) == 0;
+}