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 8 #include "devtab.h" 9 10 typedef struct Srv Srv; 11 struct Srv 12 { 13 char name[NAMELEN]; 14 char owner[NAMELEN]; 15 ulong perm; 16 Chan *chan; 17 Srv *link; 18 ulong path; 19 }; 20 21 static QLock srvlk; 22 static Srv *srv; 23 static int path; 24 25 int 26 srvgen(Chan *c, Dirtab *tab, int ntab, int s, Dir *dp) 27 { 28 Srv *sp; 29 30 USED(tab); 31 USED(ntab); 32 qlock(&srvlk); 33 for(sp = srv; sp && s; sp = sp->link) 34 s--; 35 36 if(sp == 0) { 37 qunlock(&srvlk); 38 return -1; 39 } 40 devdir(c, (Qid){sp->path, 0}, sp->name, 0, sp->owner, sp->perm, dp); 41 qunlock(&srvlk); 42 return 1; 43 } 44 45 void 46 srvinit(void) 47 { 48 path = 1; 49 } 50 51 void 52 srvreset(void) 53 { 54 } 55 56 Chan* 57 srvattach(char *spec) 58 { 59 return devattach('s', spec); 60 } 61 62 Chan* 63 srvclone(Chan *c, Chan *nc) 64 { 65 return devclone(c, nc); 66 } 67 68 int 69 srvwalk(Chan *c, char *name) 70 { 71 return devwalk(c, name, 0, 0, srvgen); 72 } 73 74 void 75 srvstat(Chan *c, char *db) 76 { 77 devstat(c, db, 0, 0, srvgen); 78 } 79 80 Chan* 81 srvopen(Chan *c, int omode) 82 { 83 Srv *sp; 84 85 if(c->qid.path == CHDIR){ 86 if(omode != OREAD) 87 error(Eisdir); 88 c->mode = omode; 89 c->flag |= COPEN; 90 c->offset = 0; 91 return c; 92 } 93 qlock(&srvlk); 94 if(waserror()){ 95 qunlock(&srvlk); 96 nexterror(); 97 } 98 99 for(sp = srv; sp; sp = sp->link) 100 if(sp->path == c->qid.path) 101 break; 102 103 if(sp == 0 || sp->chan == 0) 104 error(Eshutdown); 105 106 if(omode&OTRUNC) 107 error(Eperm); 108 if(omode!=sp->chan->mode && sp->chan->mode!=ORDWR) 109 error(Eperm); 110 111 close(c); 112 incref(sp->chan); 113 qunlock(&srvlk); 114 poperror(); 115 return sp->chan; 116 } 117 118 void 119 srvcreate(Chan *c, char *name, int omode, ulong perm) 120 { 121 Srv *sp; 122 123 if(omode != OWRITE) 124 error(Eperm); 125 126 sp = malloc(sizeof(Srv)); 127 if(sp == 0) 128 error(Enomem); 129 130 qlock(&srvlk); 131 if(waserror()){ 132 qunlock(&srvlk); 133 nexterror(); 134 } 135 sp->path = path++; 136 sp->link = srv; 137 c->qid.path = sp->path; 138 srv = sp; 139 qunlock(&srvlk); 140 poperror(); 141 142 strncpy(sp->name, name, NAMELEN); 143 strncpy(sp->owner, u->p->user, NAMELEN); 144 sp->perm = perm&0777; 145 146 c->flag |= COPEN; 147 c->mode = OWRITE; 148 } 149 150 void 151 srvremove(Chan *c) 152 { 153 Srv *sp, **l; 154 155 if(c->qid.path == CHDIR) 156 error(Eperm); 157 158 qlock(&srvlk); 159 if(waserror()){ 160 qunlock(&srvlk); 161 nexterror(); 162 } 163 l = &srv; 164 for(sp = *l; sp; sp = sp->link) { 165 if(sp->path == c->qid.path) 166 break; 167 168 l = &sp->link; 169 } 170 if(sp == 0) 171 error(Enonexist); 172 173 if(strcmp(sp->name, "boot") == 0) 174 error(Eperm); 175 176 *l = sp->link; 177 qunlock(&srvlk); 178 poperror(); 179 180 if(sp->chan) 181 close(sp->chan); 182 free(sp); 183 } 184 185 void 186 srvwstat(Chan *c, char *dp) 187 { 188 USED(c, dp); 189 error(Egreg); 190 } 191 192 void 193 srvclose(Chan *c) 194 { 195 USED(c); 196 } 197 198 long 199 srvread(Chan *c, void *va, long n, ulong offset) 200 { 201 USED(offset); 202 isdir(c); 203 return devdirread(c, va, n, 0, 0, srvgen); 204 } 205 206 long 207 srvwrite(Chan *c, void *va, long n, ulong offset) 208 { 209 Srv *sp; 210 Chan *c1; 211 int fd; 212 char buf[32]; 213 214 USED(offset); 215 if(n >= sizeof buf) 216 error(Egreg); 217 memmove(buf, va, n); /* so we can NUL-terminate */ 218 buf[n] = 0; 219 fd = strtoul(buf, 0, 0); 220 221 c1 = fdtochan(fd, -1, 0, 1); /* error check only */ 222 223 qlock(&srvlk); 224 if(waserror()) { 225 qunlock(&srvlk); 226 close(c1); 227 nexterror(); 228 } 229 for(sp = srv; sp; sp = sp->link) 230 if(sp->path == c->qid.path) 231 break; 232 233 if(sp == 0) 234 error(Enonexist); 235 236 if(sp->chan) 237 panic("srvwrite"); 238 239 sp->chan = c1; 240 qunlock(&srvlk); 241 poperror(); 242 return n; 243 } 244