├── mkfile ├── README ├── asmbackdoor.s ├── isvmware.c ├── backdoor.c ├── vmmousepoll.c ├── all.h ├── inout.c ├── msgchan.c └── fs.c /mkfile: -------------------------------------------------------------------------------- 1 | pc; 14 | /* ED is INL and EF is OUTL */ 15 | if((*p==0xED || *p==0xEF) && strstr(msg, "sys: trap: general protection violation")){ 16 | u->pc++; /* hop over INL/OUTL */ 17 | doorerror = 1; 18 | return 1; 19 | } 20 | return 0; 21 | } 22 | 23 | void 24 | backdoor(Ureg *u, int isout) 25 | { 26 | u->ax = BackMagic; 27 | u->dx &= ~0xFFFF; 28 | u->dx |= BackPort; 29 | u->di = isout; 30 | doorerror = 0; 31 | asmbackdoor(u); 32 | if(doorerror) 33 | longjmp(backdoorjmp, 1); 34 | } 35 | -------------------------------------------------------------------------------- /vmmousepoll.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void 5 | usage(void) 6 | { 7 | fprint(2, "usage: aux/vmmousepoll [/mnt/vmware/mouse]\n"); 8 | exits("usage"); 9 | } 10 | 11 | void 12 | main(int argc, char **argv) 13 | { 14 | int fd; 15 | char *file; 16 | char buf[50]; 17 | 18 | quotefmtinstall(); 19 | ARGBEGIN{ 20 | default: 21 | usage(); 22 | }ARGEND 23 | 24 | switch(argc){ 25 | default: 26 | usage(); 27 | case 0: 28 | file = "/mnt/vmware/mouse"; 29 | break; 30 | case 1: 31 | file = argv[0]; 32 | break; 33 | } 34 | 35 | if((fd = open(file, OREAD)) < 0) 36 | sysfatal("open %q: %r", file); 37 | 38 | for(;;){ 39 | sleep(250); 40 | if(pread(fd, buf, sizeof buf, 0) < 0) 41 | break; 42 | } 43 | exits(nil); 44 | } 45 | -------------------------------------------------------------------------------- /all.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | typedef struct Msgchan Msgchan; 7 | typedef struct Ureg Ureg; 8 | 9 | typedef ulong uint32; 10 | typedef int int32; 11 | typedef short int16; 12 | typedef char int8; 13 | typedef uvlong uint64; 14 | typedef vlong int64; 15 | typedef char Bool; 16 | 17 | struct Msgchan 18 | { 19 | ushort id; 20 | uchar *a; 21 | int na; 22 | }; 23 | 24 | enum 25 | { 26 | /* low bits of u.cx */ 27 | BackGetmhz = 1, 28 | BackApm = 2, 29 | BackGetdiskgeo = 3, 30 | BackGetptrloc = 4, 31 | BackSetptrloc = 5, 32 | BackGetsellength = 6, 33 | BackGetnextpiece = 7, 34 | BackSetsellength = 8, 35 | BackSetnextpiece = 9, 36 | BackGetversion = 10, 37 | BackGetdevlistel = 11, 38 | BackToggledev = 12, 39 | BackGetguiopt = 13, 40 | BackSetguiopt = 14, 41 | BackGetscreensize = 15, 42 | BackGetpcisvgaen = 16, 43 | BackSetpcisvgaen = 17, 44 | /* 18-20 not used */ 45 | BackHostcopy = 21, 46 | BackGetos2intcurs = 22, 47 | BackGettime = 23, 48 | BackStopcatchup = 24, 49 | BackPutchr = 25, 50 | BackEnablemsg = 26, 51 | BackGototcl = 27, 52 | BackInitscsiprom = 28, 53 | BackInt13 = 29, 54 | BackMessage = 30, 55 | 56 | BackMagic = 0x564D5868, 57 | VersionMagic = 6, 58 | BackPort = 0x5658, 59 | 60 | }; 61 | 62 | void asmbackdoor(Ureg*); 63 | void backdoor(Ureg*, int); 64 | int backdoorbell(void*, char*); 65 | int closemsg(Msgchan*); 66 | int getdeviceinfo(uint, uint, uint*); 67 | Point getmousepoint(void); 68 | int getsnarflength(void); 69 | uint getsnarfpiece(void); 70 | Msgchan* openmsg(ulong); 71 | int recvmsg(Msgchan*, void**); 72 | int sendmsg(Msgchan*, void*, int); 73 | int setdevicestate(uint, int); 74 | void setmousepoint(Point); 75 | void setsnarflength(uint); 76 | void setsnarfpiece(uint); 77 | int getversion(void); 78 | void setguistate(uint); 79 | uint getguistate(void); 80 | uint copystep(uint); 81 | void gettime(uint*, uint*, uint*); 82 | void stopcatchup(void); 83 | 84 | extern jmp_buf backdoorjmp; 85 | -------------------------------------------------------------------------------- /inout.c: -------------------------------------------------------------------------------- 1 | #include "all.h" 2 | 3 | void 4 | setmousepoint(Point p) 5 | { 6 | Ureg u; 7 | 8 | memset(&u, 0, sizeof u); 9 | u.cx = BackSetptrloc; 10 | u.bx = (p.x<<16) | p.y; 11 | backdoor(&u, 1); 12 | } 13 | 14 | Point 15 | getmousepoint(void) 16 | { 17 | Point p; 18 | Ureg u; 19 | 20 | memset(&u, 0, sizeof u); 21 | u.cx = BackGetptrloc; 22 | backdoor(&u, 0); 23 | p.x = (signed)((u.ax>>16)&0xFFFF); 24 | p.y = (signed)(u.ax & 0xFFFF); 25 | return p; 26 | } 27 | 28 | int 29 | getsnarflength(void) 30 | { 31 | Ureg u; 32 | 33 | memset(&u, 0, sizeof u); 34 | u.cx = BackGetsellength; 35 | backdoor(&u, 0); 36 | return u.ax; 37 | } 38 | 39 | uint 40 | getsnarfpiece(void) 41 | { 42 | Ureg u; 43 | 44 | memset(&u, 0, sizeof u); 45 | u.cx = BackGetnextpiece; 46 | backdoor(&u, 0); 47 | return u.ax; 48 | } 49 | 50 | void 51 | setsnarflength(uint len) 52 | { 53 | Ureg u; 54 | 55 | memset(&u, 0, sizeof u); 56 | u.cx = BackSetsellength; 57 | u.bx = len; 58 | backdoor(&u, 1); 59 | } 60 | 61 | void 62 | setsnarfpiece(uint p) 63 | { 64 | Ureg u; 65 | 66 | memset(&u, 0, sizeof u); 67 | u.cx = BackSetnextpiece; 68 | u.bx = p; 69 | backdoor(&u, 1); 70 | } 71 | 72 | int 73 | getversion(void) 74 | { 75 | Ureg u; 76 | jmp_buf jb; 77 | 78 | memset(&u, 0, sizeof u); 79 | u.cx = BackGetversion; 80 | memmove(jb, backdoorjmp, sizeof jb); 81 | if(setjmp(backdoorjmp)){ 82 | memmove(backdoorjmp, jb, sizeof jb); 83 | return -1; 84 | } 85 | backdoor(&u, 0); 86 | memmove(backdoorjmp, jb, sizeof jb); 87 | if(u.ax != VersionMagic || u.bx != BackMagic) 88 | return -1; 89 | return 0; 90 | } 91 | 92 | int 93 | setdevicestate(uint id, int enable) 94 | { 95 | Ureg u; 96 | 97 | if(enable) 98 | id |= 0x80000000; 99 | memset(&u, 0, sizeof u); 100 | u.cx = BackToggledev; 101 | u.bx = id; 102 | backdoor(&u, 0); 103 | return u.ax; 104 | } 105 | 106 | int 107 | getdeviceinfo(uint id, uint offset, uint *p) 108 | { 109 | Ureg u; 110 | 111 | memset(&u, 0, sizeof u); 112 | u.bx = (id<<16) | offset; 113 | u.cx = BackGetdevlistel; 114 | backdoor(&u, 0); 115 | *p = u.bx; 116 | return u.ax; 117 | } 118 | 119 | void 120 | setguistate(uint state) 121 | { 122 | Ureg u; 123 | 124 | memset(&u, 0, sizeof u); 125 | u.bx = state; 126 | u.cx = BackSetguiopt; 127 | backdoor(&u, 1); 128 | } 129 | 130 | uint 131 | getguistate(void) 132 | { 133 | Ureg u; 134 | 135 | memset(&u, 0, sizeof u); 136 | u.cx = BackGetguiopt; 137 | backdoor(&u, 0); 138 | return u.ax; 139 | } 140 | 141 | uint 142 | copystep(uint x) 143 | { 144 | Ureg u; 145 | 146 | memset(&u, 0, sizeof u); 147 | u.cx = BackHostcopy; 148 | u.bx = x; 149 | backdoor(&u, 0); 150 | return u.ax; 151 | } 152 | 153 | void 154 | gettime(uint *sec, uint *micro, uint *lag) 155 | { 156 | Ureg u; 157 | 158 | memset(&u, 0, sizeof u); 159 | u.cx = BackGettime; 160 | backdoor(&u, 0); 161 | 162 | *sec = u.ax; 163 | *micro = u.bx; 164 | *lag = u.cx; 165 | } 166 | 167 | void 168 | stopcatchup(void) 169 | { 170 | Ureg u; 171 | 172 | memset(&u, 0, sizeof u); 173 | u.cx = BackStopcatchup; 174 | backdoor(&u, 0); 175 | } 176 | -------------------------------------------------------------------------------- /msgchan.c: -------------------------------------------------------------------------------- 1 | #include "all.h" 2 | #include 3 | #include 4 | #include <9p.h> /* for emalloc9p */ 5 | 6 | enum 7 | { 8 | /* high bits of u.cx */ 9 | CmdOpen = 0x00, 10 | CmdSendsize = 0x01, 11 | CmdSenddata = 0x02, 12 | CmdRecvsize = 0x03, 13 | CmdRecvdata = 0x04, 14 | CmdRecvstatus = 0x05, 15 | CmdClose = 0x06, 16 | 17 | StatSuccess = 0x0001, /* request succeeded */ 18 | StatHavedata = 0x0002, /* vmware has message available */ 19 | StatClosed = 0x0004, /* channel got closed */ 20 | StatUnsent = 0x0008, /* vmware removed message before it got delivered */ 21 | StatChkpt = 0x0010, /* checkpoint occurred */ 22 | StatPoweroff = 0x0020, /* underlying device is powering off */ 23 | }; 24 | 25 | 26 | Msgchan* 27 | openmsg(ulong proto) 28 | { 29 | Msgchan *c; 30 | Ureg u; 31 | 32 | memset(&u, 0, sizeof u); 33 | u.cx = (CmdOpen<<16) | BackMessage; 34 | u.bx = proto; 35 | 36 | backdoor(&u, 0); 37 | 38 | fprint(2, "msgopen %.8lux\n", u.cx); 39 | if(!(u.cx & (StatSuccess<<16))){ 40 | fprint(2, "message %.8lux\n", u.cx); 41 | werrstr("unable to open message channel (%.8lux)", u.cx); 42 | return nil; 43 | } 44 | 45 | c = emalloc9p(sizeof(*c)); 46 | c->id = u.dx>>16; 47 | return c; 48 | } 49 | 50 | enum 51 | { 52 | Ok = 0, 53 | ErrBad = -1, 54 | ErrChkpt = -2, 55 | }; 56 | 57 | static int 58 | sendpiece(Msgchan *c, int ty, ulong a) 59 | { 60 | Ureg u; 61 | 62 | memset(&u, 0, sizeof u); 63 | u.cx = (ty<<16) | BackMessage; 64 | u.dx = c->id<<16; 65 | u.bx = a; 66 | 67 | backdoor(&u, 0); 68 | 69 | if(!(u.cx & (StatSuccess<<16))){ 70 | fprint(2, "cmd %x failed\n", ty); 71 | if(u.cx & (StatChkpt<<16)) 72 | return ErrChkpt; 73 | return ErrBad; 74 | } 75 | return 0; 76 | } 77 | 78 | int 79 | sendmsg(Msgchan *c, void *a, int n) 80 | { 81 | int i, m, e, left; 82 | uchar *p; 83 | ulong v; 84 | 85 | Again: 86 | v = n; 87 | if(sendpiece(c, CmdSendsize, v) < 0) 88 | return -1; 89 | 90 | p = a; 91 | left = n; 92 | while(left > 0){ 93 | m = left; 94 | if(m > 4) 95 | m = 4; 96 | v = 0; 97 | for(i=0; iid, ty); 115 | memset(&u, 0, sizeof u); 116 | u.cx = (ty<<16) | BackMessage; 117 | u.bx = StatSuccess; 118 | u.dx = c->id<<16; 119 | 120 | backdoor(&u, 0); 121 | 122 | if(!(u.cx & (StatSuccess<<16))){ 123 | fprint(2, "no success %lux\n", u.cx); 124 | if(u.cx & (StatChkpt<<16)) 125 | return ErrChkpt; 126 | return ErrBad; 127 | } 128 | *stat = u.cx; 129 | if(ty == CmdRecvsize && !(u.cx&(StatHavedata<<16))){ 130 | fprint(2, "poll got no data\n"); 131 | return 0; 132 | } 133 | 134 | if(ty != CmdRecvstatus && (u.dx>>16) != ty-2){ 135 | fprint(2, "got wrong answer! %lux\n", u.dx); 136 | werrstr("protocol error"); 137 | return ErrBad; 138 | } 139 | *a = u.bx; 140 | fprint(2, "got %lux\n", *a); 141 | return 0; 142 | } 143 | 144 | static void 145 | signalerror(Msgchan *c, int ty) 146 | { 147 | Ureg u; 148 | 149 | memset(&u, 0, sizeof u); 150 | u.cx = (ty<<16) | BackMessage; 151 | u.dx = c->id<<16; 152 | u.bx = 0; 153 | backdoor(&u, 0); 154 | } 155 | 156 | int 157 | recvmsg(Msgchan *c, void **pp) 158 | { 159 | int left; 160 | ulong v, stat, tot; 161 | uchar *p; 162 | 163 | Top: 164 | if(recvpiece(c, CmdRecvsize, &stat, &tot) < 0) 165 | return -1; 166 | 167 | if(!(stat & (StatHavedata<<16))) 168 | return 0; 169 | 170 | free(c->a); 171 | c->a = emalloc9p(tot+5); 172 | c->na = tot; 173 | p = c->a; /* NUL terminate for callers */ 174 | 175 | left = tot; 176 | while(left > 0){ 177 | switch(recvpiece(c, CmdRecvdata, &stat, &v)){ 178 | case ErrChkpt: 179 | goto Top; 180 | case ErrBad: 181 | signalerror(c, CmdRecvdata); 182 | return -1; 183 | } 184 | *(uint*)p = v; 185 | p += 4; 186 | left -= 4; 187 | } 188 | ((char*)c->a)[tot] = '\0'; 189 | 190 | switch(recvpiece(c, CmdRecvstatus, &stat, &v)){ 191 | case ErrChkpt: 192 | goto Top; 193 | case ErrBad: 194 | /* BUG: signal receipt of error */ 195 | signalerror(c, CmdRecvstatus); 196 | return -1; 197 | } 198 | 199 | *pp = c->a; 200 | return tot; 201 | } 202 | 203 | int 204 | closemsg(Msgchan *c) 205 | { 206 | Ureg u; 207 | 208 | memset(&u, 0, sizeof u); 209 | 210 | u.cx = (CmdClose<<16) | BackMessage; 211 | u.dx = c->id; 212 | 213 | backdoor(&u, 0); 214 | 215 | if(!(u.cx & (StatSuccess<<16))){ 216 | werrstr("unable to close message channel"); 217 | return -1; 218 | } 219 | 220 | free(c->a); 221 | c->a = nil; 222 | free(c); 223 | return 0; 224 | } 225 | -------------------------------------------------------------------------------- /fs.c: -------------------------------------------------------------------------------- 1 | #include "all.h" 2 | #include 3 | #include 4 | #include <9p.h> 5 | 6 | char *mtpt = "/mnt/vmware"; 7 | char *srvname; 8 | uint time0; 9 | 10 | enum 11 | { 12 | Qroot = 0, 13 | Qmousepoint, 14 | Qsnarf, 15 | Qgui, 16 | Qdev, 17 | Qtime, 18 | Qbintime, 19 | Qmsg, 20 | }; 21 | 22 | typedef struct Tab Tab; 23 | struct Tab 24 | { 25 | int qid; 26 | char *name; 27 | uint perm; 28 | uint vers; 29 | void (*open)(Req*); 30 | void (*read)(Req*); 31 | void (*write)(Req*); 32 | void (*close)(Fid*); 33 | }; 34 | 35 | static void 36 | mousepointread(Req *r) 37 | { 38 | char buf[32]; 39 | Point p; 40 | 41 | p = getmousepoint(); 42 | snprint(buf, sizeof buf, "%11d %11d ", p.x, p.y); 43 | readstr(r, buf); 44 | respond(r, nil); 45 | } 46 | 47 | static void 48 | mousepointwrite(Req *r) 49 | { 50 | char buf[32], *f[3]; 51 | int nf, n; 52 | Point p; 53 | 54 | n = r->ifcall.count; 55 | if(n >= sizeof buf){ 56 | respond(r, "write too large"); 57 | return; 58 | } 59 | memmove(buf, r->ifcall.data, n); 60 | buf[n] = '\0'; 61 | nf = tokenize(buf, f, nelem(f)); 62 | if(nf != 2){ 63 | respond(r, "bad point format"); 64 | return; 65 | } 66 | p.x = atoi(f[0]); 67 | p.y = atoi(f[1]); 68 | setmousepoint(p); 69 | respond(r, nil); 70 | } 71 | 72 | static void 73 | timeread(Req *r) 74 | { 75 | char buf[32]; 76 | uint sec, microsec, lag; 77 | 78 | gettime(&sec, µsec, &lag); 79 | snprint(buf, sizeof buf, "%11d ", sec); 80 | readstr(r, buf); 81 | respond(r, nil); 82 | } 83 | 84 | static uvlong uvorder = 0x0001020304050607ULL; 85 | static uchar* 86 | vlong2le(uchar *t, vlong from) 87 | { 88 | uchar *f, *o; 89 | int i; 90 | 91 | f = (uchar*)&from; 92 | o = (uchar*)&uvorder; 93 | for(i = 0; i < sizeof(vlong); i++) 94 | t[i] = f[o[i]]; 95 | return t+sizeof(vlong); 96 | } 97 | 98 | static void 99 | bintimeread(Req *r) 100 | { 101 | uchar *b; 102 | int i, n; 103 | uint sec, microsec, lag; 104 | vlong nsec; 105 | 106 | b = (uchar*)r->ofcall.data; 107 | n = r->ifcall.count; 108 | 109 | i = 0; 110 | if(n >= 8){ 111 | gettime(&sec, µsec, &lag); 112 | nsec = sec*1000000000LL+microsec*1000LL; 113 | vlong2le(b, nsec); 114 | i = 8; 115 | } 116 | if(n >= 16){ 117 | vlong2le(b+8, nsec); 118 | i = 16; 119 | } 120 | if(n >= 24){ 121 | vlong2le(b+16, 1000000000LL); 122 | i = 24; 123 | } 124 | r->ofcall.count = i; 125 | respond(r, nil); 126 | } 127 | 128 | char *snarf; 129 | int nsnarf; 130 | char *tsnarf; 131 | int ntsnarf; 132 | 133 | static void 134 | snarfread(Req *r) 135 | { 136 | int i; 137 | 138 | if(r->ifcall.offset == 0){ 139 | if(snarf) 140 | free(snarf); 141 | nsnarf = getsnarflength(); 142 | snarf = emalloc9p(nsnarf+4+1); 143 | for(i=0; iifcall.offset == 0){ 157 | free(tsnarf); 158 | tsnarf = nil; 159 | ntsnarf = 0; 160 | } 161 | if(r->ifcall.offset > 100*1024){ 162 | respond(r, "snarf buffer too long"); 163 | return; 164 | } 165 | tsnarf = erealloc9p(tsnarf, ntsnarf+r->ifcall.count); 166 | memmove(tsnarf+ntsnarf, r->ifcall.data, r->ifcall.count); 167 | ntsnarf += r->ifcall.count; 168 | r->ofcall.count = r->ifcall.count; 169 | respond(r, nil); 170 | } 171 | 172 | static void 173 | snarfclose(Fid *fid) 174 | { 175 | int i, n; 176 | 177 | if((fid->omode&3) == OREAD) 178 | return; 179 | 180 | // read old snarf - dunno why but it helps 181 | n = getsnarflength(); 182 | for(i=0; iifcall.data, r->ifcall.count); 240 | if(cb->nf != 2){ 241 | respondcmderror(r, cb, "bad gui ctl"); 242 | free(cb); 243 | return; 244 | } 245 | 246 | if(strcmp(cb->f[1], "off")==0) 247 | on = 0; 248 | else if(strcmp(cb->f[1], "on") == 0) 249 | on = 1; 250 | else{ 251 | respondcmderror(r, cb, "bad gui ctl"); 252 | free(cb); 253 | return; 254 | } 255 | 256 | for(i=0; if[0]) == 0) 258 | goto Have; 259 | respondcmderror(r, cb, "bad gui ctl"); 260 | free(cb); 261 | return; 262 | 263 | Have: 264 | v = getguistate(); 265 | if(on) 266 | v |= guibit[i].bit; 267 | else 268 | v &= ~guibit[i].bit; 269 | setguistate(v); 270 | r->ofcall.count = r->ifcall.count; 271 | free(cb); 272 | respond(r, nil); 273 | } 274 | 275 | typedef struct Info Info; 276 | struct Info 277 | { 278 | char name[32]; 279 | uint uid; 280 | uint enabled; 281 | }; 282 | static int 283 | getinfo(uint id, Info *p) 284 | { 285 | uint i; 286 | 287 | for(i=0; ifid->aux; 321 | if(c == nil){ 322 | respond(r, "message channel not open"); 323 | return; 324 | } 325 | 326 | if(r->ifcall.offset == 0){ 327 | if(recvmsg(c, &s) < 0){ 328 | respond(r, "no messages waiting"); 329 | return; 330 | } 331 | } 332 | if(c->a == nil){ 333 | respond(r, "no messages waiting"); 334 | return; 335 | } 336 | readbuf(r, c->a, c->na); 337 | respond(r, nil); 338 | } 339 | 340 | static void 341 | fsmsgwrite(Req *r) 342 | { 343 | char buf[32], *p; 344 | int n; 345 | Msgchan *c; 346 | 347 | if(r->ifcall.offset != 0){ 348 | respond(r, "must write at offset zero"); 349 | return; 350 | } 351 | 352 | r->ofcall.count = r->ifcall.count; 353 | c = r->fid->aux; 354 | if(c == nil){ 355 | if(r->ifcall.count >= sizeof buf){ 356 | respond(r, "bad message channel number"); 357 | return; 358 | } 359 | memmove(buf, r->ifcall.data, r->ifcall.count); 360 | buf[r->ifcall.count] = 0; 361 | p = buf; 362 | n = strtol(buf, &p, 0); 363 | if(p == buf){ 364 | respond(r, "bad message channel number"); 365 | return; 366 | } 367 | c = openmsg(n); 368 | if(c == nil){ 369 | respond(r, "could not open message channel"); 370 | return; 371 | } 372 | r->fid->aux = c; 373 | respond(r, nil); 374 | return; 375 | } 376 | 377 | if(sendmsg(c, r->ifcall.data, r->ifcall.count) < 0){ 378 | respond(r, "could not send message"); 379 | return; 380 | } 381 | respond(r, nil); 382 | } 383 | 384 | static void 385 | fsmsgclose(Fid *fid) 386 | { 387 | Msgchan *c; 388 | 389 | c = fid->aux; 390 | if(c) 391 | closemsg(c); 392 | } 393 | 394 | Tab tab[] = { 395 | Qmousepoint, "mouse", 0666, 0, nil, mousepointread, mousepointwrite, nil, 396 | Qsnarf, "snarf", 0666, 0, nil, snarfread, snarfwrite, snarfclose, 397 | Qgui, "gui", 0666, 0, nil, guiread, guiwrite, nil, 398 | Qdev, "dev", 0444, 0, nil, devread, nil, nil, 399 | Qtime, "time", 0444, 0, nil, timeread, nil, nil, 400 | Qbintime, "bintime", 0444, 0, nil, bintimeread, nil, nil, 401 | Qmsg, "msg", 0666, 0, nil, fsmsgread, fsmsgwrite, fsmsgclose, 402 | }; 403 | 404 | void 405 | fsattach(Req *r) 406 | { 407 | char *spec; 408 | 409 | spec = r->ifcall.aname; 410 | if(spec && spec[0]){ 411 | respond(r, "invalid attach specifier"); 412 | return; 413 | } 414 | r->ofcall.qid = (Qid){Qroot, 0, QTDIR}; 415 | r->fid->qid = r->ofcall.qid; 416 | respond(r, nil); 417 | } 418 | 419 | char* 420 | fswalk1(Fid *fid, char *name, Qid *qid) 421 | { 422 | int i; 423 | 424 | switch((int)fid->qid.path){ 425 | case Qroot: 426 | for(i=0; iqid.path = tab[i].qid; 429 | fid->qid.type = tab[i].perm>>24;; 430 | fid->qid.vers = tab[i].vers; 431 | *qid = fid->qid; 432 | return nil; 433 | } 434 | } 435 | break; 436 | } 437 | 438 | return "file not found"; 439 | } 440 | 441 | void 442 | fsstat(Req *r) 443 | { 444 | int i, q; 445 | Dir *d; 446 | 447 | d = &r->d; 448 | memset(d, 0, sizeof *d); 449 | q = r->fid->qid.path; 450 | d->qid = r->fid->qid; 451 | switch(q){ 452 | case Qroot: 453 | d->name = estrdup9p("/"); 454 | d->mode = DMDIR|0777; 455 | break; 456 | 457 | default: 458 | for(i=0; iqid.vers = tab[i].vers; 461 | d->qid.type = tab[i].perm>>24; 462 | d->mode = tab[i].perm; 463 | goto Out; 464 | } 465 | } 466 | respond(r, "file not found"); 467 | } 468 | 469 | Out: 470 | d->atime = d->mtime = time0; 471 | d->uid = estrdup9p("vmware"); 472 | d->gid = estrdup9p("vmware"); 473 | d->muid = estrdup9p(""); 474 | respond(r, nil); 475 | } 476 | 477 | int 478 | dirgen(int off, Dir *d, void*) 479 | { 480 | if(off >= nelem(tab)) 481 | return -1; 482 | 483 | memset(d, 0, sizeof *d); 484 | d->atime = d->mtime = time0; 485 | d->name = estrdup9p(tab[off].name); 486 | d->mode = tab[off].perm; 487 | d->qid.path = tab[off].qid; 488 | d->qid.vers = tab[off].vers; 489 | d->qid.type = d->mode>>24; 490 | d->uid = estrdup9p("vmware"); 491 | d->gid = estrdup9p("vmware"); 492 | d->muid = estrdup9p(""); 493 | return 0; 494 | } 495 | 496 | void 497 | fsread(Req *r) 498 | { 499 | int i, q; 500 | 501 | q = r->fid->qid.path; 502 | switch(q){ 503 | case Qroot: 504 | dirread9p(r, dirgen, nil); 505 | respond(r, nil); 506 | return; 507 | 508 | default: 509 | for(i=0; ifid->qid.path; 532 | for(i=0; ifid->qid.path; 551 | for(i=0; iifcall.mode&3){ 554 | case OREAD: 555 | if(!(tab[i].perm&0400)) 556 | goto Eperm; 557 | break; 558 | case OWRITE: 559 | if(!(tab[i].perm&0200)) 560 | goto Eperm; 561 | break; 562 | case ORDWR: 563 | if((tab[i].perm&0600) != 0600) 564 | goto Eperm; 565 | break; 566 | case OEXEC: 567 | Eperm: 568 | respond(r, "permission denied"); 569 | return; 570 | } 571 | if(tab[i].open) 572 | tab[i].open(r); 573 | else 574 | respond(r, nil); 575 | return; 576 | } 577 | 578 | /* directory */ 579 | if(r->ifcall.mode != OREAD) 580 | respond(r, "permission denied"); 581 | else 582 | respond(r, nil); 583 | } 584 | 585 | void 586 | fsdestroyfid(Fid *fid) 587 | { 588 | int i, q; 589 | 590 | q = fid->qid.path; 591 | for(i=0; i