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