Merge in Windows port using mingw and make.
This commit is contained in:
704
kern/devfs-win32.c
Normal file
704
kern/devfs-win32.c
Normal file
@ -0,0 +1,704 @@
|
||||
#include <windows.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifndef NAME_MAX
|
||||
# define NAME_MAX 256
|
||||
#endif
|
||||
#include "u.h"
|
||||
#include "lib.h"
|
||||
#include "dat.h"
|
||||
#include "fns.h"
|
||||
#include "error.h"
|
||||
|
||||
typedef struct DIR DIR;
|
||||
typedef struct Ufsinfo Ufsinfo;
|
||||
|
||||
enum
|
||||
{
|
||||
NUID = 256,
|
||||
NGID = 256,
|
||||
MAXPATH = 1024,
|
||||
MAXCOMP = 128
|
||||
};
|
||||
|
||||
struct DIR
|
||||
{
|
||||
HANDLE handle;
|
||||
char* path;
|
||||
int index;
|
||||
WIN32_FIND_DATA wfd;
|
||||
};
|
||||
|
||||
struct Ufsinfo
|
||||
{
|
||||
int mode;
|
||||
int fd;
|
||||
int uid;
|
||||
int gid;
|
||||
DIR* dir;
|
||||
ulong offset;
|
||||
QLock oq;
|
||||
char nextname[NAME_MAX];
|
||||
};
|
||||
|
||||
DIR* opendir(char*);
|
||||
int readdir(char*, DIR*);
|
||||
void closedir(DIR*);
|
||||
void rewinddir(DIR*);
|
||||
|
||||
char *base = "c:/.";
|
||||
|
||||
static Qid fsqid(char*, struct stat *);
|
||||
static void fspath(Chan*, char*, char*);
|
||||
// static void fsperm(Chan*, int);
|
||||
static ulong fsdirread(Chan*, uchar*, int, ulong);
|
||||
static int fsomode(int);
|
||||
static int chown(char *path, int uid, int);
|
||||
static int link(char *path, char *next);
|
||||
|
||||
/* clumsy hack, but not worse than the Path stuff in the last one */
|
||||
static char*
|
||||
uc2name(Chan *c)
|
||||
{
|
||||
char *s;
|
||||
|
||||
if(c->name == nil)
|
||||
return "/";
|
||||
s = c2name(c);
|
||||
if(s[0]=='#' && s[1]=='U')
|
||||
return s+2;
|
||||
return s;
|
||||
}
|
||||
|
||||
static char*
|
||||
lastelem(Chan *c)
|
||||
{
|
||||
char *s, *t;
|
||||
|
||||
s = uc2name(c);
|
||||
if((t = strrchr(s, '/')) == nil)
|
||||
return s;
|
||||
if(t[1] == 0)
|
||||
return t;
|
||||
return t+1;
|
||||
}
|
||||
|
||||
static Chan*
|
||||
fsattach(char *spec)
|
||||
{
|
||||
Chan *c;
|
||||
struct stat stbuf;
|
||||
static int devno;
|
||||
Ufsinfo *uif;
|
||||
|
||||
if(stat(base, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
c = devattach('U', spec);
|
||||
|
||||
uif = mallocz(sizeof(Ufsinfo), 1);
|
||||
uif->gid = stbuf.st_gid;
|
||||
uif->uid = stbuf.st_uid;
|
||||
uif->mode = stbuf.st_mode;
|
||||
|
||||
c->aux = uif;
|
||||
c->dev = devno++;
|
||||
c->qid.type = QTDIR;
|
||||
/*print("fsattach %s\n", c2name(c));*/
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
static Chan*
|
||||
fsclone(Chan *c, Chan *nc)
|
||||
{
|
||||
Ufsinfo *uif;
|
||||
|
||||
uif = mallocz(sizeof(Ufsinfo), 1);
|
||||
*uif = *(Ufsinfo*)c->aux;
|
||||
nc->aux = uif;
|
||||
|
||||
return nc;
|
||||
}
|
||||
|
||||
static int
|
||||
fswalk1(Chan *c, char *name)
|
||||
{
|
||||
struct stat stbuf;
|
||||
char path[MAXPATH];
|
||||
Ufsinfo *uif;
|
||||
|
||||
fspath(c, name, path);
|
||||
|
||||
/* print("** fs walk '%s' -> %s\n", path, name); /**/
|
||||
|
||||
if(stat(path, &stbuf) < 0)
|
||||
return 0;
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
uif->gid = stbuf.st_gid;
|
||||
uif->uid = stbuf.st_uid;
|
||||
uif->mode = stbuf.st_mode;
|
||||
|
||||
c->qid = fsqid(path, &stbuf);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern Cname* addelem(Cname*, char*);
|
||||
|
||||
static Walkqid*
|
||||
fswalk(Chan *c, Chan *nc, char **name, int nname)
|
||||
{
|
||||
int i;
|
||||
Cname *cname;
|
||||
Walkqid *wq;
|
||||
|
||||
if(nc != nil)
|
||||
panic("fswalk: nc != nil");
|
||||
wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
|
||||
nc = devclone(c);
|
||||
cname = c->name;
|
||||
incref(&cname->ref);
|
||||
|
||||
fsclone(c, nc);
|
||||
wq->clone = nc;
|
||||
for(i=0; i<nname; i++){
|
||||
nc->name = cname;
|
||||
if(fswalk1(nc, name[i]) == 0)
|
||||
break;
|
||||
cname = addelem(cname, name[i]);
|
||||
wq->qid[i] = nc->qid;
|
||||
}
|
||||
nc->name = nil;
|
||||
cnameclose(cname);
|
||||
if(i != nname){
|
||||
cclose(nc);
|
||||
wq->clone = nil;
|
||||
}
|
||||
wq->nqid = i;
|
||||
return wq;
|
||||
}
|
||||
|
||||
static int
|
||||
fsstat(Chan *c, uchar *buf, int n)
|
||||
{
|
||||
Dir d;
|
||||
struct stat stbuf;
|
||||
char path[MAXPATH];
|
||||
|
||||
if(n < BIT16SZ)
|
||||
error(Eshortstat);
|
||||
|
||||
fspath(c, 0, path);
|
||||
if(stat(path, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
d.name = lastelem(c);
|
||||
d.uid = "unknown";
|
||||
d.gid = "unknown";
|
||||
d.muid = "unknown";
|
||||
d.qid = c->qid;
|
||||
d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777);
|
||||
d.atime = stbuf.st_atime;
|
||||
d.mtime = stbuf.st_mtime;
|
||||
d.length = stbuf.st_size;
|
||||
d.type = 'U';
|
||||
d.dev = c->dev;
|
||||
return convD2M(&d, buf, n);
|
||||
}
|
||||
|
||||
static Chan*
|
||||
fsopen(Chan *c, int mode)
|
||||
{
|
||||
char path[MAXPATH];
|
||||
int m, isdir;
|
||||
Ufsinfo *uif;
|
||||
|
||||
/*print("fsopen %s\n", c2name(c));*/
|
||||
m = mode & (OTRUNC|3);
|
||||
switch(m) {
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
case 1|16:
|
||||
break;
|
||||
case 2:
|
||||
case 0|16:
|
||||
case 2|16:
|
||||
break;
|
||||
case 3:
|
||||
break;
|
||||
default:
|
||||
error(Ebadarg);
|
||||
}
|
||||
|
||||
isdir = c->qid.type & QTDIR;
|
||||
|
||||
if(isdir && mode != OREAD)
|
||||
error(Eperm);
|
||||
|
||||
m = fsomode(m & 3);
|
||||
c->mode = openmode(mode);
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
fspath(c, 0, path);
|
||||
if(isdir) {
|
||||
uif->dir = opendir(path);
|
||||
if(uif->dir == 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
else {
|
||||
if(mode & OTRUNC)
|
||||
m |= O_TRUNC;
|
||||
uif->fd = open(path, m|_O_BINARY, 0666);
|
||||
|
||||
if(uif->fd < 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
uif->offset = 0;
|
||||
|
||||
c->offset = 0;
|
||||
c->flag |= COPEN;
|
||||
return c;
|
||||
}
|
||||
|
||||
static void
|
||||
fscreate(Chan *c, char *name, int mode, ulong perm)
|
||||
{
|
||||
int fd, m;
|
||||
char path[MAXPATH];
|
||||
struct stat stbuf;
|
||||
Ufsinfo *uif;
|
||||
|
||||
m = fsomode(mode&3);
|
||||
|
||||
fspath(c, name, path);
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
if(perm & DMDIR) {
|
||||
if(m)
|
||||
error(Eperm);
|
||||
|
||||
if(mkdir(path) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
fd = open(path, 0);
|
||||
if(fd >= 0) {
|
||||
chmod(path, perm & 0777);
|
||||
chown(path, uif->uid, uif->uid);
|
||||
}
|
||||
close(fd);
|
||||
|
||||
uif->dir = opendir(path);
|
||||
if(uif->dir == 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
else {
|
||||
fd = open(path, _O_WRONLY|_O_BINARY|_O_CREAT|_O_TRUNC, 0666);
|
||||
if(fd >= 0) {
|
||||
if(m != 1) {
|
||||
close(fd);
|
||||
fd = open(path, m|_O_BINARY);
|
||||
}
|
||||
chmod(path, perm & 0777);
|
||||
chown(path, uif->uid, uif->gid);
|
||||
}
|
||||
if(fd < 0)
|
||||
error(strerror(errno));
|
||||
uif->fd = fd;
|
||||
}
|
||||
|
||||
if(stat(path, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
c->qid = fsqid(path, &stbuf);
|
||||
c->offset = 0;
|
||||
c->flag |= COPEN;
|
||||
c->mode = openmode(mode);
|
||||
}
|
||||
|
||||
static void
|
||||
fsclose(Chan *c)
|
||||
{
|
||||
Ufsinfo *uif;
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
if(c->flag & COPEN) {
|
||||
if(c->qid.type & QTDIR)
|
||||
closedir(uif->dir);
|
||||
else
|
||||
close(uif->fd);
|
||||
}
|
||||
|
||||
free(uif);
|
||||
}
|
||||
|
||||
static long
|
||||
fsread(Chan *c, void *va, long n, vlong offset)
|
||||
{
|
||||
int fd, r;
|
||||
Ufsinfo *uif;
|
||||
|
||||
/*print("fsread %s\n", c2name(c));*/
|
||||
if(c->qid.type & QTDIR)
|
||||
return fsdirread(c, va, n, offset);
|
||||
|
||||
uif = c->aux;
|
||||
qlock(&uif->oq);
|
||||
if(waserror()) {
|
||||
qunlock(&uif->oq);
|
||||
nexterror();
|
||||
}
|
||||
fd = uif->fd;
|
||||
if(uif->offset != offset) {
|
||||
r = lseek(fd, offset, 0);
|
||||
if(r < 0)
|
||||
error(strerror(errno));
|
||||
uif->offset = offset;
|
||||
}
|
||||
|
||||
n = read(fd, va, n);
|
||||
if(n < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
uif->offset += n;
|
||||
qunlock(&uif->oq);
|
||||
poperror();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static long
|
||||
fswrite(Chan *c, void *va, long n, vlong offset)
|
||||
{
|
||||
int fd, r;
|
||||
Ufsinfo *uif;
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
qlock(&uif->oq);
|
||||
if(waserror()) {
|
||||
qunlock(&uif->oq);
|
||||
nexterror();
|
||||
}
|
||||
fd = uif->fd;
|
||||
if(uif->offset != offset) {
|
||||
r = lseek(fd, offset, 0);
|
||||
if(r < 0)
|
||||
error(strerror(errno));
|
||||
uif->offset = offset;
|
||||
}
|
||||
|
||||
n = write(fd, va, n);
|
||||
if(n < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
uif->offset += n;
|
||||
qunlock(&uif->oq);
|
||||
poperror();
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static void
|
||||
fsremove(Chan *c)
|
||||
{
|
||||
int n;
|
||||
char path[MAXPATH];
|
||||
|
||||
fspath(c, 0, path);
|
||||
if(c->qid.type & QTDIR)
|
||||
n = rmdir(path);
|
||||
else
|
||||
n = remove(path);
|
||||
if(n < 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
|
||||
static int
|
||||
fswstat(Chan *c, uchar *buf, int n)
|
||||
{
|
||||
Dir d;
|
||||
struct stat stbuf;
|
||||
char old[MAXPATH], new[MAXPATH];
|
||||
char strs[MAXPATH*3], *p;
|
||||
Ufsinfo *uif;
|
||||
|
||||
if (convM2D(buf, n, &d, strs) != n)
|
||||
error(Ebadstat);
|
||||
|
||||
fspath(c, 0, old);
|
||||
if(stat(old, &stbuf) < 0)
|
||||
error(strerror(errno));
|
||||
|
||||
uif = c->aux;
|
||||
|
||||
// if(uif->uid != stbuf.st_uid)
|
||||
// error(Eowner);
|
||||
|
||||
if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) {
|
||||
fspath(c, 0, old);
|
||||
strcpy(new, old);
|
||||
p = strrchr(new, '/');
|
||||
strcpy(p+1, d.name);
|
||||
if(rename(old, new) < 0)
|
||||
error(strerror(errno));
|
||||
}
|
||||
|
||||
fspath(c, 0, old);
|
||||
if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) {
|
||||
if(chmod(old, d.mode&0777) < 0)
|
||||
error(strerror(errno));
|
||||
uif->mode &= ~0777;
|
||||
uif->mode |= d.mode&0777;
|
||||
}
|
||||
/*
|
||||
p = name2pass(gid, d.gid);
|
||||
if(p == 0)
|
||||
error(Eunknown);
|
||||
|
||||
if(p->id != stbuf.st_gid) {
|
||||
if(chown(old, stbuf.st_uid, p->id) < 0)
|
||||
error(sys_errlist[errno]);
|
||||
|
||||
uif->gid = p->id;
|
||||
}
|
||||
*/
|
||||
return n;
|
||||
}
|
||||
|
||||
static Qid
|
||||
fsqid(char *p, struct stat *st)
|
||||
{
|
||||
Qid q;
|
||||
int dev;
|
||||
ulong h;
|
||||
static int nqdev;
|
||||
static uchar *qdev;
|
||||
|
||||
if(qdev == 0)
|
||||
qdev = mallocz(65536U, 1);
|
||||
|
||||
q.type = 0;
|
||||
if((st->st_mode&S_IFMT) == S_IFDIR)
|
||||
q.type = QTDIR;
|
||||
|
||||
dev = st->st_dev & 0xFFFFUL;
|
||||
if(qdev[dev] == 0)
|
||||
qdev[dev] = ++nqdev;
|
||||
|
||||
h = 0;
|
||||
while(*p != '\0')
|
||||
h += *p++ * 13;
|
||||
|
||||
q.path = (vlong)qdev[dev]<<32;
|
||||
q.path |= h;
|
||||
q.vers = st->st_mtime;
|
||||
|
||||
return q;
|
||||
}
|
||||
|
||||
static void
|
||||
fspath(Chan *c, char *ext, char *path)
|
||||
{
|
||||
strcpy(path, base);
|
||||
strcat(path, "/");
|
||||
strcat(path, uc2name(c));
|
||||
if(ext) {
|
||||
strcat(path, "/");
|
||||
strcat(path, ext);
|
||||
}
|
||||
cleanname(path);
|
||||
}
|
||||
|
||||
static int
|
||||
isdots(char *name)
|
||||
{
|
||||
if(name[0] != '.')
|
||||
return 0;
|
||||
if(name[1] == '\0')
|
||||
return 1;
|
||||
if(name[1] != '.')
|
||||
return 0;
|
||||
if(name[2] == '\0')
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
p9readdir(char *name, Ufsinfo *uif)
|
||||
{
|
||||
if(uif->nextname[0]){
|
||||
strcpy(name, uif->nextname);
|
||||
uif->nextname[0] = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return readdir(name, uif->dir);
|
||||
}
|
||||
|
||||
static ulong
|
||||
fsdirread(Chan *c, uchar *va, int count, ulong offset)
|
||||
{
|
||||
int i;
|
||||
Dir d;
|
||||
long n;
|
||||
char de[NAME_MAX];
|
||||
struct stat stbuf;
|
||||
char path[MAXPATH], dirpath[MAXPATH];
|
||||
Ufsinfo *uif;
|
||||
|
||||
/*print("fsdirread %s\n", c2name(c));*/
|
||||
i = 0;
|
||||
uif = c->aux;
|
||||
|
||||
errno = 0;
|
||||
if(uif->offset != offset) {
|
||||
if(offset != 0)
|
||||
error("bad offset in fsdirread");
|
||||
uif->offset = offset; /* sync offset */
|
||||
uif->nextname[0] = 0;
|
||||
rewinddir(uif->dir);
|
||||
}
|
||||
|
||||
fspath(c, 0, dirpath);
|
||||
|
||||
while(i+BIT16SZ < count) {
|
||||
if(!p9readdir(de, uif))
|
||||
break;
|
||||
|
||||
if(de[0]==0 || isdots(de))
|
||||
continue;
|
||||
|
||||
d.name = de;
|
||||
sprint(path, "%s/%s", dirpath, de);
|
||||
memset(&stbuf, 0, sizeof stbuf);
|
||||
|
||||
if(stat(path, &stbuf) < 0) {
|
||||
print("dir: bad path %s\n", path);
|
||||
/* but continue... probably a bad symlink */
|
||||
}
|
||||
|
||||
d.uid = "unknown";
|
||||
d.gid = "unknown";
|
||||
d.muid = "unknown";
|
||||
d.qid = fsqid(path, &stbuf);
|
||||
d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777);
|
||||
d.atime = stbuf.st_atime;
|
||||
d.mtime = stbuf.st_mtime;
|
||||
d.length = stbuf.st_size;
|
||||
d.type = 'U';
|
||||
d.dev = c->dev;
|
||||
n = convD2M(&d, (char*)va+i, count-i);
|
||||
if(n == BIT16SZ){
|
||||
strcpy(uif->nextname, de);
|
||||
break;
|
||||
}
|
||||
i += n;
|
||||
}
|
||||
/*print("got %d\n", i);*/
|
||||
uif->offset += i;
|
||||
return i;
|
||||
}
|
||||
|
||||
static int
|
||||
fsomode(int m)
|
||||
{
|
||||
switch(m) {
|
||||
case 0: /* OREAD */
|
||||
case 3: /* OEXEC */
|
||||
return 0;
|
||||
case 1: /* OWRITE */
|
||||
return 1;
|
||||
case 2: /* ORDWR */
|
||||
return 2;
|
||||
}
|
||||
error(Ebadarg);
|
||||
return 0;
|
||||
}
|
||||
void
|
||||
closedir(DIR *d)
|
||||
{
|
||||
FindClose(d->handle);
|
||||
free(d->path);
|
||||
}
|
||||
|
||||
int
|
||||
readdir(char *name, DIR *d)
|
||||
{
|
||||
if(d->index != 0) {
|
||||
if(FindNextFile(d->handle, &d->wfd) == FALSE)
|
||||
return 0;
|
||||
}
|
||||
strcpy(name, d->wfd.cFileName);
|
||||
d->index++;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void
|
||||
rewinddir(DIR *d)
|
||||
{
|
||||
FindClose(d->handle);
|
||||
d->handle = FindFirstFile(d->path, &d->wfd);
|
||||
d->index = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
chown(char *path, int uid, int perm)
|
||||
{
|
||||
/* panic("chown"); */
|
||||
return 0;
|
||||
}
|
||||
|
||||
DIR*
|
||||
opendir(char *p)
|
||||
{
|
||||
DIR *d;
|
||||
char path[MAX_PATH];
|
||||
|
||||
|
||||
snprint(path, sizeof(path), "%s/*.*", p);
|
||||
|
||||
d = mallocz(sizeof(DIR), 1);
|
||||
if(d == 0)
|
||||
return 0;
|
||||
|
||||
d->index = 0;
|
||||
|
||||
d->handle = FindFirstFile(path, &d->wfd);
|
||||
if(d->handle == INVALID_HANDLE_VALUE) {
|
||||
free(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
d->path = strdup(path);
|
||||
return d;
|
||||
}
|
||||
|
||||
Dev fsdevtab = {
|
||||
'U',
|
||||
"fs",
|
||||
|
||||
devreset,
|
||||
devinit,
|
||||
devshutdown,
|
||||
fsattach,
|
||||
fswalk,
|
||||
fsstat,
|
||||
fsopen,
|
||||
fscreate,
|
||||
fsclose,
|
||||
fsread,
|
||||
devbread,
|
||||
fswrite,
|
||||
devbwrite,
|
||||
fsremove,
|
||||
fswstat,
|
||||
};
|
Reference in New Issue
Block a user