devroot.c 4.5 KB

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