This source file includes following definitions.
- permission
- lookup
- follow_link
- dir_namei
- _namei
- lnamei
- namei
- open_namei
- sys_mknod
- sys_mkdir
- sys_rmdir
- sys_unlink
- sys_symlink
- sys_link
- sys_rename
1
2
3
4
5
6
7
8
9
10
11 #include <linux/sched.h>
12 #include <linux/minix_fs.h>
13 #include <linux/kernel.h>
14 #include <asm/segment.h>
15
16 #include <string.h>
17 #include <fcntl.h>
18 #include <errno.h>
19 #include <const.h>
20 #include <sys/stat.h>
21
22 struct inode * _namei(const char * filename, struct inode * base,
23 int follow_links);
24
25 #define ACC_MODE(x) ("\004\002\006\377"[(x)&O_ACCMODE])
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40 int permission(struct inode * inode,int mask)
41 {
42 int mode = inode->i_mode;
43
44
45 if (inode->i_dev && !inode->i_nlink)
46 return 0;
47 else if (current->euid == inode->i_uid)
48 mode >>= 6;
49 else if (in_group_p(inode->i_gid))
50 mode >>= 3;
51 if (((mode & mask & 0007) == mask) || suser())
52 return 1;
53 return 0;
54 }
55
56
57
58
59
60
61 int lookup(struct inode * dir,const char * name, int len,
62 struct inode ** result)
63 {
64 struct super_block * sb;
65
66 *result = NULL;
67 if (len==2 && get_fs_byte(name)=='.' && get_fs_byte(name+1)=='.') {
68 if (dir == current->root)
69 len = 1;
70 else if ((sb = dir->i_sb) && (dir == sb->s_mounted)) {
71 sb = dir->i_sb;
72 iput(dir);
73 if (dir = sb->s_covered)
74 dir->i_count++;
75 }
76 }
77 if (!dir)
78 return -ENOENT;
79 if (!permission(dir,MAY_EXEC)) {
80 iput(dir);
81 return -EACCES;
82 }
83 if (!len) {
84 *result = dir;
85 return 0;
86 }
87 if (!dir->i_op || !dir->i_op->lookup) {
88 iput(dir);
89 return -ENOENT;
90 }
91 return dir->i_op->lookup(dir,name,len,result);
92 }
93
94 struct inode * follow_link(struct inode * dir, struct inode * inode)
95 {
96 if (!dir || !inode) {
97 iput(dir);
98 iput(inode);
99 return NULL;
100 }
101 if (!inode->i_op || !inode->i_op->follow_link) {
102 iput(dir);
103 return inode;
104 }
105 return inode->i_op->follow_link(dir,inode);
106 }
107
108
109
110
111
112
113
114 static struct inode * dir_namei(const char * pathname,
115 int * namelen, const char ** name, struct inode * base)
116 {
117 char c;
118 const char * thisname;
119 int len,error;
120 struct inode * inode;
121
122 if (!base) {
123 base = current->pwd;
124 base->i_count++;
125 }
126 if ((c=get_fs_byte(pathname))=='/') {
127 iput(base);
128 base = current->root;
129 pathname++;
130 base->i_count++;
131 }
132 while (1) {
133 thisname = pathname;
134 for(len=0;(c=get_fs_byte(pathname++))&&(c!='/');len++)
135 ;
136 if (!c)
137 break;
138 base->i_count++;
139 error = lookup(base,thisname,len,&inode);
140 if (error) {
141 iput(base);
142 return NULL;
143 }
144 if (!(base = follow_link(base,inode)))
145 return NULL;
146 }
147 *name = thisname;
148 *namelen = len;
149 return base;
150 }
151
152 struct inode * _namei(const char * pathname, struct inode * base,
153 int follow_links)
154 {
155 const char * basename;
156 int namelen,error;
157 struct inode * inode;
158
159 if (!(base = dir_namei(pathname,&namelen,&basename,base)))
160 return NULL;
161 base->i_count++;
162 error = lookup(base,basename,namelen,&inode);
163 if (error) {
164 iput(base);
165 return NULL;
166 }
167 if (follow_links)
168 inode = follow_link(base,inode);
169 else
170 iput(base);
171 if (inode) {
172 inode->i_atime=CURRENT_TIME;
173 inode->i_dirt=1;
174 }
175 return inode;
176 }
177
178 struct inode * lnamei(const char * pathname)
179 {
180 return _namei(pathname, NULL, 0);
181 }
182
183
184
185
186
187
188
189
190 struct inode * namei(const char * pathname)
191 {
192 return _namei(pathname,NULL,1);
193 }
194
195
196
197
198
199
200 int open_namei(const char * pathname, int flag, int mode,
201 struct inode ** res_inode)
202 {
203 const char * basename;
204 int namelen,error;
205 struct inode * dir, *inode;
206
207 if ((flag & O_TRUNC) && !(flag & O_ACCMODE))
208 flag |= O_WRONLY;
209 mode &= 0777 & ~current->umask;
210 mode |= I_REGULAR;
211 if (!(dir = dir_namei(pathname,&namelen,&basename,NULL)))
212 return -ENOENT;
213 if (!namelen) {
214 if (!(flag & (O_ACCMODE|O_CREAT|O_TRUNC))) {
215 *res_inode=dir;
216 return 0;
217 }
218 iput(dir);
219 return -EISDIR;
220 }
221 dir->i_count++;
222 error = lookup(dir,basename,namelen,&inode);
223 if (error) {
224 if (!(flag & O_CREAT)) {
225 iput(dir);
226 return error;
227 }
228 if (!permission(dir,MAY_WRITE)) {
229 iput(dir);
230 return -EACCES;
231 }
232 if (!dir->i_op || !dir->i_op->create) {
233 iput(dir);
234 return -EACCES;
235 }
236 return dir->i_op->create(dir,basename,namelen,mode,res_inode);
237 }
238 if (flag & O_EXCL) {
239 iput(dir);
240 iput(inode);
241 return -EEXIST;
242 }
243 if (!(inode = follow_link(dir,inode)))
244 return -ELOOP;
245 if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) ||
246 !permission(inode,ACC_MODE(flag))) {
247 iput(inode);
248 return -EPERM;
249 }
250 inode->i_atime = CURRENT_TIME;
251 if (flag & O_TRUNC)
252 minix_truncate(inode);
253 *res_inode = inode;
254 return 0;
255 }
256
257 int sys_mknod(const char * filename, int mode, int dev)
258 {
259 const char * basename;
260 int namelen;
261 struct inode * dir;
262
263 if (!suser())
264 return -EPERM;
265 if (!(dir = dir_namei(filename,&namelen,&basename, NULL)))
266 return -ENOENT;
267 if (!namelen) {
268 iput(dir);
269 return -ENOENT;
270 }
271 if (!permission(dir,MAY_WRITE)) {
272 iput(dir);
273 return -EPERM;
274 }
275 if (!dir->i_op || !dir->i_op->mknod) {
276 iput(dir);
277 return -EPERM;
278 }
279 return dir->i_op->mknod(dir,basename,namelen,mode,dev);
280 }
281
282 int sys_mkdir(const char * pathname, int mode)
283 {
284 const char * basename;
285 int namelen;
286 struct inode * dir;
287
288 if (!(dir = dir_namei(pathname,&namelen,&basename, NULL)))
289 return -ENOENT;
290 if (!namelen) {
291 iput(dir);
292 return -ENOENT;
293 }
294 if (!permission(dir,MAY_WRITE)) {
295 iput(dir);
296 return -EPERM;
297 }
298 if (!dir->i_op || !dir->i_op->mkdir) {
299 iput(dir);
300 return -EPERM;
301 }
302 return dir->i_op->mkdir(dir,basename,namelen,mode);
303 }
304
305 int sys_rmdir(const char * name)
306 {
307 const char * basename;
308 int namelen;
309 struct inode * dir;
310
311 if (!(dir = dir_namei(name,&namelen,&basename, NULL)))
312 return -ENOENT;
313 if (!namelen) {
314 iput(dir);
315 return -ENOENT;
316 }
317 if (!permission(dir,MAY_WRITE)) {
318 iput(dir);
319 return -EPERM;
320 }
321 if (!dir->i_op || !dir->i_op->rmdir) {
322 iput(dir);
323 return -EPERM;
324 }
325 return dir->i_op->rmdir(dir,basename,namelen);
326 }
327
328 int sys_unlink(const char * name)
329 {
330 const char * basename;
331 int namelen;
332 struct inode * dir;
333
334 if (!(dir = dir_namei(name,&namelen,&basename, NULL)))
335 return -ENOENT;
336 if (!namelen) {
337 iput(dir);
338 return -ENOENT;
339 }
340 if (!permission(dir,MAY_WRITE)) {
341 iput(dir);
342 return -EPERM;
343 }
344 if (!dir->i_op || !dir->i_op->unlink) {
345 iput(dir);
346 return -EPERM;
347 }
348 return dir->i_op->unlink(dir,basename,namelen);
349 }
350
351 int sys_symlink(const char * oldname, const char * newname)
352 {
353 struct inode * dir;
354 const char * basename;
355 int namelen;
356
357 dir = dir_namei(newname,&namelen,&basename, NULL);
358 if (!dir)
359 return -EACCES;
360 if (!namelen) {
361 iput(dir);
362 return -EPERM;
363 }
364 if (!permission(dir,MAY_WRITE)) {
365 iput(dir);
366 return -EPERM;
367 }
368 if (!dir->i_op || !dir->i_op->symlink) {
369 iput(dir);
370 return -EPERM;
371 }
372 return dir->i_op->symlink(dir,basename,namelen,oldname);
373 }
374
375 int sys_link(const char * oldname, const char * newname)
376 {
377 struct inode * oldinode, * dir;
378 const char * basename;
379 int namelen;
380
381 oldinode = namei(oldname);
382 if (!oldinode)
383 return -ENOENT;
384 dir = dir_namei(newname,&namelen,&basename, NULL);
385 if (!dir) {
386 iput(oldinode);
387 return -EACCES;
388 }
389 if (!namelen) {
390 iput(oldinode);
391 iput(dir);
392 return -EPERM;
393 }
394 if (dir->i_dev != oldinode->i_dev) {
395 iput(dir);
396 iput(oldinode);
397 return -EXDEV;
398 }
399 if (!permission(dir,MAY_WRITE)) {
400 iput(dir);
401 iput(oldinode);
402 return -EACCES;
403 }
404 if (!dir->i_op || !dir->i_op->link) {
405 iput(dir);
406 iput(oldinode);
407 return -EPERM;
408 }
409 return dir->i_op->link(oldinode, dir, basename, namelen);
410 }
411
412 int sys_rename(const char * oldname, const char * newname)
413 {
414 struct inode * old_dir, * new_dir;
415 const char * old_base, * new_base;
416 int old_len, new_len;
417
418 old_dir = dir_namei(oldname,&old_len,&old_base, NULL);
419 if (!old_dir)
420 return -ENOENT;
421 if (!permission(old_dir,MAY_WRITE)) {
422 iput(old_dir);
423 return -EACCES;
424 }
425 if (!old_len || (get_fs_byte(old_base) == '.' &&
426 (old_len == 1 || (get_fs_byte(old_base+1) == '.' &&
427 old_len == 2)))) {
428 iput(old_dir);
429 return -EPERM;
430 }
431 new_dir = dir_namei(newname,&new_len,&new_base, NULL);
432 if (!new_dir) {
433 iput(old_dir);
434 return -ENOENT;
435 }
436 if (!permission(new_dir,MAY_WRITE)) {
437 iput(old_dir);
438 iput(new_dir);
439 return -EACCES;
440 }
441 if (!new_len || (get_fs_byte(new_base) == '.' &&
442 (new_len == 1 || (get_fs_byte(new_base+1) == '.' &&
443 new_len == 2)))) {
444 iput(old_dir);
445 iput(new_dir);
446 return -EPERM;
447 }
448 if (new_dir->i_dev != old_dir->i_dev) {
449 iput(old_dir);
450 iput(new_dir);
451 return -EXDEV;
452 }
453 if (!old_dir->i_op || !old_dir->i_op->rename) {
454 iput(old_dir);
455 iput(new_dir);
456 return -EPERM;
457 }
458 return old_dir->i_op->rename(old_dir, old_base, old_len,
459 new_dir, new_base, new_len);
460 }