This source file includes following definitions.
- permission
- lookup
- follow_link
- dir_namei
- _namei
- lnamei
- namei
- open_namei
- do_mknod
- 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 <const.h>
12
13 #include <asm/segment.h>
14
15 #include <linux/errno.h>
16 #include <linux/sched.h>
17 #include <linux/kernel.h>
18 #include <linux/string.h>
19 #include <linux/fcntl.h>
20 #include <linux/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 return inode;
172 }
173
174 struct inode * lnamei(const char * pathname)
175 {
176 return _namei(pathname, NULL, 0);
177 }
178
179
180
181
182
183
184
185
186 struct inode * namei(const char * pathname)
187 {
188 return _namei(pathname,NULL,1);
189 }
190
191
192
193
194
195
196 int open_namei(const char * pathname, int flag, int mode,
197 struct inode ** res_inode)
198 {
199 const char * basename;
200 int namelen,error,i;
201 struct inode * dir, *inode;
202 struct task_struct ** p;
203
204 if ((flag & O_TRUNC) && !(flag & O_ACCMODE))
205 flag |= O_WRONLY;
206 mode &= 07777 & ~current->umask;
207 mode |= I_REGULAR;
208 if (!(dir = dir_namei(pathname,&namelen,&basename,NULL)))
209 return -ENOENT;
210 if (!namelen) {
211 if (!(flag & (O_ACCMODE|O_CREAT|O_TRUNC))) {
212 *res_inode=dir;
213 return 0;
214 }
215 iput(dir);
216 return -EISDIR;
217 }
218 dir->i_count++;
219 error = lookup(dir,basename,namelen,&inode);
220 if (error) {
221 if (!(flag & O_CREAT)) {
222 iput(dir);
223 return error;
224 }
225 if (!permission(dir,MAY_WRITE)) {
226 iput(dir);
227 return -EACCES;
228 }
229 if (!dir->i_op || !dir->i_op->create) {
230 iput(dir);
231 return -EACCES;
232 }
233 if (IS_RDONLY(dir)) {
234 iput(dir);
235 return -EROFS;
236 }
237 return dir->i_op->create(dir,basename,namelen,mode,res_inode);
238 }
239 if (flag & O_EXCL) {
240 iput(dir);
241 iput(inode);
242 return -EEXIST;
243 }
244 if (!(inode = follow_link(dir,inode)))
245 return -ELOOP;
246 if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
247 if (IS_NODEV(inode)) {
248 iput(inode);
249 return -EACCES;
250 }
251 } else {
252 if (IS_RDONLY(inode) && (flag & (O_TRUNC | O_ACCMODE))) {
253 iput(inode);
254 return -EROFS;
255 }
256 }
257 if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) ||
258 !permission(inode,ACC_MODE(flag))) {
259 iput(inode);
260 return -EPERM;
261 }
262 if ((inode->i_count > 1) && (flag & O_ACCMODE))
263 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
264 if (!*p)
265 continue;
266 if (inode == (*p)->executable) {
267 iput(inode);
268 return -ETXTBSY;
269 }
270 for (i=0; i < (*p)->numlibraries; i++)
271 if (inode == (*p)->libraries[i].library) {
272 iput(inode);
273 return -ETXTBSY;
274 }
275 }
276 if (flag & O_TRUNC)
277 if (inode->i_op && inode->i_op->truncate) {
278 inode->i_size = 0;
279 inode->i_op->truncate(inode);
280 }
281 if (!IS_RDONLY(inode)) {
282 inode->i_atime = CURRENT_TIME;
283 inode->i_dirt = 1;
284 }
285 *res_inode = inode;
286 return 0;
287 }
288
289 int do_mknod(const char * filename, int mode, int dev)
290 {
291 const char * basename;
292 int namelen;
293 struct inode * dir;
294
295 if (!(dir = dir_namei(filename,&namelen,&basename, NULL)))
296 return -ENOENT;
297 if (!namelen) {
298 iput(dir);
299 return -ENOENT;
300 }
301 if (IS_RDONLY(dir)) {
302 iput(dir);
303 return -EROFS;
304 }
305 if (!permission(dir,MAY_WRITE)) {
306 iput(dir);
307 return -EACCES;
308 }
309 if (!dir->i_op || !dir->i_op->mknod) {
310 iput(dir);
311 return -EPERM;
312 }
313 return dir->i_op->mknod(dir,basename,namelen,mode,dev);
314 }
315
316 int sys_mknod(const char * filename, int mode, int dev)
317 {
318 if (S_ISFIFO(mode) || suser())
319 return do_mknod(filename,mode,dev);
320 return -EPERM;
321 }
322
323 int sys_mkdir(const char * pathname, int mode)
324 {
325 const char * basename;
326 int namelen;
327 struct inode * dir;
328
329 if (!(dir = dir_namei(pathname,&namelen,&basename, NULL)))
330 return -ENOENT;
331 if (!namelen) {
332 iput(dir);
333 return -ENOENT;
334 }
335 if (IS_RDONLY(dir)) {
336 iput(dir);
337 return -EROFS;
338 }
339 if (!permission(dir,MAY_WRITE)) {
340 iput(dir);
341 return -EACCES;
342 }
343 if (!dir->i_op || !dir->i_op->mkdir) {
344 iput(dir);
345 return -EPERM;
346 }
347 return dir->i_op->mkdir(dir,basename,namelen,mode);
348 }
349
350 int sys_rmdir(const char * name)
351 {
352 const char * basename;
353 int namelen;
354 struct inode * dir;
355
356 if (!(dir = dir_namei(name,&namelen,&basename, NULL)))
357 return -ENOENT;
358 if (!namelen) {
359 iput(dir);
360 return -ENOENT;
361 }
362 if (IS_RDONLY(dir)) {
363 iput(dir);
364 return -EROFS;
365 }
366 if (!permission(dir,MAY_WRITE)) {
367 iput(dir);
368 return -EACCES;
369 }
370 if (!dir->i_op || !dir->i_op->rmdir) {
371 iput(dir);
372 return -EPERM;
373 }
374 return dir->i_op->rmdir(dir,basename,namelen);
375 }
376
377 int sys_unlink(const char * name)
378 {
379 const char * basename;
380 int namelen;
381 struct inode * dir;
382
383 if (!(dir = dir_namei(name,&namelen,&basename, NULL)))
384 return -ENOENT;
385 if (!namelen) {
386 iput(dir);
387 return -EPERM;
388 }
389 if (IS_RDONLY(dir)) {
390 iput(dir);
391 return -EROFS;
392 }
393 if (!permission(dir,MAY_WRITE)) {
394 iput(dir);
395 return -EACCES;
396 }
397 if (!dir->i_op || !dir->i_op->unlink) {
398 iput(dir);
399 return -EPERM;
400 }
401 return dir->i_op->unlink(dir,basename,namelen);
402 }
403
404 int sys_symlink(const char * oldname, const char * newname)
405 {
406 struct inode * dir;
407 const char * basename;
408 int namelen;
409
410 dir = dir_namei(newname,&namelen,&basename, NULL);
411 if (!dir)
412 return -ENOENT;
413 if (!namelen) {
414 iput(dir);
415 return -ENOENT;
416 }
417 if (IS_RDONLY(dir)) {
418 iput(dir);
419 return -EROFS;
420 }
421 if (!permission(dir,MAY_WRITE)) {
422 iput(dir);
423 return -EACCES;
424 }
425 if (!dir->i_op || !dir->i_op->symlink) {
426 iput(dir);
427 return -EPERM;
428 }
429 return dir->i_op->symlink(dir,basename,namelen,oldname);
430 }
431
432 int sys_link(const char * oldname, const char * newname)
433 {
434 struct inode * oldinode, * dir;
435 const char * basename;
436 int namelen;
437
438 oldinode = namei(oldname);
439 if (!oldinode)
440 return -ENOENT;
441 dir = dir_namei(newname,&namelen,&basename, NULL);
442 if (!dir) {
443 iput(oldinode);
444 return -EACCES;
445 }
446 if (!namelen) {
447 iput(oldinode);
448 iput(dir);
449 return -EPERM;
450 }
451 if (IS_RDONLY(dir)) {
452 iput(oldinode);
453 iput(dir);
454 return -EROFS;
455 }
456 if (dir->i_dev != oldinode->i_dev) {
457 iput(dir);
458 iput(oldinode);
459 return -EXDEV;
460 }
461 if (!permission(dir,MAY_WRITE)) {
462 iput(dir);
463 iput(oldinode);
464 return -EACCES;
465 }
466 if (!dir->i_op || !dir->i_op->link) {
467 iput(dir);
468 iput(oldinode);
469 return -EPERM;
470 }
471 return dir->i_op->link(oldinode, dir, basename, namelen);
472 }
473
474 int sys_rename(const char * oldname, const char * newname)
475 {
476 struct inode * old_dir, * new_dir;
477 const char * old_base, * new_base;
478 int old_len, new_len;
479
480 old_dir = dir_namei(oldname,&old_len,&old_base, NULL);
481 if (!old_dir)
482 return -ENOENT;
483 if (!permission(old_dir,MAY_WRITE)) {
484 iput(old_dir);
485 return -EACCES;
486 }
487 if (!old_len || (get_fs_byte(old_base) == '.' &&
488 (old_len == 1 || (get_fs_byte(old_base+1) == '.' &&
489 old_len == 2)))) {
490 iput(old_dir);
491 return -EPERM;
492 }
493 new_dir = dir_namei(newname,&new_len,&new_base, NULL);
494 if (!new_dir) {
495 iput(old_dir);
496 return -ENOENT;
497 }
498 if (!permission(new_dir,MAY_WRITE)) {
499 iput(old_dir);
500 iput(new_dir);
501 return -EACCES;
502 }
503 if (!new_len || (get_fs_byte(new_base) == '.' &&
504 (new_len == 1 || (get_fs_byte(new_base+1) == '.' &&
505 new_len == 2)))) {
506 iput(old_dir);
507 iput(new_dir);
508 return -EPERM;
509 }
510 if (new_dir->i_dev != old_dir->i_dev) {
511 iput(old_dir);
512 iput(new_dir);
513 return -EXDEV;
514 }
515 if (IS_RDONLY(new_dir) || IS_RDONLY(old_dir)) {
516 iput(old_dir);
517 iput(new_dir);
518 return -EROFS;
519 }
520 if (!old_dir->i_op || !old_dir->i_op->rename) {
521 iput(old_dir);
522 iput(new_dir);
523 return -EPERM;
524 }
525 return old_dir->i_op->rename(old_dir, old_base, old_len,
526 new_dir, new_base, new_len);
527 }