#include #include #include #include #include #include #include #include #include #include #define NODEFINE #include #include #include #include "fd.h" static int dstat2buf(File *dir, char *name, uchar *buf, uint nbuf) { struct stat s; char *p; if(nbuf <= BIT16SZ) return 0; p = pm_malloc(strlen(dir->path)+1+strlen(name)+1); if(p == nil) return -1; strcpy(p, dir->path); strcat(p, "/"); strcat(p, name); if(stat(p, &s) < 0){ pm_free(p); return -1; } pm_free(p); return pm_stat2buf(&s, name, buf, nbuf); } long pm_read(int fd, void *a, long n) { int tot, m, ufd; File *f; struct dirent *de; if((f = pm_lockfile(fd, 0)) == nil) return -1; switch(f->type){ default: pm_werrstr("cannot happen in pm_read"); n = -1; break; case Tdir: if(f->mdents == 0){ f->dents = pm_malloc(8*1024); if(f->dents == nil){ n = -1; break; } f->mdents = 8*1024; } tot = 0; for(;;){ for(; f->rdents+8 <= f->wdents; f->rdents+=de->d_reclen){ de = (struct dirent*)(f->dents+f->rdents); if(de->d_name[0]=='.' && (de->d_name[1]=='\0' || (de->d_name[1]=='.' && de->d_name[2]=='\0'))) continue; switch((m=dstat2buf(f, de->d_name, (uchar*)a+tot, n-tot))){ case -1: break; case 0: goto BreakWhile; default: tot += m; break; } } BreakWhile:; f->rdents = 0; f->wdents = getdents(f->ufd, f->dents, f->mdents); if(f->wdents < 0){ if(tot == 0){ pm_oserror(); tot = -1; } break; } if(f->wdents == 0) break; } n = tot; break; case Tfile: case Tpipe: ufd = f->ufd; pm_qunlock(&f->lk); n = read(ufd, a, n); if(n < 0){ pm_oserror(); n = -1; } return n; } pm_qunlock(&f->lk); return n; }