History

devfs-win32: allow access to all windows drive letters exporting them under /mnt/term/C: ect... 64-bit file offsets

cinap_lenrek committed 10 years ago

Commit 693b8861 parent a090f5f1 file · +499 −342Browse files

Unified · Split

kern/devfs-win32.c+499−342
@@ -1,16 +1,8 @@
1−/*
2− * Disable Unicode until the calls to FindFirstFile etc
3− * are changed to use wide character strings.
4− */
5−#undef UNICODE
61 #include <windows.h>
72 #include <sys/types.h>
83 #include <sys/stat.h>
94 #include <fcntl.h>
105
11−#ifndef NAME_MAX
12−# define NAME_MAX 256
13−#endif
146 #include "u.h"
157 #include "lib.h"
168 #include "dat.h"
@@ -20,47 +12,148 @@ · 3 unmodified lines
2012 typedef struct DIR DIR;
2113 typedef struct Ufsinfo Ufsinfo;
2214
15+
2316 enum
2417 {
25− NUID = 256,
26− NGID = 256,
2718 MAXPATH = 1024,
28− MAXCOMP = 128
19+ TPATH_ROOT = 0, // ""
20+ TPATH_VOLUME = 1, // "C:"
21+ TPATH_FILE = 2, // "C:\bla"
2922 };
3023
3124 struct DIR
3225 {
33− HANDLE handle;
34− char* path;
35− int index;
26+ // for FindFileFirst()
27+ HANDLE handle;
3628 WIN32_FIND_DATA wfd;
29+
30+ // for GetLogicalDriveStrings()
31+ TCHAR *drivebuf;
32+ TCHAR *drivep;
33+
34+ // dont move to the next item
35+ int keep;
3736 };
3837
3938 struct Ufsinfo
4039 {
4140 int mode;
42− int fd;
43− int uid;
44− int gid;
41+ HANDLE fh;
4542 DIR* dir;
46− ulong offset;
43+ vlong offset;
4744 QLock oq;
48− char nextname[NAME_MAX];
4945 };
5046
51−DIR* opendir(char*);
52−int readdir(char*, DIR*);
53−void closedir(DIR*);
54−void rewinddir(DIR*);
47+static void fspath(Chan *, char *, TCHAR *, int);
48+static ulong fsdirread(Chan*, uchar*, int, vlong);
49+static int fsomode(int);
50+static ulong fsaccess(int);
51+static ulong pathtype(TCHAR *);
52+static int checkvolume(TCHAR *);
5553
56−char *base = "c:/.";
54+char *base = "";
5755
58−static Qid fsqid(char*, struct stat *);
59−static void fspath(Chan*, char*, char*);
60−// static void fsperm(Chan*, int);
61−static ulong fsdirread(Chan*, uchar*, int, ulong);
62−static int fsomode(int);
63−static int chown(char *path, int uid, int);
56+static ulong
57+unixtime(FILETIME *ft)
58+{
59+ vlong t;
60+ t = ((vlong)ft->dwHighDateTime << 32)|((vlong)ft->dwLowDateTime);
61+ t -= 116444736000000000LL;
62+ return ((t<0)?(-1 - (-t - 1)) : t)/10000000;
63+}
64+
65+static uvlong
66+pathhash(TCHAR *p)
67+{
68+ uvlong h;
69+ h = 0LL;
70+ for(; *p; p++)
71+ h += *p * 13;
72+ return h;
73+}
74+
75+static ulong
76+wfdtodmode(WIN32_FIND_DATA *wfd)
77+{
78+ int m;
79+ m = DMREAD|DMWRITE|DMEXEC;
80+ if(wfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
81+ m |= DMDIR;
82+ if(wfd->dwFileAttributes & FILE_ATTRIBUTE_READONLY)
83+ m &= ~DMWRITE;
84+ m |= (m & 07)<<3;
85+ m |= (m & 07)<<6;
86+ return m;
87+}
88+
89+static Qid
90+wfdtoqid(TCHAR *path, WIN32_FIND_DATA *wfd)
91+{
92+ ulong t;
93+ WIN32_FIND_DATA f;
94+ Qid q;
95+
96+ t = pathtype(path);
97+
98+ switch(t){
99+ case TPATH_VOLUME:
100+ case TPATH_ROOT:
101+ q.type = QTDIR;
102+ q.path = pathhash(path);
103+ q.vers = 0;
104+ break;
105+
106+ case TPATH_FILE:
107+ if(!wfd){
108+ HANDLE h;
109+ if((h = FindFirstFile(path, &f))==INVALID_HANDLE_VALUE)
110+ oserror();
111+ FindClose(h);
112+ wfd = &f;
113+ }
114+ q.type = (wfd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) ? QTDIR : QTFILE;
115+ q.path = pathhash(path);
116+ q.vers = unixtime(&wfd->ftLastWriteTime);
117+ break;
118+ }
119+ return q;
120+}
121+
122+static void
123+wfdtodir(TCHAR *path, Dir *d, WIN32_FIND_DATA *wfd)
124+{
125+ WIN32_FIND_DATA f;
126+
127+ d->uid = "nul";
128+ d->gid = "nul";
129+ d->muid = "nul";
130+
131+ switch(pathtype(path)){
132+ case TPATH_VOLUME:
133+ case TPATH_ROOT:
134+ wfd = nil;
135+ d->mode = 0777 | DMDIR;
136+ d->atime = 0;
137+ d->mtime = 0;
138+ d->length = 0;
139+ break;
140+
141+ case TPATH_FILE:
142+ if(!wfd){
143+ HANDLE h;
144+ if((h = FindFirstFile(path, &f))==INVALID_HANDLE_VALUE)
145+ oserror();
146+ FindClose(h);
147+ wfd = &f;
148+ }
149+ d->mode = wfdtodmode(wfd);
150+ d->atime = unixtime(&wfd->ftLastAccessTime);
151+ d->mtime = unixtime(&wfd->ftLastWriteTime);
152+ d->length = ((uvlong)wfd->nFileSizeHigh << 32)|((uvlong)wfd->nFileSizeLow);
153+ break;
154+ }
155+ d->qid = wfdtoqid(path, wfd);
156+}
64157
65158 /* clumsy hack, but not worse than the Path stuff in the last one */
66159 static char*
@@ -69,10 +162,12 @@ uc2name(Chan *c) · 2 unmodified lines
69162 char *s;
70163
71164 if(c->name == nil)
72− return "/";
165+ return "";
73166 s = c2name(c);
74167 if(s[0]=='#' && s[1]=='U')
75− return s+2;
168+ s += 2;
169+ if(*s=='/')
170+ s++;
76171 return s;
77172 }
78173
@@ -88,29 +183,69 @@ lastelem(Chan *c) · 9 unmodified lines
88183 return t;
89184 return t+1;
90185 }
186+
187+static ulong
188+pathtype(TCHAR *path)
189+{
190+ int n;
191+ n = wcslen(path);
192+ if(n < 2){
193+ return TPATH_ROOT;
194+ }
195+ if(n==2){
196+ return TPATH_VOLUME;
197+ }
198+ return TPATH_FILE;
199+}
200+
201+static int
202+checkvolume(TCHAR *path)
203+{
204+ TCHAR vol[MAX_PATH];
205+ TCHAR volname[MAX_PATH];
206+ TCHAR fsysname[MAX_PATH];
207+ DWORD complen;
208+ DWORD flags;
209+
210+ wcsncpy(vol, path, MAX_PATH);
211+#ifdef UNICODE
212+ wcsncat(vol, L"\\", MAXPATH);
213+#else
214+ wcsncat(vol, "\\", MAXPATH);
215+#endif
216+
217+ if(!GetVolumeInformation(
218+ vol,
219+ volname,
220+ MAX_PATH,
221+ NULL,
222+ &complen,
223+ &flags,
224+ fsysname,
225+ MAX_PATH)){
226+ return 0;
227+ }
228+ return 1;
229+}
230+
231+static int
232+getfileowner(TCHAR *path, char *owner, int nowner)
233+{
234+ strncpy(owner, "Bill", nowner);
235+ return 1;
236+}
91237
92238 static Chan*
93239 fsattach(char *spec)
94240 {
95241 Chan *c;
96− struct stat stbuf;
97242 static int devno;
98243 Ufsinfo *uif;
99−
100− if(stat(base, &stbuf) < 0)
101− error(strerror(errno));
102−
103244 c = devattach('U', spec);
104−
105245 uif = mallocz(sizeof(Ufsinfo), 1);
106− uif->gid = stbuf.st_gid;
107− uif->uid = stbuf.st_uid;
108− uif->mode = stbuf.st_mode;
109−
110246 c->aux = uif;
111247 c->dev = devno++;
112248 c->qid.type = QTDIR;
113−/*print("fsattach %s\n", c2name(c));*/
114249
115250 return c;
116251 }
@@ -130,25 +265,27 @@ fsclone(Chan *c, Chan *nc) · 13 unmodified lines
130265 static int
131266 fswalk1(Chan *c, char *name)
132267 {
133− struct stat stbuf;
134− char path[MAXPATH];
135− Ufsinfo *uif;
268+ HANDLE h;
269+ WIN32_FIND_DATA wfd;
270+ TCHAR path[MAXPATH];
136271
137− fspath(c, name, path);
138−
139− /* print("** fs walk '%s' -> %s\n", path, name); */
140−
141− if(stat(path, &stbuf) < 0)
142− return 0;
272+ fspath(c, name, path, MAXPATH);
143273
144− uif = c->aux;
145−
146− uif->gid = stbuf.st_gid;
147− uif->uid = stbuf.st_uid;
148− uif->mode = stbuf.st_mode;
149−
150− c->qid = fsqid(path, &stbuf);
274+ switch(pathtype(path)){
275+ case TPATH_VOLUME:
276+ if(!checkvolume(path))
277+ return 0;
278+ case TPATH_ROOT:
279+ c->qid = wfdtoqid(path, nil);
280+ break;
151281
282+ case TPATH_FILE:
283+ if((h = FindFirstFile(path, &wfd)) == INVALID_HANDLE_VALUE)
284+ return 0;
285+ FindClose(h);
286+ c->qid = wfdtoqid(path, &wfd);
287+ break;
288+ }
152289 return 1;
153290 }
154291
@@ -190,25 +327,21 @@ static int · 35 unmodified lines
190327 fsstat(Chan *c, uchar *buf, int n)
191328 {
192329 Dir d;
193− struct stat stbuf;
194− char path[MAXPATH];
330+ TCHAR path[MAXPATH];
331+ char owner[MAXPATH];
195332
196333 if(n < BIT16SZ)
197334 error(Eshortstat);
335+ fspath(c, 0, path, MAXPATH);
336+ d.name = lastelem(c);
337+ wfdtodir(path, &d, nil);
198338
199− fspath(c, 0, path);
200− if(stat(path, &stbuf) < 0)
201− error(strerror(errno));
339+ if(getfileowner(path, owner, MAXPATH)){
340+ d.uid = owner;
341+ d.gid = owner;
342+ d.muid = owner;
343+ }
202344
203− d.name = lastelem(c);
204− d.uid = "unknown";
205− d.gid = "unknown";
206− d.muid = "unknown";
207− d.qid = c->qid;
208− d.mode = (c->qid.type<<24)|(stbuf.st_mode&0777);
209− d.atime = stbuf.st_atime;
210− d.mtime = stbuf.st_mtime;
211− d.length = stbuf.st_size;
212345 d.type = 'U';
213346 d.dev = c->dev;
214347 return convD2M(&d, buf, n);
@@ -217,11 +350,11 @@ fsstat(Chan *c, uchar *buf, int n) · 2 unmodified lines
217350 static Chan*
218351 fsopen(Chan *c, int mode)
219352 {
220− char path[MAXPATH];
353+ TCHAR path[MAXPATH];
354+ ulong t;
221355 int m, isdir;
222356 Ufsinfo *uif;
223357
224−/*print("fsopen %s\n", c2name(c));*/
225358 m = mode & (OTRUNC|3);
226359 switch(m) {
227360 case 0:
@@ -240,31 +373,55 @@ fsopen(Chan *c, int mode) · 12 unmodified lines
240373 }
241374
242375 isdir = c->qid.type & QTDIR;
243−
244376 if(isdir && mode != OREAD)
245377 error(Eperm);
246−
247378 m = fsomode(m & 3);
248379 c->mode = openmode(mode);
249−
250380 uif = c->aux;
251−
252− fspath(c, 0, path);
253− if(isdir) {
254− uif->dir = opendir(path);
255− if(uif->dir == 0)
256− error(strerror(errno));
257− }
258− else {
259− if(mode & OTRUNC)
260− m |= O_TRUNC;
261− uif->fd = open(path, m|_O_BINARY, 0666);
262−
263− if(uif->fd < 0)
264− error(strerror(errno));
265− }
266381 uif->offset = 0;
267−
382+ fspath(c, 0, path, MAXPATH);
383+ t = pathtype(path);
384+ if(isdir){
385+ DIR *d;
386+ d = malloc(sizeof(*d));
387+ switch(t){
388+ case TPATH_ROOT:
389+ d->drivebuf = malloc(sizeof(TCHAR)*MAX_PATH);
390+ if(GetLogicalDriveStrings(MAX_PATH-1, d->drivebuf) == 0){
391+ free(d->drivebuf);
392+ d->drivebuf = nil;
393+ oserror();
394+ }
395+ d->drivep = d->drivebuf;
396+ break;
397+ case TPATH_VOLUME:
398+ case TPATH_FILE:
399+#ifdef UNICODE
400+ wcsncat(path, L"\\*.*", MAXPATH);
401+#else
402+ wcsncat(path, "\\*.*", MAXPATH);
403+#endif
404+ if((d->handle = FindFirstFile(path, &d->wfd)) == INVALID_HANDLE_VALUE){
405+ free(d);
406+ oserror();
407+ }
408+ break;
409+ }
410+ d->keep = 1;
411+ uif->dir = d;
412+ } else {
413+ uif->dir = nil;
414+ if((uif->fh = CreateFile(
415+ path,
416+ fsaccess(mode),
417+ FILE_SHARE_READ | FILE_SHARE_WRITE,
418+ NULL,
419+ (mode & OTRUNC) ? TRUNCATE_EXISTING : OPEN_EXISTING,
420+ FILE_ATTRIBUTE_NORMAL,
421+ 0)) == INVALID_HANDLE_VALUE){
422+ oserror();
423+ }
424+ }
268425 c->offset = 0;
269426 c->flag |= COPEN;
270427 return c;
@@ -273,82 +430,88 @@ fsopen(Chan *c, int mode) · 2 unmodified lines
273430 static void
274431 fscreate(Chan *c, char *name, int mode, ulong perm)
275432 {
276− int fd, m;
277− char path[MAXPATH];
278− struct stat stbuf;
433+ int m;
434+ TCHAR path[MAXPATH];
279435 Ufsinfo *uif;
436+ ulong t;
280437
281438 m = fsomode(mode&3);
282439
283− fspath(c, name, path);
440+ fspath(c, name, path, MAXPATH);
441+ t = pathtype(path);
284442
285443 uif = c->aux;
286444
287445 if(perm & DMDIR) {
288− if(m)
446+ TCHAR *p;
447+ DIR *d;
448+ if(m || t!=TPATH_FILE)
289449 error(Eperm);
290−
291− if(mkdir(path) < 0)
292− error(strerror(errno));
293−
294− fd = open(path, 0);
295− if(fd >= 0) {
296− chmod(path, perm & 0777);
297− chown(path, uif->uid, uif->uid);
298− }
299− close(fd);
300−
301− uif->dir = opendir(path);
302− if(uif->dir == 0)
303− error(strerror(errno));
304− }
305− else {
306− fd = open(path, _O_WRONLY|_O_BINARY|_O_CREAT|_O_TRUNC, 0666);
307− if(fd >= 0) {
308− if(m != 1) {
309− close(fd);
310− fd = open(path, m|_O_BINARY);
311− }
312− chmod(path, perm & 0777);
313− chown(path, uif->uid, uif->gid);
450+ if(!CreateDirectory(path, NULL))
451+ oserror();
452+ d = malloc(sizeof(*d));
453+ p = &path[wcslen(path)];
454+#ifdef UNICODE
455+ wcsncat(path, L"\\*.*", MAXPATH);
456+#else
457+ wcsncat(path, "\\*.*", MAXPATH);
458+#endif
459+ if((d->handle = FindFirstFile(path, &d->wfd)) == INVALID_HANDLE_VALUE){
460+ free(d);
461+ oserror();
314462 }
315− if(fd < 0)
316− error(strerror(errno));
317− uif->fd = fd;
463+ *p = 0;
464+ d->keep = 1;
465+ uif->dir = d;
466+ } else {
467+ uif->dir = nil;
468+ if((uif->fh = CreateFile(
469+ path,
470+ fsaccess(mode),
471+ FILE_SHARE_READ | FILE_SHARE_WRITE,
472+ NULL,
473+ CREATE_NEW,
474+ FILE_ATTRIBUTE_NORMAL,
475+ 0)) == INVALID_HANDLE_VALUE){
476+ oserror();
477+ }
318478 }
319−
320− if(stat(path, &stbuf) < 0)
321− error(strerror(errno));
322− c->qid = fsqid(path, &stbuf);
479+ c->qid = wfdtoqid(path, nil);
323480 c->offset = 0;
324481 c->flag |= COPEN;
325482 c->mode = openmode(mode);
326483 }
327484
485+
328486 static void
329487 fsclose(Chan *c)
330488 {
331489 Ufsinfo *uif;
332490
333491 uif = c->aux;
334−
335492 if(c->flag & COPEN) {
336− if(c->qid.type & QTDIR)
337− closedir(uif->dir);
338− else
339− close(uif->fd);
493+ if(uif->dir){
494+ if(uif->dir->drivebuf){
495+ free(uif->dir->drivebuf);
496+ uif->dir->drivebuf = nil;
497+ } else {
498+ FindClose(uif->dir->handle);
499+ free(uif->dir);
500+ }
501+ } else {
502+ CloseHandle(uif->fh);
503+ }
340504 }
341−
342505 free(uif);
343506 }
344507
345508 static long
346509 fsread(Chan *c, void *va, long n, vlong offset)
347510 {
348− int fd, r;
511+ HANDLE fh;
512+ DWORD r;
349513 Ufsinfo *uif;
350514
351−/*print("fsread %s\n", c2name(c));*/
352515 if(c->qid.type & QTDIR)
353516 return fsdirread(c, va, n, offset);
354517
@@ -358,166 +521,158 @@ fsread(Chan *c, void *va, long n, vlong offset) · 3 unmodified lines
358521 qunlock(&uif->oq);
359522 nexterror();
360523 }
361− fd = uif->fd;
524+ fh = uif->fh;
362525 if(uif->offset != offset) {
363− r = lseek(fd, offset, 0);
364− if(r < 0)
365− error(strerror(errno));
526+ LONG high;
527+ high = offset>>32;
528+ offset = SetFilePointer(fh, (LONG)(offset & 0xFFFFFFFF), &high, FILE_BEGIN);
529+ offset |= (vlong)high<<32;
366530 uif->offset = offset;
367531 }
368−
369− n = read(fd, va, n);
370− if(n < 0)
371− error(strerror(errno));
372−
532+ r = 0;
533+ if(!ReadFile(fh, va, (DWORD)n, &r, NULL)){
534+ oserror();
535+ }
536+ n = r;
373537 uif->offset += n;
374538 qunlock(&uif->oq);
375539 poperror();
376−
377540 return n;
378541 }
379542
380543 static long
381544 fswrite(Chan *c, void *va, long n, vlong offset)
382545 {
383− int fd, r;
546+ HANDLE fh;
547+ DWORD w;
384548 Ufsinfo *uif;
385549
386− uif = c->aux;
550+ if(c->qid.type & QTDIR)
551+ return fsdirread(c, va, n, offset);
387552
553+ uif = c->aux;
388554 qlock(&uif->oq);
389555 if(waserror()) {
390556 qunlock(&uif->oq);
391557 nexterror();
392558 }
393− fd = uif->fd;
559+ fh = uif->fh;
394560 if(uif->offset != offset) {
395− r = lseek(fd, offset, 0);
396− if(r < 0)
397− error(strerror(errno));
561+ LONG high;
562+ high = offset>>32;
563+ offset = SetFilePointer(fh, (LONG)(offset & 0xFFFFFFFF), &high, FILE_BEGIN);
564+ offset |= (vlong)high<<32;
398565 uif->offset = offset;
399566 }
400−
401− n = write(fd, va, n);
402− if(n < 0)
403− error(strerror(errno));
404−
567+ w = 0;
568+ if(!WriteFile(fh, va, (DWORD)n, &w, NULL)){
569+ oserror();
570+ }
571+ n = w;
405572 uif->offset += n;
406573 qunlock(&uif->oq);
407574 poperror();
408−
409575 return n;
410576 }
411577
412578 static void
413579 fsremove(Chan *c)
414580 {
415− int n;
416− char path[MAXPATH];
417−
418− fspath(c, 0, path);
419− if(c->qid.type & QTDIR)
420− n = rmdir(path);
421− else
422− n = remove(path);
423− if(n < 0)
424− error(strerror(errno));
581+ TCHAR path[MAXPATH];
582+
583+ fspath(c, 0, path, MAXPATH);
584+ if(c->qid.type & QTDIR){
585+ if(!RemoveDirectory(path))
586+ error("RemoveDirectory...");
587+ } else {
588+ if(!DeleteFile(path))
589+ error("DeleteFile...");
590+ }
425591 }
426592
427593 static int
428594 fswstat(Chan *c, uchar *buf, int n)
429595 {
596+ TCHAR path[MAXPATH];
597+ char strs[MAXPATH*3];
430598 Dir d;
431− struct stat stbuf;
432− char old[MAXPATH], new[MAXPATH];
433− char strs[MAXPATH*3], *p;
434− Ufsinfo *uif;
599+ ulong t;
435600
436601 if (convM2D(buf, n, &d, strs) != n)
437602 error(Ebadstat);
438−
439− fspath(c, 0, old);
440− if(stat(old, &stbuf) < 0)
441− error(strerror(errno));
442−
443− uif = c->aux;
444−
445−// if(uif->uid != stbuf.st_uid)
446−// error(Eowner);
447−
448− if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) {
449− fspath(c, 0, old);
450− strcpy(new, old);
451− p = strrchr(new, '/');
452− strcpy(p+1, d.name);
453− if(rename(old, new) < 0)
454− error(strerror(errno));
455− }
456−
457− fspath(c, 0, old);
458− if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) {
459− if(chmod(old, d.mode&0777) < 0)
460− error(strerror(errno));
461− uif->mode &= ~0777;
462− uif->mode |= d.mode&0777;
603+ fspath(c, 0, path, MAXPATH);
604+ t = pathtype(path);
605+ if(t != TPATH_FILE)
606+ error(Ebadstat);
607+ /* change name */
608+ if(d.name[0]){
609+ int l;
610+ TCHAR newpath[MAXPATH];
611+ wcsncpy(newpath, path, MAXPATH);
612+
613+ /* replace last path-element with d.name */
614+ l = wcslen(newpath)-1;
615+ if(l <= 0)
616+ error(Ebadstat);
617+ for(;l>0; l--){
618+ if(newpath[l-1]=='\\')
619+ break;
620+ }
621+ if(l <= 0)
622+ error(Ebadstat);
623+ newpath[l] = 0;
624+#ifdef UNICODE
625+ if(!MultiByteToWideChar(CP_UTF8,0,d.name,-1,&newpath[l],MAXPATH-l-1))
626+ oserror();
627+#else
628+ wcsncpy(&newpath[l], d.name, MAXPATH-l-1);
629+#endif
630+ if(wcscmp(path, newpath)!=0){
631+ if(!MoveFile(path, newpath))
632+ oserror();
633+ wcsncpy(path, newpath, MAXPATH);
634+ }
463635 }
464−/*
465− p = name2pass(gid, d.gid);
466− if(p == 0)
467− error(Eunknown);
468−
469− if(p->id != stbuf.st_gid) {
470− if(chown(old, stbuf.st_uid, p->id) < 0)
471− error(sys_errlist[errno]);
472636
473− uif->gid = p->id;
474− }
475−*/
476− return n;
637+ /* fixme: change attributes */
638+ c->qid = wfdtoqid(path, nil);
639+ return n;
477640 }
478641
479−static Qid
480−fsqid(char *p, struct stat *st)
481−{
482− Qid q;
483− int dev;
484− ulong h;
485− static int nqdev;
486− static uchar *qdev;
487−
488− if(qdev == 0)
489− qdev = mallocz(65536U, 1);
490−
491− q.type = 0;
492− if((st->st_mode&S_IFMT) == S_IFDIR)
493− q.type = QTDIR;
494−
495− dev = st->st_dev & 0xFFFFUL;
496− if(qdev[dev] == 0)
497− qdev[dev] = ++nqdev;
498−
499− h = 0;
500− while(*p != '\0')
501− h += *p++ * 13;
502−
503− q.path = (vlong)qdev[dev]<<32;
504− q.path |= h;
505− q.vers = st->st_mtime;
506−
507− return q;
508−}
509642
510643 static void
511−fspath(Chan *c, char *ext, char *path)
644+_fspath(Chan *c, char *ext, char *path, int npath)
512645 {
513− strcpy(path, base);
514− strcat(path, "/");
515− strcat(path, uc2name(c));
646+ *path = 0;
647+ strncat(path, uc2name(c), npath);
516648 if(ext) {
517− strcat(path, "/");
518− strcat(path, ext);
649+ if(*path)
650+ strncat(path, "/", npath);
651+ strncat(path, ext, npath);
519652 }
520653 cleanname(path);
654+ if(*path == '.')
655+ *path = 0;
656+}
657+
658+static void
659+fspath(Chan *c, char *ext, TCHAR *path, int npath)
660+{
661+ TCHAR *p;
662+#ifdef UNICODE
663+ char buf[MAXPATH];
664+ _fspath(c, ext, buf, sizeof(buf));
665+ if(!MultiByteToWideChar(CP_UTF8,0,buf,-1,path,npath)){
666+ oserror();
667+ }
668+#else
669+ _fspath(c, ext, path, npath);
670+#endif
671+ /* make a DOS path */
672+ for(p=path; *p; p++){
673+ if(*p == '/')
674+ *p = '\\';
675+ }
521676 }
522677
523678 static int
@@ -534,78 +689,116 @@ isdots(char *name) · 10 unmodified lines
534689 return 0;
535690 }
536691
537−static int
538−p9readdir(char *name, Ufsinfo *uif)
539−{
540− if(uif->nextname[0]){
541− strcpy(name, uif->nextname);
542− uif->nextname[0] = 0;
543− return 1;
544− }
545−
546− return readdir(name, uif->dir);
547−}
548−
549692 static ulong
550−fsdirread(Chan *c, uchar *va, int count, ulong offset)
693+fsdirread(Chan *c, uchar *va, int count, vlong offset)
551694 {
552695 int i;
696+ ulong t;
553697 Dir d;
554698 long n;
555− char de[NAME_MAX];
556− struct stat stbuf;
557− char path[MAXPATH], dirpath[MAXPATH];
558699 Ufsinfo *uif;
700+ char de[MAX_PATH*3];
701+ int ndirpath;
702+ TCHAR dirpath[MAXPATH];
559703
560−/*print("fsdirread %s\n", c2name(c));*/
561704 i = 0;
562705 uif = c->aux;
563−
564706 errno = 0;
707+
708+ fspath(c, 0, dirpath, MAXPATH);
709+ ndirpath = wcslen(dirpath);
710+ t = pathtype(dirpath);
711+
565712 if(uif->offset != offset) {
566713 if(offset != 0)
567714 error("bad offset in fsdirread");
568715 uif->offset = offset; /* sync offset */
569− uif->nextname[0] = 0;
570− rewinddir(uif->dir);
716+ switch(t){
717+ case TPATH_ROOT:
718+ uif->dir->drivep = uif->dir->drivebuf;
719+ break;
720+ case TPATH_VOLUME:
721+ case TPATH_FILE:
722+ FindClose(uif->dir->handle);
723+#ifdef UNICODE
724+ wcsncat(dirpath, L"\\*.*", MAXPATH);
725+#else
726+ wcsncat(dirpath, "\\*.*", MAXPATH);
727+#endif
728+ if((uif->dir->handle = FindFirstFile(dirpath, &uif->dir->wfd))==INVALID_HANDLE_VALUE){
729+ oserror();
730+ }
731+ break;
732+ }
733+ uif->dir->keep = 1;
571734 }
572735
573− fspath(c, 0, dirpath);
574−
575736 while(i+BIT16SZ < count) {
576− if(!p9readdir(de, uif))
577− break;
578−
737+ char owner[MAXPATH];
738+
739+ if(!uif->dir->keep) {
740+ switch(t){
741+ case TPATH_ROOT:
742+ uif->dir->drivep += 4;
743+ if(*uif->dir->drivep == 0)
744+ goto out;
745+ break;
746+ case TPATH_VOLUME:
747+ case TPATH_FILE:
748+ if(!FindNextFile(uif->dir->handle, &uif->dir->wfd))
749+ goto out;
750+ break;
751+ }
752+ } else {
753+ uif->dir->keep = 0;
754+ }
755+ if(t == TPATH_ROOT){
756+ uif->dir->drivep[2] = 0;
757+#ifdef UNICODE
758+ WideCharToMultiByte(CP_UTF8,0,uif->dir->drivep,-1,de,sizeof(de),0,0);
759+#else
760+ strncpy(de, uif->dir->drivep, sizeof(de));
761+#endif
762+ } else {
763+#ifdef UNICODE
764+ WideCharToMultiByte(CP_UTF8,0,uif->dir->wfd.cFileName,-1,de,sizeof(de),0,0);
765+#else
766+ strncpy(de, uif->dir->wfd.cFileName, sizeof(de));
767+#endif
768+ }
579769 if(de[0]==0 || isdots(de))
580770 continue;
581−
582771 d.name = de;
583− sprint(path, "%s/%s", dirpath, de);
584− memset(&stbuf, 0, sizeof stbuf);
772+ dirpath[ndirpath] = 0;
773+ if(t == TPATH_ROOT){
774+ wcsncat(dirpath, uif->dir->drivep, MAXPATH);
775+ wfdtodir(dirpath, &d, nil);
776+ } else {
777+#ifdef UNICODE
778+ wcsncat(dirpath, L"\\", MAXPATH);
779+#else
780+ wcsncat(dirpath, "\\", MAXPATH);
781+#endif
782+ wcsncat(dirpath, uif->dir->wfd.cFileName, MAXPATH);
783+ wfdtodir(dirpath, &d, &uif->dir->wfd);
784+ }
585785
586− if(stat(path, &stbuf) < 0) {
587− print("dir: bad path %s\n", path);
588− /* but continue... probably a bad symlink */
786+ if(getfileowner(dirpath, owner, MAXPATH)){
787+ d.uid = owner;
788+ d.gid = owner;
789+ d.muid = owner;
589790 }
590791
591− d.uid = "unknown";
592− d.gid = "unknown";
593− d.muid = "unknown";
594− d.qid = fsqid(path, &stbuf);
595− d.mode = (d.qid.type<<24)|(stbuf.st_mode&0777);
596− d.atime = stbuf.st_atime;
597− d.mtime = stbuf.st_mtime;
598− d.length = stbuf.st_size;
599792 d.type = 'U';
600793 d.dev = c->dev;
601794 n = convD2M(&d, (uchar*)va+i, count-i);
602795 if(n == BIT16SZ){
603− strcpy(uif->nextname, de);
796+ uif->dir->keep = 1;
604797 break;
605798 }
606799 i += n;
607800 }
608−/*print("got %d\n", i);*/
801+out:
609802 uif->offset += i;
610803 return i;
611804 }
@@ -625,65 +818,29 @@ fsomode(int m) · 13 unmodified lines
625818 error(Ebadarg);
626819 return 0;
627820 }
628−void
629−closedir(DIR *d)
630−{
631− FindClose(d->handle);
632− free(d->path);
633−}
634821
635−int
636−readdir(char *name, DIR *d)
822+static ulong
823+fsaccess(int m)
637824 {
638− if(d->index != 0) {
639− if(FindNextFile(d->handle, &d->wfd) == FALSE)
640− return 0;
825+ ulong a;
826+ a = 0;
827+ switch(m & 3){
828+ default:
829+ error(Eperm);
830+ break;
831+ case OREAD:
832+ a = GENERIC_READ;
833+ break;
834+ case OWRITE:
835+ a = GENERIC_WRITE;
836+ break;
837+ case ORDWR:
838+ a = GENERIC_READ | GENERIC_WRITE;
839+ break;
641840 }
642− strcpy(name, (char*)d->wfd.cFileName);
643− d->index++;
644−
645− return 1;
646−}
647−
648−void
649−rewinddir(DIR *d)
650−{
651− FindClose(d->handle);
652− d->handle = FindFirstFile(d->path, &d->wfd);
653− d->index = 0;
654−}
655−
656−static int
657−chown(char *path, int uid, int perm)
658−{
659−/* panic("chown"); */
660− return 0;
841+ return a;
661842 }
662843
663−DIR*
664−opendir(char *p)
665−{
666− DIR *d;
667− char path[MAX_PATH];
668−
669−
670− snprint(path, sizeof(path), "%s/*.*", p);
671−
672− d = mallocz(sizeof(DIR), 1);
673− if(d == 0)
674− return 0;
675−
676− d->index = 0;
677−
678− d->handle = FindFirstFile(path, &d->wfd);
679− if(d->handle == INVALID_HANDLE_VALUE) {
680− free(d);
681− return 0;
682− }
683−
684− d->path = strdup(path);
685− return d;
686−}
687844
688845 Dev fsdevtab = {
689846 'U',

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