1 #include <u.h>
2 #include <libc.h>
3 #include <bio.h>
4 #include <auth.h>
5 #include <fcall.h>
6 #include <thread.h>
7 #include <9p.h>
8 #include "snap.h"
9
10 typedef struct PD PD;
11 struct PD {
12 int isproc;
13 union {
14 Proc *p;
15 Data *d;
16 };
17 };
18
19 PD*
PDProc(Proc * p)20 PDProc(Proc *p)
21 {
22 PD *pd;
23
24 pd = emalloc(sizeof(*pd));
25 pd->isproc = 1;
26 pd->p = p;
27 return pd;
28 }
29
30 PD*
PDData(Data * d)31 PDData(Data *d)
32 {
33 PD *pd;
34
35 pd = emalloc(sizeof(*pd));
36 pd->isproc = 0;
37 pd->d = d;
38 return pd;
39 }
40
41 void
usage(void)42 usage(void)
43 {
44 fprint(2, "usage: snapfs [-a] [-m mtpt] file\n");
45 exits("usage");
46 }
47
48 char*
memread(Proc * p,File * f,void * buf,long * count,vlong offset)49 memread(Proc *p, File *f, void *buf, long *count, vlong offset)
50 {
51 Page *pg;
52 int po;
53
54 po = offset%Pagesize;
55 if(!(pg = findpage(p, p->pid, f->name[0], offset-po)))
56 return "address not mapped";
57
58 if(*count > Pagesize-po)
59 *count = Pagesize-po;
60
61 memmove(buf, pg->data+po, *count);
62 return nil;
63 }
64
65 char*
dataread(Data * d,void * buf,long * count,vlong offset)66 dataread(Data *d, void *buf, long *count, vlong offset)
67 {
68 assert(d != nil);
69
70 if(offset >= d->len) {
71 *count = 0;
72 return nil;
73 }
74
75 if(offset+*count >= d->len)
76 *count = d->len - offset;
77
78 memmove(buf, d->data+offset, *count);
79 return nil;
80 }
81
82 void
fsread(Req * r)83 fsread(Req *r)
84 {
85 char *e;
86 PD *pd;
87 Fid *fid;
88 void *data;
89 vlong offset;
90 long count;
91
92 fid = r->fid;
93 data = r->ofcall.data;
94 offset = r->ifcall.offset;
95 count = r->ifcall.count;
96 pd = fid->file->aux;
97
98 if(pd->isproc)
99 e = memread(pd->p, fid->file, data, &count, offset);
100 else
101 e = dataread(pd->d, data, &count, offset);
102
103 if(e == nil)
104 r->ofcall.count = count;
105 respond(r, e);
106 }
107
108 Srv fs = {
109 .read = fsread,
110 };
111
112 File*
ecreatefile(File * a,char * b,char * c,ulong d,void * e)113 ecreatefile(File *a, char *b, char *c, ulong d, void *e)
114 {
115 File *f;
116
117 f = createfile(a, b, c, d, e);
118 if(f == nil)
119 sysfatal("error creating snap tree: %r");
120 return f;
121 }
122
123 void
main(int argc,char ** argv)124 main(int argc, char **argv)
125 {
126 Biobuf *b;
127 Data *d;
128 File *fdir, *f;
129 Proc *p, *plist;
130 Tree *tree;
131 char *mtpt, buf[32];
132 int i, mflag;
133
134 mtpt = "/proc";
135 mflag = MBEFORE;
136
137 ARGBEGIN{
138 case 'D':
139 chatty9p++;
140 break;
141 case 'd':
142 debug = 1;
143 break;
144 case 'a':
145 mflag = MAFTER;
146 break;
147 case 'm':
148 mtpt = ARGF();
149 break;
150 default:
151 usage();
152 }ARGEND
153
154 if(argc != 1)
155 usage();
156
157 b = Bopen(argv[0], OREAD);
158 if(b == nil) {
159 fprint(2, "cannot open \"%s\": %r\n", argv[0]);
160 exits("Bopen");
161 }
162
163 if((plist = readsnap(b)) == nil) {
164 fprint(2, "readsnap fails\n");
165 exits("readsnap");
166 }
167
168 tree = alloctree(nil, nil, DMDIR|0555, nil);
169 fs.tree = tree;
170
171 for(p=plist; p; p=p->link) {
172 print("process %ld %.*s\n", p->pid, 28, p->d[Pstatus] ? p->d[Pstatus]->data : "");
173
174 snprint(buf, sizeof buf, "%ld", p->pid);
175 fdir = ecreatefile(tree->root, buf, nil, DMDIR|0555, nil);
176 ecreatefile(fdir, "ctl", nil, 0777, nil);
177 if(p->text)
178 ecreatefile(fdir, "text", nil, 0777, PDProc(p));
179
180 ecreatefile(fdir, "mem", nil, 0666, PDProc(p));
181 for(i=0; i<Npfile; i++) {
182 if(d = p->d[i]) {
183 f = ecreatefile(fdir, pfile[i], nil, 0666, PDData(d));
184 f->length = d->len;
185 }
186 }
187 }
188
189 postmountsrv(&fs, nil, mtpt, mflag);
190 exits(0);
191 }
192