Blame


1 6f4d00ee 2013-09-23 0intro #include "stdinc.h"
2 6f4d00ee 2013-09-23 0intro
3 6f4d00ee 2013-09-23 0intro #include "9.h"
4 6f4d00ee 2013-09-23 0intro
5 6f4d00ee 2013-09-23 0intro enum {
6 6f4d00ee 2013-09-23 0intro OMODE = 0x7, /* Topen/Tcreate mode */
7 6f4d00ee 2013-09-23 0intro };
8 6f4d00ee 2013-09-23 0intro
9 6f4d00ee 2013-09-23 0intro enum {
10 6f4d00ee 2013-09-23 0intro PermX = 1,
11 6f4d00ee 2013-09-23 0intro PermW = 2,
12 6f4d00ee 2013-09-23 0intro PermR = 4,
13 6f4d00ee 2013-09-23 0intro };
14 6f4d00ee 2013-09-23 0intro
15 6f4d00ee 2013-09-23 0intro static char EPermission[] = "permission denied";
16 6f4d00ee 2013-09-23 0intro
17 6f4d00ee 2013-09-23 0intro static int
18 6f4d00ee 2013-09-23 0intro permFile(File* file, Fid* fid, int perm)
19 6f4d00ee 2013-09-23 0intro {
20 6f4d00ee 2013-09-23 0intro char *u;
21 6f4d00ee 2013-09-23 0intro DirEntry de;
22 6f4d00ee 2013-09-23 0intro
23 6f4d00ee 2013-09-23 0intro if(!fileGetDir(file, &de))
24 6f4d00ee 2013-09-23 0intro return -1;
25 6f4d00ee 2013-09-23 0intro
26 6f4d00ee 2013-09-23 0intro /*
27 6f4d00ee 2013-09-23 0intro * User none only gets other permissions.
28 6f4d00ee 2013-09-23 0intro */
29 6f4d00ee 2013-09-23 0intro if(strcmp(fid->uname, unamenone) != 0){
30 6f4d00ee 2013-09-23 0intro /*
31 6f4d00ee 2013-09-23 0intro * There is only one uid<->uname mapping
32 6f4d00ee 2013-09-23 0intro * and it's already cached in the Fid, but
33 6f4d00ee 2013-09-23 0intro * it might have changed during the lifetime
34 6f4d00ee 2013-09-23 0intro * if this Fid.
35 6f4d00ee 2013-09-23 0intro */
36 6f4d00ee 2013-09-23 0intro if((u = unameByUid(de.uid)) != nil){
37 6f4d00ee 2013-09-23 0intro if(strcmp(fid->uname, u) == 0 && ((perm<<6) & de.mode)){
38 4b576658 2013-09-23 0intro vtfree(u);
39 6f4d00ee 2013-09-23 0intro deCleanup(&de);
40 6f4d00ee 2013-09-23 0intro return 1;
41 6f4d00ee 2013-09-23 0intro }
42 4b576658 2013-09-23 0intro vtfree(u);
43 6f4d00ee 2013-09-23 0intro }
44 6f4d00ee 2013-09-23 0intro if(groupMember(de.gid, fid->uname) && ((perm<<3) & de.mode)){
45 6f4d00ee 2013-09-23 0intro deCleanup(&de);
46 6f4d00ee 2013-09-23 0intro return 1;
47 6f4d00ee 2013-09-23 0intro }
48 6f4d00ee 2013-09-23 0intro }
49 6f4d00ee 2013-09-23 0intro if(perm & de.mode){
50 6f4d00ee 2013-09-23 0intro if(perm == PermX && (de.mode & ModeDir)){
51 6f4d00ee 2013-09-23 0intro deCleanup(&de);
52 6f4d00ee 2013-09-23 0intro return 1;
53 6f4d00ee 2013-09-23 0intro }
54 6f4d00ee 2013-09-23 0intro if(!groupMember(uidnoworld, fid->uname)){
55 6f4d00ee 2013-09-23 0intro deCleanup(&de);
56 6f4d00ee 2013-09-23 0intro return 1;
57 6f4d00ee 2013-09-23 0intro }
58 6f4d00ee 2013-09-23 0intro }
59 6f4d00ee 2013-09-23 0intro if(fsysNoPermCheck(fid->fsys) || (fid->con->flags&ConNoPermCheck)){
60 6f4d00ee 2013-09-23 0intro deCleanup(&de);
61 6f4d00ee 2013-09-23 0intro return 1;
62 6f4d00ee 2013-09-23 0intro }
63 4b576658 2013-09-23 0intro werrstr(EPermission);
64 6f4d00ee 2013-09-23 0intro
65 6f4d00ee 2013-09-23 0intro deCleanup(&de);
66 6f4d00ee 2013-09-23 0intro return 0;
67 6f4d00ee 2013-09-23 0intro }
68 6f4d00ee 2013-09-23 0intro
69 6f4d00ee 2013-09-23 0intro static int
70 6f4d00ee 2013-09-23 0intro permFid(Fid* fid, int p)
71 6f4d00ee 2013-09-23 0intro {
72 6f4d00ee 2013-09-23 0intro return permFile(fid->file, fid, p);
73 6f4d00ee 2013-09-23 0intro }
74 6f4d00ee 2013-09-23 0intro
75 6f4d00ee 2013-09-23 0intro static int
76 6f4d00ee 2013-09-23 0intro permParent(Fid* fid, int p)
77 6f4d00ee 2013-09-23 0intro {
78 6f4d00ee 2013-09-23 0intro int r;
79 6f4d00ee 2013-09-23 0intro File *parent;
80 6f4d00ee 2013-09-23 0intro
81 6f4d00ee 2013-09-23 0intro parent = fileGetParent(fid->file);
82 6f4d00ee 2013-09-23 0intro r = permFile(parent, fid, p);
83 6f4d00ee 2013-09-23 0intro fileDecRef(parent);
84 6f4d00ee 2013-09-23 0intro
85 6f4d00ee 2013-09-23 0intro return r;
86 6f4d00ee 2013-09-23 0intro }
87 6f4d00ee 2013-09-23 0intro
88 6f4d00ee 2013-09-23 0intro int
89 6f4d00ee 2013-09-23 0intro validFileName(char* name)
90 6f4d00ee 2013-09-23 0intro {
91 6f4d00ee 2013-09-23 0intro char *p;
92 6f4d00ee 2013-09-23 0intro
93 6f4d00ee 2013-09-23 0intro if(name == nil || name[0] == '\0'){
94 4b576658 2013-09-23 0intro werrstr("no file name");
95 6f4d00ee 2013-09-23 0intro return 0;
96 6f4d00ee 2013-09-23 0intro }
97 6f4d00ee 2013-09-23 0intro if(name[0] == '.'){
98 6f4d00ee 2013-09-23 0intro if(name[1] == '\0' || (name[1] == '.' && name[2] == '\0')){
99 4b576658 2013-09-23 0intro werrstr(". and .. illegal as file name");
100 6f4d00ee 2013-09-23 0intro return 0;
101 6f4d00ee 2013-09-23 0intro }
102 6f4d00ee 2013-09-23 0intro }
103 6f4d00ee 2013-09-23 0intro
104 6f4d00ee 2013-09-23 0intro for(p = name; *p != '\0'; p++){
105 6f4d00ee 2013-09-23 0intro if((*p & 0xFF) < 040){
106 4b576658 2013-09-23 0intro werrstr("bad character in file name");
107 6f4d00ee 2013-09-23 0intro return 0;
108 6f4d00ee 2013-09-23 0intro }
109 6f4d00ee 2013-09-23 0intro }
110 6f4d00ee 2013-09-23 0intro
111 6f4d00ee 2013-09-23 0intro return 1;
112 6f4d00ee 2013-09-23 0intro }
113 6f4d00ee 2013-09-23 0intro
114 6f4d00ee 2013-09-23 0intro static int
115 6f4d00ee 2013-09-23 0intro rTwstat(Msg* m)
116 6f4d00ee 2013-09-23 0intro {
117 6f4d00ee 2013-09-23 0intro Dir dir;
118 6f4d00ee 2013-09-23 0intro Fid *fid;
119 6f4d00ee 2013-09-23 0intro ulong mode, oldmode;
120 6f4d00ee 2013-09-23 0intro DirEntry de;
121 6f4d00ee 2013-09-23 0intro char *gid, *strs, *uid;
122 6f4d00ee 2013-09-23 0intro int gl, op, retval, tsync, wstatallow;
123 6f4d00ee 2013-09-23 0intro
124 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, FidFWlock)) == nil)
125 6f4d00ee 2013-09-23 0intro return 0;
126 6f4d00ee 2013-09-23 0intro
127 6f4d00ee 2013-09-23 0intro gid = uid = nil;
128 6f4d00ee 2013-09-23 0intro retval = 0;
129 6f4d00ee 2013-09-23 0intro
130 6f4d00ee 2013-09-23 0intro if(strcmp(fid->uname, unamenone) == 0 || (fid->qid.type & QTAUTH)){
131 4b576658 2013-09-23 0intro werrstr(EPermission);
132 6f4d00ee 2013-09-23 0intro goto error0;
133 6f4d00ee 2013-09-23 0intro }
134 6f4d00ee 2013-09-23 0intro if(fileIsRoFs(fid->file) || !groupWriteMember(fid->uname)){
135 4b576658 2013-09-23 0intro werrstr("read-only filesystem");
136 6f4d00ee 2013-09-23 0intro goto error0;
137 6f4d00ee 2013-09-23 0intro }
138 6f4d00ee 2013-09-23 0intro
139 6f4d00ee 2013-09-23 0intro if(!fileGetDir(fid->file, &de))
140 6f4d00ee 2013-09-23 0intro goto error0;
141 6f4d00ee 2013-09-23 0intro
142 4b576658 2013-09-23 0intro strs = vtmalloc(m->t.nstat);
143 6f4d00ee 2013-09-23 0intro if(convM2D(m->t.stat, m->t.nstat, &dir, strs) == 0){
144 4b576658 2013-09-23 0intro werrstr("wstat -- protocol botch");
145 6f4d00ee 2013-09-23 0intro goto error;
146 6f4d00ee 2013-09-23 0intro }
147 6f4d00ee 2013-09-23 0intro
148 6f4d00ee 2013-09-23 0intro /*
149 6f4d00ee 2013-09-23 0intro * Run through each of the (sub-)fields in the provided Dir
150 6f4d00ee 2013-09-23 0intro * checking for validity and whether it's a default:
151 6f4d00ee 2013-09-23 0intro * .type, .dev and .atime are completely ignored and not checked;
152 6f4d00ee 2013-09-23 0intro * .qid.path, .qid.vers and .muid are checked for validity but
153 6f4d00ee 2013-09-23 0intro * any attempt to change them is an error.
154 6f4d00ee 2013-09-23 0intro * .qid.type/.mode, .mtime, .name, .length, .uid and .gid can
155 6f4d00ee 2013-09-23 0intro * possibly be changed.
156 6f4d00ee 2013-09-23 0intro *
157 6f4d00ee 2013-09-23 0intro * 'Op' flags there are changed fields, i.e. it's not a no-op.
158 6f4d00ee 2013-09-23 0intro * 'Tsync' flags all fields are defaulted.
159 6f4d00ee 2013-09-23 0intro */
160 6f4d00ee 2013-09-23 0intro tsync = 1;
161 6f4d00ee 2013-09-23 0intro if(dir.qid.path != ~0){
162 6f4d00ee 2013-09-23 0intro if(dir.qid.path != de.qid){
163 4b576658 2013-09-23 0intro werrstr("wstat -- attempt to change qid.path");
164 6f4d00ee 2013-09-23 0intro goto error;
165 6f4d00ee 2013-09-23 0intro }
166 6f4d00ee 2013-09-23 0intro tsync = 0;
167 6f4d00ee 2013-09-23 0intro }
168 3fcc209d 2013-09-26 0intro if(dir.qid.vers != (u32int)~0){
169 6f4d00ee 2013-09-23 0intro if(dir.qid.vers != de.mcount){
170 4b576658 2013-09-23 0intro werrstr("wstat -- attempt to change qid.vers");
171 6f4d00ee 2013-09-23 0intro goto error;
172 6f4d00ee 2013-09-23 0intro }
173 6f4d00ee 2013-09-23 0intro tsync = 0;
174 6f4d00ee 2013-09-23 0intro }
175 6f4d00ee 2013-09-23 0intro if(dir.muid != nil && *dir.muid != '\0'){
176 6f4d00ee 2013-09-23 0intro if((uid = uidByUname(dir.muid)) == nil){
177 4b576658 2013-09-23 0intro werrstr("wstat -- unknown muid");
178 6f4d00ee 2013-09-23 0intro goto error;
179 6f4d00ee 2013-09-23 0intro }
180 6f4d00ee 2013-09-23 0intro if(strcmp(uid, de.mid) != 0){
181 4b576658 2013-09-23 0intro werrstr("wstat -- attempt to change muid");
182 6f4d00ee 2013-09-23 0intro goto error;
183 6f4d00ee 2013-09-23 0intro }
184 4b576658 2013-09-23 0intro vtfree(uid);
185 6f4d00ee 2013-09-23 0intro uid = nil;
186 6f4d00ee 2013-09-23 0intro tsync = 0;
187 6f4d00ee 2013-09-23 0intro }
188 6f4d00ee 2013-09-23 0intro
189 6f4d00ee 2013-09-23 0intro /*
190 6f4d00ee 2013-09-23 0intro * Check .qid.type and .mode agree if neither is defaulted.
191 6f4d00ee 2013-09-23 0intro */
192 3fcc209d 2013-09-26 0intro if(dir.qid.type != (uchar)~0 && dir.mode != (u32int)~0){
193 6f4d00ee 2013-09-23 0intro if(dir.qid.type != ((dir.mode>>24) & 0xFF)){
194 4b576658 2013-09-23 0intro werrstr("wstat -- qid.type/mode mismatch");
195 6f4d00ee 2013-09-23 0intro goto error;
196 6f4d00ee 2013-09-23 0intro }
197 6f4d00ee 2013-09-23 0intro }
198 6f4d00ee 2013-09-23 0intro
199 6f4d00ee 2013-09-23 0intro op = 0;
200 6f4d00ee 2013-09-23 0intro
201 6f4d00ee 2013-09-23 0intro oldmode = de.mode;
202 3fcc209d 2013-09-26 0intro if(dir.qid.type != (uchar)~0 || dir.mode != (u32int)~0){
203 6f4d00ee 2013-09-23 0intro /*
204 6f4d00ee 2013-09-23 0intro * .qid.type or .mode isn't defaulted, check for unknown bits.
205 6f4d00ee 2013-09-23 0intro */
206 6f4d00ee 2013-09-23 0intro if(dir.mode == ~0)
207 6f4d00ee 2013-09-23 0intro dir.mode = (dir.qid.type<<24)|(de.mode & 0777);
208 6f4d00ee 2013-09-23 0intro if(dir.mode & ~(DMDIR|DMAPPEND|DMEXCL|DMTMP|0777)){
209 4b576658 2013-09-23 0intro werrstr("wstat -- unknown bits in qid.type/mode");
210 6f4d00ee 2013-09-23 0intro goto error;
211 6f4d00ee 2013-09-23 0intro }
212 6f4d00ee 2013-09-23 0intro
213 6f4d00ee 2013-09-23 0intro /*
214 6f4d00ee 2013-09-23 0intro * Synthesise a mode to check against the current settings.
215 6f4d00ee 2013-09-23 0intro */
216 6f4d00ee 2013-09-23 0intro mode = dir.mode & 0777;
217 6f4d00ee 2013-09-23 0intro if(dir.mode & DMEXCL)
218 6f4d00ee 2013-09-23 0intro mode |= ModeExclusive;
219 6f4d00ee 2013-09-23 0intro if(dir.mode & DMAPPEND)
220 6f4d00ee 2013-09-23 0intro mode |= ModeAppend;
221 6f4d00ee 2013-09-23 0intro if(dir.mode & DMDIR)
222 6f4d00ee 2013-09-23 0intro mode |= ModeDir;
223 6f4d00ee 2013-09-23 0intro if(dir.mode & DMTMP)
224 6f4d00ee 2013-09-23 0intro mode |= ModeTemporary;
225 6f4d00ee 2013-09-23 0intro
226 6f4d00ee 2013-09-23 0intro if((de.mode^mode) & ModeDir){
227 4b576658 2013-09-23 0intro werrstr("wstat -- attempt to change directory bit");
228 6f4d00ee 2013-09-23 0intro goto error;
229 6f4d00ee 2013-09-23 0intro }
230 6f4d00ee 2013-09-23 0intro
231 6f4d00ee 2013-09-23 0intro if((de.mode & (ModeAppend|ModeExclusive|ModeTemporary|0777)) != mode){
232 6f4d00ee 2013-09-23 0intro de.mode &= ~(ModeAppend|ModeExclusive|ModeTemporary|0777);
233 6f4d00ee 2013-09-23 0intro de.mode |= mode;
234 6f4d00ee 2013-09-23 0intro op = 1;
235 6f4d00ee 2013-09-23 0intro }
236 6f4d00ee 2013-09-23 0intro tsync = 0;
237 6f4d00ee 2013-09-23 0intro }
238 6f4d00ee 2013-09-23 0intro
239 3fcc209d 2013-09-26 0intro if(dir.mtime != (u32int)~0){
240 6f4d00ee 2013-09-23 0intro if(dir.mtime != de.mtime){
241 6f4d00ee 2013-09-23 0intro de.mtime = dir.mtime;
242 6f4d00ee 2013-09-23 0intro op = 1;
243 6f4d00ee 2013-09-23 0intro }
244 6f4d00ee 2013-09-23 0intro tsync = 0;
245 6f4d00ee 2013-09-23 0intro }
246 6f4d00ee 2013-09-23 0intro
247 6f4d00ee 2013-09-23 0intro if(dir.length != ~0){
248 6f4d00ee 2013-09-23 0intro if(dir.length != de.size){
249 6f4d00ee 2013-09-23 0intro /*
250 6f4d00ee 2013-09-23 0intro * Cannot change length on append-only files.
251 6f4d00ee 2013-09-23 0intro * If we're changing the append bit, it's okay.
252 6f4d00ee 2013-09-23 0intro */
253 6f4d00ee 2013-09-23 0intro if(de.mode & oldmode & ModeAppend){
254 4b576658 2013-09-23 0intro werrstr("wstat -- attempt to change length of append-only file");
255 6f4d00ee 2013-09-23 0intro goto error;
256 6f4d00ee 2013-09-23 0intro }
257 6f4d00ee 2013-09-23 0intro if(de.mode & ModeDir){
258 4b576658 2013-09-23 0intro werrstr("wstat -- attempt to change length of directory");
259 6f4d00ee 2013-09-23 0intro goto error;
260 6f4d00ee 2013-09-23 0intro }
261 6f4d00ee 2013-09-23 0intro de.size = dir.length;
262 6f4d00ee 2013-09-23 0intro op = 1;
263 6f4d00ee 2013-09-23 0intro }
264 6f4d00ee 2013-09-23 0intro tsync = 0;
265 6f4d00ee 2013-09-23 0intro }
266 6f4d00ee 2013-09-23 0intro
267 6f4d00ee 2013-09-23 0intro /*
268 6f4d00ee 2013-09-23 0intro * Check for permission to change .mode, .mtime or .length,
269 6f4d00ee 2013-09-23 0intro * must be owner or leader of either group, for which test gid
270 6f4d00ee 2013-09-23 0intro * is needed; permission checks on gid will be done later.
271 6f4d00ee 2013-09-23 0intro */
272 6f4d00ee 2013-09-23 0intro if(dir.gid != nil && *dir.gid != '\0'){
273 6f4d00ee 2013-09-23 0intro if((gid = uidByUname(dir.gid)) == nil){
274 4b576658 2013-09-23 0intro werrstr("wstat -- unknown gid");
275 6f4d00ee 2013-09-23 0intro goto error;
276 6f4d00ee 2013-09-23 0intro }
277 6f4d00ee 2013-09-23 0intro tsync = 0;
278 6f4d00ee 2013-09-23 0intro }
279 6f4d00ee 2013-09-23 0intro else
280 4b576658 2013-09-23 0intro gid = vtstrdup(de.gid);
281 6f4d00ee 2013-09-23 0intro
282 6f4d00ee 2013-09-23 0intro wstatallow = (fsysWstatAllow(fid->fsys) || (m->con->flags&ConWstatAllow));
283 6f4d00ee 2013-09-23 0intro
284 6f4d00ee 2013-09-23 0intro /*
285 6f4d00ee 2013-09-23 0intro * 'Gl' counts whether neither, one or both groups are led.
286 6f4d00ee 2013-09-23 0intro */
287 6f4d00ee 2013-09-23 0intro gl = groupLeader(gid, fid->uname) != 0;
288 6f4d00ee 2013-09-23 0intro gl += groupLeader(de.gid, fid->uname) != 0;
289 6f4d00ee 2013-09-23 0intro
290 6f4d00ee 2013-09-23 0intro if(op && !wstatallow){
291 6f4d00ee 2013-09-23 0intro if(strcmp(fid->uid, de.uid) != 0 && !gl){
292 4b576658 2013-09-23 0intro werrstr("wstat -- not owner or group leader");
293 6f4d00ee 2013-09-23 0intro goto error;
294 6f4d00ee 2013-09-23 0intro }
295 6f4d00ee 2013-09-23 0intro }
296 6f4d00ee 2013-09-23 0intro
297 6f4d00ee 2013-09-23 0intro /*
298 6f4d00ee 2013-09-23 0intro * Check for permission to change group, must be
299 6f4d00ee 2013-09-23 0intro * either owner and in new group or leader of both groups.
300 6f4d00ee 2013-09-23 0intro * If gid is nil here then
301 6f4d00ee 2013-09-23 0intro */
302 6f4d00ee 2013-09-23 0intro if(strcmp(gid, de.gid) != 0){
303 6f4d00ee 2013-09-23 0intro if(!wstatallow
304 6f4d00ee 2013-09-23 0intro && !(strcmp(fid->uid, de.uid) == 0 && groupMember(gid, fid->uname))
305 6f4d00ee 2013-09-23 0intro && !(gl == 2)){
306 4b576658 2013-09-23 0intro werrstr("wstat -- not owner and not group leaders");
307 6f4d00ee 2013-09-23 0intro goto error;
308 6f4d00ee 2013-09-23 0intro }
309 4b576658 2013-09-23 0intro vtfree(de.gid);
310 6f4d00ee 2013-09-23 0intro de.gid = gid;
311 6f4d00ee 2013-09-23 0intro gid = nil;
312 6f4d00ee 2013-09-23 0intro op = 1;
313 6f4d00ee 2013-09-23 0intro tsync = 0;
314 6f4d00ee 2013-09-23 0intro }
315 6f4d00ee 2013-09-23 0intro
316 6f4d00ee 2013-09-23 0intro /*
317 6f4d00ee 2013-09-23 0intro * Rename.
318 6f4d00ee 2013-09-23 0intro * Check .name is valid and different to the current.
319 6f4d00ee 2013-09-23 0intro * If so, check write permission in parent.
320 6f4d00ee 2013-09-23 0intro */
321 6f4d00ee 2013-09-23 0intro if(dir.name != nil && *dir.name != '\0'){
322 6f4d00ee 2013-09-23 0intro if(!validFileName(dir.name))
323 6f4d00ee 2013-09-23 0intro goto error;
324 6f4d00ee 2013-09-23 0intro if(strcmp(dir.name, de.elem) != 0){
325 6f4d00ee 2013-09-23 0intro if(permParent(fid, PermW) <= 0)
326 6f4d00ee 2013-09-23 0intro goto error;
327 4b576658 2013-09-23 0intro vtfree(de.elem);
328 4b576658 2013-09-23 0intro de.elem = vtstrdup(dir.name);
329 6f4d00ee 2013-09-23 0intro op = 1;
330 6f4d00ee 2013-09-23 0intro }
331 6f4d00ee 2013-09-23 0intro tsync = 0;
332 6f4d00ee 2013-09-23 0intro }
333 6f4d00ee 2013-09-23 0intro
334 6f4d00ee 2013-09-23 0intro /*
335 6f4d00ee 2013-09-23 0intro * Check for permission to change owner - must be god.
336 6f4d00ee 2013-09-23 0intro */
337 6f4d00ee 2013-09-23 0intro if(dir.uid != nil && *dir.uid != '\0'){
338 6f4d00ee 2013-09-23 0intro if((uid = uidByUname(dir.uid)) == nil){
339 4b576658 2013-09-23 0intro werrstr("wstat -- unknown uid");
340 6f4d00ee 2013-09-23 0intro goto error;
341 6f4d00ee 2013-09-23 0intro }
342 6f4d00ee 2013-09-23 0intro if(strcmp(uid, de.uid) != 0){
343 6f4d00ee 2013-09-23 0intro if(!wstatallow){
344 4b576658 2013-09-23 0intro werrstr("wstat -- not owner");
345 6f4d00ee 2013-09-23 0intro goto error;
346 6f4d00ee 2013-09-23 0intro }
347 6f4d00ee 2013-09-23 0intro if(strcmp(uid, uidnoworld) == 0){
348 4b576658 2013-09-23 0intro werrstr(EPermission);
349 6f4d00ee 2013-09-23 0intro goto error;
350 6f4d00ee 2013-09-23 0intro }
351 4b576658 2013-09-23 0intro vtfree(de.uid);
352 6f4d00ee 2013-09-23 0intro de.uid = uid;
353 6f4d00ee 2013-09-23 0intro uid = nil;
354 6f4d00ee 2013-09-23 0intro op = 1;
355 6f4d00ee 2013-09-23 0intro }
356 6f4d00ee 2013-09-23 0intro tsync = 0;
357 6f4d00ee 2013-09-23 0intro }
358 6f4d00ee 2013-09-23 0intro
359 6f4d00ee 2013-09-23 0intro if(op)
360 6f4d00ee 2013-09-23 0intro retval = fileSetDir(fid->file, &de, fid->uid);
361 6f4d00ee 2013-09-23 0intro else
362 6f4d00ee 2013-09-23 0intro retval = 1;
363 6f4d00ee 2013-09-23 0intro
364 6f4d00ee 2013-09-23 0intro if(tsync){
365 6f4d00ee 2013-09-23 0intro /*
366 6f4d00ee 2013-09-23 0intro * All values were defaulted,
367 6f4d00ee 2013-09-23 0intro * make the state of the file exactly what it
368 6f4d00ee 2013-09-23 0intro * claims to be before returning...
369 6f4d00ee 2013-09-23 0intro */
370 6f4d00ee 2013-09-23 0intro USED(tsync);
371 6f4d00ee 2013-09-23 0intro }
372 6f4d00ee 2013-09-23 0intro
373 6f4d00ee 2013-09-23 0intro error:
374 6f4d00ee 2013-09-23 0intro deCleanup(&de);
375 4b576658 2013-09-23 0intro vtfree(strs);
376 6f4d00ee 2013-09-23 0intro if(gid != nil)
377 4b576658 2013-09-23 0intro vtfree(gid);
378 6f4d00ee 2013-09-23 0intro if(uid != nil)
379 4b576658 2013-09-23 0intro vtfree(uid);
380 6f4d00ee 2013-09-23 0intro error0:
381 6f4d00ee 2013-09-23 0intro fidPut(fid);
382 6f4d00ee 2013-09-23 0intro return retval;
383 6f4d00ee 2013-09-23 0intro };
384 6f4d00ee 2013-09-23 0intro
385 6f4d00ee 2013-09-23 0intro static int
386 6f4d00ee 2013-09-23 0intro rTstat(Msg* m)
387 6f4d00ee 2013-09-23 0intro {
388 6f4d00ee 2013-09-23 0intro Dir dir;
389 6f4d00ee 2013-09-23 0intro Fid *fid;
390 6f4d00ee 2013-09-23 0intro DirEntry de;
391 6f4d00ee 2013-09-23 0intro
392 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, 0)) == nil)
393 6f4d00ee 2013-09-23 0intro return 0;
394 6f4d00ee 2013-09-23 0intro if(fid->qid.type & QTAUTH){
395 6f4d00ee 2013-09-23 0intro memset(&dir, 0, sizeof(Dir));
396 6f4d00ee 2013-09-23 0intro dir.qid = fid->qid;
397 6f4d00ee 2013-09-23 0intro dir.mode = DMAUTH;
398 6f4d00ee 2013-09-23 0intro dir.atime = time(0L);
399 6f4d00ee 2013-09-23 0intro dir.mtime = dir.atime;
400 6f4d00ee 2013-09-23 0intro dir.length = 0;
401 6f4d00ee 2013-09-23 0intro dir.name = "#¿";
402 6f4d00ee 2013-09-23 0intro dir.uid = fid->uname;
403 6f4d00ee 2013-09-23 0intro dir.gid = fid->uname;
404 6f4d00ee 2013-09-23 0intro dir.muid = fid->uname;
405 6f4d00ee 2013-09-23 0intro
406 6f4d00ee 2013-09-23 0intro if((m->r.nstat = convD2M(&dir, m->data, m->con->msize)) == 0){
407 4b576658 2013-09-23 0intro werrstr("stat QTAUTH botch");
408 6f4d00ee 2013-09-23 0intro fidPut(fid);
409 6f4d00ee 2013-09-23 0intro return 0;
410 6f4d00ee 2013-09-23 0intro }
411 6f4d00ee 2013-09-23 0intro m->r.stat = m->data;
412 6f4d00ee 2013-09-23 0intro
413 6f4d00ee 2013-09-23 0intro fidPut(fid);
414 6f4d00ee 2013-09-23 0intro return 1;
415 6f4d00ee 2013-09-23 0intro }
416 6f4d00ee 2013-09-23 0intro if(!fileGetDir(fid->file, &de)){
417 6f4d00ee 2013-09-23 0intro fidPut(fid);
418 6f4d00ee 2013-09-23 0intro return 0;
419 6f4d00ee 2013-09-23 0intro }
420 6f4d00ee 2013-09-23 0intro fidPut(fid);
421 6f4d00ee 2013-09-23 0intro
422 6f4d00ee 2013-09-23 0intro /*
423 6f4d00ee 2013-09-23 0intro * TODO: optimise this copy (in convS2M) away somehow.
424 6f4d00ee 2013-09-23 0intro * This pettifoggery with m->data will do for the moment.
425 6f4d00ee 2013-09-23 0intro */
426 6f4d00ee 2013-09-23 0intro m->r.nstat = dirDe2M(&de, m->data, m->con->msize);
427 6f4d00ee 2013-09-23 0intro m->r.stat = m->data;
428 6f4d00ee 2013-09-23 0intro deCleanup(&de);
429 6f4d00ee 2013-09-23 0intro
430 6f4d00ee 2013-09-23 0intro return 1;
431 6f4d00ee 2013-09-23 0intro }
432 6f4d00ee 2013-09-23 0intro
433 6f4d00ee 2013-09-23 0intro static int
434 6f4d00ee 2013-09-23 0intro _rTclunk(Fid* fid, int remove)
435 6f4d00ee 2013-09-23 0intro {
436 6f4d00ee 2013-09-23 0intro int rok;
437 6f4d00ee 2013-09-23 0intro
438 6f4d00ee 2013-09-23 0intro if(fid->excl)
439 6f4d00ee 2013-09-23 0intro exclFree(fid);
440 6f4d00ee 2013-09-23 0intro
441 6f4d00ee 2013-09-23 0intro rok = 1;
442 6f4d00ee 2013-09-23 0intro if(remove && !(fid->qid.type & QTAUTH)){
443 6f4d00ee 2013-09-23 0intro if((rok = permParent(fid, PermW)) > 0)
444 6f4d00ee 2013-09-23 0intro rok = fileRemove(fid->file, fid->uid);
445 6f4d00ee 2013-09-23 0intro }
446 6f4d00ee 2013-09-23 0intro fidClunk(fid);
447 6f4d00ee 2013-09-23 0intro
448 6f4d00ee 2013-09-23 0intro return rok;
449 6f4d00ee 2013-09-23 0intro }
450 6f4d00ee 2013-09-23 0intro
451 6f4d00ee 2013-09-23 0intro static int
452 6f4d00ee 2013-09-23 0intro rTremove(Msg* m)
453 6f4d00ee 2013-09-23 0intro {
454 6f4d00ee 2013-09-23 0intro Fid *fid;
455 6f4d00ee 2013-09-23 0intro
456 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, FidFWlock)) == nil)
457 6f4d00ee 2013-09-23 0intro return 0;
458 6f4d00ee 2013-09-23 0intro return _rTclunk(fid, 1);
459 6f4d00ee 2013-09-23 0intro }
460 6f4d00ee 2013-09-23 0intro
461 6f4d00ee 2013-09-23 0intro static int
462 6f4d00ee 2013-09-23 0intro rTclunk(Msg* m)
463 6f4d00ee 2013-09-23 0intro {
464 6f4d00ee 2013-09-23 0intro Fid *fid;
465 6f4d00ee 2013-09-23 0intro
466 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, FidFWlock)) == nil)
467 6f4d00ee 2013-09-23 0intro return 0;
468 6f4d00ee 2013-09-23 0intro _rTclunk(fid, (fid->open & FidORclose));
469 6f4d00ee 2013-09-23 0intro
470 6f4d00ee 2013-09-23 0intro return 1;
471 6f4d00ee 2013-09-23 0intro }
472 6f4d00ee 2013-09-23 0intro
473 6f4d00ee 2013-09-23 0intro static int
474 6f4d00ee 2013-09-23 0intro rTwrite(Msg* m)
475 6f4d00ee 2013-09-23 0intro {
476 6f4d00ee 2013-09-23 0intro Fid *fid;
477 6f4d00ee 2013-09-23 0intro int count, n;
478 6f4d00ee 2013-09-23 0intro
479 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, 0)) == nil)
480 6f4d00ee 2013-09-23 0intro return 0;
481 6f4d00ee 2013-09-23 0intro if(!(fid->open & FidOWrite)){
482 4b576658 2013-09-23 0intro werrstr("fid not open for write");
483 6f4d00ee 2013-09-23 0intro goto error;
484 6f4d00ee 2013-09-23 0intro }
485 6f4d00ee 2013-09-23 0intro
486 6f4d00ee 2013-09-23 0intro count = m->t.count;
487 6f4d00ee 2013-09-23 0intro if(count < 0 || count > m->con->msize-IOHDRSZ){
488 4b576658 2013-09-23 0intro werrstr("write count too big");
489 6f4d00ee 2013-09-23 0intro goto error;
490 6f4d00ee 2013-09-23 0intro }
491 6f4d00ee 2013-09-23 0intro if(m->t.offset < 0){
492 4b576658 2013-09-23 0intro werrstr("write offset negative");
493 6f4d00ee 2013-09-23 0intro goto error;
494 6f4d00ee 2013-09-23 0intro }
495 6f4d00ee 2013-09-23 0intro if(fid->excl != nil && !exclUpdate(fid))
496 6f4d00ee 2013-09-23 0intro goto error;
497 6f4d00ee 2013-09-23 0intro
498 6f4d00ee 2013-09-23 0intro if(fid->qid.type & QTDIR){
499 4b576658 2013-09-23 0intro werrstr("is a directory");
500 6f4d00ee 2013-09-23 0intro goto error;
501 6f4d00ee 2013-09-23 0intro }
502 6f4d00ee 2013-09-23 0intro else if(fid->qid.type & QTAUTH)
503 6f4d00ee 2013-09-23 0intro n = authWrite(fid, m->t.data, count);
504 6f4d00ee 2013-09-23 0intro else
505 6f4d00ee 2013-09-23 0intro n = fileWrite(fid->file, m->t.data, count, m->t.offset, fid->uid);
506 6f4d00ee 2013-09-23 0intro if(n < 0)
507 6f4d00ee 2013-09-23 0intro goto error;
508 6f4d00ee 2013-09-23 0intro
509 6f4d00ee 2013-09-23 0intro
510 6f4d00ee 2013-09-23 0intro m->r.count = n;
511 6f4d00ee 2013-09-23 0intro
512 6f4d00ee 2013-09-23 0intro fidPut(fid);
513 6f4d00ee 2013-09-23 0intro return 1;
514 6f4d00ee 2013-09-23 0intro
515 6f4d00ee 2013-09-23 0intro error:
516 6f4d00ee 2013-09-23 0intro fidPut(fid);
517 6f4d00ee 2013-09-23 0intro return 0;
518 6f4d00ee 2013-09-23 0intro }
519 6f4d00ee 2013-09-23 0intro
520 6f4d00ee 2013-09-23 0intro static int
521 6f4d00ee 2013-09-23 0intro rTread(Msg* m)
522 6f4d00ee 2013-09-23 0intro {
523 6f4d00ee 2013-09-23 0intro Fid *fid;
524 6f4d00ee 2013-09-23 0intro uchar *data;
525 6f4d00ee 2013-09-23 0intro int count, n;
526 6f4d00ee 2013-09-23 0intro
527 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, 0)) == nil)
528 6f4d00ee 2013-09-23 0intro return 0;
529 6f4d00ee 2013-09-23 0intro if(!(fid->open & FidORead)){
530 4b576658 2013-09-23 0intro werrstr("fid not open for read");
531 6f4d00ee 2013-09-23 0intro goto error;
532 6f4d00ee 2013-09-23 0intro }
533 6f4d00ee 2013-09-23 0intro
534 6f4d00ee 2013-09-23 0intro count = m->t.count;
535 6f4d00ee 2013-09-23 0intro if(count < 0 || count > m->con->msize-IOHDRSZ){
536 4b576658 2013-09-23 0intro werrstr("read count too big");
537 6f4d00ee 2013-09-23 0intro goto error;
538 6f4d00ee 2013-09-23 0intro }
539 6f4d00ee 2013-09-23 0intro if(m->t.offset < 0){
540 4b576658 2013-09-23 0intro werrstr("read offset negative");
541 6f4d00ee 2013-09-23 0intro goto error;
542 6f4d00ee 2013-09-23 0intro }
543 6f4d00ee 2013-09-23 0intro if(fid->excl != nil && !exclUpdate(fid))
544 6f4d00ee 2013-09-23 0intro goto error;
545 6f4d00ee 2013-09-23 0intro
546 6f4d00ee 2013-09-23 0intro /*
547 6f4d00ee 2013-09-23 0intro * TODO: optimise this copy (in convS2M) away somehow.
548 6f4d00ee 2013-09-23 0intro * This pettifoggery with m->data will do for the moment.
549 6f4d00ee 2013-09-23 0intro */
550 6f4d00ee 2013-09-23 0intro data = m->data+IOHDRSZ;
551 6f4d00ee 2013-09-23 0intro if(fid->qid.type & QTDIR)
552 6f4d00ee 2013-09-23 0intro n = dirRead(fid, data, count, m->t.offset);
553 6f4d00ee 2013-09-23 0intro else if(fid->qid.type & QTAUTH)
554 6f4d00ee 2013-09-23 0intro n = authRead(fid, data, count);
555 6f4d00ee 2013-09-23 0intro else
556 6f4d00ee 2013-09-23 0intro n = fileRead(fid->file, data, count, m->t.offset);
557 6f4d00ee 2013-09-23 0intro if(n < 0)
558 6f4d00ee 2013-09-23 0intro goto error;
559 6f4d00ee 2013-09-23 0intro
560 6f4d00ee 2013-09-23 0intro m->r.count = n;
561 6f4d00ee 2013-09-23 0intro m->r.data = (char*)data;
562 6f4d00ee 2013-09-23 0intro
563 6f4d00ee 2013-09-23 0intro fidPut(fid);
564 6f4d00ee 2013-09-23 0intro return 1;
565 6f4d00ee 2013-09-23 0intro
566 6f4d00ee 2013-09-23 0intro error:
567 6f4d00ee 2013-09-23 0intro fidPut(fid);
568 6f4d00ee 2013-09-23 0intro return 0;
569 6f4d00ee 2013-09-23 0intro }
570 6f4d00ee 2013-09-23 0intro
571 6f4d00ee 2013-09-23 0intro static int
572 6f4d00ee 2013-09-23 0intro rTcreate(Msg* m)
573 6f4d00ee 2013-09-23 0intro {
574 6f4d00ee 2013-09-23 0intro Fid *fid;
575 6f4d00ee 2013-09-23 0intro File *file;
576 6f4d00ee 2013-09-23 0intro ulong mode;
577 6f4d00ee 2013-09-23 0intro int omode, open, perm;
578 6f4d00ee 2013-09-23 0intro
579 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, FidFWlock)) == nil)
580 6f4d00ee 2013-09-23 0intro return 0;
581 6f4d00ee 2013-09-23 0intro if(fid->open){
582 4b576658 2013-09-23 0intro werrstr("fid open for I/O");
583 6f4d00ee 2013-09-23 0intro goto error;
584 6f4d00ee 2013-09-23 0intro }
585 6f4d00ee 2013-09-23 0intro if(fileIsRoFs(fid->file) || !groupWriteMember(fid->uname)){
586 4b576658 2013-09-23 0intro werrstr("read-only filesystem");
587 6f4d00ee 2013-09-23 0intro goto error;
588 6f4d00ee 2013-09-23 0intro }
589 6f4d00ee 2013-09-23 0intro if(!fileIsDir(fid->file)){
590 4b576658 2013-09-23 0intro werrstr("not a directory");
591 6f4d00ee 2013-09-23 0intro goto error;
592 6f4d00ee 2013-09-23 0intro }
593 6f4d00ee 2013-09-23 0intro if(permFid(fid, PermW) <= 0)
594 6f4d00ee 2013-09-23 0intro goto error;
595 6f4d00ee 2013-09-23 0intro if(!validFileName(m->t.name))
596 6f4d00ee 2013-09-23 0intro goto error;
597 6f4d00ee 2013-09-23 0intro if(strcmp(fid->uid, uidnoworld) == 0){
598 4b576658 2013-09-23 0intro werrstr(EPermission);
599 6f4d00ee 2013-09-23 0intro goto error;
600 6f4d00ee 2013-09-23 0intro }
601 6f4d00ee 2013-09-23 0intro
602 6f4d00ee 2013-09-23 0intro omode = m->t.mode & OMODE;
603 6f4d00ee 2013-09-23 0intro open = 0;
604 6f4d00ee 2013-09-23 0intro
605 6f4d00ee 2013-09-23 0intro if(omode == OREAD || omode == ORDWR || omode == OEXEC)
606 6f4d00ee 2013-09-23 0intro open |= FidORead;
607 6f4d00ee 2013-09-23 0intro if(omode == OWRITE || omode == ORDWR)
608 6f4d00ee 2013-09-23 0intro open |= FidOWrite;
609 6f4d00ee 2013-09-23 0intro if((open & (FidOWrite|FidORead)) == 0){
610 4b576658 2013-09-23 0intro werrstr("unknown mode");
611 6f4d00ee 2013-09-23 0intro goto error;
612 6f4d00ee 2013-09-23 0intro }
613 6f4d00ee 2013-09-23 0intro if(m->t.perm & DMDIR){
614 6f4d00ee 2013-09-23 0intro if((m->t.mode & (ORCLOSE|OTRUNC)) || (open & FidOWrite)){
615 4b576658 2013-09-23 0intro werrstr("illegal mode");
616 6f4d00ee 2013-09-23 0intro goto error;
617 6f4d00ee 2013-09-23 0intro }
618 6f4d00ee 2013-09-23 0intro if(m->t.perm & DMAPPEND){
619 4b576658 2013-09-23 0intro werrstr("illegal perm");
620 6f4d00ee 2013-09-23 0intro goto error;
621 6f4d00ee 2013-09-23 0intro }
622 6f4d00ee 2013-09-23 0intro }
623 6f4d00ee 2013-09-23 0intro
624 6f4d00ee 2013-09-23 0intro mode = fileGetMode(fid->file);
625 6f4d00ee 2013-09-23 0intro perm = m->t.perm;
626 6f4d00ee 2013-09-23 0intro if(m->t.perm & DMDIR)
627 6f4d00ee 2013-09-23 0intro perm &= ~0777|(mode & 0777);
628 6f4d00ee 2013-09-23 0intro else
629 6f4d00ee 2013-09-23 0intro perm &= ~0666|(mode & 0666);
630 6f4d00ee 2013-09-23 0intro mode = perm & 0777;
631 6f4d00ee 2013-09-23 0intro if(m->t.perm & DMDIR)
632 6f4d00ee 2013-09-23 0intro mode |= ModeDir;
633 6f4d00ee 2013-09-23 0intro if(m->t.perm & DMAPPEND)
634 6f4d00ee 2013-09-23 0intro mode |= ModeAppend;
635 6f4d00ee 2013-09-23 0intro if(m->t.perm & DMEXCL)
636 6f4d00ee 2013-09-23 0intro mode |= ModeExclusive;
637 6f4d00ee 2013-09-23 0intro if(m->t.perm & DMTMP)
638 6f4d00ee 2013-09-23 0intro mode |= ModeTemporary;
639 6f4d00ee 2013-09-23 0intro
640 6f4d00ee 2013-09-23 0intro if((file = fileCreate(fid->file, m->t.name, mode, fid->uid)) == nil){
641 6f4d00ee 2013-09-23 0intro fidPut(fid);
642 6f4d00ee 2013-09-23 0intro return 0;
643 6f4d00ee 2013-09-23 0intro }
644 6f4d00ee 2013-09-23 0intro fileDecRef(fid->file);
645 6f4d00ee 2013-09-23 0intro
646 6f4d00ee 2013-09-23 0intro fid->qid.vers = fileGetMcount(file);
647 6f4d00ee 2013-09-23 0intro fid->qid.path = fileGetId(file);
648 6f4d00ee 2013-09-23 0intro fid->file = file;
649 6f4d00ee 2013-09-23 0intro mode = fileGetMode(fid->file);
650 6f4d00ee 2013-09-23 0intro if(mode & ModeDir)
651 6f4d00ee 2013-09-23 0intro fid->qid.type = QTDIR;
652 6f4d00ee 2013-09-23 0intro else
653 6f4d00ee 2013-09-23 0intro fid->qid.type = QTFILE;
654 6f4d00ee 2013-09-23 0intro if(mode & ModeAppend)
655 6f4d00ee 2013-09-23 0intro fid->qid.type |= QTAPPEND;
656 6f4d00ee 2013-09-23 0intro if(mode & ModeExclusive){
657 6f4d00ee 2013-09-23 0intro fid->qid.type |= QTEXCL;
658 6f4d00ee 2013-09-23 0intro assert(exclAlloc(fid) != 0);
659 6f4d00ee 2013-09-23 0intro }
660 6f4d00ee 2013-09-23 0intro if(m->t.mode & ORCLOSE)
661 6f4d00ee 2013-09-23 0intro open |= FidORclose;
662 6f4d00ee 2013-09-23 0intro fid->open = open;
663 6f4d00ee 2013-09-23 0intro
664 6f4d00ee 2013-09-23 0intro m->r.qid = fid->qid;
665 6f4d00ee 2013-09-23 0intro m->r.iounit = m->con->msize-IOHDRSZ;
666 6f4d00ee 2013-09-23 0intro
667 6f4d00ee 2013-09-23 0intro fidPut(fid);
668 6f4d00ee 2013-09-23 0intro return 1;
669 6f4d00ee 2013-09-23 0intro
670 6f4d00ee 2013-09-23 0intro error:
671 6f4d00ee 2013-09-23 0intro fidPut(fid);
672 6f4d00ee 2013-09-23 0intro return 0;
673 6f4d00ee 2013-09-23 0intro }
674 6f4d00ee 2013-09-23 0intro
675 6f4d00ee 2013-09-23 0intro static int
676 6f4d00ee 2013-09-23 0intro rTopen(Msg* m)
677 6f4d00ee 2013-09-23 0intro {
678 6f4d00ee 2013-09-23 0intro Fid *fid;
679 6f4d00ee 2013-09-23 0intro int isdir, mode, omode, open, rofs;
680 6f4d00ee 2013-09-23 0intro
681 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, FidFWlock)) == nil)
682 6f4d00ee 2013-09-23 0intro return 0;
683 6f4d00ee 2013-09-23 0intro if(fid->open){
684 4b576658 2013-09-23 0intro werrstr("fid open for I/O");
685 6f4d00ee 2013-09-23 0intro goto error;
686 6f4d00ee 2013-09-23 0intro }
687 6f4d00ee 2013-09-23 0intro
688 6f4d00ee 2013-09-23 0intro isdir = fileIsDir(fid->file);
689 6f4d00ee 2013-09-23 0intro open = 0;
690 6f4d00ee 2013-09-23 0intro rofs = fileIsRoFs(fid->file) || !groupWriteMember(fid->uname);
691 6f4d00ee 2013-09-23 0intro
692 6f4d00ee 2013-09-23 0intro if(m->t.mode & ORCLOSE){
693 6f4d00ee 2013-09-23 0intro if(isdir){
694 4b576658 2013-09-23 0intro werrstr("is a directory");
695 6f4d00ee 2013-09-23 0intro goto error;
696 6f4d00ee 2013-09-23 0intro }
697 6f4d00ee 2013-09-23 0intro if(rofs){
698 4b576658 2013-09-23 0intro werrstr("read-only filesystem");
699 6f4d00ee 2013-09-23 0intro goto error;
700 6f4d00ee 2013-09-23 0intro }
701 6f4d00ee 2013-09-23 0intro if(permParent(fid, PermW) <= 0)
702 6f4d00ee 2013-09-23 0intro goto error;
703 6f4d00ee 2013-09-23 0intro
704 6f4d00ee 2013-09-23 0intro open |= FidORclose;
705 6f4d00ee 2013-09-23 0intro }
706 6f4d00ee 2013-09-23 0intro
707 6f4d00ee 2013-09-23 0intro omode = m->t.mode & OMODE;
708 6f4d00ee 2013-09-23 0intro if(omode == OREAD || omode == ORDWR){
709 6f4d00ee 2013-09-23 0intro if(permFid(fid, PermR) <= 0)
710 6f4d00ee 2013-09-23 0intro goto error;
711 6f4d00ee 2013-09-23 0intro open |= FidORead;
712 6f4d00ee 2013-09-23 0intro }
713 6f4d00ee 2013-09-23 0intro if(omode == OWRITE || omode == ORDWR || (m->t.mode & OTRUNC)){
714 6f4d00ee 2013-09-23 0intro if(isdir){
715 4b576658 2013-09-23 0intro werrstr("is a directory");
716 6f4d00ee 2013-09-23 0intro goto error;
717 6f4d00ee 2013-09-23 0intro }
718 6f4d00ee 2013-09-23 0intro if(rofs){
719 4b576658 2013-09-23 0intro werrstr("read-only filesystem");
720 6f4d00ee 2013-09-23 0intro goto error;
721 6f4d00ee 2013-09-23 0intro }
722 6f4d00ee 2013-09-23 0intro if(permFid(fid, PermW) <= 0)
723 6f4d00ee 2013-09-23 0intro goto error;
724 6f4d00ee 2013-09-23 0intro open |= FidOWrite;
725 6f4d00ee 2013-09-23 0intro }
726 6f4d00ee 2013-09-23 0intro if(omode == OEXEC){
727 6f4d00ee 2013-09-23 0intro if(isdir){
728 4b576658 2013-09-23 0intro werrstr("is a directory");
729 6f4d00ee 2013-09-23 0intro goto error;
730 6f4d00ee 2013-09-23 0intro }
731 6f4d00ee 2013-09-23 0intro if(permFid(fid, PermX) <= 0)
732 6f4d00ee 2013-09-23 0intro goto error;
733 6f4d00ee 2013-09-23 0intro open |= FidORead;
734 6f4d00ee 2013-09-23 0intro }
735 6f4d00ee 2013-09-23 0intro if((open & (FidOWrite|FidORead)) == 0){
736 4b576658 2013-09-23 0intro werrstr("unknown mode");
737 6f4d00ee 2013-09-23 0intro goto error;
738 6f4d00ee 2013-09-23 0intro }
739 6f4d00ee 2013-09-23 0intro
740 6f4d00ee 2013-09-23 0intro mode = fileGetMode(fid->file);
741 6f4d00ee 2013-09-23 0intro if((mode & ModeExclusive) && exclAlloc(fid) == 0)
742 6f4d00ee 2013-09-23 0intro goto error;
743 6f4d00ee 2013-09-23 0intro
744 6f4d00ee 2013-09-23 0intro /*
745 6f4d00ee 2013-09-23 0intro * Everything checks out, try to commit any changes.
746 6f4d00ee 2013-09-23 0intro */
747 6f4d00ee 2013-09-23 0intro if((m->t.mode & OTRUNC) && !(mode & ModeAppend))
748 6f4d00ee 2013-09-23 0intro if(!fileTruncate(fid->file, fid->uid))
749 6f4d00ee 2013-09-23 0intro goto error;
750 6f4d00ee 2013-09-23 0intro
751 6f4d00ee 2013-09-23 0intro if(isdir && fid->db != nil){
752 6f4d00ee 2013-09-23 0intro dirBufFree(fid->db);
753 6f4d00ee 2013-09-23 0intro fid->db = nil;
754 6f4d00ee 2013-09-23 0intro }
755 6f4d00ee 2013-09-23 0intro
756 6f4d00ee 2013-09-23 0intro fid->qid.vers = fileGetMcount(fid->file);
757 6f4d00ee 2013-09-23 0intro m->r.qid = fid->qid;
758 6f4d00ee 2013-09-23 0intro m->r.iounit = m->con->msize-IOHDRSZ;
759 6f4d00ee 2013-09-23 0intro
760 6f4d00ee 2013-09-23 0intro fid->open = open;
761 6f4d00ee 2013-09-23 0intro
762 6f4d00ee 2013-09-23 0intro fidPut(fid);
763 6f4d00ee 2013-09-23 0intro return 1;
764 6f4d00ee 2013-09-23 0intro
765 6f4d00ee 2013-09-23 0intro error:
766 6f4d00ee 2013-09-23 0intro if(fid->excl != nil)
767 6f4d00ee 2013-09-23 0intro exclFree(fid);
768 6f4d00ee 2013-09-23 0intro fidPut(fid);
769 6f4d00ee 2013-09-23 0intro return 0;
770 6f4d00ee 2013-09-23 0intro }
771 6f4d00ee 2013-09-23 0intro
772 6f4d00ee 2013-09-23 0intro static int
773 6f4d00ee 2013-09-23 0intro rTwalk(Msg* m)
774 6f4d00ee 2013-09-23 0intro {
775 6f4d00ee 2013-09-23 0intro Qid qid;
776 6f4d00ee 2013-09-23 0intro Fcall *r, *t;
777 6f4d00ee 2013-09-23 0intro int nwname, wlock;
778 6f4d00ee 2013-09-23 0intro File *file, *nfile;
779 6f4d00ee 2013-09-23 0intro Fid *fid, *ofid, *nfid;
780 6f4d00ee 2013-09-23 0intro
781 6f4d00ee 2013-09-23 0intro t = &m->t;
782 6f4d00ee 2013-09-23 0intro if(t->fid == t->newfid)
783 6f4d00ee 2013-09-23 0intro wlock = FidFWlock;
784 6f4d00ee 2013-09-23 0intro else
785 6f4d00ee 2013-09-23 0intro wlock = 0;
786 6f4d00ee 2013-09-23 0intro
787 6f4d00ee 2013-09-23 0intro /*
788 6f4d00ee 2013-09-23 0intro * The file identified by t->fid must be valid in the
789 6f4d00ee 2013-09-23 0intro * current session and must not have been opened for I/O
790 6f4d00ee 2013-09-23 0intro * by an open or create message.
791 6f4d00ee 2013-09-23 0intro */
792 6f4d00ee 2013-09-23 0intro if((ofid = fidGet(m->con, t->fid, wlock)) == nil)
793 6f4d00ee 2013-09-23 0intro return 0;
794 6f4d00ee 2013-09-23 0intro if(ofid->open){
795 4b576658 2013-09-23 0intro werrstr("file open for I/O");
796 6f4d00ee 2013-09-23 0intro fidPut(ofid);
797 6f4d00ee 2013-09-23 0intro return 0;
798 6f4d00ee 2013-09-23 0intro }
799 6f4d00ee 2013-09-23 0intro
800 6f4d00ee 2013-09-23 0intro /*
801 6f4d00ee 2013-09-23 0intro * If newfid is not the same as fid, allocate a new file;
802 6f4d00ee 2013-09-23 0intro * a side effect is checking newfid is not already in use (error);
803 6f4d00ee 2013-09-23 0intro * if there are no names to walk this will be equivalent to a
804 6f4d00ee 2013-09-23 0intro * simple 'clone' operation.
805 6f4d00ee 2013-09-23 0intro * It's a no-op if newfid is the same as fid and t->nwname is 0.
806 6f4d00ee 2013-09-23 0intro */
807 6f4d00ee 2013-09-23 0intro nfid = nil;
808 6f4d00ee 2013-09-23 0intro if(t->fid != t->newfid){
809 6f4d00ee 2013-09-23 0intro nfid = fidGet(m->con, t->newfid, FidFWlock|FidFCreate);
810 6f4d00ee 2013-09-23 0intro if(nfid == nil){
811 4b576658 2013-09-23 0intro werrstr("%s: walk: newfid 0x%ud in use",
812 6f4d00ee 2013-09-23 0intro argv0, t->newfid);
813 6f4d00ee 2013-09-23 0intro fidPut(ofid);
814 6f4d00ee 2013-09-23 0intro return 0;
815 6f4d00ee 2013-09-23 0intro }
816 6f4d00ee 2013-09-23 0intro nfid->open = ofid->open & ~FidORclose;
817 6f4d00ee 2013-09-23 0intro nfid->file = fileIncRef(ofid->file);
818 6f4d00ee 2013-09-23 0intro nfid->qid = ofid->qid;
819 4b576658 2013-09-23 0intro nfid->uid = vtstrdup(ofid->uid);
820 4b576658 2013-09-23 0intro nfid->uname = vtstrdup(ofid->uname);
821 6f4d00ee 2013-09-23 0intro nfid->fsys = fsysIncRef(ofid->fsys);
822 6f4d00ee 2013-09-23 0intro fid = nfid;
823 6f4d00ee 2013-09-23 0intro }
824 6f4d00ee 2013-09-23 0intro else
825 6f4d00ee 2013-09-23 0intro fid = ofid;
826 6f4d00ee 2013-09-23 0intro
827 6f4d00ee 2013-09-23 0intro r = &m->r;
828 6f4d00ee 2013-09-23 0intro r->nwqid = 0;
829 6f4d00ee 2013-09-23 0intro
830 6f4d00ee 2013-09-23 0intro if(t->nwname == 0){
831 6f4d00ee 2013-09-23 0intro if(nfid != nil)
832 6f4d00ee 2013-09-23 0intro fidPut(nfid);
833 6f4d00ee 2013-09-23 0intro fidPut(ofid);
834 6f4d00ee 2013-09-23 0intro
835 6f4d00ee 2013-09-23 0intro return 1;
836 6f4d00ee 2013-09-23 0intro }
837 6f4d00ee 2013-09-23 0intro
838 6f4d00ee 2013-09-23 0intro file = fid->file;
839 6f4d00ee 2013-09-23 0intro fileIncRef(file);
840 6f4d00ee 2013-09-23 0intro qid = fid->qid;
841 6f4d00ee 2013-09-23 0intro
842 6f4d00ee 2013-09-23 0intro for(nwname = 0; nwname < t->nwname; nwname++){
843 6f4d00ee 2013-09-23 0intro /*
844 6f4d00ee 2013-09-23 0intro * Walked elements must represent a directory and
845 6f4d00ee 2013-09-23 0intro * the implied user must have permission to search
846 6f4d00ee 2013-09-23 0intro * the directory. Walking .. is always allowed, so that
847 6f4d00ee 2013-09-23 0intro * you can't walk into a directory and then not be able
848 6f4d00ee 2013-09-23 0intro * to walk out of it.
849 6f4d00ee 2013-09-23 0intro */
850 6f4d00ee 2013-09-23 0intro if(!(qid.type & QTDIR)){
851 4b576658 2013-09-23 0intro werrstr("not a directory");
852 6f4d00ee 2013-09-23 0intro break;
853 6f4d00ee 2013-09-23 0intro }
854 6f4d00ee 2013-09-23 0intro switch(permFile(file, fid, PermX)){
855 6f4d00ee 2013-09-23 0intro case 1:
856 6f4d00ee 2013-09-23 0intro break;
857 6f4d00ee 2013-09-23 0intro case 0:
858 6f4d00ee 2013-09-23 0intro if(strcmp(t->wname[nwname], "..") == 0)
859 6f4d00ee 2013-09-23 0intro break;
860 6f4d00ee 2013-09-23 0intro case -1:
861 6f4d00ee 2013-09-23 0intro goto Out;
862 6f4d00ee 2013-09-23 0intro }
863 6f4d00ee 2013-09-23 0intro if((nfile = fileWalk(file, t->wname[nwname])) == nil)
864 6f4d00ee 2013-09-23 0intro break;
865 6f4d00ee 2013-09-23 0intro fileDecRef(file);
866 6f4d00ee 2013-09-23 0intro file = nfile;
867 6f4d00ee 2013-09-23 0intro qid.type = QTFILE;
868 6f4d00ee 2013-09-23 0intro if(fileIsDir(file))
869 6f4d00ee 2013-09-23 0intro qid.type = QTDIR;
870 6f4d00ee 2013-09-23 0intro if(fileIsAppend(file))
871 6f4d00ee 2013-09-23 0intro qid.type |= QTAPPEND;
872 6f4d00ee 2013-09-23 0intro if(fileIsTemporary(file))
873 6f4d00ee 2013-09-23 0intro qid.type |= QTTMP;
874 6f4d00ee 2013-09-23 0intro if(fileIsExclusive(file))
875 6f4d00ee 2013-09-23 0intro qid.type |= QTEXCL;
876 6f4d00ee 2013-09-23 0intro qid.vers = fileGetMcount(file);
877 6f4d00ee 2013-09-23 0intro qid.path = fileGetId(file);
878 6f4d00ee 2013-09-23 0intro r->wqid[r->nwqid++] = qid;
879 6f4d00ee 2013-09-23 0intro }
880 6f4d00ee 2013-09-23 0intro
881 6f4d00ee 2013-09-23 0intro if(nwname == t->nwname){
882 6f4d00ee 2013-09-23 0intro /*
883 6f4d00ee 2013-09-23 0intro * Walked all elements. Update the target fid
884 6f4d00ee 2013-09-23 0intro * from the temporary qid used during the walk,
885 6f4d00ee 2013-09-23 0intro * and tidy up.
886 6f4d00ee 2013-09-23 0intro */
887 6f4d00ee 2013-09-23 0intro fid->qid = r->wqid[r->nwqid-1];
888 6f4d00ee 2013-09-23 0intro fileDecRef(fid->file);
889 6f4d00ee 2013-09-23 0intro fid->file = file;
890 6f4d00ee 2013-09-23 0intro
891 6f4d00ee 2013-09-23 0intro if(nfid != nil)
892 6f4d00ee 2013-09-23 0intro fidPut(nfid);
893 6f4d00ee 2013-09-23 0intro
894 6f4d00ee 2013-09-23 0intro fidPut(ofid);
895 6f4d00ee 2013-09-23 0intro return 1;
896 6f4d00ee 2013-09-23 0intro }
897 6f4d00ee 2013-09-23 0intro
898 6f4d00ee 2013-09-23 0intro Out:
899 6f4d00ee 2013-09-23 0intro /*
900 6f4d00ee 2013-09-23 0intro * Didn't walk all elements, 'clunk' nfid if it exists
901 6f4d00ee 2013-09-23 0intro * and leave fid untouched.
902 6f4d00ee 2013-09-23 0intro * It's not an error if some of the elements were walked OK.
903 6f4d00ee 2013-09-23 0intro */
904 6f4d00ee 2013-09-23 0intro fileDecRef(file);
905 6f4d00ee 2013-09-23 0intro if(nfid != nil)
906 6f4d00ee 2013-09-23 0intro fidClunk(nfid);
907 6f4d00ee 2013-09-23 0intro
908 6f4d00ee 2013-09-23 0intro fidPut(ofid);
909 6f4d00ee 2013-09-23 0intro if(nwname == 0)
910 6f4d00ee 2013-09-23 0intro return 0;
911 6f4d00ee 2013-09-23 0intro return 1;
912 6f4d00ee 2013-09-23 0intro }
913 6f4d00ee 2013-09-23 0intro
914 6f4d00ee 2013-09-23 0intro static int
915 6f4d00ee 2013-09-23 0intro rTflush(Msg* m)
916 6f4d00ee 2013-09-23 0intro {
917 6f4d00ee 2013-09-23 0intro if(m->t.oldtag != NOTAG)
918 6f4d00ee 2013-09-23 0intro msgFlush(m);
919 6f4d00ee 2013-09-23 0intro return 1;
920 6f4d00ee 2013-09-23 0intro }
921 6f4d00ee 2013-09-23 0intro
922 6f4d00ee 2013-09-23 0intro static void
923 6f4d00ee 2013-09-23 0intro parseAname(char *aname, char **fsname, char **path)
924 6f4d00ee 2013-09-23 0intro {
925 6f4d00ee 2013-09-23 0intro char *s;
926 6f4d00ee 2013-09-23 0intro
927 6f4d00ee 2013-09-23 0intro if(aname && aname[0])
928 4b576658 2013-09-23 0intro s = vtstrdup(aname);
929 6f4d00ee 2013-09-23 0intro else
930 4b576658 2013-09-23 0intro s = vtstrdup("main/active");
931 6f4d00ee 2013-09-23 0intro *fsname = s;
932 6f4d00ee 2013-09-23 0intro if((*path = strchr(s, '/')) != nil)
933 6f4d00ee 2013-09-23 0intro *(*path)++ = '\0';
934 6f4d00ee 2013-09-23 0intro else
935 6f4d00ee 2013-09-23 0intro *path = "";
936 6f4d00ee 2013-09-23 0intro }
937 6f4d00ee 2013-09-23 0intro
938 b32de4ae 2013-09-26 0intro #ifndef PLAN9PORT
939 6f4d00ee 2013-09-23 0intro /*
940 6f4d00ee 2013-09-23 0intro * Check remote IP address against /mnt/ipok.
941 6f4d00ee 2013-09-23 0intro * Sources.cs.bell-labs.com uses this to disallow
942 fa325e9b 2020-01-10 cross * network connections from Sudan, Libya, etc.,
943 6f4d00ee 2013-09-23 0intro * following U.S. cryptography export regulations.
944 6f4d00ee 2013-09-23 0intro */
945 6f4d00ee 2013-09-23 0intro static int
946 6f4d00ee 2013-09-23 0intro conIPCheck(Con* con)
947 6f4d00ee 2013-09-23 0intro {
948 6f4d00ee 2013-09-23 0intro char ok[256], *p;
949 6f4d00ee 2013-09-23 0intro int fd;
950 6f4d00ee 2013-09-23 0intro
951 6f4d00ee 2013-09-23 0intro if(con->flags&ConIPCheck){
952 6f4d00ee 2013-09-23 0intro if(con->remote[0] == 0){
953 4b576658 2013-09-23 0intro werrstr("cannot verify unknown remote address");
954 6f4d00ee 2013-09-23 0intro return 0;
955 6f4d00ee 2013-09-23 0intro }
956 6f4d00ee 2013-09-23 0intro if(access("/mnt/ipok/ok", AEXIST) < 0){
957 6f4d00ee 2013-09-23 0intro /* mount closes the fd on success */
958 fa325e9b 2020-01-10 cross if((fd = open("/srv/ipok", ORDWR)) >= 0
959 6f4d00ee 2013-09-23 0intro && mount(fd, -1, "/mnt/ipok", MREPL, "") < 0)
960 6f4d00ee 2013-09-23 0intro close(fd);
961 6f4d00ee 2013-09-23 0intro if(access("/mnt/ipok/ok", AEXIST) < 0){
962 4b576658 2013-09-23 0intro werrstr("cannot verify remote address");
963 6f4d00ee 2013-09-23 0intro return 0;
964 6f4d00ee 2013-09-23 0intro }
965 6f4d00ee 2013-09-23 0intro }
966 6f4d00ee 2013-09-23 0intro snprint(ok, sizeof ok, "/mnt/ipok/ok/%s", con->remote);
967 6f4d00ee 2013-09-23 0intro if((p = strchr(ok, '!')) != nil)
968 6f4d00ee 2013-09-23 0intro *p = 0;
969 6f4d00ee 2013-09-23 0intro if(access(ok, AEXIST) < 0){
970 4b576658 2013-09-23 0intro werrstr("restricted remote address");
971 6f4d00ee 2013-09-23 0intro return 0;
972 6f4d00ee 2013-09-23 0intro }
973 6f4d00ee 2013-09-23 0intro }
974 6f4d00ee 2013-09-23 0intro return 1;
975 6f4d00ee 2013-09-23 0intro }
976 b32de4ae 2013-09-26 0intro #endif
977 6f4d00ee 2013-09-23 0intro
978 6f4d00ee 2013-09-23 0intro static int
979 6f4d00ee 2013-09-23 0intro rTattach(Msg* m)
980 6f4d00ee 2013-09-23 0intro {
981 6f4d00ee 2013-09-23 0intro Fid *fid;
982 6f4d00ee 2013-09-23 0intro Fsys *fsys;
983 6f4d00ee 2013-09-23 0intro char *fsname, *path;
984 6f4d00ee 2013-09-23 0intro
985 6f4d00ee 2013-09-23 0intro if((fid = fidGet(m->con, m->t.fid, FidFWlock|FidFCreate)) == nil)
986 6f4d00ee 2013-09-23 0intro return 0;
987 6f4d00ee 2013-09-23 0intro
988 6f4d00ee 2013-09-23 0intro parseAname(m->t.aname, &fsname, &path);
989 6f4d00ee 2013-09-23 0intro if((fsys = fsysGet(fsname)) == nil){
990 6f4d00ee 2013-09-23 0intro fidClunk(fid);
991 4b576658 2013-09-23 0intro vtfree(fsname);
992 6f4d00ee 2013-09-23 0intro return 0;
993 6f4d00ee 2013-09-23 0intro }
994 6f4d00ee 2013-09-23 0intro fid->fsys = fsys;
995 6f4d00ee 2013-09-23 0intro
996 6f4d00ee 2013-09-23 0intro if(m->t.uname[0] != '\0')
997 4b576658 2013-09-23 0intro fid->uname = vtstrdup(m->t.uname);
998 6f4d00ee 2013-09-23 0intro else
999 4b576658 2013-09-23 0intro fid->uname = vtstrdup(unamenone);
1000 6f4d00ee 2013-09-23 0intro
1001 b32de4ae 2013-09-26 0intro #ifndef PLAN9PORT
1002 6f4d00ee 2013-09-23 0intro if((fid->con->flags&ConIPCheck) && !conIPCheck(fid->con)){
1003 4b576658 2013-09-23 0intro consPrint("reject %s from %s: %r\n", fid->uname, fid->con->remote);
1004 6f4d00ee 2013-09-23 0intro fidClunk(fid);
1005 4b576658 2013-09-23 0intro vtfree(fsname);
1006 6f4d00ee 2013-09-23 0intro return 0;
1007 6f4d00ee 2013-09-23 0intro }
1008 b32de4ae 2013-09-26 0intro #endif
1009 6f4d00ee 2013-09-23 0intro if(fsysNoAuthCheck(fsys) || (m->con->flags&ConNoAuthCheck)){
1010 6f4d00ee 2013-09-23 0intro if((fid->uid = uidByUname(fid->uname)) == nil)
1011 4b576658 2013-09-23 0intro fid->uid = vtstrdup(unamenone);
1012 6f4d00ee 2013-09-23 0intro }
1013 6f4d00ee 2013-09-23 0intro else if(!authCheck(&m->t, fid, fsys)){
1014 6f4d00ee 2013-09-23 0intro fidClunk(fid);
1015 4b576658 2013-09-23 0intro vtfree(fsname);
1016 6f4d00ee 2013-09-23 0intro return 0;
1017 6f4d00ee 2013-09-23 0intro }
1018 6f4d00ee 2013-09-23 0intro
1019 6f4d00ee 2013-09-23 0intro fsysFsRlock(fsys);
1020 6f4d00ee 2013-09-23 0intro if((fid->file = fsysGetRoot(fsys, path)) == nil){
1021 6f4d00ee 2013-09-23 0intro fsysFsRUnlock(fsys);
1022 6f4d00ee 2013-09-23 0intro fidClunk(fid);
1023 4b576658 2013-09-23 0intro vtfree(fsname);
1024 6f4d00ee 2013-09-23 0intro return 0;
1025 6f4d00ee 2013-09-23 0intro }
1026 6f4d00ee 2013-09-23 0intro fsysFsRUnlock(fsys);
1027 4b576658 2013-09-23 0intro vtfree(fsname);
1028 6f4d00ee 2013-09-23 0intro
1029 6f4d00ee 2013-09-23 0intro fid->qid = (Qid){fileGetId(fid->file), 0, QTDIR};
1030 6f4d00ee 2013-09-23 0intro m->r.qid = fid->qid;
1031 6f4d00ee 2013-09-23 0intro
1032 6f4d00ee 2013-09-23 0intro fidPut(fid);
1033 6f4d00ee 2013-09-23 0intro return 1;
1034 6f4d00ee 2013-09-23 0intro }
1035 6f4d00ee 2013-09-23 0intro
1036 6f4d00ee 2013-09-23 0intro static int
1037 6f4d00ee 2013-09-23 0intro rTauth(Msg* m)
1038 6f4d00ee 2013-09-23 0intro {
1039 b32de4ae 2013-09-26 0intro #ifndef PLAN9PORT
1040 6f4d00ee 2013-09-23 0intro int afd;
1041 b32de4ae 2013-09-26 0intro #endif
1042 6f4d00ee 2013-09-23 0intro Con *con;
1043 6f4d00ee 2013-09-23 0intro Fid *afid;
1044 6f4d00ee 2013-09-23 0intro Fsys *fsys;
1045 6f4d00ee 2013-09-23 0intro char *fsname, *path;
1046 6f4d00ee 2013-09-23 0intro
1047 6f4d00ee 2013-09-23 0intro parseAname(m->t.aname, &fsname, &path);
1048 6f4d00ee 2013-09-23 0intro if((fsys = fsysGet(fsname)) == nil){
1049 4b576658 2013-09-23 0intro vtfree(fsname);
1050 6f4d00ee 2013-09-23 0intro return 0;
1051 6f4d00ee 2013-09-23 0intro }
1052 4b576658 2013-09-23 0intro vtfree(fsname);
1053 6f4d00ee 2013-09-23 0intro
1054 6f4d00ee 2013-09-23 0intro if(fsysNoAuthCheck(fsys) || (m->con->flags&ConNoAuthCheck)){
1055 6f4d00ee 2013-09-23 0intro m->con->aok = 1;
1056 4b576658 2013-09-23 0intro werrstr("authentication disabled");
1057 6f4d00ee 2013-09-23 0intro fsysPut(fsys);
1058 6f4d00ee 2013-09-23 0intro return 0;
1059 6f4d00ee 2013-09-23 0intro }
1060 6f4d00ee 2013-09-23 0intro if(strcmp(m->t.uname, unamenone) == 0){
1061 4b576658 2013-09-23 0intro werrstr("user 'none' requires no authentication");
1062 6f4d00ee 2013-09-23 0intro fsysPut(fsys);
1063 6f4d00ee 2013-09-23 0intro return 0;
1064 6f4d00ee 2013-09-23 0intro }
1065 6f4d00ee 2013-09-23 0intro
1066 6f4d00ee 2013-09-23 0intro con = m->con;
1067 6f4d00ee 2013-09-23 0intro if((afid = fidGet(con, m->t.afid, FidFWlock|FidFCreate)) == nil){
1068 6f4d00ee 2013-09-23 0intro fsysPut(fsys);
1069 6f4d00ee 2013-09-23 0intro return 0;
1070 6f4d00ee 2013-09-23 0intro }
1071 6f4d00ee 2013-09-23 0intro afid->fsys = fsys;
1072 6f4d00ee 2013-09-23 0intro
1073 b32de4ae 2013-09-26 0intro #ifndef PLAN9PORT
1074 6f4d00ee 2013-09-23 0intro if((afd = open("/mnt/factotum/rpc", ORDWR)) < 0){
1075 4b576658 2013-09-23 0intro werrstr("can't open \"/mnt/factotum/rpc\"");
1076 6f4d00ee 2013-09-23 0intro fidClunk(afid);
1077 6f4d00ee 2013-09-23 0intro return 0;
1078 6f4d00ee 2013-09-23 0intro }
1079 b32de4ae 2013-09-26 0intro #endif
1080 b32de4ae 2013-09-26 0intro
1081 b32de4ae 2013-09-26 0intro #ifdef PLAN9PORT
1082 b32de4ae 2013-09-26 0intro if((afid->rpc = auth_allocrpc()) == nil){
1083 b32de4ae 2013-09-26 0intro #else
1084 6f4d00ee 2013-09-23 0intro if((afid->rpc = auth_allocrpc(afd)) == nil){
1085 6f4d00ee 2013-09-23 0intro close(afd);
1086 b32de4ae 2013-09-26 0intro #endif
1087 4b576658 2013-09-23 0intro werrstr("can't auth_allocrpc");
1088 6f4d00ee 2013-09-23 0intro fidClunk(afid);
1089 6f4d00ee 2013-09-23 0intro return 0;
1090 6f4d00ee 2013-09-23 0intro }
1091 6f4d00ee 2013-09-23 0intro if(auth_rpc(afid->rpc, "start", "proto=p9any role=server", 23) != ARok){
1092 4b576658 2013-09-23 0intro werrstr("can't auth_rpc");
1093 6f4d00ee 2013-09-23 0intro fidClunk(afid);
1094 6f4d00ee 2013-09-23 0intro return 0;
1095 6f4d00ee 2013-09-23 0intro }
1096 6f4d00ee 2013-09-23 0intro
1097 6f4d00ee 2013-09-23 0intro afid->open = FidOWrite|FidORead;
1098 6f4d00ee 2013-09-23 0intro afid->qid.type = QTAUTH;
1099 6f4d00ee 2013-09-23 0intro afid->qid.path = m->t.afid;
1100 4b576658 2013-09-23 0intro afid->uname = vtstrdup(m->t.uname);
1101 6f4d00ee 2013-09-23 0intro
1102 6f4d00ee 2013-09-23 0intro m->r.qid = afid->qid;
1103 6f4d00ee 2013-09-23 0intro
1104 6f4d00ee 2013-09-23 0intro fidPut(afid);
1105 6f4d00ee 2013-09-23 0intro return 1;
1106 6f4d00ee 2013-09-23 0intro }
1107 6f4d00ee 2013-09-23 0intro
1108 6f4d00ee 2013-09-23 0intro static int
1109 6f4d00ee 2013-09-23 0intro rTversion(Msg* m)
1110 6f4d00ee 2013-09-23 0intro {
1111 6f4d00ee 2013-09-23 0intro int v;
1112 6f4d00ee 2013-09-23 0intro Con *con;
1113 6f4d00ee 2013-09-23 0intro Fcall *r, *t;
1114 6f4d00ee 2013-09-23 0intro
1115 6f4d00ee 2013-09-23 0intro t = &m->t;
1116 6f4d00ee 2013-09-23 0intro r = &m->r;
1117 6f4d00ee 2013-09-23 0intro con = m->con;
1118 6f4d00ee 2013-09-23 0intro
1119 4b576658 2013-09-23 0intro qlock(&con->lock);
1120 6f4d00ee 2013-09-23 0intro if(con->state != ConInit){
1121 4b576658 2013-09-23 0intro qunlock(&con->lock);
1122 4b576658 2013-09-23 0intro werrstr("Tversion: down");
1123 6f4d00ee 2013-09-23 0intro return 0;
1124 6f4d00ee 2013-09-23 0intro }
1125 6f4d00ee 2013-09-23 0intro con->state = ConNew;
1126 6f4d00ee 2013-09-23 0intro
1127 6f4d00ee 2013-09-23 0intro /*
1128 6f4d00ee 2013-09-23 0intro * Release the karma of past lives and suffering.
1129 6f4d00ee 2013-09-23 0intro * Should this be done before or after checking the
1130 6f4d00ee 2013-09-23 0intro * validity of the Tversion?
1131 6f4d00ee 2013-09-23 0intro */
1132 6f4d00ee 2013-09-23 0intro fidClunkAll(con);
1133 6f4d00ee 2013-09-23 0intro
1134 6f4d00ee 2013-09-23 0intro if(t->tag != NOTAG){
1135 4b576658 2013-09-23 0intro qunlock(&con->lock);
1136 4b576658 2013-09-23 0intro werrstr("Tversion: invalid tag");
1137 6f4d00ee 2013-09-23 0intro return 0;
1138 6f4d00ee 2013-09-23 0intro }
1139 6f4d00ee 2013-09-23 0intro
1140 6f4d00ee 2013-09-23 0intro if(t->msize < 256){
1141 4b576658 2013-09-23 0intro qunlock(&con->lock);
1142 4b576658 2013-09-23 0intro werrstr("Tversion: message size too small");
1143 6f4d00ee 2013-09-23 0intro return 0;
1144 6f4d00ee 2013-09-23 0intro }
1145 6f4d00ee 2013-09-23 0intro if(t->msize < con->msize)
1146 6f4d00ee 2013-09-23 0intro r->msize = t->msize;
1147 6f4d00ee 2013-09-23 0intro else
1148 6f4d00ee 2013-09-23 0intro r->msize = con->msize;
1149 6f4d00ee 2013-09-23 0intro
1150 6f4d00ee 2013-09-23 0intro r->version = "unknown";
1151 6f4d00ee 2013-09-23 0intro if(t->version[0] == '9' && t->version[1] == 'P'){
1152 6f4d00ee 2013-09-23 0intro /*
1153 6f4d00ee 2013-09-23 0intro * Currently, the only defined version
1154 6f4d00ee 2013-09-23 0intro * is "9P2000"; ignore any later versions.
1155 6f4d00ee 2013-09-23 0intro */
1156 6f4d00ee 2013-09-23 0intro v = strtol(&t->version[2], 0, 10);
1157 6f4d00ee 2013-09-23 0intro if(v >= 2000){
1158 6f4d00ee 2013-09-23 0intro r->version = VERSION9P;
1159 6f4d00ee 2013-09-23 0intro con->msize = r->msize;
1160 6f4d00ee 2013-09-23 0intro con->state = ConUp;
1161 6f4d00ee 2013-09-23 0intro }
1162 6f4d00ee 2013-09-23 0intro else if(strcmp(t->version, "9PEoF") == 0){
1163 6f4d00ee 2013-09-23 0intro r->version = "9PEoF";
1164 6f4d00ee 2013-09-23 0intro con->msize = r->msize;
1165 6f4d00ee 2013-09-23 0intro con->state = ConMoribund;
1166 6f4d00ee 2013-09-23 0intro
1167 6f4d00ee 2013-09-23 0intro /*
1168 6f4d00ee 2013-09-23 0intro * Don't want to attempt to write this
1169 6f4d00ee 2013-09-23 0intro * message as the connection may be already
1170 6f4d00ee 2013-09-23 0intro * closed.
1171 6f4d00ee 2013-09-23 0intro */
1172 6f4d00ee 2013-09-23 0intro m->state = MsgF;
1173 6f4d00ee 2013-09-23 0intro }
1174 6f4d00ee 2013-09-23 0intro }
1175 4b576658 2013-09-23 0intro qunlock(&con->lock);
1176 6f4d00ee 2013-09-23 0intro
1177 6f4d00ee 2013-09-23 0intro return 1;
1178 6f4d00ee 2013-09-23 0intro }
1179 6f4d00ee 2013-09-23 0intro
1180 6f4d00ee 2013-09-23 0intro int (*rFcall[Tmax])(Msg*) = {
1181 6f4d00ee 2013-09-23 0intro [Tversion] = rTversion,
1182 6f4d00ee 2013-09-23 0intro [Tauth] = rTauth,
1183 6f4d00ee 2013-09-23 0intro [Tattach] = rTattach,
1184 6f4d00ee 2013-09-23 0intro [Tflush] = rTflush,
1185 6f4d00ee 2013-09-23 0intro [Twalk] = rTwalk,
1186 6f4d00ee 2013-09-23 0intro [Topen] = rTopen,
1187 6f4d00ee 2013-09-23 0intro [Tcreate] = rTcreate,
1188 6f4d00ee 2013-09-23 0intro [Tread] = rTread,
1189 6f4d00ee 2013-09-23 0intro [Twrite] = rTwrite,
1190 6f4d00ee 2013-09-23 0intro [Tclunk] = rTclunk,
1191 6f4d00ee 2013-09-23 0intro [Tremove] = rTremove,
1192 6f4d00ee 2013-09-23 0intro [Tstat] = rTstat,
1193 6f4d00ee 2013-09-23 0intro [Twstat] = rTwstat,
1194 6f4d00ee 2013-09-23 0intro };