devroot.c 4.4 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("net");
  102. addrootdir("net.alt");
  103. addrootdir("proc");
  104. addrootdir("root");
  105. addrootdir("srv");
  106. }
  107. static Chan*
  108. rootattach(char *spec)
  109. {
  110. return devattach('/', spec);
  111. }
  112. static int
  113. rootgen(Chan *c, char *name, Dirtab*, int, int s, Dir *dp)
  114. {
  115. int t;
  116. Dirtab *d;
  117. Dirlist *l;
  118. switch((int)c->qid.path){
  119. case Qdir:
  120. if(s == DEVDOTDOT){
  121. devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
  122. return 1;
  123. }
  124. return devgen(c, name, rootlist.dir, rootlist.ndir, s, dp);
  125. case Qboot:
  126. if(s == DEVDOTDOT){
  127. devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
  128. return 1;
  129. }
  130. return devgen(c, name, bootlist.dir, bootlist.ndir, s, dp);
  131. default:
  132. if(s == DEVDOTDOT){
  133. if((int)c->qid.path < Qboot)
  134. devdir(c, (Qid){Qdir, 0, QTDIR}, "#/", 0, eve, 0555, dp);
  135. else
  136. devdir(c, (Qid){Qboot, 0, QTDIR}, "#/", 0, eve, 0555, dp);
  137. return 1;
  138. }
  139. if(s != 0)
  140. return -1;
  141. if((int)c->qid.path < Qboot){
  142. t = c->qid.path-1;
  143. l = &rootlist;
  144. }else{
  145. t = c->qid.path - Qboot - 1;
  146. l = &bootlist;
  147. }
  148. if(t >= l->ndir)
  149. return -1;
  150. if(t < 0){
  151. print("rootgen %#llux %d %d\n", c->qid.path, s, t);
  152. panic("whoops");
  153. }
  154. d = &l->dir[t];
  155. devdir(c, d->qid, d->name, d->length, eve, d->perm, dp);
  156. return 1;
  157. }
  158. }
  159. static Walkqid*
  160. rootwalk(Chan *c, Chan *nc, char **name, int nname)
  161. {
  162. return devwalk(c, nc, name, nname, nil, 0, rootgen);
  163. }
  164. static int32_t
  165. rootstat(Chan *c, uint8_t *dp, int32_t n)
  166. {
  167. return devstat(c, dp, n, nil, 0, rootgen);
  168. }
  169. static Chan*
  170. rootopen(Chan *c, int omode)
  171. {
  172. return devopen(c, omode, nil, 0, devgen);
  173. }
  174. /*
  175. * sysremove() knows this is a nop
  176. */
  177. static void
  178. rootclose(Chan*)
  179. {
  180. }
  181. static int32_t
  182. rootread(Chan *c, void *buf, int32_t n, int64_t off)
  183. {
  184. uint32_t t;
  185. Dirtab *d;
  186. Dirlist *l;
  187. uint8_t *data;
  188. uint32_t offset = off;
  189. t = c->qid.path;
  190. switch(t){
  191. case Qdir:
  192. case Qboot:
  193. return devdirread(c, buf, n, nil, 0, rootgen);
  194. }
  195. if(t<Qboot)
  196. l = &rootlist;
  197. else{
  198. t -= Qboot;
  199. l = &bootlist;
  200. }
  201. t--;
  202. if(t >= l->ndir)
  203. error(Egreg);
  204. d = &l->dir[t];
  205. data = l->data[t];
  206. if(offset >= d->length)
  207. return 0;
  208. if(offset+n > d->length)
  209. n = d->length - offset;
  210. memmove(buf, data+offset, n);
  211. return n;
  212. }
  213. static int32_t
  214. rootwrite(Chan*, void*, int32_t, int64_t)
  215. {
  216. error(Egreg);
  217. return 0;
  218. }
  219. Dev rootdevtab = {
  220. '/',
  221. "root",
  222. rootreset,
  223. devinit,
  224. devshutdown,
  225. rootattach,
  226. rootwalk,
  227. rootstat,
  228. rootopen,
  229. devcreate,
  230. rootclose,
  231. rootread,
  232. devbread,
  233. rootwrite,
  234. devbwrite,
  235. devremove,
  236. devwstat,
  237. };