#include <sys/types.h>
#include <dirent.h>
#include <sys/time.h>
#include <unistd.h>
#include <sys/stat.h>
#include <errno.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#define NODEFINE
#include <u.h>
#include <libc.h>
#include <fcall.h>
#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;
}
syntax highlighted by Code2HTML, v. 0.9.1