devsrv.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  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. typedef struct Srv Srv;
  8. struct Srv
  9. {
  10. char *name;
  11. char *owner;
  12. ulong perm;
  13. Chan *chan;
  14. Srv *link;
  15. ulong path;
  16. };
  17. static QLock srvlk;
  18. static Srv *srv;
  19. static int qidpath;
  20. static int
  21. srvgen(Chan *c, char*, Dirtab*, int, int s, Dir *dp)
  22. {
  23. Srv *sp;
  24. Qid q;
  25. if(s == DEVDOTDOT){
  26. devdir(c, c->qid, "#s", 0, eve, 0555, dp);
  27. return 1;
  28. }
  29. qlock(&srvlk);
  30. for(sp = srv; sp && s; sp = sp->link)
  31. s--;
  32. if(sp == 0) {
  33. qunlock(&srvlk);
  34. return -1;
  35. }
  36. mkqid(&q, sp->path, 0, QTFILE);
  37. /* make sure name string continues to exist after we release lock */
  38. kstrcpy(up->genbuf, sp->name, sizeof up->genbuf);
  39. devdir(c, q, up->genbuf, 0, sp->owner, sp->perm, dp);
  40. qunlock(&srvlk);
  41. return 1;
  42. }
  43. static void
  44. srvinit(void)
  45. {
  46. qidpath = 1;
  47. }
  48. static Chan*
  49. srvattach(char *spec)
  50. {
  51. return devattach('s', spec);
  52. }
  53. static Walkqid*
  54. srvwalk(Chan *c, Chan *nc, char **name, int nname)
  55. {
  56. return devwalk(c, nc, name, nname, 0, 0, srvgen);
  57. }
  58. static Srv*
  59. srvlookup(char *name, ulong qidpath)
  60. {
  61. Srv *sp;
  62. for(sp = srv; sp; sp = sp->link)
  63. if(sp->path == qidpath || (name && strcmp(sp->name, name) == 0))
  64. return sp;
  65. return nil;
  66. }
  67. static int
  68. srvstat(Chan *c, uchar *db, int n)
  69. {
  70. return devstat(c, db, n, 0, 0, srvgen);
  71. }
  72. char*
  73. srvname(Chan *c)
  74. {
  75. Srv *sp;
  76. char *s;
  77. for(sp = srv; sp; sp = sp->link)
  78. if(sp->chan == c){
  79. s = smalloc(3+strlen(sp->name)+1);
  80. sprint(s, "#s/%s", sp->name);
  81. return s;
  82. }
  83. return nil;
  84. }
  85. static Chan*
  86. srvopen(Chan *c, int omode)
  87. {
  88. Srv *sp;
  89. if(c->qid.type == QTDIR){
  90. if(omode & ORCLOSE)
  91. error(Eperm);
  92. if(omode != OREAD)
  93. error(Eisdir);
  94. c->mode = omode;
  95. c->flag |= COPEN;
  96. c->offset = 0;
  97. return c;
  98. }
  99. qlock(&srvlk);
  100. if(waserror()){
  101. qunlock(&srvlk);
  102. nexterror();
  103. }
  104. sp = srvlookup(nil, c->qid.path);
  105. if(sp == 0 || sp->chan == 0)
  106. error(Eshutdown);
  107. if(omode&OTRUNC)
  108. error("srv file already exists");
  109. if(openmode(omode)!=sp->chan->mode && sp->chan->mode!=ORDWR)
  110. error(Eperm);
  111. devpermcheck(sp->owner, sp->perm, omode);
  112. cclose(c);
  113. incref(sp->chan);
  114. qunlock(&srvlk);
  115. poperror();
  116. return sp->chan;
  117. }
  118. static void
  119. srvcreate(Chan *c, char *name, int omode, ulong perm)
  120. {
  121. char *sname;
  122. Srv *sp;
  123. if(openmode(omode) != OWRITE)
  124. error(Eperm);
  125. if(omode & OCEXEC) /* can't happen */
  126. panic("someone broke namec");
  127. sp = smalloc(sizeof *sp);
  128. sname = smalloc(strlen(name)+1);
  129. if(sp == nil || sname == nil) {
  130. free(sp);
  131. free(sname);
  132. error(Enomem);
  133. }
  134. qlock(&srvlk);
  135. if(waserror()){
  136. free(sp);
  137. qunlock(&srvlk);
  138. nexterror();
  139. }
  140. if(srvlookup(name, -1))
  141. error(Eexist);
  142. sp->path = qidpath++;
  143. sp->link = srv;
  144. strcpy(sname, name);
  145. sp->name = sname;
  146. c->qid.type = QTFILE;
  147. c->qid.path = sp->path;
  148. srv = sp;
  149. qunlock(&srvlk);
  150. poperror();
  151. kstrdup(&sp->owner, up->user);
  152. sp->perm = perm&0777;
  153. c->flag |= COPEN;
  154. c->mode = OWRITE;
  155. }
  156. static void
  157. srvremove(Chan *c)
  158. {
  159. Srv *sp, **l;
  160. if(c->qid.type == QTDIR)
  161. error(Eperm);
  162. qlock(&srvlk);
  163. if(waserror()){
  164. qunlock(&srvlk);
  165. nexterror();
  166. }
  167. l = &srv;
  168. for(sp = *l; sp; sp = sp->link) {
  169. if(sp->path == c->qid.path)
  170. break;
  171. l = &sp->link;
  172. }
  173. if(sp == 0)
  174. error(Enonexist);
  175. /*
  176. * Only eve can remove system services.
  177. * No one can remove #s/boot.
  178. */
  179. if(strcmp(sp->owner, eve) == 0 && !iseve())
  180. error(Eperm);
  181. if(strcmp(sp->name, "boot") == 0)
  182. error(Eperm);
  183. /*
  184. * No removing personal services.
  185. */
  186. if((sp->perm&7) != 7 && strcmp(sp->owner, up->user) && !iseve())
  187. error(Eperm);
  188. *l = sp->link;
  189. qunlock(&srvlk);
  190. poperror();
  191. if(sp->chan)
  192. cclose(sp->chan);
  193. free(sp->name);
  194. free(sp);
  195. }
  196. static int
  197. srvwstat(Chan *c, uchar *dp, int n)
  198. {
  199. char *strs;
  200. Dir d;
  201. Srv *sp;
  202. if(c->qid.type & QTDIR)
  203. error(Eperm);
  204. strs = nil;
  205. qlock(&srvlk);
  206. if(waserror()){
  207. qunlock(&srvlk);
  208. free(strs);
  209. nexterror();
  210. }
  211. sp = srvlookup(nil, c->qid.path);
  212. if(sp == 0)
  213. error(Enonexist);
  214. if(strcmp(sp->owner, up->user) != 0 && !iseve())
  215. error(Eperm);
  216. strs = smalloc(n);
  217. n = convM2D(dp, n, &d, strs);
  218. if(n == 0)
  219. error(Eshortstat);
  220. if(d.mode != ~0UL)
  221. sp->perm = d.mode & 0777;
  222. if(d.uid && *d.uid)
  223. kstrdup(&sp->owner, d.uid);
  224. if(d.name && *d.name && strcmp(sp->name, d.name) != 0) {
  225. if(strchr(d.name, '/') != nil)
  226. error(Ebadchar);
  227. kstrdup(&sp->name, d.name);
  228. }
  229. qunlock(&srvlk);
  230. free(strs);
  231. poperror();
  232. return n;
  233. }
  234. static void
  235. srvclose(Chan *c)
  236. {
  237. /*
  238. * in theory we need to override any changes in removability
  239. * since open, but since all that's checked is the owner,
  240. * which is immutable, all is well.
  241. */
  242. if(c->flag & CRCLOSE){
  243. if(waserror())
  244. return;
  245. srvremove(c);
  246. poperror();
  247. }
  248. }
  249. static long
  250. srvread(Chan *c, void *va, long n, vlong)
  251. {
  252. isdir(c);
  253. return devdirread(c, va, n, 0, 0, srvgen);
  254. }
  255. static long
  256. srvwrite(Chan *c, void *va, long n, vlong)
  257. {
  258. Srv *sp;
  259. Chan *c1;
  260. int fd;
  261. char buf[32];
  262. if(n >= sizeof buf)
  263. error(Egreg);
  264. memmove(buf, va, n); /* so we can NUL-terminate */
  265. buf[n] = 0;
  266. fd = strtoul(buf, 0, 0);
  267. c1 = fdtochan(fd, -1, 0, 1); /* error check and inc ref */
  268. qlock(&srvlk);
  269. if(waserror()) {
  270. qunlock(&srvlk);
  271. cclose(c1);
  272. nexterror();
  273. }
  274. if(c1->flag & (CCEXEC|CRCLOSE))
  275. error("posted fd has remove-on-close or close-on-exec");
  276. if(c1->qid.type & QTAUTH)
  277. error("cannot post auth file in srv");
  278. sp = srvlookup(nil, c->qid.path);
  279. if(sp == 0)
  280. error(Enonexist);
  281. if(sp->chan)
  282. error(Ebadusefd);
  283. sp->chan = c1;
  284. qunlock(&srvlk);
  285. poperror();
  286. return n;
  287. }
  288. Dev srvdevtab = {
  289. 's',
  290. "srv",
  291. devreset,
  292. srvinit,
  293. devshutdown,
  294. srvattach,
  295. srvwalk,
  296. srvstat,
  297. srvopen,
  298. srvcreate,
  299. srvclose,
  300. srvread,
  301. devbread,
  302. srvwrite,
  303. devbwrite,
  304. srvremove,
  305. srvwstat,
  306. };