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 * opendir(const char * filename)143e12c5d1SDavid du Colombieropendir(const char *filename) 153e12c5d1SDavid du Colombier { 163e12c5d1SDavid du Colombier int f; 173e12c5d1SDavid du Colombier DIR *d; 18219b2ee8SDavid du Colombier struct stat sb; 199a747e4fSDavid du Colombier Dir *d9; 203e12c5d1SDavid du Colombier 219a747e4fSDavid du Colombier if((d9 = _dirstat(filename)) == nil){ 22219b2ee8SDavid du Colombier _syserrno(); 23219b2ee8SDavid du Colombier return NULL; 24219b2ee8SDavid du Colombier } 259a747e4fSDavid du Colombier _dirtostat(&sb, d9, 0); 269a747e4fSDavid du Colombier free(d9); 27219b2ee8SDavid du Colombier if(S_ISDIR(sb.st_mode) == 0) { 28219b2ee8SDavid du Colombier errno = ENOTDIR; 29219b2ee8SDavid du Colombier return NULL; 30219b2ee8SDavid du Colombier } 31219b2ee8SDavid du Colombier 32219b2ee8SDavid du Colombier f = open(filename, O_RDONLY); 333e12c5d1SDavid du Colombier if(f < 0){ 343e12c5d1SDavid du Colombier _syserrno(); 353e12c5d1SDavid du Colombier return NULL; 363e12c5d1SDavid du Colombier } 373e12c5d1SDavid du Colombier _fdinfo[f].flags |= FD_CLOEXEC; 383e12c5d1SDavid du Colombier d = (DIR *)malloc(sizeof(DIR) + DBLOCKSIZE*sizeof(struct dirent)); 393e12c5d1SDavid du Colombier if(!d){ 403e12c5d1SDavid du Colombier errno = ENOMEM; 413e12c5d1SDavid du Colombier return NULL; 423e12c5d1SDavid du Colombier } 4325fc6993SDavid du Colombier d->dd_buf = (char *)d + sizeof(DIR); 443e12c5d1SDavid du Colombier d->dd_fd = f; 453e12c5d1SDavid du Colombier d->dd_loc = 0; 463e12c5d1SDavid du Colombier d->dd_size = 0; 479a747e4fSDavid du Colombier d->dirs = nil; 489a747e4fSDavid du Colombier d->dirsize = 0; 499a747e4fSDavid du Colombier d->dirloc = 0; 503e12c5d1SDavid du Colombier return d; 513e12c5d1SDavid du Colombier } 523e12c5d1SDavid du Colombier 533e12c5d1SDavid du Colombier int closedir(DIR * d)543e12c5d1SDavid du Colombierclosedir(DIR *d) 553e12c5d1SDavid du Colombier { 563e12c5d1SDavid du Colombier if(!d){ 573e12c5d1SDavid du Colombier errno = EBADF; 583e12c5d1SDavid du Colombier return -1; 593e12c5d1SDavid du Colombier } 603e12c5d1SDavid du Colombier if(close(d->dd_fd) < 0) 613e12c5d1SDavid du Colombier return -1; 629a747e4fSDavid du Colombier free(d->dirs); 633e12c5d1SDavid du Colombier free(d); 643e12c5d1SDavid du Colombier return 0; 653e12c5d1SDavid du Colombier } 663e12c5d1SDavid du Colombier 673e12c5d1SDavid du Colombier void rewinddir(DIR * d)683e12c5d1SDavid du Colombierrewinddir(DIR *d) 693e12c5d1SDavid du Colombier { 7025fc6993SDavid du Colombier if(!d) 7125fc6993SDavid du Colombier return; 72219b2ee8SDavid du Colombier d->dd_loc = 0; 73219b2ee8SDavid du Colombier d->dd_size = 0; 749a747e4fSDavid du Colombier d->dirsize = 0; 759a747e4fSDavid du Colombier d->dirloc = 0; 769a747e4fSDavid du Colombier free(d->dirs); 779a747e4fSDavid du Colombier d->dirs = nil; 789a747e4fSDavid du Colombier if(_SEEK(d->dd_fd, 0, 0) < 0){ 79219b2ee8SDavid du Colombier _syserrno(); 80219b2ee8SDavid du Colombier return; 81219b2ee8SDavid du Colombier } 823e12c5d1SDavid du Colombier } 833e12c5d1SDavid du Colombier 843e12c5d1SDavid du Colombier struct dirent * readdir(DIR * d)853e12c5d1SDavid du Colombierreaddir(DIR *d) 863e12c5d1SDavid du Colombier { 87*781103c4SDavid du Colombier int i; 883e12c5d1SDavid du Colombier struct dirent *dr; 899a747e4fSDavid du Colombier Dir *dirs; 903e12c5d1SDavid du Colombier 913e12c5d1SDavid du Colombier if(!d){ 923e12c5d1SDavid du Colombier errno = EBADF; 933e12c5d1SDavid du Colombier return NULL; 943e12c5d1SDavid du Colombier } 953e12c5d1SDavid du Colombier if(d->dd_loc >= d->dd_size){ 969a747e4fSDavid du Colombier if(d->dirloc >= d->dirsize){ 979a747e4fSDavid du Colombier free(d->dirs); 9825fc6993SDavid du Colombier d->dirs = NULL; 999a747e4fSDavid du Colombier d->dirsize = _dirread(d->dd_fd, &d->dirs); 1009a747e4fSDavid du Colombier d->dirloc = 0; 1019a747e4fSDavid du Colombier } 10225fc6993SDavid du Colombier if(d->dirsize < 0) { /* malloc or read failed in _dirread? */ 10325fc6993SDavid du Colombier free(d->dirs); 10425fc6993SDavid du Colombier d->dirs = NULL; 10525fc6993SDavid du Colombier } 1069a747e4fSDavid du Colombier if(d->dirs == NULL) 1073e12c5d1SDavid du Colombier return NULL; 10825fc6993SDavid du Colombier 10925fc6993SDavid du Colombier dr = (struct dirent *)d->dd_buf; 1109a747e4fSDavid du Colombier dirs = d->dirs; 1119a747e4fSDavid du Colombier for(i=0; i<DBLOCKSIZE && d->dirloc < d->dirsize; i++){ 1129a747e4fSDavid du Colombier strncpy(dr[i].d_name, dirs[d->dirloc++].name, MAXNAMLEN); 1139a747e4fSDavid du Colombier dr[i].d_name[MAXNAMLEN] = 0; 1143e12c5d1SDavid du Colombier } 1153e12c5d1SDavid du Colombier d->dd_loc = 0; 1169a747e4fSDavid du Colombier d->dd_size = i*sizeof(struct dirent); 1173e12c5d1SDavid du Colombier } 1183e12c5d1SDavid du Colombier dr = (struct dirent*)(d->dd_buf+d->dd_loc); 1193e12c5d1SDavid du Colombier d->dd_loc += sizeof(struct dirent); 1203e12c5d1SDavid du Colombier return dr; 1213e12c5d1SDavid du Colombier } 122