#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <pwd.h>
#include <grp.h>
#include <fcntl.h>
#include <unistd.h>
#define NODEFINE
#include <u.h>
#include <libc.h>
#include <fcall.h>
#include "fd.h"
File fdtbl[Nfd];
File*
pm_lockfile(int fd, int closedokay)
{
File *f;
if(fd < 0 || fd >= Nfd){
pm_werrstr("bad file descriptor");
return nil;
}
f = &fdtbl[fd];
pm_qlock(&f->lk);
if(!closedokay && f->type == Tfree){
pm_qunlock(&f->lk);
pm_werrstr("bad file descriptor");
return nil;
}
return f;
}
File*
pm_allocfile(int fd)
{
File *f;
if(fd < 0 || fd >= Nfd){
pm_werrstr("bad file descriptor");
return nil;
}
f = &fdtbl[fd];
pm_qlock(&f->lk);
if(f->type != Tfree){
pm_qunlock(&f->lk);
pm_werrstr("file descriptor already in use");
return nil;
}
return f;
}
int
pm_closefile(File *f)
{
int ret;
switch(f->type){
default:
pm_werrstr("cannot happen in pm_close");
ret = -1;
break;
case Tfree:
pm_werrstr("file descriptor not open");
ret = -1;
break;
case Tpipe:
case Tfile:
close(f->ufd);
f->ufd = -1;
ret = 0;
break;
case Tdir:
close(f->ufd);
f->ufd = -1;
pm_free(f->dents);
f->dents = 0;
f->mdents = 0;
ret = 0;
break;
}
f->type = Tfree;
pm_free(f->path);
f->path = nil;
pm_qunlock(&f->lk);
return ret;
}
static int
isopen(int ufd)
{
struct stat s;
if(fstat(ufd, &s) < 0 && errno == EBADF)
return 0;
return 1;
}
void
pm_fdinit(void)
{
int i;
for(i=0; i<Nfd; i++){
fdtbl[i].type = Tfree;
fdtbl[i].pmfd = i;
}
for(i=0; i<=20; i++){
if(isopen(i)){
fdtbl[i].ufd = i;
fdtbl[i].mode = PM_ORDWR;
fdtbl[i].type = Tfile;
}
}
}
int
pm_stat2buf(struct stat *s, char *name, uchar *buf, uint nbuf)
{
Dir d;
char *p;
struct passwd *pw;
struct group *gp;
int n;
d.type = 'M';
d.dev = s->st_dev;
d.qid.path = s->st_ino;
d.qid.vers = s->st_mtime;
d.mode = (s->st_mode&0777);
d.length = s->st_size;
if(S_ISDIR(s->st_mode)){
d.length = 0;
d.mode |= PM_DMDIR;
}
if(s->st_flags&(UF_APPEND|SF_APPEND))
d.mode |= PM_DMAPPEND;
d.qid.type = d.mode>>24;
d.atime = s->st_atimespec.tv_sec;
d.mtime = s->st_mtimespec.tv_sec;
if((p = pm_strrchr(name, '/')) != nil)
d.name = p+1;
else
d.name = name;
if((pw = getpwuid(s->st_uid)) != nil)
d.uid = pw->pw_name;
else
d.uid = "";
if((gp = getgrgid(s->st_gid)) != nil)
d.gid = gp->gr_name;
else
d.gid = "";
d.muid = "";
if((n=convD2M(&d, buf, nbuf)) <= BIT16SZ)
return 0;
return n;
}
char*
pm_openpath(char *p)
{
return pm_strdup(p);
}
int
pm_pmfd2ufd(int fd)
{
File *f;
int ufd;
if((f = pm_lockfile(fd, 0)) == nil)
return -1;
ufd = f->ufd;
pm_qunlock(&f->lk);
return ufd;
}
syntax highlighted by Code2HTML, v. 0.9.1