]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/disk/kfs/9p12.c
Add Erik Quanstrom's smart tool for ATA SMART.
[plan9front.git] / sys / src / cmd / disk / kfs / 9p12.c
1 #include "all.h"
2
3 static int
4 readmsg(Chan *c, void *abuf, int n, int *ninep)
5 {
6         int fd, len;
7         uchar *buf;
8
9         buf = abuf;
10         fd = c->chan;
11         qlock(&c->rlock);
12         if(readn(fd, buf, 3) != 3){
13                 qunlock(&c->rlock);
14                 print("readn(3) fails: %r\n");
15                 return -1;
16         }
17         if((50 <= buf[0] && buf[0] <= 87 && (buf[0]&1)==0 && GBIT16(buf+1) == 0xFFFF)
18         || buf[0] == 86 /* Tattach */){
19                 *ninep = 1;
20                 /* assume message boundaries */
21                 n = read(fd, buf+3, n-3);
22                 if(n < 0){
23                         qunlock(&c->rlock);
24                         return -1;
25                 }
26                 return n+3;
27         }
28
29         *ninep = 2;
30         if(read(fd, buf+3, 1) != 1){
31                 qunlock(&c->rlock);
32                 print("read(1) fails: %r\n");
33                 return -1;
34         }
35         len = GBIT32(buf);
36         if(len > n){
37                 print("msg too large\n");
38                 qunlock(&c->rlock);
39                 return -1;
40         }
41         if(readn(fd, buf+4, len-4) != len-4){
42                 print("readn(%d) fails: %r\n", len-4);
43                 qunlock(&c->rlock);
44                 return -1;
45         }
46         qunlock(&c->rlock);
47         return len;
48 }
49
50 int
51 startserveproc(void (*f)(Chan*, uchar*, int), char *name, Chan *c, uchar *b, int nb)
52 {
53         int pid;
54
55         switch(pid = rfork(RFMEM|RFPROC)){
56         case -1:
57                 panic("can't fork");
58         case 0:
59                 break;
60         default:
61                 return pid;
62         }
63         procname = name;
64         f(c, b, nb);
65         _exits(nil);
66         return -1;      /* can't happen */
67 }
68
69 void
70 serve(Chan *chan)
71 {
72         int i, nin, p9, npid;
73         uchar inbuf[1024];
74         void (*s)(Chan*, uchar*, int);
75         int *pid;
76         Waitmsg *w;
77
78         p9 = 0;
79         if((nin = readmsg(chan, inbuf, sizeof inbuf, &p9)) < 0)
80                 return;
81
82         switch(p9){
83         default:
84                 print("unknown 9P type\n");
85                 return;
86         case 1:
87                 s = serve9p1;
88                 break;
89         case 2:
90                 s = serve9p2;
91                 break;
92         }
93
94         pid = malloc(sizeof(pid)*(conf.nserve-1));
95         if(pid == nil)
96                 return;
97         for(i=1; i<conf.nserve; i++)
98                 pid[i-1] = startserveproc(s, "srv", chan, nil, 0);
99
100         (*s)(chan, inbuf, nin);
101
102         /* wait till all other servers for this chan are done */
103         for(npid = conf.nserve-1; npid > 0;){
104                 w = wait();
105                 if(w == 0)
106                         break;
107                 for(i = 0; i < conf.nserve-1; i++)
108                         if(pid[i] == w->pid)
109                                 npid--;
110                 free(w);
111         }
112         free(pid);
113 }
114