xref: /plan9-contrib/sys/src/ape/lib/ap/plan9/opendir.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include "lib.h"
2 #include <stdlib.h>
3 #include <sys/stat.h>
4 #include <dirent.h>
5 #include <unistd.h>
6 #include <errno.h>
7 #include <string.h>
8 #include "sys9.h"
9 #include "dir.h"
10 
11 #define DBLOCKSIZE 20
12 
13 DIR *
14 opendir(const char *filename)
15 {
16 	int f;
17 	DIR *d;
18 	struct stat sb;
19 	char cd[DIRLEN];
20 
21 	if(_STAT(filename, cd) < 0){
22 		_syserrno();
23 		return NULL;
24 	}
25 	_dirtostat(&sb, cd, 0);
26 	if(S_ISDIR(sb.st_mode) == 0) {
27 		errno = ENOTDIR;
28 		return NULL;
29 	}
30 
31 	f = open(filename, O_RDONLY);
32 	if(f < 0){
33 		_syserrno();
34 		return NULL;
35 	}
36 	_fdinfo[f].flags |= FD_CLOEXEC;
37 	d = (DIR *)malloc(sizeof(DIR) + DBLOCKSIZE*sizeof(struct dirent));
38 	if(!d){
39 		errno = ENOMEM;
40 		return NULL;
41 	}
42 	d->dd_buf = ((char *)d) + sizeof(DIR);
43 	d->dd_fd = f;
44 	d->dd_loc = 0;
45 	d->dd_size = 0;
46 	return d;
47 }
48 
49 int
50 closedir(DIR *d)
51 {
52 	if(!d){
53 		errno = EBADF;
54 		return -1;
55 	}
56 	if(close(d->dd_fd) < 0)
57 		return -1;
58 	free(d);
59 	return 0;
60 }
61 
62 void
63 rewinddir(DIR *d)
64 {
65 	int f;
66 	char dname[300];
67 
68 	d->dd_loc = 0;
69 	d->dd_size = 0;
70 	if(!d){
71 		return;
72 	}
73 	/* seeks aren't allowed on directories, so reopen */
74 	strncpy(dname, _fdinfo[d->dd_fd].name, sizeof(dname));
75 	close(d->dd_fd);
76 	 f = open(dname, O_RDONLY);
77 	if (f < 0) {
78 		_syserrno();
79 		return;
80 	}
81 	_fdinfo[f].flags |= FD_CLOEXEC;
82 	d->dd_fd = f;
83 }
84 
85 struct dirent *
86 readdir(DIR *d)
87 {
88 	int i, n;
89 	struct dirent *dr;
90 	Dir dirs[DBLOCKSIZE];
91 	Dir td;
92 
93 	if(!d){
94 		errno = EBADF;
95 		return NULL;
96 	}
97 	if(d->dd_loc >= d->dd_size){
98 		n = read(d->dd_fd, (char *)dirs, sizeof dirs);
99 		if(n <= 0)
100 			return NULL;
101 		n = n/sizeof(Dir);
102 		dr = (struct dirent *)(d->dd_buf);
103 		for(i=0; i<n; i++, dr++){
104 			convM2D((char *)&dirs[i], &td);
105 			strncpy(dr->d_name, td.name, MAXNAMLEN);
106 			dr->d_name[MAXNAMLEN] = 0;
107 		}
108 		d->dd_loc = 0;
109 		d->dd_size = n*sizeof(struct dirent);
110 	}
111 	dr = (struct dirent*)(d->dd_buf+d->dd_loc);
112 	d->dd_loc += sizeof(struct dirent);
113 	return dr;
114 }
115