Handle streams separately in tree_add_track()
[cmus.git] / load_dir.c
blob6d5a0eec8d7f3df5c68bb43a611232e992715b41
1 /*
2 * Copyright Timo Hirvonen
3 */
5 #include "load_dir.h"
6 #include "xmalloc.h"
8 #include <sys/types.h>
9 #include <sys/stat.h>
10 #include <unistd.h>
11 #include <dirent.h>
12 #include <errno.h>
14 int dir_open(struct directory *dir, const char *name)
16 int len = strlen(name);
18 if (len >= sizeof(dir->path) - 2) {
19 errno = ENAMETOOLONG;
20 return -1;
23 dir->d = opendir(name);
24 if (!dir->d)
25 return -1;
27 memcpy(dir->path, name, len);
28 dir->path[len++] = '/';
29 dir->path[len] = 0;
30 dir->len = len;
31 return 0;
34 void dir_close(struct directory *dir)
36 closedir(dir->d);
39 const char *dir_read(struct directory *dir)
41 DIR *d = dir->d;
42 int len = dir->len;
43 char *full = dir->path;
44 struct dirent *de;
46 #if defined(__CYGWIN__)
47 /* Fix for cygwin "hang" bug when browsing /
48 * Windows treats // as a network path.
50 if (strcmp(full, "//") == 0)
51 full++;
52 #endif
54 while ((de = readdir(d))) {
55 const char *name = de->d_name;
56 int nlen = strlen(name);
58 /* just ignore too long paths
59 * + 2 -> space for \0 or / and \0
61 if (len + nlen + 2 >= sizeof(dir->path))
62 continue;
64 memcpy(full + len, name, nlen + 1);
65 if (lstat(full, &dir->st))
66 continue;
68 dir->is_link = 0;
69 if (S_ISLNK(dir->st.st_mode)) {
70 /* argh. must stat the target */
71 if (stat(full, &dir->st))
72 continue;
73 dir->is_link = 1;
76 return full + len;
78 return NULL;
81 void ptr_array_add(struct ptr_array *array, void *ptr)
83 void **ptrs = ptrs = array->ptrs;
84 int alloc = array->alloc;
86 if (alloc == array->count) {
87 alloc = alloc * 3 / 2 + 16;
88 ptrs = xrealloc(ptrs, alloc * sizeof(void *));
89 array->ptrs = ptrs;
90 array->alloc = alloc;
92 ptrs[array->count++] = ptr;