dev.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "../port/error.h"
  15. extern uint32_t kerndate;
  16. void
  17. mkqid(Qid *q, int64_t path, uint32_t vers, int type)
  18. {
  19. q->type = type;
  20. q->vers = vers;
  21. q->path = path;
  22. }
  23. void
  24. devdir(Chan *c, Qid qid, char *n, int64_t length, char *user,
  25. int32_t perm,
  26. Dir *db)
  27. {
  28. db->name = n;
  29. if(c->flag&CMSG)
  30. qid.type |= QTMOUNT;
  31. db->qid = qid;
  32. /*
  33. * When called via devwalk c->dev is nil
  34. * until the walk succeeds.
  35. */
  36. if(c->dev != nil)
  37. db->type = c->dev->dc;
  38. else
  39. db->type = -1;
  40. db->dev = c->devno;
  41. db->mode = perm;
  42. db->mode |= qid.type << 24;
  43. db->atime = seconds();
  44. db->mtime = kerndate;
  45. db->length = length;
  46. db->uid = user;
  47. db->gid = eve;
  48. db->muid = user;
  49. }
  50. /*
  51. * (here, Devgen is the prototype; devgen is the function in dev.c.)
  52. *
  53. * a Devgen is expected to return the directory entry for ".."
  54. * if you pass it s==DEVDOTDOT (-1). otherwise...
  55. *
  56. * there are two contradictory rules.
  57. *
  58. * (i) if c is a directory, a Devgen is expected to list its children
  59. * as you iterate s.
  60. *
  61. * (ii) whether or not c is a directory, a Devgen is expected to list
  62. * its siblings as you iterate s.
  63. *
  64. * devgen always returns the list of children in the root
  65. * directory. thus it follows (i) when c is the root and (ii) otherwise.
  66. * many other Devgens follow (i) when c is a directory and (ii) otherwise.
  67. *
  68. * devwalk assumes (i). it knows that devgen breaks (i)
  69. * for children that are themselves directories, and explicitly catches them.
  70. *
  71. * devstat assumes (ii). if the Devgen in question follows (i)
  72. * for this particular c, devstat will not find the necessary info.
  73. * with our particular Devgen functions, this happens only for
  74. * directories, so devstat makes something up, assuming
  75. * c->name, c->qid, eve, DMDIR|0555.
  76. *
  77. * devdirread assumes (i). the callers have to make sure
  78. * that the Devgen satisfies (i) for the chan being read.
  79. */
  80. /*
  81. * the zeroth element of the table MUST be the directory itself for ..
  82. */
  83. int
  84. devgen(Chan *c, char *name, Dirtab *tab, int ntab, int i, Dir *dp)
  85. {
  86. if(tab == 0)
  87. return -1;
  88. if(i == DEVDOTDOT){
  89. /* nothing */
  90. }else if(name){
  91. for(i=1; i<ntab; i++)
  92. if(strcmp(tab[i].name, name) == 0)
  93. break;
  94. if(i==ntab)
  95. return -1;
  96. tab += i;
  97. }else{
  98. /* skip over the first element, that for . itself */
  99. i++;
  100. if(i >= ntab)
  101. return -1;
  102. tab += i;
  103. }
  104. devdir(c, tab->qid, tab->name, tab->length, eve, tab->perm, dp);
  105. return 1;
  106. }
  107. void
  108. devreset(void)
  109. {
  110. }
  111. void
  112. devinit(void)
  113. {
  114. }
  115. void
  116. devshutdown(void)
  117. {
  118. }
  119. Chan*
  120. devattach(int dc, char *spec)
  121. {
  122. Chan *c;
  123. char *buf;
  124. /*
  125. * There are no error checks here because
  126. * this can only be called from the driver of dc
  127. * which pretty much guarantees devtabget will
  128. * succeed.
  129. */
  130. c = newchan();
  131. mkqid(&c->qid, 0, 0, QTDIR);
  132. c->dev = devtabget(dc, 0);
  133. if(spec == nil)
  134. spec = "";
  135. buf = smalloc(1+UTFmax+strlen(spec)+1);
  136. sprint(buf, "#%C%s", dc, spec);
  137. c->path = newpath(buf);
  138. free(buf);
  139. return c;
  140. }
  141. Chan*
  142. devclone(Chan *c)
  143. {
  144. Chan *nc;
  145. if(c->flag & COPEN){
  146. panic("devclone: file of type %C already open\n",
  147. c->dev != nil? c->dev->dc: -1);
  148. }
  149. nc = newchan();
  150. /*
  151. * The caller fills dev in if and when necessary.
  152. nc->dev = nil; //XDYNXX
  153. */
  154. nc->devno = c->devno;
  155. nc->mode = c->mode;
  156. nc->qid = c->qid;
  157. nc->offset = c->offset;
  158. nc->umh = nil;
  159. nc->aux = c->aux;
  160. nc->mqid = c->mqid;
  161. nc->mc = c->mc;
  162. return nc;
  163. }
  164. Walkqid*
  165. devwalk(Chan *c, Chan *nc, char **name, int nname, Dirtab *tab, int ntab,
  166. Devgen *gen)
  167. {
  168. int i, j, alloc;
  169. Walkqid *wq;
  170. char *n;
  171. Dir dir;
  172. if(nname > 0)
  173. isdir(c);
  174. alloc = 0;
  175. wq = smalloc(sizeof(Walkqid)+(nname-1)*sizeof(Qid));
  176. if(waserror()){
  177. if(alloc && wq->clone!=nil)
  178. cclose(wq->clone);
  179. free(wq);
  180. return nil;
  181. }
  182. if(nc == nil){
  183. nc = devclone(c);
  184. /*
  185. * nc->dev remains nil for now. //XDYNX
  186. */
  187. alloc = 1;
  188. }
  189. wq->clone = nc;
  190. for(j=0; j<nname; j++){
  191. if(!(nc->qid.type & QTDIR)){
  192. if(j==0)
  193. error(Enotdir);
  194. goto Done;
  195. }
  196. n = name[j];
  197. if(strcmp(n, ".") == 0){
  198. Accept:
  199. wq->qid[wq->nqid++] = nc->qid;
  200. continue;
  201. }
  202. if(strcmp(n, "..") == 0){
  203. /*
  204. * Use c->dev->name in the error because
  205. * nc->dev should be nil here.
  206. */
  207. if((*gen)(nc, nil, tab, ntab, DEVDOTDOT, &dir) != 1){
  208. print("devgen walk .. in dev%s %#llux broken\n",
  209. c->dev->name, nc->qid.path);
  210. error("broken devgen");
  211. }
  212. nc->qid = dir.qid;
  213. goto Accept;
  214. }
  215. /*
  216. * Ugly problem: If we're using devgen, make sure we're
  217. * walking the directory itself, represented by the first
  218. * entry in the table, and not trying to step into a sub-
  219. * directory of the table, e.g. /net/net. Devgen itself
  220. * should take care of the problem, but it doesn't have
  221. * the necessary information (that we're doing a walk).
  222. */
  223. if(gen==devgen && nc->qid.path!=tab[0].qid.path)
  224. goto Notfound;
  225. for(i=0;; i++) {
  226. switch((*gen)(nc, n, tab, ntab, i, &dir)){
  227. case -1:
  228. Notfound:
  229. if(j == 0)
  230. error(Enonexist);
  231. kstrcpy(up->errstr, Enonexist, ERRMAX);
  232. goto Done;
  233. case 0:
  234. continue;
  235. case 1:
  236. if(strcmp(n, dir.name) == 0){
  237. nc->qid = dir.qid;
  238. goto Accept;
  239. }
  240. continue;
  241. }
  242. }
  243. }
  244. /*
  245. * We processed at least one name, so will return some data.
  246. * If we didn't process all nname entries succesfully, we drop
  247. * the cloned channel and return just the Qids of the walks.
  248. */
  249. Done:
  250. poperror();
  251. if(wq->nqid < nname){
  252. if(alloc)
  253. cclose(wq->clone);
  254. wq->clone = nil;
  255. }else if(wq->clone){
  256. /* attach cloned channel to same device */
  257. //what goes here: //XDYNX
  258. // ->dev must be nil because can't walk an open chan, right?
  259. // what about ref count on dev?
  260. wq->clone->dev = c->dev;
  261. //if(wq->clone->dev) //XDYNX
  262. // devtabincr(wq->clone->dev);
  263. }
  264. return wq;
  265. }
  266. int32_t
  267. devstat(Chan *c, uint8_t *db, int32_t n, Dirtab *tab, int ntab,
  268. Devgen *gen)
  269. {
  270. int i;
  271. Dir dir;
  272. char *p, *elem;
  273. for(i=0;; i++){
  274. switch((*gen)(c, nil, tab, ntab, i, &dir)){
  275. case -1:
  276. if(c->qid.type & QTDIR){
  277. if(c->path == nil)
  278. elem = "???";
  279. else if(strcmp(c->path->s, "/") == 0)
  280. elem = "/";
  281. else
  282. for(elem=p=c->path->s; *p; p++)
  283. if(*p == '/')
  284. elem = p+1;
  285. devdir(c, c->qid, elem, 0, eve, DMDIR|0555, &dir);
  286. n = convD2M(&dir, db, n);
  287. if(n == 0)
  288. error(Ebadarg);
  289. return n;
  290. }
  291. error(Enonexist);
  292. case 0:
  293. break;
  294. case 1:
  295. if(c->qid.path == dir.qid.path) {
  296. if(c->flag&CMSG)
  297. dir.mode |= DMMOUNT;
  298. n = convD2M(&dir, db, n);
  299. if(n == 0)
  300. error(Ebadarg);
  301. return n;
  302. }
  303. break;
  304. }
  305. }
  306. }
  307. int32_t
  308. devdirread(Chan *c, char *d, int32_t n, Dirtab *tab, int ntab,
  309. Devgen *gen)
  310. {
  311. int32_t m, dsz;
  312. Dir dir;
  313. for(m=0; m<n; c->dri++) {
  314. switch((*gen)(c, nil, tab, ntab, c->dri, &dir)){
  315. case -1:
  316. return m;
  317. case 0:
  318. break;
  319. case 1:
  320. dsz = convD2M(&dir, (uint8_t*)d, n-m);
  321. if(dsz <= BIT16SZ){ /* <= not < because this isn't stat; read is stuck */
  322. if(m == 0)
  323. error(Eshort);
  324. return m;
  325. }
  326. m += dsz;
  327. d += dsz;
  328. break;
  329. }
  330. }
  331. return m;
  332. }
  333. /*
  334. * error(Eperm) if open permission not granted for up->user.
  335. */
  336. void
  337. devpermcheck(char *fileuid, int perm, int omode)
  338. {
  339. int t;
  340. static int access[] = { 0400, 0200, 0600, 0100 };
  341. if(strcmp(up->user, fileuid) == 0)
  342. perm <<= 0;
  343. else
  344. if(strcmp(up->user, eve) == 0)
  345. perm <<= 3;
  346. else
  347. perm <<= 6;
  348. t = access[omode&3];
  349. if((t&perm) != t)
  350. error(Eperm);
  351. }
  352. Chan*
  353. devopen(Chan *c, int omode, Dirtab *tab, int ntab, Devgen *gen)
  354. {
  355. int i;
  356. Dir dir;
  357. for(i=0;; i++) {
  358. switch((*gen)(c, nil, tab, ntab, i, &dir)){
  359. case -1:
  360. goto Return;
  361. case 0:
  362. break;
  363. case 1:
  364. if(c->qid.path == dir.qid.path) {
  365. devpermcheck(dir.uid, dir.mode, omode);
  366. goto Return;
  367. }
  368. break;
  369. }
  370. }
  371. Return:
  372. c->offset = 0;
  373. if((c->qid.type & QTDIR) && omode!=OREAD)
  374. error(Eperm);
  375. c->mode = openmode(omode);
  376. c->flag |= COPEN;
  377. return c;
  378. }
  379. void
  380. devcreate(Chan*, char*, int, int)
  381. {
  382. error(Eperm);
  383. }
  384. Block*
  385. devbread(Chan *c, int32_t n, int64_t offset)
  386. {
  387. Block *bp;
  388. bp = allocb(n);
  389. if(bp == 0)
  390. error(Enomem);
  391. if(waserror()) {
  392. freeb(bp);
  393. nexterror();
  394. }
  395. bp->wp += c->dev->read(c, bp->wp, n, offset);
  396. poperror();
  397. return bp;
  398. }
  399. int32_t
  400. devbwrite(Chan *c, Block *bp, int64_t offset)
  401. {
  402. int32_t n;
  403. if(waserror()) {
  404. freeb(bp);
  405. nexterror();
  406. }
  407. n = c->dev->write(c, bp->rp, BLEN(bp), offset);
  408. poperror();
  409. freeb(bp);
  410. return n;
  411. }
  412. void
  413. devremove(Chan*)
  414. {
  415. error(Eperm);
  416. }
  417. int32_t
  418. devwstat(Chan*, uint8_t*, int32_t)
  419. {
  420. error(Eperm);
  421. return 0;
  422. }
  423. void
  424. devpower(int)
  425. {
  426. error(Eperm);
  427. }
  428. int
  429. devconfig(int, char *, DevConf *)
  430. {
  431. error(Eperm);
  432. return 0;
  433. }