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
6#include <windows.h>1#include <windows.h>
7#include <sys/types.h>2#include <sys/types.h>
8#include <sys/stat.h>3#include <sys/stat.h>
9#include <fcntl.h>4#include <fcntl.h>
10 5
11#ifndef NAME_MAX
12# define NAME_MAX 256
13#endif
14#include "u.h"6#include "u.h"
15#include "lib.h"7#include "lib.h"
16#include "dat.h"8#include "dat.h"
@@ -20,47 +12,148 @@ · 3 unmodified lines
20typedef struct DIR DIR;12typedef struct DIR DIR;
21typedef struct Ufsinfo Ufsinfo;13typedef struct Ufsinfo Ufsinfo;
22 14
15
23enum16enum
24{17{
25 NUID = 256,
26 NGID = 256,
27 MAXPATH = 1024,18 MAXPATH = 1024,
28 MAXCOMP = 12819 TPATH_ROOT = 0, // ""
20 TPATH_VOLUME = 1, // "C:"
21 TPATH_FILE = 2, // "C:\bla"
29};22};
30 23
31struct DIR24struct DIR
32{25{
33 HANDLE handle;26 // for FindFileFirst()
34 char* path;27 HANDLE handle;
35 int index;
36 WIN32_FIND_DATA wfd;28 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;
37};36};
38 37
39struct Ufsinfo38struct Ufsinfo
40{39{
41 int mode;40 int mode;
42 int fd;41 HANDLE fh;
43 int uid;
44 int gid;
45 DIR* dir;42 DIR* dir;
46 ulong offset;43 vlong offset;
47 QLock oq;44 QLock oq;
48 char nextname[NAME_MAX];
49};45};
50 46
51DIR* opendir(char*);47static void fspath(Chan *, char *, TCHAR *, int);
52int readdir(char*, DIR*);48static ulong fsdirread(Chan*, uchar*, int, vlong);
53void closedir(DIR*);49static int fsomode(int);
54void rewinddir(DIR*);50static ulong fsaccess(int);
51static ulong pathtype(TCHAR *);
52static int checkvolume(TCHAR *);
55 53
56char *base = "c:/.";54char *base = "";
57 55
58static Qid fsqid(char*, struct stat *);56static ulong
59static void fspath(Chan*, char*, char*);57unixtime(FILETIME *ft)
60// static void fsperm(Chan*, int);58{
61static ulong fsdirread(Chan*, uchar*, int, ulong);59 vlong t;
62static int fsomode(int);60 t = ((vlong)ft->dwHighDateTime << 32)|((vlong)ft->dwLowDateTime);
63static int chown(char *path, int uid, int);61 t -= 116444736000000000LL;
62 return ((t<0)?(-1 - (-t - 1)) : t)/10000000;
63}
64
65static uvlong
66pathhash(TCHAR *p)
67{
68 uvlong h;
69 h = 0LL;
70 for(; *p; p++)
71 h += *p * 13;
72 return h;
73}
74
75static ulong
76wfdtodmode(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
89static Qid
90wfdtoqid(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
122static void
123wfdtodir(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}
64 157
65/* clumsy hack, but not worse than the Path stuff in the last one */158/* clumsy hack, but not worse than the Path stuff in the last one */
66static char*159static char*
@@ -69,10 +162,12 @@ uc2name(Chan *c) · 2 unmodified lines
69 char *s;162 char *s;
70 163
71 if(c->name == nil)164 if(c->name == nil)
72 return "/";165 return "";
73 s = c2name(c);166 s = c2name(c);
74 if(s[0]=='#' && s[1]=='U')167 if(s[0]=='#' && s[1]=='U')
75 return s+2;168 s += 2;
169 if(*s=='/')
170 s++;
76 return s;171 return s;
77}172}
78 173
@@ -88,29 +183,69 @@ lastelem(Chan *c) · 9 unmodified lines
88 return t;183 return t;
89 return t+1;184 return t+1;
90}185}
186
187static ulong
188pathtype(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
201static int
202checkvolume(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
231static int
232getfileowner(TCHAR *path, char *owner, int nowner)
233{
234 strncpy(owner, "Bill", nowner);
235 return 1;
236}
91 237
92static Chan*238static Chan*
93fsattach(char *spec)239fsattach(char *spec)
94{240{
95 Chan *c;241 Chan *c;
96 struct stat stbuf;
97 static int devno;242 static int devno;
98 Ufsinfo *uif;243 Ufsinfo *uif;
99
100 if(stat(base, &stbuf) < 0)
101 error(strerror(errno));
102
103 c = devattach('U', spec);244 c = devattach('U', spec);
104
105 uif = mallocz(sizeof(Ufsinfo), 1);245 uif = mallocz(sizeof(Ufsinfo), 1);
106 uif->gid = stbuf.st_gid;
107 uif->uid = stbuf.st_uid;
108 uif->mode = stbuf.st_mode;
109
110 c->aux = uif;246 c->aux = uif;
111 c->dev = devno++;247 c->dev = devno++;
112 c->qid.type = QTDIR;248 c->qid.type = QTDIR;
113/*print("fsattach %s\n", c2name(c));*/
114 249
115 return c;250 return c;
116}251}
@@ -130,25 +265,27 @@ fsclone(Chan *c, Chan *nc) · 13 unmodified lines
130static int265static int
131fswalk1(Chan *c, char *name)266fswalk1(Chan *c, char *name)
132{267{
133 struct stat stbuf;268 HANDLE h;
134 char path[MAXPATH];269 WIN32_FIND_DATA wfd;
135 Ufsinfo *uif;270 TCHAR path[MAXPATH];
136 271
137 fspath(c, name, path);272 fspath(c, name, path, MAXPATH);
138
139 /* print("** fs walk '%s' -> %s\n", path, name); */
140
141 if(stat(path, &stbuf) < 0)
142 return 0;
143 273
144 uif = c->aux;274 switch(pathtype(path)){
145 275 case TPATH_VOLUME:
146 uif->gid = stbuf.st_gid;276 if(!checkvolume(path))
147 uif->uid = stbuf.st_uid;277 return 0;
148 uif->mode = stbuf.st_mode;278 case TPATH_ROOT:
149 279 c->qid = wfdtoqid(path, nil);
150 c->qid = fsqid(path, &stbuf);280 break;
151 281
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 }
152 return 1;289 return 1;
153}290}
154 291
@@ -190,25 +327,21 @@ static int · 35 unmodified lines
190fsstat(Chan *c, uchar *buf, int n)327fsstat(Chan *c, uchar *buf, int n)
191{328{
192 Dir d;329 Dir d;
193 struct stat stbuf;330 TCHAR path[MAXPATH];
194 char path[MAXPATH];331 char owner[MAXPATH];
195 332
196 if(n < BIT16SZ)333 if(n < BIT16SZ)
197 error(Eshortstat);334 error(Eshortstat);
335 fspath(c, 0, path, MAXPATH);
336 d.name = lastelem(c);
337 wfdtodir(path, &d, nil);
198 338
199 fspath(c, 0, path);339 if(getfileowner(path, owner, MAXPATH)){
200 if(stat(path, &stbuf) < 0)340 d.uid = owner;
201 error(strerror(errno));341 d.gid = owner;
342 d.muid = owner;
343 }
202 344
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;
212 d.type = 'U';345 d.type = 'U';
213 d.dev = c->dev;346 d.dev = c->dev;
214 return convD2M(&d, buf, n);347 return convD2M(&d, buf, n);
@@ -217,11 +350,11 @@ fsstat(Chan *c, uchar *buf, int n) · 2 unmodified lines
217static Chan*350static Chan*
218fsopen(Chan *c, int mode)351fsopen(Chan *c, int mode)
219{352{
220 char path[MAXPATH];353 TCHAR path[MAXPATH];
354 ulong t;
221 int m, isdir;355 int m, isdir;
222 Ufsinfo *uif;356 Ufsinfo *uif;
223 357
224/*print("fsopen %s\n", c2name(c));*/
225 m = mode & (OTRUNC|3);358 m = mode & (OTRUNC|3);
226 switch(m) {359 switch(m) {
227 case 0:360 case 0:
@@ -240,31 +373,55 @@ fsopen(Chan *c, int mode) · 12 unmodified lines
240 }373 }
241 374
242 isdir = c->qid.type & QTDIR;375 isdir = c->qid.type & QTDIR;
243
244 if(isdir && mode != OREAD)376 if(isdir && mode != OREAD)
245 error(Eperm);377 error(Eperm);
246
247 m = fsomode(m & 3);378 m = fsomode(m & 3);
248 c->mode = openmode(mode);379 c->mode = openmode(mode);
249
250 uif = c->aux;380 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 }
266 uif->offset = 0;381 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 }
268 c->offset = 0;425 c->offset = 0;
269 c->flag |= COPEN;426 c->flag |= COPEN;
270 return c;427 return c;
@@ -273,82 +430,88 @@ fsopen(Chan *c, int mode) · 2 unmodified lines
273static void430static void
274fscreate(Chan *c, char *name, int mode, ulong perm)431fscreate(Chan *c, char *name, int mode, ulong perm)
275{432{
276 int fd, m;433 int m;
277 char path[MAXPATH];434 TCHAR path[MAXPATH];
278 struct stat stbuf;
279 Ufsinfo *uif;435 Ufsinfo *uif;
436 ulong t;
280 437
281 m = fsomode(mode&3);438 m = fsomode(mode&3);
282 439
283 fspath(c, name, path);440 fspath(c, name, path, MAXPATH);
441 t = pathtype(path);
284 442
285 uif = c->aux;443 uif = c->aux;
286 444
287 if(perm & DMDIR) {445 if(perm & DMDIR) {
288 if(m)446 TCHAR *p;
447 DIR *d;
448 if(m || t!=TPATH_FILE)
289 error(Eperm);449 error(Eperm);
290 450 if(!CreateDirectory(path, NULL))
291 if(mkdir(path) < 0)451 oserror();
292 error(strerror(errno));452 d = malloc(sizeof(*d));
293 453 p = &path[wcslen(path)];
294 fd = open(path, 0);454#ifdef UNICODE
295 if(fd >= 0) {455 wcsncat(path, L"\\*.*", MAXPATH);
296 chmod(path, perm & 0777);456#else
297 chown(path, uif->uid, uif->uid);457 wcsncat(path, "\\*.*", MAXPATH);
298 }458#endif
299 close(fd);459 if((d->handle = FindFirstFile(path, &d->wfd)) == INVALID_HANDLE_VALUE){
300 460 free(d);
301 uif->dir = opendir(path);461 oserror();
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);
314 }462 }
315 if(fd < 0)463 *p = 0;
316 error(strerror(errno));464 d->keep = 1;
317 uif->fd = fd;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 }
318 }478 }
319 479 c->qid = wfdtoqid(path, nil);
320 if(stat(path, &stbuf) < 0)
321 error(strerror(errno));
322 c->qid = fsqid(path, &stbuf);
323 c->offset = 0;480 c->offset = 0;
324 c->flag |= COPEN;481 c->flag |= COPEN;
325 c->mode = openmode(mode);482 c->mode = openmode(mode);
326}483}
327 484
485
328static void486static void
329fsclose(Chan *c)487fsclose(Chan *c)
330{488{
331 Ufsinfo *uif;489 Ufsinfo *uif;
332 490
333 uif = c->aux;491 uif = c->aux;
334
335 if(c->flag & COPEN) {492 if(c->flag & COPEN) {
336 if(c->qid.type & QTDIR)493 if(uif->dir){
337 closedir(uif->dir);494 if(uif->dir->drivebuf){
338 else495 free(uif->dir->drivebuf);
339 close(uif->fd);496 uif->dir->drivebuf = nil;
497 } else {
498 FindClose(uif->dir->handle);
499 free(uif->dir);
500 }
501 } else {
502 CloseHandle(uif->fh);
503 }
340 }504 }
341
342 free(uif);505 free(uif);
343}506}
344 507
345static long508static long
346fsread(Chan *c, void *va, long n, vlong offset)509fsread(Chan *c, void *va, long n, vlong offset)
347{510{
348 int fd, r;511 HANDLE fh;
512 DWORD r;
349 Ufsinfo *uif;513 Ufsinfo *uif;
350 514
351/*print("fsread %s\n", c2name(c));*/
352 if(c->qid.type & QTDIR)515 if(c->qid.type & QTDIR)
353 return fsdirread(c, va, n, offset);516 return fsdirread(c, va, n, offset);
354 517
@@ -358,166 +521,158 @@ fsread(Chan *c, void *va, long n, vlong offset) · 3 unmodified lines
358 qunlock(&uif->oq);521 qunlock(&uif->oq);
359 nexterror();522 nexterror();
360 }523 }
361 fd = uif->fd;524 fh = uif->fh;
362 if(uif->offset != offset) {525 if(uif->offset != offset) {
363 r = lseek(fd, offset, 0);526 LONG high;
364 if(r < 0)527 high = offset>>32;
365 error(strerror(errno));528 offset = SetFilePointer(fh, (LONG)(offset & 0xFFFFFFFF), &high, FILE_BEGIN);
529 offset |= (vlong)high<<32;
366 uif->offset = offset;530 uif->offset = offset;
367 }531 }
368 532 r = 0;
369 n = read(fd, va, n);533 if(!ReadFile(fh, va, (DWORD)n, &r, NULL)){
370 if(n < 0)534 oserror();
371 error(strerror(errno));535 }
372 536 n = r;
373 uif->offset += n;537 uif->offset += n;
374 qunlock(&uif->oq);538 qunlock(&uif->oq);
375 poperror();539 poperror();
376
377 return n;540 return n;
378}541}
379 542
380static long543static long
381fswrite(Chan *c, void *va, long n, vlong offset)544fswrite(Chan *c, void *va, long n, vlong offset)
382{545{
383 int fd, r;546 HANDLE fh;
547 DWORD w;
384 Ufsinfo *uif;548 Ufsinfo *uif;
385 549
386 uif = c->aux;550 if(c->qid.type & QTDIR)
551 return fsdirread(c, va, n, offset);
387 552
553 uif = c->aux;
388 qlock(&uif->oq);554 qlock(&uif->oq);
389 if(waserror()) {555 if(waserror()) {
390 qunlock(&uif->oq);556 qunlock(&uif->oq);
391 nexterror();557 nexterror();
392 }558 }
393 fd = uif->fd;559 fh = uif->fh;
394 if(uif->offset != offset) {560 if(uif->offset != offset) {
395 r = lseek(fd, offset, 0);561 LONG high;
396 if(r < 0)562 high = offset>>32;
397 error(strerror(errno));563 offset = SetFilePointer(fh, (LONG)(offset & 0xFFFFFFFF), &high, FILE_BEGIN);
564 offset |= (vlong)high<<32;
398 uif->offset = offset;565 uif->offset = offset;
399 }566 }
400 567 w = 0;
401 n = write(fd, va, n);568 if(!WriteFile(fh, va, (DWORD)n, &w, NULL)){
402 if(n < 0)569 oserror();
403 error(strerror(errno));570 }
404 571 n = w;
405 uif->offset += n;572 uif->offset += n;
406 qunlock(&uif->oq);573 qunlock(&uif->oq);
407 poperror();574 poperror();
408
409 return n;575 return n;
410}576}
411 577
412static void578static void
413fsremove(Chan *c)579fsremove(Chan *c)
414{580{
415 int n;581 TCHAR path[MAXPATH];
416 char path[MAXPATH];582
417 583 fspath(c, 0, path, MAXPATH);
418 fspath(c, 0, path);584 if(c->qid.type & QTDIR){
419 if(c->qid.type & QTDIR)585 if(!RemoveDirectory(path))
420 n = rmdir(path);586 error("RemoveDirectory...");
421 else587 } else {
422 n = remove(path);588 if(!DeleteFile(path))
423 if(n < 0)589 error("DeleteFile...");
424 error(strerror(errno));590 }
425}591}
426 592
427static int593static int
428fswstat(Chan *c, uchar *buf, int n)594fswstat(Chan *c, uchar *buf, int n)
429{595{
596 TCHAR path[MAXPATH];
597 char strs[MAXPATH*3];
430 Dir d;598 Dir d;
431 struct stat stbuf;599 ulong t;
432 char old[MAXPATH], new[MAXPATH];
433 char strs[MAXPATH*3], *p;
434 Ufsinfo *uif;
435 600
436 if (convM2D(buf, n, &d, strs) != n)601 if (convM2D(buf, n, &d, strs) != n)
437 error(Ebadstat);602 error(Ebadstat);
438 603 fspath(c, 0, path, MAXPATH);
439 fspath(c, 0, old);604 t = pathtype(path);
440 if(stat(old, &stbuf) < 0)605 if(t != TPATH_FILE)
441 error(strerror(errno));606 error(Ebadstat);
442 607 /* change name */
443 uif = c->aux;608 if(d.name[0]){
444 609 int l;
445// if(uif->uid != stbuf.st_uid)610 TCHAR newpath[MAXPATH];
446// error(Eowner);611 wcsncpy(newpath, path, MAXPATH);
447 612
448 if(d.name[0] && strcmp(d.name, lastelem(c)) != 0) {613 /* replace last path-element with d.name */
449 fspath(c, 0, old);614 l = wcslen(newpath)-1;
450 strcpy(new, old);615 if(l <= 0)
451 p = strrchr(new, '/');616 error(Ebadstat);
452 strcpy(p+1, d.name);617 for(;l>0; l--){
453 if(rename(old, new) < 0)618 if(newpath[l-1]=='\\')
454 error(strerror(errno));619 break;
455 }620 }
456 621 if(l <= 0)
457 fspath(c, 0, old);622 error(Ebadstat);
458 if(~d.mode != 0 && (int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) {623 newpath[l] = 0;
459 if(chmod(old, d.mode&0777) < 0)624#ifdef UNICODE
460 error(strerror(errno));625 if(!MultiByteToWideChar(CP_UTF8,0,d.name,-1,&newpath[l],MAXPATH-l-1))
461 uif->mode &= ~0777;626 oserror();
462 uif->mode |= d.mode&0777;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 }
463 }635 }
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]);
472 636
473 uif->gid = p->id;637 /* fixme: change attributes */
474 }638 c->qid = wfdtoqid(path, nil);
475*/639 return n;
476 return n;
477}640}
478 641
479static Qid
480fsqid(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}
509 642
510static void643static void
511fspath(Chan *c, char *ext, char *path)644_fspath(Chan *c, char *ext, char *path, int npath)
512{645{
513 strcpy(path, base);646 *path = 0;
514 strcat(path, "/");647 strncat(path, uc2name(c), npath);
515 strcat(path, uc2name(c));
516 if(ext) {648 if(ext) {
517 strcat(path, "/");649 if(*path)
518 strcat(path, ext);650 strncat(path, "/", npath);
651 strncat(path, ext, npath);
519 }652 }
520 cleanname(path);653 cleanname(path);
654 if(*path == '.')
655 *path = 0;
656}
657
658static void
659fspath(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 }
521}676}
522 677
523static int678static int
@@ -534,78 +689,116 @@ isdots(char *name) · 10 unmodified lines
534 return 0;689 return 0;
535}690}
536 691
537static int
538p9readdir(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
549static ulong692static ulong
550fsdirread(Chan *c, uchar *va, int count, ulong offset)693fsdirread(Chan *c, uchar *va, int count, vlong offset)
551{694{
552 int i;695 int i;
696 ulong t;
553 Dir d;697 Dir d;
554 long n;698 long n;
555 char de[NAME_MAX];
556 struct stat stbuf;
557 char path[MAXPATH], dirpath[MAXPATH];
558 Ufsinfo *uif;699 Ufsinfo *uif;
700 char de[MAX_PATH*3];
701 int ndirpath;
702 TCHAR dirpath[MAXPATH];
559 703
560/*print("fsdirread %s\n", c2name(c));*/
561 i = 0;704 i = 0;
562 uif = c->aux;705 uif = c->aux;
563
564 errno = 0;706 errno = 0;
707
708 fspath(c, 0, dirpath, MAXPATH);
709 ndirpath = wcslen(dirpath);
710 t = pathtype(dirpath);
711
565 if(uif->offset != offset) {712 if(uif->offset != offset) {
566 if(offset != 0)713 if(offset != 0)
567 error("bad offset in fsdirread");714 error("bad offset in fsdirread");
568 uif->offset = offset; /* sync offset */715 uif->offset = offset; /* sync offset */
569 uif->nextname[0] = 0;716 switch(t){
570 rewinddir(uif->dir);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;
571 }734 }
572 735
573 fspath(c, 0, dirpath);
574
575 while(i+BIT16SZ < count) {736 while(i+BIT16SZ < count) {
576 if(!p9readdir(de, uif))737 char owner[MAXPATH];
577 break;738
578 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 }
579 if(de[0]==0 || isdots(de))769 if(de[0]==0 || isdots(de))
580 continue;770 continue;
581
582 d.name = de;771 d.name = de;
583 sprint(path, "%s/%s", dirpath, de);772 dirpath[ndirpath] = 0;
584 memset(&stbuf, 0, sizeof stbuf);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 }
585 785
586 if(stat(path, &stbuf) < 0) {786 if(getfileowner(dirpath, owner, MAXPATH)){
587 print("dir: bad path %s\n", path);787 d.uid = owner;
588 /* but continue... probably a bad symlink */788 d.gid = owner;
789 d.muid = owner;
589 }790 }
590 791
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;
599 d.type = 'U';792 d.type = 'U';
600 d.dev = c->dev;793 d.dev = c->dev;
601 n = convD2M(&d, (uchar*)va+i, count-i);794 n = convD2M(&d, (uchar*)va+i, count-i);
602 if(n == BIT16SZ){795 if(n == BIT16SZ){
603 strcpy(uif->nextname, de);796 uif->dir->keep = 1;
604 break;797 break;
605 }798 }
606 i += n;799 i += n;
607 }800 }
608/*print("got %d\n", i);*/801out:
609 uif->offset += i;802 uif->offset += i;
610 return i;803 return i;
611}804}
@@ -625,65 +818,29 @@ fsomode(int m) · 13 unmodified lines
625 error(Ebadarg);818 error(Ebadarg);
626 return 0;819 return 0;
627}820}
628void
629closedir(DIR *d)
630{
631 FindClose(d->handle);
632 free(d->path);
633}
634 821
635int822static ulong
636readdir(char *name, DIR *d)823fsaccess(int m)
637{824{
638 if(d->index != 0) {825 ulong a;
639 if(FindNextFile(d->handle, &d->wfd) == FALSE)826 a = 0;
640 return 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;
641 }840 }
642 strcpy(name, (char*)d->wfd.cFileName);841 return a;
643 d->index++;
644
645 return 1;
646}
647
648void
649rewinddir(DIR *d)
650{
651 FindClose(d->handle);
652 d->handle = FindFirstFile(d->path, &d->wfd);
653 d->index = 0;
654}
655
656static int
657chown(char *path, int uid, int perm)
658{
659/* panic("chown"); */
660 return 0;
661}842}
662 843
663DIR*
664opendir(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}
687 844
688Dev fsdevtab = {845Dev fsdevtab = {
689 'U',846 '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