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 * opendir(const char * filename)14opendir(const char *filename) 15 { 16 int f; 17 DIR *d; 18 struct stat sb; 19 Dir *d9; 20 21 if((d9 = _dirstat(filename)) == nil){ 22 _syserrno(); 23 return NULL; 24 } 25 _dirtostat(&sb, d9, 0); 26 free(d9); 27 if(S_ISDIR(sb.st_mode) == 0) { 28 errno = ENOTDIR; 29 return NULL; 30 } 31 32 f = open(filename, O_RDONLY); 33 if(f < 0){ 34 _syserrno(); 35 return NULL; 36 } 37 _fdinfo[f].flags |= FD_CLOEXEC; 38 d = (DIR *)malloc(sizeof(DIR) + DBLOCKSIZE*sizeof(struct dirent)); 39 if(!d){ 40 errno = ENOMEM; 41 return NULL; 42 } 43 d->dd_buf = (char *)d + sizeof(DIR); 44 d->dd_fd = f; 45 d->dd_loc = 0; 46 d->dd_size = 0; 47 d->dirs = nil; 48 d->dirsize = 0; 49 d->dirloc = 0; 50 return d; 51 } 52 53 int closedir(DIR * d)54closedir(DIR *d) 55 { 56 if(!d){ 57 errno = EBADF; 58 return -1; 59 } 60 if(close(d->dd_fd) < 0) 61 return -1; 62 free(d->dirs); 63 free(d); 64 return 0; 65 } 66 67 void rewinddir(DIR * d)68rewinddir(DIR *d) 69 { 70 if(!d) 71 return; 72 d->dd_loc = 0; 73 d->dd_size = 0; 74 d->dirsize = 0; 75 d->dirloc = 0; 76 free(d->dirs); 77 d->dirs = nil; 78 if(_SEEK(d->dd_fd, 0, 0) < 0){ 79 _syserrno(); 80 return; 81 } 82 } 83 84 struct dirent * readdir(DIR * d)85readdir(DIR *d) 86 { 87 int i; 88 struct dirent *dr; 89 Dir *dirs; 90 91 if(!d){ 92 errno = EBADF; 93 return NULL; 94 } 95 if(d->dd_loc >= d->dd_size){ 96 if(d->dirloc >= d->dirsize){ 97 free(d->dirs); 98 d->dirs = NULL; 99 d->dirsize = _dirread(d->dd_fd, &d->dirs); 100 d->dirloc = 0; 101 } 102 if(d->dirsize < 0) { /* malloc or read failed in _dirread? */ 103 free(d->dirs); 104 d->dirs = NULL; 105 } 106 if(d->dirs == NULL) 107 return NULL; 108 109 dr = (struct dirent *)d->dd_buf; 110 dirs = d->dirs; 111 for(i=0; i<DBLOCKSIZE && d->dirloc < d->dirsize; i++){ 112 strncpy(dr[i].d_name, dirs[d->dirloc++].name, MAXNAMLEN); 113 dr[i].d_name[MAXNAMLEN] = 0; 114 } 115 d->dd_loc = 0; 116 d->dd_size = i*sizeof(struct dirent); 117 } 118 dr = (struct dirent*)(d->dd_buf+d->dd_loc); 119 d->dd_loc += sizeof(struct dirent); 120 return dr; 121 } 122