ref: 693b886abbc71ece150ca9d462488672d2ebea98
parent: a090f5f5efa78bb496bd9f033903f842250dc7f3
author: cinap_lenrek <[email protected]>
date: Fri Feb 19 13:43:04 EST 2016
devfs-win32: allow access to all windows drive letters exporting them under /mnt/term/C: ect... 64-bit file offsets
--- a/kern/devfs-win32.c
+++ b/kern/devfs-win32.c
@@ -1,16 +1,8 @@
-/*
- * Disable Unicode until the calls to FindFirstFile etc
- * are changed to use wide character strings.
- */
-#undef UNICODE
#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"
@@ -20,48 +12,149 @@
typedef struct DIR DIR;
typedef struct Ufsinfo Ufsinfo;
+
enum
{
- NUID = 256,
- NGID = 256,
MAXPATH = 1024,
- MAXCOMP = 128
+ TPATH_ROOT = 0, // ""
+ TPATH_VOLUME = 1, // "C:"
+ TPATH_FILE = 2, // "C:\bla"
};
struct DIR
{
- HANDLE handle;
- char* path;
- int index;
+ // for FindFileFirst()
+ HANDLE handle;
WIN32_FIND_DATA wfd;
+
+ // for GetLogicalDriveStrings()
+ TCHAR *drivebuf;
+ TCHAR *drivep;
+
+ // dont move to the next item
+ int keep;
};
struct Ufsinfo
{
int mode;
- int fd;
- int uid;
- int gid;
+ HANDLE fh;
DIR* dir;
- ulong offset;
+ vlong offset;
QLock oq;
- char nextname[NAME_MAX];
};
-DIR* opendir(char*);
-int readdir(char*, DIR*);
-void closedir(DIR*);
-void rewinddir(DIR*);
+static void fspath(Chan *, char *, TCHAR *, int);
+static ulong fsdirread(Chan*, uchar*, int, vlong);
+static int fsomode(int);
+static ulong fsaccess(int);
+static ulong pathtype(TCHAR *);
+static int checkvolume(TCHAR *);
-char *base = "c:/.";
+char *base = "";
-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 ulong
+unixtime(FILETIME *ft)
+{
+ vlong t;
+ t = ((vlong)ft->dwHighDateTime << 32)|((vlong)ft->dwLowDateTime);
+ t -= 116444736000000000LL;
+ return ((t<0)?(-1 - (-t - 1)) : t)/10000000;
+}
+static uvlong
+pathhash(TCHAR *p)
+{
+ uvlong h;
+ h = 0LL;
+ for(; *p; p++)
+ h += *p * 13;
+ return h;
+}
+
+static ulong
+wfdtodmode(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 Qid
+wfdtoqid(TCHAR *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 void
+wfdtodir(TCHAR *path, Dir *d, WIN32_FIND_DATA *wfd)
+{
+ WIN32_FIND_DATA f;
+
+ d->uid = "nul";
+ d->gid = "nul";
+ d->muid = "nul";
+
+ switch(pathtype(path)){
+ case TPATH_VOLUME:
+ case TPATH_ROOT:
+ wfd = nil;
+ d->mode = 0777 | DMDIR;
+ d->atime = 0;
+ d->mtime = 0;
+ d->length = 0;
+ break;
+
+ case TPATH_FILE:
+ if(!wfd){
+ 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);
+}
+
/* clumsy hack, but not worse than the Path stuff in the last one */
static char*
uc2name(Chan *c)
@@ -69,10 +162,12 @@
char *s;
if(c->name == nil)
- return "/";
+ return "";
s = c2name(c);
if(s[0]=='#' && s[1]=='U')
- return s+2;
+ s += 2;
+ if(*s=='/')
+ s++;
return s;
}
@@ -88,29 +183,69 @@
return t;
return t+1;
}
+
+static ulong
+pathtype(TCHAR *path)
+{
+ int n;
+ n = wcslen(path);
+ if(n < 2){
+ return TPATH_ROOT;
+ }
+ if(n==2){
+ return TPATH_VOLUME;
+ }
+ return TPATH_FILE;
+}
+
+static int
+checkvolume(TCHAR *path)
+{
+ TCHAR vol[MAX_PATH];
+ TCHAR volname[MAX_PATH];
+ TCHAR fsysname[MAX_PATH];
+ DWORD complen;
+ DWORD flags;
+
+ wcsncpy(vol, path, MAX_PATH);
+#ifdef UNICODE
+ wcsncat(vol, L"\\", MAXPATH);
+#else
+ wcsncat(vol, "\\", MAXPATH);
+#endif
+
+ if(!GetVolumeInformation(
+ vol,
+ volname,
+ MAX_PATH,
+ NULL,
+ &complen,
+ &flags,
+ fsysname,
+ MAX_PATH)){
+ return 0;
+ }
+ return 1;
+}
+
+static int
+getfileowner(TCHAR *path, char *owner, int nowner)
+{
+ strncpy(owner, "Bill", nowner);
+ return 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;
}
@@ -130,25 +265,27 @@
static int
fswalk1(Chan *c, char *name)
{
- struct stat stbuf;
- char path[MAXPATH];
- Ufsinfo *uif;
+ HANDLE h;
+ WIN32_FIND_DATA wfd;
+ TCHAR path[MAXPATH];
- fspath(c, name, path);
+ fspath(c, name, path, MAXPATH);
- /* print("** fs walk '%s' -> %s\n", path, name); */
+ switch(pathtype(path)){
+ case TPATH_VOLUME:
+ if(!checkvolume(path))
+ return 0;
+ case TPATH_ROOT:
+ c->qid = wfdtoqid(path, nil);
+ break;
- 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);
-
+ case TPATH_FILE:
+ if((h = FindFirstFile(path, &wfd)) == INVALID_HANDLE_VALUE)
+ return 0;
+ FindClose(h);
+ c->qid = wfdtoqid(path, &wfd);
+ break;
+ }
return 1;
}
@@ -190,25 +327,21 @@
fsstat(Chan *c, uchar *buf, int n)
{
Dir d;
- struct stat stbuf;
- char path[MAXPATH];
+ TCHAR path[MAXPATH];
+ char owner[MAXPATH];
if(n < BIT16SZ)
error(Eshortstat);
+ fspath(c, 0, path, MAXPATH);
+ d.name = lastelem(c);
+ wfdtodir(path, &d, nil);
- fspath(c, 0, path);
- if(stat(path, &stbuf) < 0)
- error(strerror(errno));
+ if(getfileowner(path, owner, MAXPATH)){
+ d.uid = owner;
+ d.gid = owner;
+ d.muid = owner;
+ }
- 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);
@@ -217,11 +350,11 @@
static Chan*
fsopen(Chan *c, int mode)
{
- char path[MAXPATH];
+ TCHAR path[MAXPATH];
+ ulong t;
int m, isdir;
Ufsinfo *uif;
-/*print("fsopen %s\n", c2name(c));*/
m = mode & (OTRUNC|3);
switch(m) {
case 0:
@@ -240,31 +373,55 @@
}
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;
-
+ fspath(c, 0, path, MAXPATH);
+ t = pathtype(path);
+ if(isdir){
+ DIR *d;
+ d = malloc(sizeof(*d));
+ switch(t){
+ case TPATH_ROOT:
+ d->drivebuf = malloc(sizeof(TCHAR)*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:
+#ifdef UNICODE
+ wcsncat(path, L"\\*.*", MAXPATH);
+#else
+ wcsncat(path, "\\*.*", MAXPATH);
+#endif
+ if((d->handle = FindFirstFile(path, &d->wfd)) == INVALID_HANDLE_VALUE){
+ free(d);
+ oserror();
+ }
+ break;
+ }
+ d->keep = 1;
+ uif->dir = d;
+ } else {
+ uif->dir = nil;
+ if((uif->fh = CreateFile(
+ path,
+ fsaccess(mode),
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ (mode & OTRUNC) ? TRUNCATE_EXISTING : OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ 0)) == INVALID_HANDLE_VALUE){
+ oserror();
+ }
+ }
c->offset = 0;
c->flag |= COPEN;
return c;
@@ -273,58 +430,59 @@
static void
fscreate(Chan *c, char *name, int mode, ulong perm)
{
- int fd, m;
- char path[MAXPATH];
- struct stat stbuf;
+ int m;
+ TCHAR path[MAXPATH];
Ufsinfo *uif;
+ ulong t;
m = fsomode(mode&3);
- fspath(c, name, path);
+ fspath(c, name, path, MAXPATH);
+ t = pathtype(path);
uif = c->aux;
if(perm & DMDIR) {
- if(m)
+ TCHAR *p;
+ DIR *d;
+ if(m || t!=TPATH_FILE)
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);
+ if(!CreateDirectory(path, NULL))
+ oserror();
+ d = malloc(sizeof(*d));
+ p = &path[wcslen(path)];
+#ifdef UNICODE
+ wcsncat(path, L"\\*.*", MAXPATH);
+#else
+ wcsncat(path, "\\*.*", MAXPATH);
+#endif
+ if((d->handle = FindFirstFile(path, &d->wfd)) == INVALID_HANDLE_VALUE){
+ free(d);
+ oserror();
}
- close(fd);
-
- uif->dir = opendir(path);
- if(uif->dir == 0)
- error(strerror(errno));
+ *p = 0;
+ d->keep = 1;
+ uif->dir = d;
+ } else {
+ uif->dir = nil;
+ if((uif->fh = CreateFile(
+ path,
+ fsaccess(mode),
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ CREATE_NEW,
+ FILE_ATTRIBUTE_NORMAL,
+ 0)) == INVALID_HANDLE_VALUE){
+ oserror();
+ }
}
- 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->qid = wfdtoqid(path, nil);
c->offset = 0;
c->flag |= COPEN;
c->mode = openmode(mode);
}
+
static void
fsclose(Chan *c)
{
@@ -331,14 +489,19 @@
Ufsinfo *uif;
uif = c->aux;
-
if(c->flag & COPEN) {
- if(c->qid.type & QTDIR)
- closedir(uif->dir);
- else
- close(uif->fd);
+ if(uif->dir){
+ if(uif->dir->drivebuf){
+ free(uif->dir->drivebuf);
+ uif->dir->drivebuf = nil;
+ } else {
+ FindClose(uif->dir->handle);
+ free(uif->dir);
+ }
+ } else {
+ CloseHandle(uif->fh);
+ }
}
-
free(uif);
}
@@ -345,10 +508,10 @@
static long
fsread(Chan *c, void *va, long n, vlong offset)
{
- int fd, r;
+ HANDLE fh;
+ DWORD r;
Ufsinfo *uif;
-/*print("fsread %s\n", c2name(c));*/
if(c->qid.type & QTDIR)
return fsdirread(c, va, n, offset);
@@ -358,22 +521,22 @@
qunlock(&uif->oq);
nexterror();
}
- fd = uif->fd;
+ fh = uif->fh;
if(uif->offset != offset) {
- r = lseek(fd, offset, 0);
- if(r < 0)
- error(strerror(errno));
+ LONG high;
+ high = offset>>32;
+ offset = SetFilePointer(fh, (LONG)(offset & 0xFFFFFFFF), &high, FILE_BEGIN);
+ offset |= (vlong)high<<32;
uif->offset = offset;
}
-
- n = read(fd, va, n);
- if(n < 0)
- error(strerror(errno));
-
+ r = 0;
+ if(!ReadFile(fh, va, (DWORD)n, &r, NULL)){
+ oserror();
+ }
+ n = r;
uif->offset += n;
qunlock(&uif->oq);
poperror();
-
return n;
}
@@ -380,32 +543,35 @@
static long
fswrite(Chan *c, void *va, long n, vlong offset)
{
- int fd, r;
+ HANDLE fh;
+ DWORD w;
Ufsinfo *uif;
- uif = c->aux;
+ 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;
+ fh = uif->fh;
if(uif->offset != offset) {
- r = lseek(fd, offset, 0);
- if(r < 0)
- error(strerror(errno));
+ LONG high;
+ high = offset>>32;
+ offset = SetFilePointer(fh, (LONG)(offset & 0xFFFFFFFF), &high, FILE_BEGIN);
+ offset |= (vlong)high<<32;
uif->offset = offset;
}
-
- n = write(fd, va, n);
- if(n < 0)
- error(strerror(errno));
-
+ w = 0;
+ if(!WriteFile(fh, va, (DWORD)n, &w, NULL)){
+ oserror();
+ }
+ n = w;
uif->offset += n;
qunlock(&uif->oq);
poperror();
-
return n;
}
@@ -412,114 +578,103 @@
static void
fsremove(Chan *c)
{
- int n;
- char path[MAXPATH];
+ TCHAR path[MAXPATH];
- fspath(c, 0, path);
- if(c->qid.type & QTDIR)
- n = rmdir(path);
- else
- n = remove(path);
- if(n < 0)
- error(strerror(errno));
+ fspath(c, 0, path, MAXPATH);
+ if(c->qid.type & QTDIR){
+ if(!RemoveDirectory(path))
+ error("RemoveDirectory...");
+ } else {
+ if(!DeleteFile(path))
+ error("DeleteFile...");
+ }
}
static int
fswstat(Chan *c, uchar *buf, int n)
{
+ TCHAR path[MAXPATH];
+ char strs[MAXPATH*3];
Dir d;
- struct stat stbuf;
- char old[MAXPATH], new[MAXPATH];
- char strs[MAXPATH*3], *p;
- Ufsinfo *uif;
+ ulong t;
if (convM2D(buf, n, &d, strs) != n)
error(Ebadstat);
-
- fspath(c, 0, old);
- if(stat(old, &stbuf) < 0)
- error(strerror(errno));
+ fspath(c, 0, path, MAXPATH);
+ t = pathtype(path);
+ if(t != TPATH_FILE)
+ error(Ebadstat);
+ /* change name */
+ if(d.name[0]){
+ int l;
+ TCHAR newpath[MAXPATH];
+ wcsncpy(newpath, path, MAXPATH);
- 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));
+ /* replace last path-element with d.name */
+ l = wcslen(newpath)-1;
+ if(l <= 0)
+ error(Ebadstat);
+ for(;l>0; l--){
+ if(newpath[l-1]=='\\')
+ break;
+ }
+ if(l <= 0)
+ error(Ebadstat);
+ newpath[l] = 0;
+#ifdef UNICODE
+ if(!MultiByteToWideChar(CP_UTF8,0,d.name,-1,&newpath[l],MAXPATH-l-1))
+ oserror();
+#else
+ wcsncpy(&newpath[l], d.name, MAXPATH-l-1);
+#endif
+ if(wcscmp(path, newpath)!=0){
+ if(!MoveFile(path, newpath))
+ oserror();
+ wcsncpy(path, newpath, MAXPATH);
+ }
}
- 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;
+ /* fixme: change attributes */
+ c->qid = wfdtoqid(path, nil);
+ 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)
+_fspath(Chan *c, char *ext, char *path, int npath)
{
- strcpy(path, base);
- strcat(path, "/");
- strcat(path, uc2name(c));
+ *path = 0;
+ strncat(path, uc2name(c), npath);
if(ext) {
- strcat(path, "/");
- strcat(path, ext);
+ if(*path)
+ strncat(path, "/", npath);
+ strncat(path, ext, npath);
}
cleanname(path);
+ if(*path == '.')
+ *path = 0;
}
+static void
+fspath(Chan *c, char *ext, TCHAR *path, int npath)
+{
+ TCHAR *p;
+#ifdef UNICODE
+ char buf[MAXPATH];
+ _fspath(c, ext, buf, sizeof(buf));
+ if(!MultiByteToWideChar(CP_UTF8,0,buf,-1,path,npath)){
+ oserror();
+ }
+#else
+ _fspath(c, ext, path, npath);
+#endif
+ /* make a DOS path */
+ for(p=path; *p; p++){
+ if(*p == '/')
+ *p = '\\';
+ }
+}
+
static int
isdots(char *name)
{
@@ -534,78 +689,116 @@
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)
+fsdirread(Chan *c, uchar *va, int count, vlong offset)
{
int i;
+ ulong t;
Dir d;
long n;
- char de[NAME_MAX];
- struct stat stbuf;
- char path[MAXPATH], dirpath[MAXPATH];
Ufsinfo *uif;
+ char de[MAX_PATH*3];
+ int ndirpath;
+ TCHAR dirpath[MAXPATH];
-/*print("fsdirread %s\n", c2name(c));*/
i = 0;
uif = c->aux;
-
errno = 0;
+
+ fspath(c, 0, dirpath, MAXPATH);
+ ndirpath = wcslen(dirpath);
+ t = pathtype(dirpath);
+
if(uif->offset != offset) {
if(offset != 0)
error("bad offset in fsdirread");
uif->offset = offset; /* sync offset */
- uif->nextname[0] = 0;
- rewinddir(uif->dir);
+ switch(t){
+ case TPATH_ROOT:
+ uif->dir->drivep = uif->dir->drivebuf;
+ break;
+ case TPATH_VOLUME:
+ case TPATH_FILE:
+ FindClose(uif->dir->handle);
+#ifdef UNICODE
+ wcsncat(dirpath, L"\\*.*", MAXPATH);
+#else
+ wcsncat(dirpath, "\\*.*", MAXPATH);
+#endif
+ if((uif->dir->handle = FindFirstFile(dirpath, &uif->dir->wfd))==INVALID_HANDLE_VALUE){
+ oserror();
+ }
+ break;
+ }
+ uif->dir->keep = 1;
}
- fspath(c, 0, dirpath);
-
while(i+BIT16SZ < count) {
- if(!p9readdir(de, uif))
- break;
+ char owner[MAXPATH];
+ if(!uif->dir->keep) {
+ switch(t){
+ case TPATH_ROOT:
+ uif->dir->drivep += 4;
+ if(*uif->dir->drivep == 0)
+ goto out;
+ break;
+ case TPATH_VOLUME:
+ case TPATH_FILE:
+ if(!FindNextFile(uif->dir->handle, &uif->dir->wfd))
+ goto out;
+ break;
+ }
+ } else {
+ uif->dir->keep = 0;
+ }
+ if(t == TPATH_ROOT){
+ uif->dir->drivep[2] = 0;
+#ifdef UNICODE
+ WideCharToMultiByte(CP_UTF8,0,uif->dir->drivep,-1,de,sizeof(de),0,0);
+#else
+ strncpy(de, uif->dir->drivep, sizeof(de));
+#endif
+ } else {
+#ifdef UNICODE
+ WideCharToMultiByte(CP_UTF8,0,uif->dir->wfd.cFileName,-1,de,sizeof(de),0,0);
+#else
+ strncpy(de, uif->dir->wfd.cFileName, sizeof(de));
+#endif
+ }
if(de[0]==0 || isdots(de))
continue;
-
d.name = de;
- sprint(path, "%s/%s", dirpath, de);
- memset(&stbuf, 0, sizeof stbuf);
+ dirpath[ndirpath] = 0;
+ if(t == TPATH_ROOT){
+ wcsncat(dirpath, uif->dir->drivep, MAXPATH);
+ wfdtodir(dirpath, &d, nil);
+ } else {
+#ifdef UNICODE
+ wcsncat(dirpath, L"\\", MAXPATH);
+#else
+ wcsncat(dirpath, "\\", MAXPATH);
+#endif
+ wcsncat(dirpath, uif->dir->wfd.cFileName, MAXPATH);
+ wfdtodir(dirpath, &d, &uif->dir->wfd);
+ }
- if(stat(path, &stbuf) < 0) {
- print("dir: bad path %s\n", path);
- /* but continue... probably a bad symlink */
+ if(getfileowner(dirpath, owner, MAXPATH)){
+ d.uid = owner;
+ d.gid = owner;
+ d.muid = owner;
}
- 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, (uchar*)va+i, count-i);
if(n == BIT16SZ){
- strcpy(uif->nextname, de);
+ uif->dir->keep = 1;
break;
}
i += n;
}
-/*print("got %d\n", i);*/
+out:
uif->offset += i;
return i;
}
@@ -625,65 +818,29 @@
error(Ebadarg);
return 0;
}
-void
-closedir(DIR *d)
-{
- FindClose(d->handle);
- free(d->path);
-}
-int
-readdir(char *name, DIR *d)
+static ulong
+fsaccess(int m)
{
- if(d->index != 0) {
- if(FindNextFile(d->handle, &d->wfd) == FALSE)
- return 0;
+ ulong a;
+ a = 0;
+ switch(m & 3){
+ default:
+ error(Eperm);
+ break;
+ case OREAD:
+ a = GENERIC_READ;
+ break;
+ case OWRITE:
+ a = GENERIC_WRITE;
+ break;
+ case ORDWR:
+ a = GENERIC_READ | GENERIC_WRITE;
+ break;
}
- strcpy(name, (char*)d->wfd.cFileName);
- d->index++;
-
- return 1;
+ return a;
}
-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',