devroot.c 3.5 KB

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