diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/lib/ap/plan9/opendir.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/ap/plan9/opendir.c')
-rwxr-xr-x | sys/src/ape/lib/ap/plan9/opendir.c | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/sys/src/ape/lib/ap/plan9/opendir.c b/sys/src/ape/lib/ap/plan9/opendir.c new file mode 100755 index 000000000..ebc22dbf6 --- /dev/null +++ b/sys/src/ape/lib/ap/plan9/opendir.c @@ -0,0 +1,121 @@ +#include "lib.h" +#include <stdlib.h> +#include <sys/stat.h> +#include <dirent.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include "sys9.h" +#include "dir.h" + +#define DBLOCKSIZE 20 + +DIR * +opendir(const char *filename) +{ + int f; + DIR *d; + struct stat sb; + Dir *d9; + + if((d9 = _dirstat(filename)) == nil){ + _syserrno(); + return NULL; + } + _dirtostat(&sb, d9, 0); + free(d9); + if(S_ISDIR(sb.st_mode) == 0) { + errno = ENOTDIR; + return NULL; + } + + f = open(filename, O_RDONLY); + if(f < 0){ + _syserrno(); + return NULL; + } + _fdinfo[f].flags |= FD_CLOEXEC; + d = (DIR *)malloc(sizeof(DIR) + DBLOCKSIZE*sizeof(struct dirent)); + if(!d){ + errno = ENOMEM; + return NULL; + } + d->dd_buf = (char *)d + sizeof(DIR); + d->dd_fd = f; + d->dd_loc = 0; + d->dd_size = 0; + d->dirs = nil; + d->dirsize = 0; + d->dirloc = 0; + return d; +} + +int +closedir(DIR *d) +{ + if(!d){ + errno = EBADF; + return -1; + } + if(close(d->dd_fd) < 0) + return -1; + free(d->dirs); + free(d); + return 0; +} + +void +rewinddir(DIR *d) +{ + if(!d) + return; + d->dd_loc = 0; + d->dd_size = 0; + d->dirsize = 0; + d->dirloc = 0; + free(d->dirs); + d->dirs = nil; + if(_SEEK(d->dd_fd, 0, 0) < 0){ + _syserrno(); + return; + } +} + +struct dirent * +readdir(DIR *d) +{ + int i, n; + struct dirent *dr; + Dir *dirs; + + if(!d){ + errno = EBADF; + return NULL; + } + if(d->dd_loc >= d->dd_size){ + if(d->dirloc >= d->dirsize){ + free(d->dirs); + d->dirs = NULL; + d->dirsize = _dirread(d->dd_fd, &d->dirs); + d->dirloc = 0; + } + if(d->dirsize < 0) { /* malloc or read failed in _dirread? */ + free(d->dirs); + d->dirs = NULL; + } + if(d->dirs == NULL) + return NULL; + + dr = (struct dirent *)d->dd_buf; + dirs = d->dirs; + for(i=0; i<DBLOCKSIZE && d->dirloc < d->dirsize; i++){ + strncpy(dr[i].d_name, dirs[d->dirloc++].name, MAXNAMLEN); + dr[i].d_name[MAXNAMLEN] = 0; + } + d->dd_loc = 0; + d->dd_size = i*sizeof(struct dirent); + } + dr = (struct dirent*)(d->dd_buf+d->dd_loc); + d->dd_loc += sizeof(struct dirent); + return dr; +} |