devroot.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264
  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. enum
  16. {
  17. Qdir = 0,
  18. Qboot = 0x1000,
  19. Nrootfiles = 32,
  20. Nbootfiles = 32,
  21. };
  22. typedef struct Dirlist Dirlist;
  23. struct Dirlist
  24. {
  25. uint base;
  26. Dirtab *dir;
  27. uint8_t **data;
  28. int ndir;
  29. int mdir;
  30. };
  31. static Dirtab rootdir[Nrootfiles] = {
  32. {"#/", {Qdir, 0, QTDIR}, 0, DMDIR|0555},
  33. {"boot", {Qboot, 0, QTDIR}, 0, DMDIR|0555},
  34. };
  35. static uint8_t *rootdata[Nrootfiles];
  36. static Dirlist rootlist =
  37. {
  38. 0,
  39. rootdir,
  40. rootdata,
  41. 2,
  42. Nrootfiles
  43. };
  44. static Dirtab bootdir[Nbootfiles] = {
  45. {"boot", {Qboot, 0, QTDIR}, 0, DMDIR|0555},
  46. };
  47. static uint8_t *bootdata[Nbootfiles];
  48. static Dirlist bootlist =
  49. {
  50. Qboot,
  51. bootdir,
  52. bootdata,
  53. 1,
  54. Nbootfiles
  55. };
  56. /*
  57. * add a file to the list
  58. */
  59. static void
  60. addlist(Dirlist *l, char *name, uint8_t *contents, uint32_t len,
  61. int perm)
  62. {
  63. Dirtab *d;
  64. if(l->ndir >= l->mdir)
  65. panic("too many root files");
  66. l->data[l->ndir] = contents;
  67. d = &l->dir[l->ndir];
  68. strcpy(d->name, name);
  69. d->length = len;
  70. d->perm = perm;
  71. d->qid.type = 0;
  72. d->qid.vers = 0;
  73. d->qid.path = ++l->ndir + l->base;
  74. if(perm & DMDIR)
  75. d->qid.type |= QTDIR;
  76. }
  77. /*
  78. * add a root file
  79. */
  80. void
  81. addbootfile(char *name, uint8_t *contents, uint32_t len)
  82. {
  83. addlist(&bootlist, name, contents, len, 0555);
  84. }
  85. /*
  86. * add a root directory
  87. */
  88. static void
  89. addrootdir(char *name)
  90. {
  91. addlist(&rootlist, name, nil, 0, DMDIR|0555);
  92. }
  93. static void
  94. rootreset(void)
  95. {
  96. addrootdir("bin");
  97. addrootdir("dev");
  98. addrootdir("env");
  99. addrootdir("fd");
  100. addrootdir("mnt");
  101. addrootdir("n");
  102. addrootdir("net");
  103. addrootdir("net.alt");
  104. addrootdir("proc");
  105. addrootdir("root");
  106. addrootdir("srv");
  107. }
  108. static Chan*
  109. rootattach(char *spec)
  110. {
  111. return devattach('/', spec);
  112. }
  113. static int
  114. rootgen(Chan *c, char *name, Dirtab* dir, int j, int s, Dir *dp)
  115. {
  116. int t;
  117. Dirtab *d;
  118. Dirlist *l;
  119. switch((int)c->qid.path){
  120. case Qdir:
  121. if(s == DEVDOTDOT){
  122. devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
  123. return 1;
  124. }
  125. return devgen(c, name, rootlist.dir, rootlist.ndir, s, dp);
  126. case Qboot:
  127. if(s == DEVDOTDOT){
  128. devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
  129. return 1;
  130. }
  131. return devgen(c, name, bootlist.dir, bootlist.ndir, s, dp);
  132. default:
  133. if(s == DEVDOTDOT){
  134. if((int)c->qid.path < Qboot)
  135. devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
  136. else
  137. devdir(c, (Qid){Qboot, 0, QTDIR}, "#/", 0, eve, 0555, dp);
  138. return 1;
  139. }
  140. if(s != 0)
  141. return -1;
  142. if((int)c->qid.path < Qboot){
  143. t = c->qid.path-1;
  144. l = &rootlist;
  145. }else{
  146. t = c->qid.path - Qboot - 1;
  147. l = &bootlist;
  148. }
  149. if(t >= l->ndir)
  150. return -1;
  151. if(t < 0){
  152. print("rootgen %#llx %d %d\n", c->qid.path, s, t);
  153. panic("whoops");
  154. }
  155. d = &l->dir[t];
  156. devdir(c, d->qid, d->name, d->length, eve, d->perm, dp);
  157. return 1;
  158. }
  159. }
  160. static Walkqid*
  161. rootwalk(Chan *c, Chan *nc, char **name, int nname)
  162. {
  163. return devwalk(c, nc, name, nname, nil, 0, rootgen);
  164. }
  165. static int32_t
  166. rootstat(Chan *c, uint8_t *dp, int32_t n)
  167. {
  168. return devstat(c, dp, n, nil, 0, rootgen);
  169. }
  170. static Chan*
  171. rootopen(Chan *c, int omode)
  172. {
  173. return devopen(c, omode, nil, 0, devgen);
  174. }
  175. /*
  176. * sysremove() knows this is a nop
  177. */
  178. static void
  179. rootclose(Chan* c)
  180. {
  181. }
  182. static int32_t
  183. rootread(Chan *c, void *buf, int32_t n, int64_t off)
  184. {
  185. uint32_t t;
  186. Dirtab *d;
  187. Dirlist *l;
  188. uint8_t *data;
  189. uint32_t offset = off;
  190. t = c->qid.path;
  191. switch(t){
  192. case Qdir:
  193. case Qboot:
  194. return devdirread(c, buf, n, nil, 0, rootgen);
  195. }
  196. if(t<Qboot)
  197. l = &rootlist;
  198. else{
  199. t -= Qboot;
  200. l = &bootlist;
  201. }
  202. t--;
  203. if(t >= l->ndir)
  204. error(Egreg);
  205. d = &l->dir[t];
  206. data = l->data[t];
  207. if(offset >= d->length)
  208. return 0;
  209. if(offset+n > d->length)
  210. n = d->length - offset;
  211. memmove(buf, data+offset, n);
  212. return n;
  213. }
  214. static int32_t
  215. rootwrite(Chan* c, void* v, int32_t n, int64_t m)
  216. {
  217. error(Egreg);
  218. return 0;
  219. }
  220. Dev rootdevtab = {
  221. .dc = '/',
  222. .name = "root",
  223. .reset = rootreset,
  224. .init = devinit,
  225. .shutdown = devshutdown,
  226. .attach = rootattach,
  227. .walk = rootwalk,
  228. .stat = rootstat,
  229. .open = rootopen,
  230. .create = devcreate,
  231. .close = rootclose,
  232. .read = rootread,
  233. .bread = devbread,
  234. .write = rootwrite,
  235. .bwrite = devbwrite,
  236. .remove = devremove,
  237. .wstat = devwstat,
  238. };