123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700 |
- #include <windows.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- #include <fcntl.h>
- #include "lib9.h"
- #include "sys.h"
- #include "error.h"
- typedef struct DIR DIR;
- typedef struct Ufsinfo Ufsinfo;
- enum
- {
- NUID = 256,
- NGID = 256,
- MAXPATH = 1024,
- MAXCOMP = 128
- };
- extern char* sys_errlist[];
- struct DIR
- {
- HANDLE handle;
- char* path;
- int index;
- WIN32_FIND_DATA wfd;
- };
- struct Ufsinfo
- {
- int uid;
- int gid;
- int mode;
- int fd;
- DIR* dir;
- ulong offset;
- Qlock oq;
- };
- 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(Path*, 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);
- void
- fsinit(void)
- {
- }
- Chan*
- fsattach(void *spec)
- {
- Chan *c;
- struct stat stbuf;
- static int devno;
- Ufsinfo *uif;
- if(stat(base, &stbuf) < 0)
- error(sys_errlist[errno]);
- c = devattach('U', spec);
- uif = mallocz(sizeof(Ufsinfo));
- uif->gid = stbuf.st_gid;
- uif->uid = stbuf.st_uid;
- uif->mode = stbuf.st_mode;
- c->u.aux = uif;
- c->dev = devno++;
- return c;
- }
- Chan*
- fsclone(Chan *c, Chan *nc)
- {
- Ufsinfo *uif;
- nc = devclone(c, nc);
- uif = mallocz(sizeof(Ufsinfo));
- *uif = *(Ufsinfo*)c->u.aux;
- nc->u.aux = uif;
- return nc;
- }
- int
- fswalk(Chan *c, char *name)
- {
- Path *op;
- struct stat stbuf;
- char path[MAXPATH];
- Ufsinfo *uif;
- fspath(c->path, name, path);
- /* print("** fs walk '%s' -> %s\n", path, name); /**/
- if(stat(path, &stbuf) < 0)
- return 0;
- uif = c->u.aux;
- uif->gid = stbuf.st_gid;
- uif->uid = stbuf.st_uid;
- uif->mode = stbuf.st_mode;
- c->qid = fsqid(path, &stbuf);
- op = c->path;
- c->path = ptenter(&syspt, op, name);
- refdec(&op->r);
- return 1;
- }
- void
- fsstat(Chan *c, char *buf)
- {
- Dir d;
- struct stat stbuf;
- char path[MAXPATH];
- fspath(c->path, 0, path);
- if(stat(path, &stbuf) < 0)
- error(sys_errlist[errno]);
- strncpy(d.name, c->path->elem, NAMELEN);
- strncpy(d.uid, "unknown", NAMELEN);
- strncpy(d.gid, "unknown", NAMELEN);
- d.qid = c->qid;
- d.mode = (c->qid.path&CHDIR)|(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;
- convD2M(&d, buf);
- }
- Chan*
- fsopen(Chan *c, int mode)
- {
- char path[MAXPATH];
- int m, isdir;
- Ufsinfo *uif;
- m = mode & (OTRUNC|3);
- switch(m) {
- case 0:
- fsperm(c, 4);
- break;
- case 1:
- case 1|16:
- fsperm(c, 2);
- break;
- case 2:
- case 0|16:
- case 2|16:
- fsperm(c, 4);
- fsperm(c, 2);
- break;
- case 3:
- fsperm(c, 1);
- break;
- default:
- error(Ebadarg);
- }
- isdir = c->qid.path & CHDIR;
- if(isdir && mode != OREAD)
- error(Eperm);
- m = fsomode(m & 3);
- c->mode = openmode(mode);
- uif = c->u.aux;
- fspath(c->path, 0, path);
- if(isdir) {
- uif->dir = opendir(path);
- if(uif->dir == 0)
- error(sys_errlist[errno]);
- }
- else {
- if(mode & OTRUNC)
- m |= O_TRUNC;
- uif->fd = open(path, m|_O_BINARY, 0666);
- if(uif->fd < 0)
- error(sys_errlist[errno]);
- }
- uif->offset = 0;
- c->offset = 0;
- c->flag |= COPEN;
- return c;
- }
- void
- fscreate(Chan *c, char *name, int mode, ulong perm)
- {
- int fd, m;
- char path[MAXPATH];
- struct stat stbuf;
- Path *op;
- Ufsinfo *uif;
- fsperm(c, 2);
- m = fsomode(mode&3);
- fspath(c->path, name, path);
- uif = c->u.aux;
- if(perm & CHDIR) {
- if(m)
- error(Eperm);
- if(mkdir(path) < 0)
- error(sys_errlist[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(sys_errlist[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(sys_errlist[errno]);
- uif->fd = fd;
- }
- if(stat(path, &stbuf) < 0)
- error(sys_errlist[errno]);
- c->qid = fsqid(path, &stbuf);
- c->offset = 0;
- c->flag |= COPEN;
- c->mode = openmode(mode);
- op = c->path;
- c->path = ptenter(&syspt, op, name);
- refdec(&op->r);
- }
- void
- fsclose(Chan *c)
- {
- Ufsinfo *uif;
- uif = c->u.aux;
- if(c->flag & COPEN) {
- if(c->qid.path & CHDIR)
- closedir(uif->dir);
- else
- close(uif->fd);
- }
- free(uif);
- }
- long
- fsread(Chan *c, void *va, long n, ulong offset)
- {
- int fd, r;
- Ufsinfo *uif;
- if(c->qid.path & CHDIR)
- return fsdirread(c, va, n, offset);
- uif = c->u.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(sys_errlist[errno]);
- uif->offset = offset;
- }
- n = read(fd, va, n);
- if(n < 0)
- error(sys_errlist[errno]);
- uif->offset += n;
- qunlock(&uif->oq);
- poperror();
- return n;
- }
- long
- fswrite(Chan *c, void *va, long n, ulong offset)
- {
- int fd, r;
- Ufsinfo *uif;
- uif = c->u.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(sys_errlist[errno]);
- uif->offset = offset;
- }
- n = write(fd, va, n);
- if(n < 0)
- error(sys_errlist[errno]);
- uif->offset += n;
- qunlock(&uif->oq);
- poperror();
- return n;
- }
- void
- fsremove(Chan *c)
- {
- int n;
- char path[MAXPATH];
- fspath(c->path, 0, path);
- if(c->qid.path & CHDIR)
- n = rmdir(path);
- else
- n = remove(path);
- if(n < 0)
- error(sys_errlist[errno]);
- }
- void
- fswchk(char *path)
- {
- struct stat stbuf;
- if(stat(path, &stbuf) < 0)
- error(sys_errlist[errno]);
- if(stbuf.st_uid == up->uid)
- stbuf.st_mode >>= 6;
- else
- if(stbuf.st_gid == up->gid)
- stbuf.st_mode >>= 3;
- if(stbuf.st_mode & S_IWRITE)
- return;
- error(Eperm);
- }
- void
- fswstat(Chan *c, char *buf)
- {
- Dir d;
- Path *ph;
- struct stat stbuf;
- char old[MAXPATH], new[MAXPATH], dir[MAXPATH];
- Ufsinfo *uif;
- convM2D(buf, &d);
-
- fspath(c->path, 0, old);
- if(stat(old, &stbuf) < 0)
- error(sys_errlist[errno]);
- uif = c->u.aux;
- if(uif->uid != stbuf.st_uid)
- error(Eowner);
- if(strcmp(d.name, c->path->elem) != 0) {
- fspath(c->path->parent, 0, dir);
- fswchk(dir);
- fspath(c->path, 0, old);
- ph = ptenter(&syspt, c->path->parent, d.name);
- fspath(ph, 0, new);
- if(link(old, new) < 0)
- error(sys_errlist[errno]);
- if(unlink(old) < 0)
- error(sys_errlist[errno]);
- refdec(&c->path->r);
- c->path = ph;
- }
- fspath(c->path, 0, old);
- if((int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) {
- if(chmod(old, d.mode&0777) < 0)
- error(sys_errlist[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;
- }
- */
- }
- static Qid
- fsqid(char *p, struct stat *st)
- {
- Qid q;
- int dev;
- ulong h;
- static int nqdev;
- static uchar *qdev;
- uchar *name;
- name = p;
- if(qdev == 0)
- qdev = mallocz(65536U);
- q.path = 0;
- if((st->st_mode&S_IFMT) == S_IFDIR)
- q.path = CHDIR;
- dev = st->st_dev & 0xFFFFUL;
- if(qdev[dev] == 0) {
- if(++nqdev >= 128)
- error("too many devices");
- qdev[dev] = nqdev;
- }
- h = 0;
- while(*p != '\0')
- h += *p++ * 13;
-
- q.path |= qdev[dev]<<24;
- q.path |= h & 0x00FFFFFFUL;
- q.vers = st->st_mtime;
- return q;
- }
- static void
- fspath(Path *p, char *ext, char *path)
- {
- int i, n;
- char *comp[MAXCOMP];
- strcpy(path, base);
- i = strlen(base);
- if(p == 0) {
- if(ext) {
- path[i++] = '/';
- strcpy(path+i, ext);
- }
- return;
- }
- n = 0;
- if(ext)
- comp[n++] = ext;
- while(p->parent) {
- comp[n++] = p->elem;
- p = p->parent;
- }
- while(n) {
- path[i++] = '/';
- strcpy(path+i, comp[--n]);
- i += strlen(comp[n]);
- }
- path[i] = '\0';
- }
- static void
- fsperm(Chan *c, int mask)
- {
- int m;
- Ufsinfo *uif;
- uif = c->u.aux;
- m = uif->mode;
- /*
- print("fsperm: %o %o uuid %d ugid %d cuid %d cgid %d\n",
- m, mask, up->uid, up->gid, uif->uid, uif->gid);
- */
- if(uif->uid == up->uid)
- m >>= 6;
- else
- if(uif->gid == up->gid)
- m >>= 3;
- m &= mask;
- if(m == 0)
- error(Eperm);
- }
- 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 ulong
- fsdirread(Chan *c, uchar *va, int count, ulong offset)
- {
- int i;
- Dir d;
- long n;
- char de[256];
- struct stat stbuf;
- char path[MAXPATH], dirpath[MAXPATH];
- Ufsinfo *uif;
- count = (count/DIRLEN)*DIRLEN;
- i = 0;
- uif = c->u.aux;
- errno = 0;
- if(uif->offset != offset) {
- uif->offset = offset; /* sync offset */
- rewinddir(uif->dir);
- for(n=0; n<(int)offset; ) {
- if(!readdir(de, uif->dir))
- break;
- if(de[0]==0 || isdots(de))
- continue;
- n += DIRLEN;
- }
- }
- fspath(c->path, 0, dirpath);
- while(i < count) {
- if(!readdir(de, uif->dir))
- break;
- if(de[0]==0 || isdots(de))
- continue;
- strncpy(d.name, de, NAMELEN-1);
- d.name[NAMELEN-1] = 0;
- sprint(path, "%s/%s", dirpath, de);
- memset(&stbuf, 0, sizeof stbuf);
- if(stat(path, &stbuf) < 0) {
- iprint("dir: bad path %s\n", path);
- /* but continue... probably a bad symlink */
- }
- strncpy(d.uid, "unknown", NAMELEN);
- strncpy(d.gid, "unknown", NAMELEN);
- d.qid = fsqid(path, &stbuf);
- d.mode = (d.qid.path&CHDIR)|(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;
- convD2M(&d, va+i);
- i += DIRLEN;
- }
- 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;
- }
- static int
- link(char *path, char *next)
- {
- panic("link");
- return 0;
- }
- DIR*
- opendir(char *p)
- {
- DIR *d;
- char path[MAX_PATH];
-
- snprint(path, sizeof(path), "%s/*.*", p);
- d = mallocz(sizeof(DIR));
- 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;
- }
|