820 lines · 13.7 KB · C
RawDownload
#include	<windows.h>#include	<sys/types.h>#include	<sys/stat.h>#include	<fcntl.h> #include	"u.h"#include	"lib.h"#include	"dat.h"#include	"fns.h"#include	"error.h" #include	<libsec.h>	/* for sha1 in pathhash() */ typedef struct DIR	DIR;typedef	struct Ufsinfo	Ufsinfo; enum{	TPATH_ROOT	= 0,	// ""	TPATH_VOLUME	= 1,	// "C:"	TPATH_FILE	= 2,	// "C:\bla"}; struct DIR{	// for FindFileFirst()	HANDLE		handle;	WIN32_FIND_DATA	wfd; 	// for GetLogicalDriveStrings()	wchar_t		*drivebuf;	wchar_t		*drivep; 	// dont move to the next item	int		keep;}; struct Ufsinfo{	int	mode;	HANDLE	fh;	DIR*	dir;	vlong	offset;	QLock	oq;	wchar_t	*path;}; static	wchar_t *catpath(wchar_t *, char *, wchar_t *);static	ulong	fsdirread(Chan*, uchar*, int, vlong);static	ulong	fsaccess(int);static	ulong	pathtype(wchar_t *);static	int	checkvolume(wchar_t *); static ulongunixtime(FILETIME *ft){	vlong t;	t = ((vlong)ft->dwHighDateTime << 32)|((vlong)ft->dwLowDateTime);	t -= 116444736000000000LL;	return ((t<0)?(-1 - (-t - 1)) : t)/10000000;} static FILETIMEfiletime(ulong ut){	FILETIME ft;	vlong t = (vlong)ut * 10000000LL;	t += 116444736000000000LL;	ft.dwLowDateTime = t;	ft.dwHighDateTime = t >> 32;	return ft;} static uvlongpathhash(wchar_t *p){	uchar digest[SHA1dlen];	sha1((uchar*)p, wcslen(p)*sizeof(wchar_t), digest, nil);	return *(uvlong*)digest;} static ulongwfdtodmode(WIN32_FIND_DATA *wfd){	int m;	m = DMREAD|DMWRITE|DMEXEC;	if(wfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)		m |= DMDIR;	if(wfd->dwFileAttributes & FILE_ATTRIBUTE_READONLY)		m &= ~DMWRITE;	m |= (m & 07)<<3;	m |= (m & 07)<<6;	return m;} static Qidwfdtoqid(wchar_t *path, WIN32_FIND_DATA *wfd){	ulong t;	WIN32_FIND_DATA f;	Qid q; 	t = pathtype(path);	switch(t){	case TPATH_VOLUME:	case TPATH_ROOT:		q.type = QTDIR;		q.path = pathhash(path);		q.vers = 0;		break; 	case TPATH_FILE:		if(!wfd){			HANDLE h;			if((h = FindFirstFile(path, &f))==INVALID_HANDLE_VALUE)				oserror();			FindClose(h);			wfd = &f;		}		q.type = (wfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? QTDIR : QTFILE;		q.path = pathhash(path);		q.vers = unixtime(&wfd->ftLastWriteTime);		break;	}	return q;} static voidwfdtodir(wchar_t *path, Dir *d, WIN32_FIND_DATA *wfd){	extern ulong kerndate;	WIN32_FIND_DATA f; 	switch(pathtype(path)){	case TPATH_VOLUME:	case TPATH_ROOT:		wfd = nil;		d->mode = 0777 | DMDIR;		d->atime = seconds();		d->mtime = kerndate;		d->length = 0;		break; 	case TPATH_FILE:		if(wfd == nil){			HANDLE h;			if((h = FindFirstFile(path, &f))==INVALID_HANDLE_VALUE)				oserror();			FindClose(h);			wfd = &f;		}		d->mode		= wfdtodmode(wfd);		d->atime	= unixtime(&wfd->ftLastAccessTime);		d->mtime	= unixtime(&wfd->ftLastWriteTime);		d->length	= ((uvlong)wfd->nFileSizeHigh << 32)|((uvlong)wfd->nFileSizeLow);		break;	}	d->qid = wfdtoqid(path, wfd);	d->uid = eve;	d->gid = eve;	d->muid = eve;} static char*lastelem(Chan *c){	char *s, *t; 	s = chanpath(c);	if((t = strrchr(s, '/')) == nil)		return s;	if(t[1] == 0)		return t;	return t+1;} static ulongpathtype(wchar_t *path){	if(path[0] == 0 || path[1] == 0)		return TPATH_ROOT;	if(path[1] == ':' && path[2] == 0)		return TPATH_VOLUME;	return TPATH_FILE;} static intcheckvolume(wchar_t *path){	wchar_t vol[MAX_PATH];	wchar_t volname[MAX_PATH];	wchar_t fsysname[MAX_PATH];	DWORD complen;	DWORD flags; 	wcscpy(vol, path);	wcscat(vol, L"\\");	if(!GetVolumeInformation(		vol,		volname,		MAX_PATH,		NULL,		&complen,		&flags,		fsysname,		MAX_PATH))		return 0; 	return 1;	} static wchar_t*wstrdup(wchar_t *s){	wchar_t *d;	long n; 	n = (wcslen(s)+1)*sizeof(wchar_t);	d = mallocz(n, 0);	memmove(d, s, n);	return d;}	static Chan*fsattach(char *spec){	static int devno;	Ufsinfo *uif;	Chan *c; 	uif = mallocz(sizeof(Ufsinfo), 1);	uif->path = wstrdup(L""); 	c = devattach('U', spec);	c->aux = uif;	c->dev = devno++;	c->qid.type = QTDIR; 	return c;} static Chan*fsclone(Chan *c, Chan *nc){	Ufsinfo *uif; 	uif = mallocz(sizeof(Ufsinfo), 1);	*uif = *(Ufsinfo*)c->aux;	uif->path = wstrdup(uif->path);	nc->aux = uif; 	return nc;} static intfswalk1(Chan *c, char *name){	WIN32_FIND_DATA wfd;	HANDLE h;	wchar_t *p;	Ufsinfo *uif;		uif = c->aux;	p = catpath(uif->path, name, nil);	switch(pathtype(p)){	case TPATH_VOLUME:		if(!checkvolume(p)){			free(p);			return 0;		}	case TPATH_ROOT:		c->qid = wfdtoqid(p, nil);		break; 	case TPATH_FILE:		if((h = FindFirstFile(p, &wfd)) == INVALID_HANDLE_VALUE){			free(p);			return 0;		}		FindClose(h);		c->qid = wfdtoqid(p, &wfd);		break;	}	free(uif->path);	uif->path = p;	return 1;} static Walkqid*fswalk(Chan *c, Chan *nc, char **name, int nname){	int i;	Walkqid *wq; 	if(nc != nil)		panic("fswalk: nc != nil");	wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));	nc = devclone(c);	fsclone(c, nc);	wq->clone = nc;	for(i=0; i<nname; i++){		if(fswalk1(nc, name[i]) == 0)			break;		wq->qid[i] = nc->qid;	}	if(i != nname){		cclose(nc);		wq->clone = nil;	}	wq->nqid = i;	return wq;}	static intfsstat(Chan *c, uchar *buf, int n){	Dir d;	Ufsinfo *uif; 	if(n < BIT16SZ)		error(Eshortstat);	uif = c->aux;	d.name = lastelem(c);	wfdtodir(uif->path, &d, nil);	d.type = 'U';	d.dev = c->dev;	return convD2M(&d, buf, n);} static Chan*fsopen(Chan *c, int mode){	wchar_t *p;	Ufsinfo *uif;	int omode; 	omode = openmode(mode); 	uif = c->aux;	if(c->qid.type & QTDIR){		DIR *d; 		if(omode != OREAD)			error(Eperm);		d = malloc(sizeof(*d));		if(waserror()){			free(d);			nexterror();		}		switch(pathtype(uif->path)){		case TPATH_ROOT:			d->drivebuf = malloc(sizeof(wchar_t)*MAX_PATH);			if(GetLogicalDriveStrings(MAX_PATH-1, d->drivebuf) == 0){				free(d->drivebuf);				d->drivebuf = nil;				oserror();			}			d->drivep = d->drivebuf;			break;		case TPATH_VOLUME:		case TPATH_FILE:			p = catpath(uif->path, "*.*", nil);			if((d->handle = FindFirstFile(p, &d->wfd)) == INVALID_HANDLE_VALUE){				free(p);				oserror();			}			free(p);			break;		}		d->keep = 1;		uif->dir = d;		poperror();	} else {		uif->dir = NULL;		if((uif->fh = CreateFile(			uif->path,			fsaccess(omode & 3),			FILE_SHARE_READ | FILE_SHARE_WRITE,			NULL,			(mode & OTRUNC) ? TRUNCATE_EXISTING : OPEN_EXISTING,			FILE_ATTRIBUTE_NORMAL,			0)) == INVALID_HANDLE_VALUE)			oserror();	}	uif->offset = 0; 	c->offset = 0;	c->mode = omode;	c->flag |= COPEN;	return c;} static Chan*fscreate(Chan *c, char *name, int mode, ulong perm){	wchar_t *newpath;	Ufsinfo *uif;	DIR *d;	HANDLE h;	int omode; 	omode = openmode(mode & ~OEXCL); 	uif = c->aux;	newpath = catpath(uif->path, name, nil);	if(waserror()){		free(newpath);		nexterror();	}	d = NULL;	h = INVALID_HANDLE_VALUE;	if(perm & DMDIR) {		wchar_t *p; 		if(omode != OREAD || pathtype(uif->path) == TPATH_ROOT)			error(Eperm);		if(!CreateDirectory(newpath, NULL)){			if(GetLastError() != ERROR_ALREADY_EXISTS || mode & OEXCL)				oserror();		}		d = malloc(sizeof(*d));		p = catpath(newpath, "*.*", nil);		if((d->handle = FindFirstFile(p, &d->wfd)) == INVALID_HANDLE_VALUE){			free(p);			free(d);			oserror();		}		free(p);		if(waserror()){			FindClose(d->handle);			free(d);			nexterror();		}		d->keep = 1;	} else {		if((h = CreateFile(			newpath,			fsaccess(omode & 3),			FILE_SHARE_READ | FILE_SHARE_WRITE,			NULL,			(mode & OEXCL) ? CREATE_NEW : CREATE_ALWAYS,			FILE_ATTRIBUTE_NORMAL,			0)) == INVALID_HANDLE_VALUE)			oserror();		if(waserror()){			CloseHandle(h);			nexterror();		}	}	c->qid = wfdtoqid(newpath, nil);	uif->dir = d;	uif->fh = h;	poperror();	free(uif->path);	uif->path = newpath;	uif->offset = 0;	poperror(); 	c->offset = 0;	c->mode = omode;	c->flag |= COPEN;	return c;}  static voidfsclose(Chan *c){	Ufsinfo *uif; 	uif = c->aux;	if(c->flag & COPEN) {		if(uif->dir != nil){			if(uif->dir->drivebuf != nil){				free(uif->dir->drivebuf);				uif->dir->drivebuf = nil;			} else {				FindClose(uif->dir->handle);				free(uif->dir);			}		} else {			CloseHandle(uif->fh);		}		c->flag &= ~COPEN;		if(c->flag & CRCLOSE) {			devtab[c->type]->remove(c);			return;		}	}	free(uif->path);	free(uif);} static longfsread(Chan *c, void *va, long n, vlong offset){	HANDLE fh;	DWORD r;	Ufsinfo *uif; 

Lines 1–500 of 820.

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t