devntfs.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700
  1. #include <windows.h>
  2. #include <sys/types.h>
  3. #include <sys/stat.h>
  4. #include <fcntl.h>
  5. #include "lib9.h"
  6. #include "sys.h"
  7. #include "error.h"
  8. typedef struct DIR DIR;
  9. typedef struct Ufsinfo Ufsinfo;
  10. enum
  11. {
  12. NUID = 256,
  13. NGID = 256,
  14. MAXPATH = 1024,
  15. MAXCOMP = 128
  16. };
  17. extern char* sys_errlist[];
  18. struct DIR
  19. {
  20. HANDLE handle;
  21. char* path;
  22. int index;
  23. WIN32_FIND_DATA wfd;
  24. };
  25. struct Ufsinfo
  26. {
  27. int uid;
  28. int gid;
  29. int mode;
  30. int fd;
  31. DIR* dir;
  32. ulong offset;
  33. Qlock oq;
  34. };
  35. DIR* opendir(char*);
  36. int readdir(char*, DIR*);
  37. void closedir(DIR*);
  38. void rewinddir(DIR*);
  39. char *base = "c:/.";
  40. static Qid fsqid(char*, struct stat *);
  41. static void fspath(Path*, char*, char*);
  42. static void fsperm(Chan*, int);
  43. static ulong fsdirread(Chan*, uchar*, int, ulong);
  44. static int fsomode(int);
  45. static int chown(char *path, int uid, int);
  46. static int link(char *path, char *next);
  47. void
  48. fsinit(void)
  49. {
  50. }
  51. Chan*
  52. fsattach(void *spec)
  53. {
  54. Chan *c;
  55. struct stat stbuf;
  56. static int devno;
  57. Ufsinfo *uif;
  58. if(stat(base, &stbuf) < 0)
  59. error(sys_errlist[errno]);
  60. c = devattach('U', spec);
  61. uif = mallocz(sizeof(Ufsinfo));
  62. uif->gid = stbuf.st_gid;
  63. uif->uid = stbuf.st_uid;
  64. uif->mode = stbuf.st_mode;
  65. c->u.aux = uif;
  66. c->dev = devno++;
  67. return c;
  68. }
  69. Chan*
  70. fsclone(Chan *c, Chan *nc)
  71. {
  72. Ufsinfo *uif;
  73. nc = devclone(c, nc);
  74. uif = mallocz(sizeof(Ufsinfo));
  75. *uif = *(Ufsinfo*)c->u.aux;
  76. nc->u.aux = uif;
  77. return nc;
  78. }
  79. int
  80. fswalk(Chan *c, char *name)
  81. {
  82. Path *op;
  83. struct stat stbuf;
  84. char path[MAXPATH];
  85. Ufsinfo *uif;
  86. fspath(c->path, name, path);
  87. /* print("** fs walk '%s' -> %s\n", path, name); /**/
  88. if(stat(path, &stbuf) < 0)
  89. return 0;
  90. uif = c->u.aux;
  91. uif->gid = stbuf.st_gid;
  92. uif->uid = stbuf.st_uid;
  93. uif->mode = stbuf.st_mode;
  94. c->qid = fsqid(path, &stbuf);
  95. op = c->path;
  96. c->path = ptenter(&syspt, op, name);
  97. refdec(&op->r);
  98. return 1;
  99. }
  100. void
  101. fsstat(Chan *c, char *buf)
  102. {
  103. Dir d;
  104. struct stat stbuf;
  105. char path[MAXPATH];
  106. fspath(c->path, 0, path);
  107. if(stat(path, &stbuf) < 0)
  108. error(sys_errlist[errno]);
  109. strncpy(d.name, c->path->elem, NAMELEN);
  110. strncpy(d.uid, "unknown", NAMELEN);
  111. strncpy(d.gid, "unknown", NAMELEN);
  112. d.qid = c->qid;
  113. d.mode = (c->qid.path&CHDIR)|(stbuf.st_mode&0777);
  114. d.atime = stbuf.st_atime;
  115. d.mtime = stbuf.st_mtime;
  116. d.length = stbuf.st_size;
  117. d.type = 'U';
  118. d.dev = c->dev;
  119. convD2M(&d, buf);
  120. }
  121. Chan*
  122. fsopen(Chan *c, int mode)
  123. {
  124. char path[MAXPATH];
  125. int m, isdir;
  126. Ufsinfo *uif;
  127. m = mode & (OTRUNC|3);
  128. switch(m) {
  129. case 0:
  130. fsperm(c, 4);
  131. break;
  132. case 1:
  133. case 1|16:
  134. fsperm(c, 2);
  135. break;
  136. case 2:
  137. case 0|16:
  138. case 2|16:
  139. fsperm(c, 4);
  140. fsperm(c, 2);
  141. break;
  142. case 3:
  143. fsperm(c, 1);
  144. break;
  145. default:
  146. error(Ebadarg);
  147. }
  148. isdir = c->qid.path & CHDIR;
  149. if(isdir && mode != OREAD)
  150. error(Eperm);
  151. m = fsomode(m & 3);
  152. c->mode = openmode(mode);
  153. uif = c->u.aux;
  154. fspath(c->path, 0, path);
  155. if(isdir) {
  156. uif->dir = opendir(path);
  157. if(uif->dir == 0)
  158. error(sys_errlist[errno]);
  159. }
  160. else {
  161. if(mode & OTRUNC)
  162. m |= O_TRUNC;
  163. uif->fd = open(path, m|_O_BINARY, 0666);
  164. if(uif->fd < 0)
  165. error(sys_errlist[errno]);
  166. }
  167. uif->offset = 0;
  168. c->offset = 0;
  169. c->flag |= COPEN;
  170. return c;
  171. }
  172. void
  173. fscreate(Chan *c, char *name, int mode, ulong perm)
  174. {
  175. int fd, m;
  176. char path[MAXPATH];
  177. struct stat stbuf;
  178. Path *op;
  179. Ufsinfo *uif;
  180. fsperm(c, 2);
  181. m = fsomode(mode&3);
  182. fspath(c->path, name, path);
  183. uif = c->u.aux;
  184. if(perm & CHDIR) {
  185. if(m)
  186. error(Eperm);
  187. if(mkdir(path) < 0)
  188. error(sys_errlist[errno]);
  189. fd = open(path, 0);
  190. if(fd >= 0) {
  191. chmod(path, perm & 0777);
  192. chown(path, uif->uid, uif->uid);
  193. }
  194. close(fd);
  195. uif->dir = opendir(path);
  196. if(uif->dir == 0)
  197. error(sys_errlist[errno]);
  198. }
  199. else {
  200. fd = open(path, _O_WRONLY|_O_BINARY|_O_CREAT|_O_TRUNC, 0666);
  201. if(fd >= 0) {
  202. if(m != 1) {
  203. close(fd);
  204. fd = open(path, m|_O_BINARY);
  205. }
  206. chmod(path, perm & 0777);
  207. chown(path, uif->uid, uif->gid);
  208. }
  209. if(fd < 0)
  210. error(sys_errlist[errno]);
  211. uif->fd = fd;
  212. }
  213. if(stat(path, &stbuf) < 0)
  214. error(sys_errlist[errno]);
  215. c->qid = fsqid(path, &stbuf);
  216. c->offset = 0;
  217. c->flag |= COPEN;
  218. c->mode = openmode(mode);
  219. op = c->path;
  220. c->path = ptenter(&syspt, op, name);
  221. refdec(&op->r);
  222. }
  223. void
  224. fsclose(Chan *c)
  225. {
  226. Ufsinfo *uif;
  227. uif = c->u.aux;
  228. if(c->flag & COPEN) {
  229. if(c->qid.path & CHDIR)
  230. closedir(uif->dir);
  231. else
  232. close(uif->fd);
  233. }
  234. free(uif);
  235. }
  236. long
  237. fsread(Chan *c, void *va, long n, ulong offset)
  238. {
  239. int fd, r;
  240. Ufsinfo *uif;
  241. if(c->qid.path & CHDIR)
  242. return fsdirread(c, va, n, offset);
  243. uif = c->u.aux;
  244. qlock(&uif->oq);
  245. if(waserror()) {
  246. qunlock(&uif->oq);
  247. nexterror();
  248. }
  249. fd = uif->fd;
  250. if(uif->offset != offset) {
  251. r = lseek(fd, offset, 0);
  252. if(r < 0)
  253. error(sys_errlist[errno]);
  254. uif->offset = offset;
  255. }
  256. n = read(fd, va, n);
  257. if(n < 0)
  258. error(sys_errlist[errno]);
  259. uif->offset += n;
  260. qunlock(&uif->oq);
  261. poperror();
  262. return n;
  263. }
  264. long
  265. fswrite(Chan *c, void *va, long n, ulong offset)
  266. {
  267. int fd, r;
  268. Ufsinfo *uif;
  269. uif = c->u.aux;
  270. qlock(&uif->oq);
  271. if(waserror()) {
  272. qunlock(&uif->oq);
  273. nexterror();
  274. }
  275. fd = uif->fd;
  276. if(uif->offset != offset) {
  277. r = lseek(fd, offset, 0);
  278. if(r < 0)
  279. error(sys_errlist[errno]);
  280. uif->offset = offset;
  281. }
  282. n = write(fd, va, n);
  283. if(n < 0)
  284. error(sys_errlist[errno]);
  285. uif->offset += n;
  286. qunlock(&uif->oq);
  287. poperror();
  288. return n;
  289. }
  290. void
  291. fsremove(Chan *c)
  292. {
  293. int n;
  294. char path[MAXPATH];
  295. fspath(c->path, 0, path);
  296. if(c->qid.path & CHDIR)
  297. n = rmdir(path);
  298. else
  299. n = remove(path);
  300. if(n < 0)
  301. error(sys_errlist[errno]);
  302. }
  303. void
  304. fswchk(char *path)
  305. {
  306. struct stat stbuf;
  307. if(stat(path, &stbuf) < 0)
  308. error(sys_errlist[errno]);
  309. if(stbuf.st_uid == up->uid)
  310. stbuf.st_mode >>= 6;
  311. else
  312. if(stbuf.st_gid == up->gid)
  313. stbuf.st_mode >>= 3;
  314. if(stbuf.st_mode & S_IWRITE)
  315. return;
  316. error(Eperm);
  317. }
  318. void
  319. fswstat(Chan *c, char *buf)
  320. {
  321. Dir d;
  322. Path *ph;
  323. struct stat stbuf;
  324. char old[MAXPATH], new[MAXPATH], dir[MAXPATH];
  325. Ufsinfo *uif;
  326. convM2D(buf, &d);
  327. fspath(c->path, 0, old);
  328. if(stat(old, &stbuf) < 0)
  329. error(sys_errlist[errno]);
  330. uif = c->u.aux;
  331. if(uif->uid != stbuf.st_uid)
  332. error(Eowner);
  333. if(strcmp(d.name, c->path->elem) != 0) {
  334. fspath(c->path->parent, 0, dir);
  335. fswchk(dir);
  336. fspath(c->path, 0, old);
  337. ph = ptenter(&syspt, c->path->parent, d.name);
  338. fspath(ph, 0, new);
  339. if(link(old, new) < 0)
  340. error(sys_errlist[errno]);
  341. if(unlink(old) < 0)
  342. error(sys_errlist[errno]);
  343. refdec(&c->path->r);
  344. c->path = ph;
  345. }
  346. fspath(c->path, 0, old);
  347. if((int)(d.mode&0777) != (int)(stbuf.st_mode&0777)) {
  348. if(chmod(old, d.mode&0777) < 0)
  349. error(sys_errlist[errno]);
  350. uif->mode &= ~0777;
  351. uif->mode |= d.mode&0777;
  352. }
  353. /*
  354. p = name2pass(gid, d.gid);
  355. if(p == 0)
  356. error(Eunknown);
  357. if(p->id != stbuf.st_gid) {
  358. if(chown(old, stbuf.st_uid, p->id) < 0)
  359. error(sys_errlist[errno]);
  360. uif->gid = p->id;
  361. }
  362. */
  363. }
  364. static Qid
  365. fsqid(char *p, struct stat *st)
  366. {
  367. Qid q;
  368. int dev;
  369. ulong h;
  370. static int nqdev;
  371. static uchar *qdev;
  372. uchar *name;
  373. name = p;
  374. if(qdev == 0)
  375. qdev = mallocz(65536U);
  376. q.path = 0;
  377. if((st->st_mode&S_IFMT) == S_IFDIR)
  378. q.path = CHDIR;
  379. dev = st->st_dev & 0xFFFFUL;
  380. if(qdev[dev] == 0) {
  381. if(++nqdev >= 128)
  382. error("too many devices");
  383. qdev[dev] = nqdev;
  384. }
  385. h = 0;
  386. while(*p != '\0')
  387. h += *p++ * 13;
  388. q.path |= qdev[dev]<<24;
  389. q.path |= h & 0x00FFFFFFUL;
  390. q.vers = st->st_mtime;
  391. return q;
  392. }
  393. static void
  394. fspath(Path *p, char *ext, char *path)
  395. {
  396. int i, n;
  397. char *comp[MAXCOMP];
  398. strcpy(path, base);
  399. i = strlen(base);
  400. if(p == 0) {
  401. if(ext) {
  402. path[i++] = '/';
  403. strcpy(path+i, ext);
  404. }
  405. return;
  406. }
  407. n = 0;
  408. if(ext)
  409. comp[n++] = ext;
  410. while(p->parent) {
  411. comp[n++] = p->elem;
  412. p = p->parent;
  413. }
  414. while(n) {
  415. path[i++] = '/';
  416. strcpy(path+i, comp[--n]);
  417. i += strlen(comp[n]);
  418. }
  419. path[i] = '\0';
  420. }
  421. static void
  422. fsperm(Chan *c, int mask)
  423. {
  424. int m;
  425. Ufsinfo *uif;
  426. uif = c->u.aux;
  427. m = uif->mode;
  428. /*
  429. print("fsperm: %o %o uuid %d ugid %d cuid %d cgid %d\n",
  430. m, mask, up->uid, up->gid, uif->uid, uif->gid);
  431. */
  432. if(uif->uid == up->uid)
  433. m >>= 6;
  434. else
  435. if(uif->gid == up->gid)
  436. m >>= 3;
  437. m &= mask;
  438. if(m == 0)
  439. error(Eperm);
  440. }
  441. static int
  442. isdots(char *name)
  443. {
  444. if(name[0] != '.')
  445. return 0;
  446. if(name[1] == '\0')
  447. return 1;
  448. if(name[1] != '.')
  449. return 0;
  450. if(name[2] == '\0')
  451. return 1;
  452. return 0;
  453. }
  454. static ulong
  455. fsdirread(Chan *c, uchar *va, int count, ulong offset)
  456. {
  457. int i;
  458. Dir d;
  459. long n;
  460. char de[256];
  461. struct stat stbuf;
  462. char path[MAXPATH], dirpath[MAXPATH];
  463. Ufsinfo *uif;
  464. count = (count/DIRLEN)*DIRLEN;
  465. i = 0;
  466. uif = c->u.aux;
  467. errno = 0;
  468. if(uif->offset != offset) {
  469. uif->offset = offset; /* sync offset */
  470. rewinddir(uif->dir);
  471. for(n=0; n<(int)offset; ) {
  472. if(!readdir(de, uif->dir))
  473. break;
  474. if(de[0]==0 || isdots(de))
  475. continue;
  476. n += DIRLEN;
  477. }
  478. }
  479. fspath(c->path, 0, dirpath);
  480. while(i < count) {
  481. if(!readdir(de, uif->dir))
  482. break;
  483. if(de[0]==0 || isdots(de))
  484. continue;
  485. strncpy(d.name, de, NAMELEN-1);
  486. d.name[NAMELEN-1] = 0;
  487. sprint(path, "%s/%s", dirpath, de);
  488. memset(&stbuf, 0, sizeof stbuf);
  489. if(stat(path, &stbuf) < 0) {
  490. iprint("dir: bad path %s\n", path);
  491. /* but continue... probably a bad symlink */
  492. }
  493. strncpy(d.uid, "unknown", NAMELEN);
  494. strncpy(d.gid, "unknown", NAMELEN);
  495. d.qid = fsqid(path, &stbuf);
  496. d.mode = (d.qid.path&CHDIR)|(stbuf.st_mode&0777);
  497. d.atime = stbuf.st_atime;
  498. d.mtime = stbuf.st_mtime;
  499. d.length = stbuf.st_size;
  500. d.type = 'U';
  501. d.dev = c->dev;
  502. convD2M(&d, va+i);
  503. i += DIRLEN;
  504. }
  505. return i;
  506. }
  507. static int
  508. fsomode(int m)
  509. {
  510. switch(m) {
  511. case 0: /* OREAD */
  512. case 3: /* OEXEC */
  513. return 0;
  514. case 1: /* OWRITE */
  515. return 1;
  516. case 2: /* ORDWR */
  517. return 2;
  518. }
  519. error(Ebadarg);
  520. return 0;
  521. }
  522. void
  523. closedir(DIR *d)
  524. {
  525. FindClose(d->handle);
  526. free(d->path);
  527. }
  528. int
  529. readdir(char *name, DIR *d)
  530. {
  531. if(d->index != 0) {
  532. if(FindNextFile(d->handle, &d->wfd) == FALSE)
  533. return 0;
  534. }
  535. strcpy(name, d->wfd.cFileName);
  536. d->index++;
  537. return 1;
  538. }
  539. void
  540. rewinddir(DIR *d)
  541. {
  542. FindClose(d->handle);
  543. d->handle = FindFirstFile(d->path, &d->wfd);
  544. d->index = 0;
  545. }
  546. static int
  547. chown(char *path, int uid, int perm)
  548. {
  549. /* panic("chown"); */
  550. return 0;
  551. }
  552. static int
  553. link(char *path, char *next)
  554. {
  555. panic("link");
  556. return 0;
  557. }
  558. DIR*
  559. opendir(char *p)
  560. {
  561. DIR *d;
  562. char path[MAX_PATH];
  563. snprint(path, sizeof(path), "%s/*.*", p);
  564. d = mallocz(sizeof(DIR));
  565. if(d == 0)
  566. return 0;
  567. d->index = 0;
  568. d->handle = FindFirstFile(path, &d->wfd);
  569. if(d->handle == INVALID_HANDLE_VALUE) {
  570. free(d);
  571. return 0;
  572. }
  573. d->path = strdup(path);
  574. return d;
  575. }