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 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 54 closedir(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 68 rewinddir(DIR *d) 69 { 70 int f; 71 char dname[300]; 72 73 d->dd_loc = 0; 74 d->dd_size = 0; 75 d->dirsize = 0; 76 d->dirloc = 0; 77 free(d->dirs); 78 d->dirs = nil; 79 if(!d){ 80 return; 81 } 82 if(_SEEK(d->dd_fd, 0, 0) < 0){ 83 _syserrno(); 84 return; 85 } 86 } 87 88 struct dirent * 89 readdir(DIR *d) 90 { 91 int i, n; 92 struct dirent *dr; 93 Dir *dirs; 94 95 if(!d){ 96 errno = EBADF; 97 return NULL; 98 } 99 if(d->dd_loc >= d->dd_size){ 100 if(d->dirloc >= d->dirsize){ 101 free(d->dirs); 102 d->dirsize = _dirread(d->dd_fd, &d->dirs); 103 d->dirloc = 0; 104 } 105 if(d->dirs == NULL) 106 return NULL; 107 dr = (struct dirent *)(d->dd_buf); 108 dirs = d->dirs; 109 for(i=0; i<DBLOCKSIZE && d->dirloc < d->dirsize; i++){ 110 strncpy(dr[i].d_name, dirs[d->dirloc++].name, MAXNAMLEN); 111 dr[i].d_name[MAXNAMLEN] = 0; 112 } 113 d->dd_loc = 0; 114 d->dd_size = i*sizeof(struct dirent); 115 } 116 dr = (struct dirent*)(d->dd_buf+d->dd_loc); 117 d->dd_loc += sizeof(struct dirent); 118 return dr; 119 } 120