devsrv.c 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356
  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. qlock(&srvlk);
  130. if(waserror()){
  131. free(sp);
  132. free(sname);
  133. qunlock(&srvlk);
  134. nexterror();
  135. }
  136. if(sp == nil || sname == nil)
  137. error(Enomem);
  138. if(srvlookup(name, -1))
  139. error(Eexist);
  140. sp->path = qidpath++;
  141. sp->link = srv;
  142. strcpy(sname, name);
  143. sp->name = sname;
  144. c->qid.type = QTFILE;
  145. c->qid.path = sp->path;
  146. srv = sp;
  147. qunlock(&srvlk);
  148. poperror();
  149. kstrdup(&sp->owner, up->user);
  150. sp->perm = perm&0777;
  151. c->flag |= COPEN;
  152. c->mode = OWRITE;
  153. }
  154. static void
  155. srvremove(Chan *c)
  156. {
  157. Srv *sp, **l;
  158. if(c->qid.type == QTDIR)
  159. error(Eperm);
  160. qlock(&srvlk);
  161. if(waserror()){
  162. qunlock(&srvlk);
  163. nexterror();
  164. }
  165. l = &srv;
  166. for(sp = *l; sp; sp = sp->link) {
  167. if(sp->path == c->qid.path)
  168. break;
  169. l = &sp->link;
  170. }
  171. if(sp == 0)
  172. error(Enonexist);
  173. /*
  174. * Only eve can remove system services.
  175. * No one can remove #s/boot.
  176. */
  177. if(strcmp(sp->owner, eve) == 0 && !iseve())
  178. error(Eperm);
  179. if(strcmp(sp->name, "boot") == 0)
  180. error(Eperm);
  181. /*
  182. * No removing personal services.
  183. */
  184. if((sp->perm&7) != 7 && strcmp(sp->owner, up->user) && !iseve())
  185. error(Eperm);
  186. *l = sp->link;
  187. qunlock(&srvlk);
  188. poperror();
  189. if(sp->chan)
  190. cclose(sp->chan);
  191. free(sp->name);
  192. free(sp);
  193. }
  194. static int
  195. srvwstat(Chan *c, uchar *dp, int n)
  196. {
  197. char *strs;
  198. Dir d;
  199. Srv *sp;
  200. if(c->qid.type & QTDIR)
  201. error(Eperm);
  202. strs = nil;
  203. qlock(&srvlk);
  204. if(waserror()){
  205. qunlock(&srvlk);
  206. free(strs);
  207. nexterror();
  208. }
  209. sp = srvlookup(nil, c->qid.path);
  210. if(sp == 0)
  211. error(Enonexist);
  212. if(strcmp(sp->owner, up->user) != 0 && !iseve())
  213. error(Eperm);
  214. strs = smalloc(n);
  215. n = convM2D(dp, n, &d, strs);
  216. if(n == 0)
  217. error(Eshortstat);
  218. if(d.mode != ~0UL)
  219. sp->perm = d.mode & 0777;
  220. if(d.uid && *d.uid)
  221. kstrdup(&sp->owner, d.uid);
  222. if(d.name && *d.name && strcmp(sp->name, d.name) != 0) {
  223. if(strchr(d.name, '/') != nil)
  224. error(Ebadchar);
  225. kstrdup(&sp->name, d.name);
  226. }
  227. qunlock(&srvlk);
  228. free(strs);
  229. poperror();
  230. return n;
  231. }
  232. static void
  233. srvclose(Chan *c)
  234. {
  235. /*
  236. * in theory we need to override any changes in removability
  237. * since open, but since all that's checked is the owner,
  238. * which is immutable, all is well.
  239. */
  240. if(c->flag & CRCLOSE){
  241. if(waserror())
  242. return;
  243. srvremove(c);
  244. poperror();
  245. }
  246. }
  247. static long
  248. srvread(Chan *c, void *va, long n, vlong)
  249. {
  250. isdir(c);
  251. return devdirread(c, va, n, 0, 0, srvgen);
  252. }
  253. static long
  254. srvwrite(Chan *c, void *va, long n, vlong)
  255. {
  256. Srv *sp;
  257. Chan *c1;
  258. int fd;
  259. char buf[32];
  260. if(n >= sizeof buf)
  261. error(Egreg);
  262. memmove(buf, va, n); /* so we can NUL-terminate */
  263. buf[n] = 0;
  264. fd = strtoul(buf, 0, 0);
  265. c1 = fdtochan(fd, -1, 0, 1); /* error check and inc ref */
  266. qlock(&srvlk);
  267. if(waserror()) {
  268. qunlock(&srvlk);
  269. cclose(c1);
  270. nexterror();
  271. }
  272. if(c1->flag & (CCEXEC|CRCLOSE))
  273. error("posted fd has remove-on-close or close-on-exec");
  274. if(c1->qid.type & QTAUTH)
  275. error("cannot post auth file in srv");
  276. sp = srvlookup(nil, c->qid.path);
  277. if(sp == 0)
  278. error(Enonexist);
  279. if(sp->chan)
  280. error(Ebadusefd);
  281. sp->chan = c1;
  282. qunlock(&srvlk);
  283. poperror();
  284. return n;
  285. }
  286. Dev srvdevtab = {
  287. 's',
  288. "srv",
  289. devreset,
  290. srvinit,
  291. devshutdown,
  292. srvattach,
  293. srvwalk,
  294. srvstat,
  295. srvopen,
  296. srvcreate,
  297. srvclose,
  298. srvread,
  299. devbread,
  300. srvwrite,
  301. devbwrite,
  302. srvremove,
  303. srvwstat,
  304. };