devramfs.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301
  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. struct RamFile {
  16. char name[KNAMELEN];
  17. struct RamFile *parent;
  18. struct RamFile *sibling;
  19. uint64_t length;
  20. int perm;
  21. int opencount;
  22. int deleteonclose;
  23. union {
  24. uint8_t *data; // List of children if directory
  25. struct RamFile* firstchild;
  26. };
  27. };
  28. static struct RamFile *ramroot;
  29. static QLock ramlock;
  30. static void
  31. raminit(void)
  32. {
  33. ramroot = (struct RamFile *)smalloc(sizeof(struct RamFile));
  34. strcpy(ramroot->name, ".");
  35. ramroot->length = 0;
  36. ramroot->perm = DMDIR|0777;
  37. ramroot->firstchild = nil;
  38. }
  39. static void
  40. ramreset(void)
  41. {
  42. }
  43. static Chan*
  44. ramattach(char *spec)
  45. {
  46. Chan *c;
  47. char *buf;
  48. c = newchan();
  49. mkqid(&c->qid, (int64_t)ramroot, 0, QTDIR);
  50. c->dev = devtabget('@', 0);
  51. if(spec == nil)
  52. spec = "";
  53. buf = smalloc(1+UTFmax+strlen(spec)+1);
  54. sprint(buf, "#@%s", spec);
  55. c->path = newpath(buf);
  56. c->mode = 0777;
  57. free(buf);
  58. return c;
  59. }
  60. static int
  61. ramgen(Chan *c, char *name, Dirtab *tab, int ntab, int pos, Dir *dp)
  62. {
  63. Qid qid;
  64. int i;
  65. struct RamFile *current = (struct RamFile *)c->qid.path;
  66. if(pos == DEVDOTDOT){
  67. if(current->parent == nil){
  68. mkqid(&qid, (uintptr_t)current, 0, QTDIR);
  69. devdir(c, qid, "#@", 0, "harvey", 0555, dp);
  70. return 1;
  71. } else {
  72. mkqid(&qid, (uintptr_t)current->parent, 0, QTDIR);
  73. devdir(c, qid, current->name, 0, "harvey", 0555, dp);
  74. return 1;
  75. }
  76. }
  77. if(current->perm & QTDIR){
  78. current = current->firstchild;
  79. if(current == nil){
  80. return -1;
  81. }
  82. }
  83. for(i = 0; i < pos; i++){
  84. current = current->sibling;
  85. if (current == nil){
  86. return -1;
  87. }
  88. }
  89. mkqid(&qid, (uintptr_t)current, 0, current->perm & DMDIR ? QTDIR : 0);
  90. devdir(c, qid, current->name, current->length, "harvey", current->perm, dp);
  91. if(name == nil || strcmp(current->name, name) == 0){
  92. return 1;
  93. } else {
  94. return 0;
  95. }
  96. }
  97. static Walkqid*
  98. ramwalk(Chan *c, Chan *nc, char **name, int nname)
  99. {
  100. Proc *up = externup();
  101. qlock(&ramlock);
  102. if(waserror()){
  103. qunlock(&ramlock);
  104. nexterror();
  105. }
  106. Walkqid* wqid = devwalk(c, nc, name, nname, 0, 0, ramgen);
  107. qunlock(&ramlock);
  108. poperror();
  109. return wqid;
  110. }
  111. static int32_t
  112. ramstat(Chan *c, uint8_t *dp, int32_t n)
  113. {
  114. Dir dir;
  115. Qid qid;
  116. struct RamFile* current = (struct RamFile*)c->qid.path;
  117. qlock(&ramlock);
  118. mkqid(&qid, c->qid.path, 0, current->perm & DMDIR ? QTDIR : 0);
  119. devdir(c, qid, current->name, 0, "harvey", 0555, &dir);
  120. int32_t ret = convD2M(&dir, dp, n);
  121. qunlock(&ramlock);
  122. return ret;
  123. }
  124. static Chan*
  125. ramopen(Chan *c, int omode)
  126. {
  127. Proc *up = externup();
  128. qlock(&ramlock);
  129. if(waserror()){
  130. qunlock(&ramlock);
  131. nexterror();
  132. }
  133. Chan* ret = devopen(c, omode, nil, 0, ramgen);
  134. qunlock(&ramlock);
  135. poperror();
  136. return ret;
  137. }
  138. static void
  139. delete(struct RamFile* file)
  140. {
  141. qlock(&ramlock);
  142. struct RamFile* prev = file->parent->firstchild;
  143. if(prev == file) {
  144. file->parent->firstchild = file->sibling;
  145. } else {
  146. // Find previous file
  147. for(; prev != nil && prev->sibling != file; prev = prev->sibling)
  148. ;
  149. if(prev == nil){
  150. qunlock(&ramlock);
  151. error(Eperm);
  152. } else {
  153. prev->sibling = file->sibling;
  154. }
  155. }
  156. if(file->perm & DMDIR){
  157. free(file->data);
  158. }
  159. free(file);
  160. qunlock(&ramlock);
  161. }
  162. static void
  163. ramclose(Chan* c)
  164. {
  165. struct RamFile* file = (struct RamFile *)c->qid.path;
  166. if(file->deleteonclose){
  167. delete(file);
  168. }
  169. }
  170. static int32_t
  171. ramread(Chan *c, void *buf, int32_t n, int64_t off)
  172. {
  173. qlock(&ramlock);
  174. if (c->qid.type == QTDIR){
  175. int32_t len = devdirread(c, buf, n, nil, 0, ramgen);
  176. qunlock(&ramlock);
  177. return len;
  178. }
  179. // Read file
  180. struct RamFile *file = (void*)c->qid.path;
  181. int filelen = file->length;
  182. if (off > filelen){
  183. qunlock(&ramlock);
  184. return 0;
  185. }
  186. if (off + n > filelen){
  187. n = filelen - off;
  188. }
  189. memcpy(buf, file->data, n);
  190. qunlock(&ramlock);
  191. return n;
  192. }
  193. static int32_t
  194. ramwrite(Chan* c, void* v, int32_t n, int64_t off)
  195. {
  196. qlock(&ramlock);
  197. struct RamFile *file = (void*)c->qid.path;
  198. if(n+off > file->length){
  199. void *newfile = realloc(file->data, n+off);
  200. if(newfile == nil){
  201. return 0;
  202. }
  203. file->data = newfile;
  204. file->length = n+off;
  205. }
  206. memcpy(file->data + off, v, n);
  207. qunlock(&ramlock);
  208. return n;
  209. }
  210. void
  211. ramcreate(Chan* c, char *name, int omode, int perm)
  212. {
  213. Proc *up = externup();
  214. if(c->qid.type != QTDIR)
  215. error(Eperm);
  216. struct RamFile* parent = (struct RamFile *)c->qid.path;
  217. omode = openmode(omode);
  218. struct RamFile* file = (struct RamFile*)smalloc(sizeof(struct RamFile));
  219. file->length = 0;
  220. strcpy(file->name, name);
  221. file->perm = perm;
  222. file->parent = parent;
  223. qlock(&ramlock);
  224. if(waserror()) {
  225. free(file->data);
  226. free(file);
  227. qunlock(&ramlock);
  228. nexterror();
  229. }
  230. file->sibling = parent->firstchild;
  231. parent->firstchild = file;
  232. qunlock(&ramlock);
  233. mkqid(&c->qid, (uintptr_t)file, 0, file->perm & DMDIR ? QTDIR : 0);
  234. poperror();
  235. c->offset = 0;
  236. c->mode = omode;
  237. c->flag |= COPEN;
  238. }
  239. void
  240. ramshutdown(void)
  241. {
  242. }
  243. void
  244. ramremove(Chan* c)
  245. {
  246. struct RamFile* doomed = (struct RamFile *)c->qid.path;
  247. if(doomed->opencount == 0){
  248. delete(doomed);
  249. }
  250. doomed->deleteonclose =1;
  251. }
  252. Dev ramdevtab = {
  253. .dc = '@',
  254. .name = "ram",
  255. .reset = ramreset,
  256. .init = raminit,
  257. .shutdown = ramshutdown,
  258. .attach = ramattach,
  259. .walk = ramwalk,
  260. .stat = ramstat,
  261. .open = ramopen,
  262. .create = ramcreate,
  263. .close = ramclose,
  264. .read = ramread,
  265. .bread = devbread,
  266. .write = ramwrite,
  267. .bwrite = devbwrite,
  268. .remove = ramremove,
  269. .wstat = devwstat,
  270. };