Introduction
Introduction Statistics Contact Development Disclaimer Help
dirread.c - 9base - revived minimalist port of Plan 9 userland to Unix
git clone git://git.suckless.org/9base
Log
Files
Refs
README
LICENSE
---
dirread.c (3712B)
---
1 #include <u.h>
2 #define NOPLAN9DEFINES
3 #include <libc.h>
4 #include <sys/stat.h>
5 #include <dirent.h>
6
7 #if defined (__linux__)
8 # include <sys/syscall.h>
9 # if defined (_LARGEFILE64_SOURCE)
10 # define getdents SYS_getdents64
11 # else
12 # define getdents SYS_getdents
13 # endif
14 #endif
15
16 extern int _p9dir(struct stat*, struct stat*, char*, Dir*, char**, char*…
17
18 #if defined(__linux__)
19 static int
20 mygetdents(int fd, struct dirent *buf, int n) {
21 return syscall (getdents, fd, (void*) buf, n);
22 }
23 #elif defined(__APPLE__) || defined(__FreeBSD__)
24 static int
25 mygetdents(int fd, struct dirent *buf, int n)
26 {
27 long off;
28 return getdirentries(fd, (void*)buf, n, &off);
29 }
30 #elif defined(__OpenBSD__)
31 #include <sys/param.h>
32 # if OpenBSD < 201405 /* for OpenBSD 5.4 and earlier */
33 static int
34 mygetdents(int fd, struct dirent *buf, int n)
35 {
36 off_t off;
37 return getdirentries(fd, (void*)buf, n, &off);
38 }
39 # else
40 static int
41 mygetdents(int fd, struct dirent *buf, int n)
42 {
43 return getdents(fd, (void*)buf, n);
44 }
45 # endif
46 #elif defined(__sun__) || defined(__NetBSD__)
47 static int
48 mygetdents(int fd, struct dirent *buf, int n)
49 {
50 return getdents(fd, (void*)buf, n);
51 }
52 #elif defined(__AIX__)
53 static int
54 mygetdents(int fd, struct dirent *buf, int n)
55 {
56 return getdirent(fd, (void*)buf, n);
57 }
58 #endif
59
60 static int
61 countde(char *p, int n)
62 {
63 char *e;
64 int m;
65 struct dirent *de;
66
67 e = p+n;
68 m = 0;
69 while(p < e){
70 de = (struct dirent*)p;
71 if(de->d_reclen <= 4+2+2+1 || p+de->d_reclen > e)
72 break;
73 if(de->d_name[0]=='.' && de->d_name[1]==0)
74 de->d_name[0] = 0;
75 else if(de->d_name[0]=='.' && de->d_name[1]=='.' && de->…
76 de->d_name[0] = 0;
77 m++;
78 p += de->d_reclen;
79 }
80 return m;
81 }
82
83 static int
84 dirpackage(int fd, char *buf, int n, Dir **dp)
85 {
86 int oldwd;
87 char *p, *str, *estr;
88 int i, nstr, m;
89 struct dirent *de;
90 struct stat st, lst;
91 Dir *d;
92
93 n = countde(buf, n);
94 if(n <= 0)
95 return n;
96
97 if((oldwd = open(".", O_RDONLY)) < 0)
98 return -1;
99 if(fchdir(fd) < 0)
100 return -1;
101
102 p = buf;
103 nstr = 0;
104
105 for(i=0; i<n; i++){
106 de = (struct dirent*)p;
107 memset(&lst, 0, sizeof lst);
108 if(de->d_name[0] == 0)
109 /* nothing */ {}
110 else if(lstat(de->d_name, &lst) < 0)
111 de->d_name[0] = 0;
112 else{
113 st = lst;
114 if(S_ISLNK(lst.st_mode))
115 stat(de->d_name, &st);
116 nstr += _p9dir(&lst, &st, de->d_name, nil, nil, …
117 }
118 p += de->d_reclen;
119 }
120
121 d = malloc(sizeof(Dir)*n+nstr);
122 if(d == nil){
123 fchdir(oldwd);
124 close(oldwd);
125 return -1;
126 }
127 str = (char*)&d[n];
128 estr = str+nstr;
129
130 p = buf;
131 m = 0;
132 for(i=0; i<n; i++){
133 de = (struct dirent*)p;
134 if(de->d_name[0] != 0 && lstat(de->d_name, &lst) >= 0){
135 st = lst;
136 if((lst.st_mode&S_IFMT) == S_IFLNK)
137 stat(de->d_name, &st);
138 _p9dir(&lst, &st, de->d_name, &d[m++], &str, est…
139 }
140 p += de->d_reclen;
141 }
142
143 fchdir(oldwd);
144 close(oldwd);
145 *dp = d;
146 return m;
147 }
148
149 long
150 dirread(int fd, Dir **dp)
151 {
152 char *buf;
153 struct stat st;
154 int n;
155
156 *dp = 0;
157
158 if(fstat(fd, &st) < 0)
159 return -1;
160
161 if(st.st_blksize < 8192)
162 st.st_blksize = 8192;
163
164 buf = malloc(st.st_blksize);
165 if(buf == nil)
166 return -1;
167
168 n = mygetdents(fd, (void*)buf, st.st_blksize);
169 if(n < 0){
170 free(buf);
171 return -1;
172 }
173 n = dirpackage(fd, buf, n, dp);
174 free(buf);
175 return n;
176 }
177
178
179 long
180 dirreadall(int fd, Dir **d)
181 {
182 uchar *buf, *nbuf;
183 long n, ts;
184 struct stat st;
185
186 if(fstat(fd, &st) < 0)
187 return -1;
188
189 if(st.st_blksize < 8192)
190 st.st_blksize = 8192;
191
192 buf = nil;
193 ts = 0;
194 for(;;){
195 nbuf = realloc(buf, ts+st.st_blksize);
196 if(nbuf == nil){
197 free(buf);
198 return -1;
199 }
200 buf = nbuf;
201 n = mygetdents(fd, (void*)(buf+ts), st.st_blksize);
202 if(n <= 0)
203 break;
204 ts += n;
205 }
206 if(ts >= 0)
207 ts = dirpackage(fd, (char*)buf, ts, d);
208 free(buf);
209 if(ts == 0 && n < 0)
210 return -1;
211 return ts;
212 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.