1*14093dc2SDavid du Colombier /*
2*14093dc2SDavid du Colombier * Disable Unicode until the calls to FindFirstFile etc
3*14093dc2SDavid du Colombier * are changed to use wide character strings.
4*14093dc2SDavid du Colombier */
5*14093dc2SDavid du Colombier #undef UNICODE
68ccd4a63SDavid du Colombier #include <windows.h>
78ccd4a63SDavid du Colombier #include <sys/types.h>
88ccd4a63SDavid du Colombier #include <sys/stat.h>
98ccd4a63SDavid du Colombier #include <fcntl.h>
108ccd4a63SDavid du Colombier
118ccd4a63SDavid du Colombier #ifndef NAME_MAX
128ccd4a63SDavid du Colombier # define NAME_MAX 256
138ccd4a63SDavid du Colombier #endif
148ccd4a63SDavid du Colombier #include "u.h"
158ccd4a63SDavid du Colombier #include "lib.h"
168ccd4a63SDavid du Colombier #include "dat.h"
178ccd4a63SDavid du Colombier #include "fns.h"
188ccd4a63SDavid du Colombier #include "error.h"
198ccd4a63SDavid du Colombier
208ccd4a63SDavid du Colombier typedef struct DIR DIR;
218ccd4a63SDavid du Colombier typedef struct Ufsinfo Ufsinfo;
228ccd4a63SDavid du Colombier
238ccd4a63SDavid du Colombier enum
248ccd4a63SDavid du Colombier {
258ccd4a63SDavid du Colombier NUID = 256,
268ccd4a63SDavid du Colombier NGID = 256,
278ccd4a63SDavid du Colombier MAXPATH = 1024,
288ccd4a63SDavid du Colombier MAXCOMP = 128
298ccd4a63SDavid du Colombier };
308ccd4a63SDavid du Colombier
318ccd4a63SDavid du Colombier struct DIR
328ccd4a63SDavid du Colombier {
338ccd4a63SDavid du Colombier HANDLE handle;
348ccd4a63SDavid du Colombier char* path;
358ccd4a63SDavid du Colombier int index;
368ccd4a63SDavid du Colombier WIN32_FIND_DATA wfd;
378ccd4a63SDavid du Colombier };
388ccd4a63SDavid du Colombier
398ccd4a63SDavid du Colombier struct Ufsinfo
408ccd4a63SDavid du Colombier {
418ccd4a63SDavid du Colombier int mode;
428ccd4a63SDavid du Colombier int fd;
438ccd4a63SDavid du Colombier int uid;
448ccd4a63SDavid du Colombier int gid;
458ccd4a63SDavid du Colombier DIR* dir;
468ccd4a63SDavid du Colombier ulong offset;
478ccd4a63SDavid du Colombier QLock oq;
488ccd4a63SDavid du Colombier char nextname[NAME_MAX];
498ccd4a63SDavid du Colombier };
508ccd4a63SDavid du Colombier
518ccd4a63SDavid du Colombier DIR* opendir(char*);
528ccd4a63SDavid du Colombier int readdir(char*, DIR*);
538ccd4a63SDavid du Colombier void closedir(DIR*);
548ccd4a63SDavid du Colombier void rewinddir(DIR*);
558ccd4a63SDavid du Colombier
568ccd4a63SDavid du Colombier char *base = "c:/.";
578ccd4a63SDavid du Colombier
588ccd4a63SDavid du Colombier static Qid fsqid(char*, struct stat *);
598ccd4a63SDavid du Colombier static void fspath(Chan*, char*, char*);
608ccd4a63SDavid du Colombier // static void fsperm(Chan*, int);
618ccd4a63SDavid du Colombier static ulong fsdirread(Chan*, uchar*, int, ulong);
628ccd4a63SDavid du Colombier static int fsomode(int);
638ccd4a63SDavid du Colombier static int chown(char *path, int uid, int);
648ccd4a63SDavid du Colombier
658ccd4a63SDavid du Colombier /* clumsy hack, but not worse than the Path stuff in the last one */
668ccd4a63SDavid du Colombier static char*
uc2name(Chan * c)678ccd4a63SDavid du Colombier uc2name(Chan *c)
688ccd4a63SDavid du Colombier {
698ccd4a63SDavid du Colombier char *s;
708ccd4a63SDavid du Colombier
718ccd4a63SDavid du Colombier if(c->name == nil)
728ccd4a63SDavid du Colombier return "/";
738ccd4a63SDavid du Colombier s = c2name(c);
748ccd4a63SDavid du Colombier if(s[0]=='#' && s[1]=='U')
758ccd4a63SDavid du Colombier return s+2;
768ccd4a63SDavid du Colombier return s;
778ccd4a63SDavid du Colombier }
788ccd4a63SDavid du Colombier
798ccd4a63SDavid du Colombier static char*
lastelem(Chan * c)808ccd4a63SDavid du Colombier lastelem(Chan *c)
818ccd4a63SDavid du Colombier {
828ccd4a63SDavid du Colombier char *s, *t;
838ccd4a63SDavid du Colombier
848ccd4a63SDavid du Colombier s = uc2name(c);
858ccd4a63SDavid du Colombier if((t = strrchr(s, '/')) == nil)
868ccd4a63SDavid du Colombier return s;
878ccd4a63SDavid du Colombier if(t[1] == 0)
888ccd4a63SDavid du Colombier return t;
898ccd4a63SDavid du Colombier return t+1;
908ccd4a63SDavid du Colombier }
918ccd4a63SDavid du Colombier
928ccd4a63SDavid du Colombier static Chan*
fsattach(char * spec)938ccd4a63SDavid du Colombier fsattach(char *spec)
948ccd4a63SDavid du Colombier {
958ccd4a63SDavid du Colombier Chan *c;
968ccd4a63SDavid du Colombier struct stat stbuf;
978ccd4a63SDavid du Colombier static int devno;
988ccd4a63SDavid du Colombier Ufsinfo *uif;
998ccd4a63SDavid du Colombier
1008ccd4a63SDavid du Colombier if(stat(base, &stbuf) < 0)
1018ccd4a63SDavid du Colombier error(strerror(errno));
1028ccd4a63SDavid du Colombier
1038ccd4a63SDavid du Colombier c = devattach('U', spec);
1048ccd4a63SDavid du Colombier
1058ccd4a63SDavid du Colombier uif = mallocz(sizeof(Ufsinfo), 1);
1068ccd4a63SDavid du Colombier uif->gid = stbuf.st_gid;
1078ccd4a63SDavid du Colombier uif->uid = stbuf.st_uid;
1088ccd4a63SDavid du Colombier uif->mode = stbuf.st_mode;
1098ccd4a63SDavid du Colombier
1108ccd4a63SDavid du Colombier c->aux = uif;
1118ccd4a63SDavid du Colombier c->dev = devno++;
1128ccd4a63SDavid du Colombier c->qid.type = QTDIR;
1138ccd4a63SDavid du Colombier /*print("fsattach %s\n", c2name(c));*/
1148ccd4a63SDavid du Colombier
1158ccd4a63SDavid du Colombier return c;
1168ccd4a63SDavid du Colombier }
1178ccd4a63SDavid du Colombier
1188ccd4a63SDavid du Colombier static Chan*
fsclone(Chan * c,Chan * nc)1198ccd4a63SDavid du Colombier fsclone(Chan *c, Chan *nc)
1208ccd4a63SDavid du Colombier {
1218ccd4a63SDavid du Colombier Ufsinfo *uif;
1228ccd4a63SDavid du Colombier
1238ccd4a63SDavid du Colombier uif = mallocz(sizeof(Ufsinfo), 1);
1248ccd4a63SDavid du Colombier *uif = *(Ufsinfo*)c->aux;
1258ccd4a63SDavid du Colombier nc->aux = uif;
1268ccd4a63SDavid du Colombier
1278ccd4a63SDavid du Colombier return nc;
1288ccd4a63SDavid du Colombier }
1298ccd4a63SDavid du Colombier
1308ccd4a63SDavid du Colombier static int
fswalk1(Chan * c,char * name)1318ccd4a63SDavid du Colombier fswalk1(Chan *c, char *name)
1328ccd4a63SDavid du Colombier {
1338ccd4a63SDavid du Colombier struct stat stbuf;
1348ccd4a63SDavid du Colombier char path[MAXPATH];
1358ccd4a63SDavid du Colombier Ufsinfo *uif;
1368ccd4a63SDavid du Colombier
1378ccd4a63SDavid du Colombier fspath(c, name, path);
1388ccd4a63SDavid du Colombier
1398ccd4a63SDavid du Colombier /* print("** fs walk '%s' -> %s\n", path, name); */
1408ccd4a63SDavid du Colombier
1418ccd4a63SDavid du Colombier if(stat(path, &stbuf) < 0)
1428ccd4a63SDavid du Colombier return 0;
1438ccd4a63SDavid du Colombier
1448ccd4a63SDavid du Colombier uif = c->aux;
1458ccd4a63SDavid du Colombier
1468ccd4a63SDavid du Colombier uif->gid = stbuf.st_gid;
1478ccd4a63SDavid du Colombier uif->uid = stbuf.st_uid;
1488ccd4a63SDavid du Colombier uif->mode = stbuf.st_mode;
1498ccd4a63SDavid du Colombier
1508ccd4a63SDavid du Colombier c->qid = fsqid(path, &stbuf);
1518ccd4a63SDavid du Colombier
1528ccd4a63SDavid du Colombier return 1;
1538ccd4a63SDavid du Colombier }
1548ccd4a63SDavid du Colombier
1558ccd4a63SDavid du Colombier extern Cname* addelem(Cname*, char*);
1568ccd4a63SDavid du Colombier
1578ccd4a63SDavid du Colombier static Walkqid*
fswalk(Chan * c,Chan * nc,char ** name,int nname)1588ccd4a63SDavid du Colombier fswalk(Chan *c, Chan *nc, char **name, int nname)
1598ccd4a63SDavid du Colombier {
1608ccd4a63SDavid du Colombier int i;
1618ccd4a63SDavid du Colombier Cname *cname;
1628ccd4a63SDavid du Colombier Walkqid *wq;
1638ccd4a63SDavid du Colombier
1648ccd4a63SDavid du Colombier if(nc != nil)
1658ccd4a63SDavid du Colombier panic("fswalk: nc != nil");
1668ccd4a63SDavid du Colombier wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
1678ccd4a63SDavid du Colombier nc = devclone(c);
1688ccd4a63SDavid du Colombier cname = c->name;
1698ccd4a63SDavid du Colombier incref(&cname->ref);
1708ccd4a63SDavid du Colombier
1718ccd4a63SDavid du Colombier fsclone(c, nc);
1728ccd4a63SDavid du Colombier wq->clone = nc;
1738ccd4a63SDavid du Colombier for(i=0; i<nname; i++){
1748ccd4a63SDavid du Colombier nc->name = cname;
1758ccd4a63SDavid du Colombier if(fswalk1(nc, name[i]) == 0)
1768ccd4a63SDavid du Colombier break;
1778ccd4a63SDavid du Colombier cname = addelem(cname, name[i]);
1788ccd4a63SDavid du Colombier wq->qid[i] = nc->qid;
1798ccd4a63SDavid du Colombier }
18096cbc34fSDavid du Colombier nc->name = cname;
1818ccd4a63SDavid du Colombier if(i != nname){
1828ccd4a63SDavid du Colombier cclose(nc);
1838ccd4a63SDavid du Colombier wq->clone = nil;
1848ccd4a63SDavid du Colombier }
1858ccd4a63SDavid du Colombier wq->nqid = i;
1868ccd4a63SDavid du Colombier return wq;
1878ccd4a63SDavid du Colombier }
1888ccd4a63SDavid du Colombier
1898ccd4a63SDavid du Colombier static int
fsstat(Chan * c,uchar * buf,int n)1908ccd4a63SDavid du Colombier fsstat(Chan *c, uchar *buf, int n)
1918ccd4a63SDavid du Colombier {
1928ccd4a63SDavid du Colombier Dir d;
1938ccd4a63SDavid du Colombier struct stat stbuf;
1948ccd4a63SDavid du Colombier char path[MAXPATH];
1958ccd4a63SDavid du Colombier
1968ccd4a63SDavid du Colombier if(n < BIT16SZ)
1978ccd4a63SDavid du Colombier error(Eshortstat);
1988ccd4a63SDavid du Colombier
1998ccd4a63SDavid du Colombier fspath(c, 0, path);
2008ccd4a63SDavid du Colombier if(stat(path, &stbuf) < 0)
2018ccd4a63SDavid du Colombier error(strerror(errno));
2028ccd4a63SDavid du Colombier
2038ccd4a63SDavid du Colombier d.name = lastelem(c);
2048ccd4a63SDavid du Colombier d.uid = "unknown";
2058ccd4a63SDavid du Colombier d.gid = "unknown";
2068ccd4a63SDavid du Colombier d.muid = "unknown";
2078ccd4a63SDavid du Colombier d.qid = c->qid;
2088ccd4a63SDavid du Colombier d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777);
2098ccd4a63SDavid du Colombier d.atime = stbuf.st_atime;
2108ccd4a63SDavid du Colombier d.mtime = stbuf.st_mtime;
2118ccd4a63SDavid du Colombier d.length = stbuf.st_size;
2128ccd4a63SDavid du Colombier d.type = 'U';
2138ccd4a63SDavid du Colombier d.dev = c->dev;
2148ccd4a63SDavid du Colombier return convD2M(&d, buf, n);
2158ccd4a63SDavid du Colombier }
2168ccd4a63SDavid du Colombier
2178ccd4a63SDavid du Colombier static Chan*
fsopen(Chan * c,int mode)2188ccd4a63SDavid du Colombier fsopen(Chan *c, int mode)
2198ccd4a63SDavid du Colombier {
2208ccd4a63SDavid du Colombier char path[MAXPATH];
2218ccd4a63SDavid du Colombier int m, isdir;
2228ccd4a63SDavid du Colombier Ufsinfo *uif;
2238ccd4a63SDavid du Colombier
2248ccd4a63SDavid du Colombier /*print("fsopen %s\n", c2name(c));*/
2258ccd4a63SDavid du Colombier m = mode & (OTRUNC|3);
2268ccd4a63SDavid du Colombier switch(m) {
2278ccd4a63SDavid du Colombier case 0:
2288ccd4a63SDavid du Colombier break;
2298ccd4a63SDavid du Colombier case 1:
2308ccd4a63SDavid du Colombier case 1|16:
2318ccd4a63SDavid du Colombier break;
2328ccd4a63SDavid du Colombier case 2:
2338ccd4a63SDavid du Colombier case 0|16:
2348ccd4a63SDavid du Colombier case 2|16:
2358ccd4a63SDavid du Colombier break;
2368ccd4a63SDavid du Colombier case 3:
2378ccd4a63SDavid du Colombier break;
2388ccd4a63SDavid du Colombier default:
2398ccd4a63SDavid du Colombier error(Ebadarg);
2408ccd4a63SDavid du Colombier }
2418ccd4a63SDavid du Colombier
2428ccd4a63SDavid du Colombier isdir = c->qid.type & QTDIR;
2438ccd4a63SDavid du Colombier
2448ccd4a63SDavid du Colombier if(isdir && mode != OREAD)
2458ccd4a63SDavid du Colombier error(Eperm);
2468ccd4a63SDavid du Colombier
2478ccd4a63SDavid du Colombier m = fsomode(m & 3);
2488ccd4a63SDavid du Colombier c->mode = openmode(mode);
2498ccd4a63SDavid du Colombier
2508ccd4a63SDavid du Colombier uif = c->aux;
2518ccd4a63SDavid du Colombier
2528ccd4a63SDavid du Colombier fspath(c, 0, path);
2538ccd4a63SDavid du Colombier if(isdir) {
2548ccd4a63SDavid du Colombier uif->dir = opendir(path);
2558ccd4a63SDavid du Colombier if(uif->dir == 0)
2568ccd4a63SDavid du Colombier error(strerror(errno));
2578ccd4a63SDavid du Colombier }
2588ccd4a63SDavid du Colombier else {
2598ccd4a63SDavid du Colombier if(mode & OTRUNC)
2608ccd4a63SDavid du Colombier m |= O_TRUNC;
2618ccd4a63SDavid du Colombier uif->fd = open(path, m|_O_BINARY, 0666);
2628ccd4a63SDavid du Colombier
2638ccd4a63SDavid du Colombier if(uif->fd < 0)
2648ccd4a63SDavid du Colombier error(strerror(errno));
2658ccd4a63SDavid du Colombier }
2668ccd4a63SDavid du Colombier uif->offset = 0;
2678ccd4a63SDavid du Colombier
2688ccd4a63SDavid du Colombier c->offset = 0;
2698ccd4a63SDavid du Colombier c->flag |= COPEN;
2708ccd4a63SDavid du Colombier return c;
2718ccd4a63SDavid du Colombier }
2728ccd4a63SDavid du Colombier
2738ccd4a63SDavid du Colombier static void
fscreate(Chan * c,char * name,int mode,ulong perm)2748ccd4a63SDavid du Colombier fscreate(Chan *c, char *name, int mode, ulong perm)
2758ccd4a63SDavid du Colombier {
2768ccd4a63SDavid du Colombier int fd, m;
2778ccd4a63SDavid du Colombier char path[MAXPATH];
2788ccd4a63SDavid du Colombier struct stat stbuf;
2798ccd4a63SDavid du Colombier Ufsinfo *uif;
2808ccd4a63SDavid du Colombier
2818ccd4a63SDavid du Colombier m = fsomode(mode&3);
2828ccd4a63SDavid du Colombier
2838ccd4a63SDavid du Colombier fspath(c, name, path);
2848ccd4a63SDavid du Colombier
2858ccd4a63SDavid du Colombier uif = c->aux;
2868ccd4a63SDavid du Colombier
2878ccd4a63SDavid du Colombier if(perm & DMDIR) {
2888ccd4a63SDavid du Colombier if(m)
2898ccd4a63SDavid du Colombier error(Eperm);
2908ccd4a63SDavid du Colombier
2918ccd4a63SDavid du Colombier if(mkdir(path) < 0)
2928ccd4a63SDavid du Colombier error(strerror(errno));
2938ccd4a63SDavid du Colombier
2948ccd4a63SDavid du Colombier fd = open(path, 0);
2958ccd4a63SDavid du Colombier if(fd >= 0) {
2968ccd4a63SDavid du Colombier chmod(path, perm & 0777);
2978ccd4a63SDavid du Colombier chown(path, uif->uid, uif->uid);
2988ccd4a63SDavid du Colombier }
2998ccd4a63SDavid du Colombier close(fd);
3008ccd4a63SDavid du Colombier
3018ccd4a63SDavid du Colombier uif->dir = opendir(path);
3028ccd4a63SDavid du Colombier if(uif->dir == 0)
3038ccd4a63SDavid du Colombier error(strerror(errno));
3048ccd4a63SDavid du Colombier }
3058ccd4a63SDavid du Colombier else {
3068ccd4a63SDavid du Colombier fd = open(path, _O_WRONLY|_O_BINARY|_O_CREAT|_O_TRUNC, 0666);
3078ccd4a63SDavid du Colombier if(fd >= 0) {
3088ccd4a63SDavid du Colombier if(m != 1) {
3098ccd4a63SDavid du Colombier close(fd);
3108ccd4a63SDavid du Colombier fd = open(path, m|_O_BINARY);
3118ccd4a63SDavid du Colombier }
3128ccd4a63SDavid du Colombier chmod(path, perm & 0777);
3138ccd4a63SDavid du Colombier chown(path, uif->uid, uif->gid);
3148ccd4a63SDavid du Colombier }
3158ccd4a63SDavid du Colombier if(fd < 0)
3168ccd4a63SDavid du Colombier error(strerror(errno));
3178ccd4a63SDavid du Colombier uif->fd = fd;
3188ccd4a63SDavid du Colombier }
3198ccd4a63SDavid du Colombier
3208ccd4a63SDavid du Colombier if(stat(path, &stbuf) < 0)
3218ccd4a63SDavid du Colombier error(strerror(errno));
3228ccd4a63SDavid du Colombier c->qid = fsqid(path, &stbuf);
3238ccd4a63SDavid du Colombier c->offset = 0;
3248ccd4a63SDavid du Colombier c->flag |= COPEN;
3258ccd4a63SDavid du Colombier c->mode = openmode(mode);
3268ccd4a63SDavid du Colombier }
3278ccd4a63SDavid du Colombier
3288ccd4a63SDavid du Colombier static void
fsclose(Chan * c)3298ccd4a63SDavid du Colombier fsclose(Chan *c)
3308ccd4a63SDavid du Colombier {
3318ccd4a63SDavid du Colombier Ufsinfo *uif;
3328ccd4a63SDavid du Colombier
3338ccd4a63SDavid du Colombier uif = c->aux;
3348ccd4a63SDavid du Colombier
3358ccd4a63SDavid du Colombier if(c->flag & COPEN) {
3368ccd4a63SDavid du Colombier if(c->qid.type & QTDIR)
3378ccd4a63SDavid du Colombier closedir(uif->dir);
3388ccd4a63SDavid du Colombier else
3398ccd4a63SDavid du Colombier close(uif->fd);
3408ccd4a63SDavid du Colombier }
3418ccd4a63SDavid du Colombier
3428ccd4a63SDavid du Colombier free(uif);
3438ccd4a63SDavid du Colombier }
3448ccd4a63SDavid du Colombier
3458ccd4a63SDavid du Colombier static long
fsread(Chan * c,void * va,long n,vlong offset)3468ccd4a63SDavid du Colombier fsread(Chan *c, void *va, long n, vlong offset)
3478ccd4a63SDavid du Colombier {
3488ccd4a63SDavid du Colombier int fd, r;
3498ccd4a63SDavid du Colombier Ufsinfo *uif;
3508ccd4a63SDavid du Colombier
3518ccd4a63SDavid du Colombier /*print("fsread %s\n", c2name(c));*/
3528ccd4a63SDavid du Colombier if(c->qid.type & QTDIR)
3538ccd4a63SDavid du Colombier return fsdirread(c, va, n, offset);
3548ccd4a63SDavid du Colombier
3558ccd4a63SDavid du Colombier uif = c->aux;
3568ccd4a63SDavid du Colombier qlock(&uif->oq);
3578ccd4a63SDavid du Colombier if(waserror()) {
3588ccd4a63SDavid du Colombier qunlock(&uif->oq);
3598ccd4a63SDavid du Colombier nexterror();
3608ccd4a63SDavid du Colombier }
3618ccd4a63SDavid du Colombier fd = uif->fd;
3628ccd4a63SDavid du Colombier if(uif->offset != offset) {
3638ccd4a63SDavid du Colombier r = lseek(fd, offset, 0);
3648ccd4a63SDavid du Colombier if(r < 0)
3658ccd4a63SDavid du Colombier error(strerror(errno));
3668ccd4a63SDavid du Colombier uif->offset = offset;
3678ccd4a63SDavid du Colombier }
3688ccd4a63SDavid du Colombier
3698ccd4a63SDavid du Colombier n = read(fd, va, n);
3708ccd4a63SDavid du Colombier if(n < 0)
3718ccd4a63SDavid du Colombier error(strerror(errno));
3728ccd4a63SDavid du Colombier
3738ccd4a63SDavid du Colombier uif->offset += n;
3748ccd4a63SDavid du Colombier qunlock(&uif->oq);
3758ccd4a63SDavid du Colombier poperror();
3768ccd4a63SDavid du Colombier
3778ccd4a63SDavid du Colombier return n;
3788ccd4a63SDavid du Colombier }
3798ccd4a63SDavid du Colombier
3808ccd4a63SDavid du Colombier static long
fswrite(Chan * c,void * va,long n,vlong offset)3818ccd4a63SDavid du Colombier fswrite(Chan *c, void *va, long n, vlong offset)
3828ccd4a63SDavid du Colombier {
3838ccd4a63SDavid du Colombier int fd, r;
3848ccd4a63SDavid du Colombier Ufsinfo *uif;
3858ccd4a63SDavid du Colombier
3868ccd4a63SDavid du Colombier uif = c->aux;
3878ccd4a63SDavid du Colombier
3888ccd4a63SDavid du Colombier qlock(&uif->oq);
3898ccd4a63SDavid du Colombier if(waserror()) {
3908ccd4a63SDavid du Colombier qunlock(&uif->oq);
3918ccd4a63SDavid du Colombier nexterror();
3928ccd4a63SDavid du Colombier }
3938ccd4a63SDavid du Colombier fd = uif->fd;
3948ccd4a63SDavid du Colombier if(uif->offset != offset) {
3958ccd4a63SDavid du Colombier r = lseek(fd, offset, 0);
3968ccd4a63SDavid du Colombier if(r < 0)
3978ccd4a63SDavid du Colombier error(strerror(errno));
3988ccd4a63SDavid du Colombier uif->offset = offset;
3998ccd4a63SDavid du Colombier }
4008ccd4a63SDavid du Colombier
4018ccd4a63SDavid du Colombier n = write(fd, va, n);
4028ccd4a63SDavid du Colombier if(n < 0)
4038ccd4a63SDavid du Colombier error(strerror(errno));
4048ccd4a63SDavid du Colombier
4058ccd4a63SDavid du Colombier uif->offset += n;
4068ccd4a63SDavid du Colombier qunlock(&uif->oq);
4078ccd4a63SDavid du Colombier poperror();
4088ccd4a63SDavid du Colombier
4098ccd4a63SDavid du Colombier return n;
4108ccd4a63SDavid du Colombier }
4118ccd4a63SDavid du Colombier
4128ccd4a63SDavid du Colombier static void
fsremove(Chan * c)4138ccd4a63SDavid du Colombier fsremove(Chan *c)
4148ccd4a63SDavid du Colombier {
4158ccd4a63SDavid du Colombier int n;
4168ccd4a63SDavid du Colombier char path[MAXPATH];
4178ccd4a63SDavid du Colombier
4188ccd4a63SDavid du Colombier fspath(c, 0, path);
4198ccd4a63SDavid du Colombier if(c->qid.type & QTDIR)
4208ccd4a63SDavid du Colombier n = rmdir(path);
4218ccd4a63SDavid du Colombier else
4228ccd4a63SDavid du Colombier n = remove(path);
4238ccd4a63SDavid du Colombier if(n < 0)
4248ccd4a63SDavid du Colombier error(strerror(errno));
4258ccd4a63SDavid du Colombier }
4268ccd4a63SDavid du Colombier
4278ccd4a63SDavid du Colombier static int
fswstat(Chan * c,uchar * buf,int n)4288ccd4a63SDavid du Colombier fswstat(Chan *c, uchar *buf, int n)
4298ccd4a63SDavid du Colombier {
4308ccd4a63SDavid du Colombier Dir d;
4318ccd4a63SDavid du Colombier struct stat stbuf;
4328ccd4a63SDavid du Colombier char old[MAXPATH], new[MAXPATH];
4338ccd4a63SDavid du Colombier char strs[MAXPATH*3], *p;
4348ccd4a63SDavid du Colombier Ufsinfo *uif;
4358ccd4a63SDavid du Colombier
4368ccd4a63SDavid du Colombier if (convM2D(buf, n, &d, strs) != n)
4378ccd4a63SDavid du Colombier error(Ebadstat);
4388ccd4a63SDavid du Colombier
4398ccd4a63SDavid du Colombier fspath(c, 0, old);
4408ccd4a63SDavid du Colombier if(stat(old, &stbuf) < 0)
4418ccd4a63SDavid du Colombier error(strerror(errno));
4428ccd4a63SDavid du Colombier
4438ccd4a63SDavid du Colombier uif = c->aux;
4448ccd4a63SDavid du Colombier
4458ccd4a63SDavid du Colombier // if(uif->uid != stbuf.st_uid)
4468ccd4a63SDavid du Colombier // error(Eowner);
4478ccd4a63SDavid du Colombier
4488ccd4a63SDavid du Colombier if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) {
4498ccd4a63SDavid du Colombier fspath(c, 0, old);
4508ccd4a63SDavid du Colombier strcpy(new, old);
4518ccd4a63SDavid du Colombier p = strrchr(new, '/');
4528ccd4a63SDavid du Colombier strcpy(p+1, d.name);
4538ccd4a63SDavid du Colombier if(rename(old, new) < 0)
4548ccd4a63SDavid du Colombier error(strerror(errno));
4558ccd4a63SDavid du Colombier }
4568ccd4a63SDavid du Colombier
4578ccd4a63SDavid du Colombier fspath(c, 0, old);
4588ccd4a63SDavid du Colombier if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) {
4598ccd4a63SDavid du Colombier if(chmod(old, d.mode&0777) < 0)
4608ccd4a63SDavid du Colombier error(strerror(errno));
4618ccd4a63SDavid du Colombier uif->mode &= ~0777;
4628ccd4a63SDavid du Colombier uif->mode |= d.mode&0777;
4638ccd4a63SDavid du Colombier }
4648ccd4a63SDavid du Colombier /*
4658ccd4a63SDavid du Colombier p = name2pass(gid, d.gid);
4668ccd4a63SDavid du Colombier if(p == 0)
4678ccd4a63SDavid du Colombier error(Eunknown);
4688ccd4a63SDavid du Colombier
4698ccd4a63SDavid du Colombier if(p->id != stbuf.st_gid) {
4708ccd4a63SDavid du Colombier if(chown(old, stbuf.st_uid, p->id) < 0)
4718ccd4a63SDavid du Colombier error(sys_errlist[errno]);
4728ccd4a63SDavid du Colombier
4738ccd4a63SDavid du Colombier uif->gid = p->id;
4748ccd4a63SDavid du Colombier }
4758ccd4a63SDavid du Colombier */
4768ccd4a63SDavid du Colombier return n;
4778ccd4a63SDavid du Colombier }
4788ccd4a63SDavid du Colombier
4798ccd4a63SDavid du Colombier static Qid
fsqid(char * p,struct stat * st)4808ccd4a63SDavid du Colombier fsqid(char *p, struct stat *st)
4818ccd4a63SDavid du Colombier {
4828ccd4a63SDavid du Colombier Qid q;
4838ccd4a63SDavid du Colombier int dev;
4848ccd4a63SDavid du Colombier ulong h;
4858ccd4a63SDavid du Colombier static int nqdev;
4868ccd4a63SDavid du Colombier static uchar *qdev;
4878ccd4a63SDavid du Colombier
4888ccd4a63SDavid du Colombier if(qdev == 0)
4898ccd4a63SDavid du Colombier qdev = mallocz(65536U, 1);
4908ccd4a63SDavid du Colombier
4918ccd4a63SDavid du Colombier q.type = 0;
4928ccd4a63SDavid du Colombier if((st->st_mode&S_IFMT) == S_IFDIR)
4938ccd4a63SDavid du Colombier q.type = QTDIR;
4948ccd4a63SDavid du Colombier
4958ccd4a63SDavid du Colombier dev = st->st_dev & 0xFFFFUL;
4968ccd4a63SDavid du Colombier if(qdev[dev] == 0)
4978ccd4a63SDavid du Colombier qdev[dev] = ++nqdev;
4988ccd4a63SDavid du Colombier
4998ccd4a63SDavid du Colombier h = 0;
5008ccd4a63SDavid du Colombier while(*p != '\0')
5018ccd4a63SDavid du Colombier h += *p++ * 13;
5028ccd4a63SDavid du Colombier
5038ccd4a63SDavid du Colombier q.path = (vlong)qdev[dev]<<32;
5048ccd4a63SDavid du Colombier q.path |= h;
5058ccd4a63SDavid du Colombier q.vers = st->st_mtime;
5068ccd4a63SDavid du Colombier
5078ccd4a63SDavid du Colombier return q;
5088ccd4a63SDavid du Colombier }
5098ccd4a63SDavid du Colombier
5108ccd4a63SDavid du Colombier static void
fspath(Chan * c,char * ext,char * path)5118ccd4a63SDavid du Colombier fspath(Chan *c, char *ext, char *path)
5128ccd4a63SDavid du Colombier {
5138ccd4a63SDavid du Colombier strcpy(path, base);
5148ccd4a63SDavid du Colombier strcat(path, "/");
5158ccd4a63SDavid du Colombier strcat(path, uc2name(c));
5168ccd4a63SDavid du Colombier if(ext) {
5178ccd4a63SDavid du Colombier strcat(path, "/");
5188ccd4a63SDavid du Colombier strcat(path, ext);
5198ccd4a63SDavid du Colombier }
5208ccd4a63SDavid du Colombier cleanname(path);
5218ccd4a63SDavid du Colombier }
5228ccd4a63SDavid du Colombier
5238ccd4a63SDavid du Colombier static int
isdots(char * name)5248ccd4a63SDavid du Colombier isdots(char *name)
5258ccd4a63SDavid du Colombier {
5268ccd4a63SDavid du Colombier if(name[0] != '.')
5278ccd4a63SDavid du Colombier return 0;
5288ccd4a63SDavid du Colombier if(name[1] == '\0')
5298ccd4a63SDavid du Colombier return 1;
5308ccd4a63SDavid du Colombier if(name[1] != '.')
5318ccd4a63SDavid du Colombier return 0;
5328ccd4a63SDavid du Colombier if(name[2] == '\0')
5338ccd4a63SDavid du Colombier return 1;
5348ccd4a63SDavid du Colombier return 0;
5358ccd4a63SDavid du Colombier }
5368ccd4a63SDavid du Colombier
5378ccd4a63SDavid du Colombier static int
p9readdir(char * name,Ufsinfo * uif)5388ccd4a63SDavid du Colombier p9readdir(char *name, Ufsinfo *uif)
5398ccd4a63SDavid du Colombier {
5408ccd4a63SDavid du Colombier if(uif->nextname[0]){
5418ccd4a63SDavid du Colombier strcpy(name, uif->nextname);
5428ccd4a63SDavid du Colombier uif->nextname[0] = 0;
5438ccd4a63SDavid du Colombier return 1;
5448ccd4a63SDavid du Colombier }
5458ccd4a63SDavid du Colombier
5468ccd4a63SDavid du Colombier return readdir(name, uif->dir);
5478ccd4a63SDavid du Colombier }
5488ccd4a63SDavid du Colombier
5498ccd4a63SDavid du Colombier static ulong
fsdirread(Chan * c,uchar * va,int count,ulong offset)5508ccd4a63SDavid du Colombier fsdirread(Chan *c, uchar *va, int count, ulong offset)
5518ccd4a63SDavid du Colombier {
5528ccd4a63SDavid du Colombier int i;
5538ccd4a63SDavid du Colombier Dir d;
5548ccd4a63SDavid du Colombier long n;
5558ccd4a63SDavid du Colombier char de[NAME_MAX];
5568ccd4a63SDavid du Colombier struct stat stbuf;
5578ccd4a63SDavid du Colombier char path[MAXPATH], dirpath[MAXPATH];
5588ccd4a63SDavid du Colombier Ufsinfo *uif;
5598ccd4a63SDavid du Colombier
5608ccd4a63SDavid du Colombier /*print("fsdirread %s\n", c2name(c));*/
5618ccd4a63SDavid du Colombier i = 0;
5628ccd4a63SDavid du Colombier uif = c->aux;
5638ccd4a63SDavid du Colombier
5648ccd4a63SDavid du Colombier errno = 0;
5658ccd4a63SDavid du Colombier if(uif->offset != offset) {
5668ccd4a63SDavid du Colombier if(offset != 0)
5678ccd4a63SDavid du Colombier error("bad offset in fsdirread");
5688ccd4a63SDavid du Colombier uif->offset = offset; /* sync offset */
5698ccd4a63SDavid du Colombier uif->nextname[0] = 0;
5708ccd4a63SDavid du Colombier rewinddir(uif->dir);
5718ccd4a63SDavid du Colombier }
5728ccd4a63SDavid du Colombier
5738ccd4a63SDavid du Colombier fspath(c, 0, dirpath);
5748ccd4a63SDavid du Colombier
5758ccd4a63SDavid du Colombier while(i+BIT16SZ < count) {
5768ccd4a63SDavid du Colombier if(!p9readdir(de, uif))
5778ccd4a63SDavid du Colombier break;
5788ccd4a63SDavid du Colombier
5798ccd4a63SDavid du Colombier if(de[0]==0 || isdots(de))
5808ccd4a63SDavid du Colombier continue;
5818ccd4a63SDavid du Colombier
5828ccd4a63SDavid du Colombier d.name = de;
5838ccd4a63SDavid du Colombier sprint(path, "%s/%s", dirpath, de);
5848ccd4a63SDavid du Colombier memset(&stbuf, 0, sizeof stbuf);
5858ccd4a63SDavid du Colombier
5868ccd4a63SDavid du Colombier if(stat(path, &stbuf) < 0) {
5878ccd4a63SDavid du Colombier print("dir: bad path %s\n", path);
5888ccd4a63SDavid du Colombier /* but continue... probably a bad symlink */
5898ccd4a63SDavid du Colombier }
5908ccd4a63SDavid du Colombier
5918ccd4a63SDavid du Colombier d.uid = "unknown";
5928ccd4a63SDavid du Colombier d.gid = "unknown";
5938ccd4a63SDavid du Colombier d.muid = "unknown";
5948ccd4a63SDavid du Colombier d.qid = fsqid(path, &stbuf);
5958ccd4a63SDavid du Colombier d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777);
5968ccd4a63SDavid du Colombier d.atime = stbuf.st_atime;
5978ccd4a63SDavid du Colombier d.mtime = stbuf.st_mtime;
5988ccd4a63SDavid du Colombier d.length = stbuf.st_size;
5998ccd4a63SDavid du Colombier d.type = 'U';
6008ccd4a63SDavid du Colombier d.dev = c->dev;
601*14093dc2SDavid du Colombier n = convD2M(&d, (uchar*)va+i, count-i);
6028ccd4a63SDavid du Colombier if(n == BIT16SZ){
6038ccd4a63SDavid du Colombier strcpy(uif->nextname, de);
6048ccd4a63SDavid du Colombier break;
6058ccd4a63SDavid du Colombier }
6068ccd4a63SDavid du Colombier i += n;
6078ccd4a63SDavid du Colombier }
6088ccd4a63SDavid du Colombier /*print("got %d\n", i);*/
6098ccd4a63SDavid du Colombier uif->offset += i;
6108ccd4a63SDavid du Colombier return i;
6118ccd4a63SDavid du Colombier }
6128ccd4a63SDavid du Colombier
6138ccd4a63SDavid du Colombier static int
fsomode(int m)6148ccd4a63SDavid du Colombier fsomode(int m)
6158ccd4a63SDavid du Colombier {
6168ccd4a63SDavid du Colombier switch(m) {
6178ccd4a63SDavid du Colombier case 0: /* OREAD */
6188ccd4a63SDavid du Colombier case 3: /* OEXEC */
6198ccd4a63SDavid du Colombier return 0;
6208ccd4a63SDavid du Colombier case 1: /* OWRITE */
6218ccd4a63SDavid du Colombier return 1;
6228ccd4a63SDavid du Colombier case 2: /* ORDWR */
6238ccd4a63SDavid du Colombier return 2;
6248ccd4a63SDavid du Colombier }
6258ccd4a63SDavid du Colombier error(Ebadarg);
6268ccd4a63SDavid du Colombier return 0;
6278ccd4a63SDavid du Colombier }
6288ccd4a63SDavid du Colombier void
closedir(DIR * d)6298ccd4a63SDavid du Colombier closedir(DIR *d)
6308ccd4a63SDavid du Colombier {
6318ccd4a63SDavid du Colombier FindClose(d->handle);
6328ccd4a63SDavid du Colombier free(d->path);
6338ccd4a63SDavid du Colombier }
6348ccd4a63SDavid du Colombier
6358ccd4a63SDavid du Colombier int
readdir(char * name,DIR * d)6368ccd4a63SDavid du Colombier readdir(char *name, DIR *d)
6378ccd4a63SDavid du Colombier {
6388ccd4a63SDavid du Colombier if(d->index != 0) {
6398ccd4a63SDavid du Colombier if(FindNextFile(d->handle, &d->wfd) == FALSE)
6408ccd4a63SDavid du Colombier return 0;
6418ccd4a63SDavid du Colombier }
642*14093dc2SDavid du Colombier strcpy(name, (char*)d->wfd.cFileName);
6438ccd4a63SDavid du Colombier d->index++;
6448ccd4a63SDavid du Colombier
6458ccd4a63SDavid du Colombier return 1;
6468ccd4a63SDavid du Colombier }
6478ccd4a63SDavid du Colombier
6488ccd4a63SDavid du Colombier void
rewinddir(DIR * d)6498ccd4a63SDavid du Colombier rewinddir(DIR *d)
6508ccd4a63SDavid du Colombier {
6518ccd4a63SDavid du Colombier FindClose(d->handle);
6528ccd4a63SDavid du Colombier d->handle = FindFirstFile(d->path, &d->wfd);
6538ccd4a63SDavid du Colombier d->index = 0;
6548ccd4a63SDavid du Colombier }
6558ccd4a63SDavid du Colombier
6568ccd4a63SDavid du Colombier static int
chown(char * path,int uid,int perm)6578ccd4a63SDavid du Colombier chown(char *path, int uid, int perm)
6588ccd4a63SDavid du Colombier {
6598ccd4a63SDavid du Colombier /* panic("chown"); */
6608ccd4a63SDavid du Colombier return 0;
6618ccd4a63SDavid du Colombier }
6628ccd4a63SDavid du Colombier
6638ccd4a63SDavid du Colombier DIR*
opendir(char * p)6648ccd4a63SDavid du Colombier opendir(char *p)
6658ccd4a63SDavid du Colombier {
6668ccd4a63SDavid du Colombier DIR *d;
6678ccd4a63SDavid du Colombier char path[MAX_PATH];
6688ccd4a63SDavid du Colombier
6698ccd4a63SDavid du Colombier
6708ccd4a63SDavid du Colombier snprint(path, sizeof(path), "%s/*.*", p);
6718ccd4a63SDavid du Colombier
6728ccd4a63SDavid du Colombier d = mallocz(sizeof(DIR), 1);
6738ccd4a63SDavid du Colombier if(d == 0)
6748ccd4a63SDavid du Colombier return 0;
6758ccd4a63SDavid du Colombier
6768ccd4a63SDavid du Colombier d->index = 0;
6778ccd4a63SDavid du Colombier
6788ccd4a63SDavid du Colombier d->handle = FindFirstFile(path, &d->wfd);
6798ccd4a63SDavid du Colombier if(d->handle == INVALID_HANDLE_VALUE) {
6808ccd4a63SDavid du Colombier free(d);
6818ccd4a63SDavid du Colombier return 0;
6828ccd4a63SDavid du Colombier }
6838ccd4a63SDavid du Colombier
6848ccd4a63SDavid du Colombier d->path = strdup(path);
6858ccd4a63SDavid du Colombier return d;
6868ccd4a63SDavid du Colombier }
6878ccd4a63SDavid du Colombier
6888ccd4a63SDavid du Colombier Dev fsdevtab = {
6898ccd4a63SDavid du Colombier 'U',
6908ccd4a63SDavid du Colombier "fs",
6918ccd4a63SDavid du Colombier
6928ccd4a63SDavid du Colombier devreset,
6938ccd4a63SDavid du Colombier devinit,
6948ccd4a63SDavid du Colombier devshutdown,
6958ccd4a63SDavid du Colombier fsattach,
6968ccd4a63SDavid du Colombier fswalk,
6978ccd4a63SDavid du Colombier fsstat,
6988ccd4a63SDavid du Colombier fsopen,
6998ccd4a63SDavid du Colombier fscreate,
7008ccd4a63SDavid du Colombier fsclose,
7018ccd4a63SDavid du Colombier fsread,
7028ccd4a63SDavid du Colombier devbread,
7038ccd4a63SDavid du Colombier fswrite,
7048ccd4a63SDavid du Colombier devbwrite,
7058ccd4a63SDavid du Colombier fsremove,
7068ccd4a63SDavid du Colombier fswstat,
7078ccd4a63SDavid du Colombier };
708