13e12c5d1SDavid du Colombier #include "lib.h" 23e12c5d1SDavid du Colombier #include <stdlib.h> 33e12c5d1SDavid du Colombier #include <sys/stat.h> 43e12c5d1SDavid du Colombier #include <dirent.h> 53e12c5d1SDavid du Colombier #include <unistd.h> 63e12c5d1SDavid du Colombier #include <errno.h> 73e12c5d1SDavid du Colombier #include <string.h> 83e12c5d1SDavid du Colombier #include "sys9.h" 93e12c5d1SDavid du Colombier #include "dir.h" 103e12c5d1SDavid du Colombier 113e12c5d1SDavid du Colombier #define DBLOCKSIZE 20 123e12c5d1SDavid du Colombier 133e12c5d1SDavid du Colombier DIR * 143e12c5d1SDavid du Colombier opendir(const char *filename) 153e12c5d1SDavid du Colombier { 163e12c5d1SDavid du Colombier int f; 173e12c5d1SDavid du Colombier DIR *d; 18*219b2ee8SDavid du Colombier struct stat sb; 19*219b2ee8SDavid du Colombier char cd[DIRLEN]; 203e12c5d1SDavid du Colombier 21*219b2ee8SDavid du Colombier if(_STAT(filename, cd) < 0){ 22*219b2ee8SDavid du Colombier _syserrno(); 23*219b2ee8SDavid du Colombier return NULL; 24*219b2ee8SDavid du Colombier } 25*219b2ee8SDavid du Colombier _dirtostat(&sb, cd, 0); 26*219b2ee8SDavid du Colombier if(S_ISDIR(sb.st_mode) == 0) { 27*219b2ee8SDavid du Colombier errno = ENOTDIR; 28*219b2ee8SDavid du Colombier return NULL; 29*219b2ee8SDavid du Colombier } 30*219b2ee8SDavid du Colombier 31*219b2ee8SDavid du Colombier f = open(filename, O_RDONLY); 323e12c5d1SDavid du Colombier if(f < 0){ 333e12c5d1SDavid du Colombier _syserrno(); 343e12c5d1SDavid du Colombier return NULL; 353e12c5d1SDavid du Colombier } 363e12c5d1SDavid du Colombier _fdinfo[f].flags |= FD_CLOEXEC; 373e12c5d1SDavid du Colombier d = (DIR *)malloc(sizeof(DIR) + DBLOCKSIZE*sizeof(struct dirent)); 383e12c5d1SDavid du Colombier if(!d){ 393e12c5d1SDavid du Colombier errno = ENOMEM; 403e12c5d1SDavid du Colombier return NULL; 413e12c5d1SDavid du Colombier } 423e12c5d1SDavid du Colombier d->dd_buf = ((char *)d) + sizeof(DIR); 433e12c5d1SDavid du Colombier d->dd_fd = f; 443e12c5d1SDavid du Colombier d->dd_loc = 0; 453e12c5d1SDavid du Colombier d->dd_size = 0; 463e12c5d1SDavid du Colombier return d; 473e12c5d1SDavid du Colombier } 483e12c5d1SDavid du Colombier 493e12c5d1SDavid du Colombier int 503e12c5d1SDavid du Colombier closedir(DIR *d) 513e12c5d1SDavid du Colombier { 523e12c5d1SDavid du Colombier if(!d){ 533e12c5d1SDavid du Colombier errno = EBADF; 543e12c5d1SDavid du Colombier return -1; 553e12c5d1SDavid du Colombier } 563e12c5d1SDavid du Colombier if(close(d->dd_fd) < 0) 573e12c5d1SDavid du Colombier return -1; 583e12c5d1SDavid du Colombier free(d); 593e12c5d1SDavid du Colombier return 0; 603e12c5d1SDavid du Colombier } 613e12c5d1SDavid du Colombier 623e12c5d1SDavid du Colombier void 633e12c5d1SDavid du Colombier rewinddir(DIR *d) 643e12c5d1SDavid du Colombier { 65*219b2ee8SDavid du Colombier int f; 66*219b2ee8SDavid du Colombier char dname[300]; 67*219b2ee8SDavid du Colombier 68*219b2ee8SDavid du Colombier d->dd_loc = 0; 69*219b2ee8SDavid du Colombier d->dd_size = 0; 703e12c5d1SDavid du Colombier if(!d){ 713e12c5d1SDavid du Colombier return; 723e12c5d1SDavid du Colombier } 73*219b2ee8SDavid du Colombier /* seeks aren't allowed on directories, so reopen */ 74*219b2ee8SDavid du Colombier strncpy(dname, _fdinfo[d->dd_fd].name, sizeof(dname)); 75*219b2ee8SDavid du Colombier close(d->dd_fd); 76*219b2ee8SDavid du Colombier f = open(dname, O_RDONLY); 77*219b2ee8SDavid du Colombier if (f < 0) { 78*219b2ee8SDavid du Colombier _syserrno(); 79*219b2ee8SDavid du Colombier return; 80*219b2ee8SDavid du Colombier } 81*219b2ee8SDavid du Colombier _fdinfo[f].flags |= FD_CLOEXEC; 82*219b2ee8SDavid du Colombier d->dd_fd = f; 833e12c5d1SDavid du Colombier } 843e12c5d1SDavid du Colombier 853e12c5d1SDavid du Colombier struct dirent * 863e12c5d1SDavid du Colombier readdir(DIR *d) 873e12c5d1SDavid du Colombier { 883e12c5d1SDavid du Colombier int i, n; 893e12c5d1SDavid du Colombier struct dirent *dr; 903e12c5d1SDavid du Colombier Dir dirs[DBLOCKSIZE]; 913e12c5d1SDavid du Colombier Dir td; 923e12c5d1SDavid du Colombier 933e12c5d1SDavid du Colombier if(!d){ 943e12c5d1SDavid du Colombier errno = EBADF; 953e12c5d1SDavid du Colombier return NULL; 963e12c5d1SDavid du Colombier } 973e12c5d1SDavid du Colombier if(d->dd_loc >= d->dd_size){ 983e12c5d1SDavid du Colombier n = read(d->dd_fd, (char *)dirs, sizeof dirs); 993e12c5d1SDavid du Colombier if(n <= 0) 1003e12c5d1SDavid du Colombier return NULL; 1013e12c5d1SDavid du Colombier n = n/sizeof(Dir); 1023e12c5d1SDavid du Colombier dr = (struct dirent *)(d->dd_buf); 1033e12c5d1SDavid du Colombier for(i=0; i<n; i++, dr++){ 1043e12c5d1SDavid du Colombier convM2D((char *)&dirs[i], &td); 1053e12c5d1SDavid du Colombier strncpy(dr->d_name, td.name, MAXNAMLEN); 1063e12c5d1SDavid du Colombier dr->d_name[MAXNAMLEN] = 0; 1073e12c5d1SDavid du Colombier } 1083e12c5d1SDavid du Colombier d->dd_loc = 0; 1093e12c5d1SDavid du Colombier d->dd_size = n*sizeof(struct dirent); 1103e12c5d1SDavid du Colombier } 1113e12c5d1SDavid du Colombier dr = (struct dirent*)(d->dd_buf+d->dd_loc); 1123e12c5d1SDavid du Colombier d->dd_loc += sizeof(struct dirent); 1133e12c5d1SDavid du Colombier return dr; 1143e12c5d1SDavid du Colombier } 115