xref: /plan9/sys/src/cmd/snap/snapfs.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
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