xref: /plan9/sys/src/cmd/unix/drawterm/kern/devfs-win32.c (revision 14093dc2f1c686bec1bc44cefce44368c26be35a)
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