This source file includes following definitions.
- getname
- putname
- permission
- lookup
- follow_link
- dir_namei
- _namei
- lnamei
- namei
- open_namei
- do_mknod
- sys_mknod
- do_mkdir
- sys_mkdir
- do_rmdir
- sys_rmdir
- do_unlink
- sys_unlink
- do_symlink
- sys_symlink
- do_link
- sys_link
- do_rename
- sys_rename
1
2
3
4
5
6
7
8
9
10
11 #include <asm/segment.h>
12
13 #include <linux/errno.h>
14 #include <linux/sched.h>
15 #include <linux/kernel.h>
16 #include <linux/string.h>
17 #include <linux/fcntl.h>
18 #include <linux/stat.h>
19
20 #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
21
22
23
24
25
26
27
28
29 int getname(const char * filename, char **result)
30 {
31 int error;
32 unsigned long i, page;
33 char * tmp, c;
34
35 i = (unsigned long) filename;
36 if (!i || i >= TASK_SIZE)
37 return -EFAULT;
38 i = TASK_SIZE - i;
39 error = -EFAULT;
40 if (i > PAGE_SIZE) {
41 i = PAGE_SIZE;
42 error = -ENAMETOOLONG;
43 }
44 c = get_fs_byte(filename++);
45 if (!c)
46 return -ENOENT;
47 page = __get_free_page(GFP_KERNEL);
48 if (!page)
49 return -ENOMEM;
50 *result = tmp = (char *) page;
51 while (--i) {
52 *(tmp++) = c;
53 c = get_fs_byte(filename++);
54 if (!c) {
55 *tmp = '\0';
56 return 0;
57 }
58 }
59 free_page(page);
60 return error;
61 }
62
63 void putname(char * name)
64 {
65 free_page((unsigned long) name);
66 }
67
68
69
70
71
72
73
74
75 int permission(struct inode * inode,int mask)
76 {
77 int mode = inode->i_mode;
78
79
80 if (inode->i_dev && !inode->i_nlink)
81 return 0;
82 else if (inode->i_op && inode->i_op->permission)
83 return inode->i_op->permission(inode, mask);
84 else if (current->euid == inode->i_uid)
85 mode >>= 6;
86 else if (in_group_p(inode->i_gid))
87 mode >>= 3;
88 if (((mode & mask & 0007) == mask) || suser())
89 return 1;
90 return 0;
91 }
92
93
94
95
96
97
98 int lookup(struct inode * dir,const char * name, int len,
99 struct inode ** result)
100 {
101 struct super_block * sb;
102 int perm;
103
104 *result = NULL;
105 if (!dir)
106 return -ENOENT;
107
108 perm = permission(dir,MAY_EXEC);
109 if (len==2 && name[0] == '.' && name[1] == '.') {
110 if (dir == current->root) {
111 *result = dir;
112 return 0;
113 } else if ((sb = dir->i_sb) && (dir == sb->s_mounted)) {
114 sb = dir->i_sb;
115 iput(dir);
116 dir = sb->s_covered;
117 if (!dir)
118 return -ENOENT;
119 dir->i_count++;
120 }
121 }
122 if (!dir->i_op || !dir->i_op->lookup) {
123 iput(dir);
124 return -ENOTDIR;
125 }
126 if (!perm) {
127 iput(dir);
128 return -EACCES;
129 }
130 if (!len) {
131 *result = dir;
132 return 0;
133 }
134 return dir->i_op->lookup(dir,name,len,result);
135 }
136
137 int follow_link(struct inode * dir, struct inode * inode,
138 int flag, int mode, struct inode ** res_inode)
139 {
140 if (!dir || !inode) {
141 iput(dir);
142 iput(inode);
143 *res_inode = NULL;
144 return -ENOENT;
145 }
146 if (!inode->i_op || !inode->i_op->follow_link) {
147 iput(dir);
148 *res_inode = inode;
149 return 0;
150 }
151 return inode->i_op->follow_link(dir,inode,flag,mode,res_inode);
152 }
153
154
155
156
157
158
159
160 static int dir_namei(const char * pathname, int * namelen, const char ** name,
161 struct inode * base, struct inode ** res_inode)
162 {
163 char c;
164 const char * thisname;
165 int len,error;
166 struct inode * inode;
167
168 *res_inode = NULL;
169 if (!base) {
170 base = current->pwd;
171 base->i_count++;
172 }
173 if ((c = *pathname) == '/') {
174 iput(base);
175 base = current->root;
176 pathname++;
177 base->i_count++;
178 }
179 while (1) {
180 thisname = pathname;
181 for(len=0;(c = *(pathname++))&&(c != '/');len++)
182 ;
183 if (!c)
184 break;
185 base->i_count++;
186 error = lookup(base,thisname,len,&inode);
187 if (error) {
188 iput(base);
189 return error;
190 }
191 error = follow_link(base,inode,0,0,&base);
192 if (error)
193 return error;
194 }
195 if (!base->i_op || !base->i_op->lookup) {
196 iput(base);
197 return -ENOTDIR;
198 }
199 *name = thisname;
200 *namelen = len;
201 *res_inode = base;
202 return 0;
203 }
204
205 static int _namei(const char * pathname, struct inode * base,
206 int follow_links, struct inode ** res_inode)
207 {
208 const char * basename;
209 int namelen,error;
210 struct inode * inode;
211
212 *res_inode = NULL;
213 error = dir_namei(pathname,&namelen,&basename,base,&base);
214 if (error)
215 return error;
216 base->i_count++;
217 error = lookup(base,basename,namelen,&inode);
218 if (error) {
219 iput(base);
220 return error;
221 }
222 if (follow_links) {
223 error = follow_link(base,inode,0,0,&inode);
224 if (error)
225 return error;
226 } else
227 iput(base);
228 *res_inode = inode;
229 return 0;
230 }
231
232 int lnamei(const char * pathname, struct inode ** res_inode)
233 {
234 int error;
235 char * tmp;
236
237 error = getname(pathname,&tmp);
238 if (!error) {
239 error = _namei(tmp,NULL,0,res_inode);
240 putname(tmp);
241 }
242 return error;
243 }
244
245
246
247
248
249
250
251
252 int namei(const char * pathname, struct inode ** res_inode)
253 {
254 int error;
255 char * tmp;
256
257 error = getname(pathname,&tmp);
258 if (!error) {
259 error = _namei(tmp,NULL,1,res_inode);
260 putname(tmp);
261 }
262 return error;
263 }
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278 int open_namei(const char * pathname, int flag, int mode,
279 struct inode ** res_inode, struct inode * base)
280 {
281 const char * basename;
282 int namelen,error,i;
283 struct inode * dir, *inode;
284 struct task_struct ** p;
285
286 mode &= 07777 & ~current->umask;
287 mode |= S_IFREG;
288 error = dir_namei(pathname,&namelen,&basename,base,&dir);
289 if (error)
290 return error;
291 if (!namelen) {
292 if (flag & 2) {
293 iput(dir);
294 return -EISDIR;
295 }
296
297 if (!permission(dir,ACC_MODE(flag))) {
298 iput(dir);
299 return -EACCES;
300 }
301 *res_inode=dir;
302 return 0;
303 }
304 for (i = 0; i < 5; i++) {
305 dir->i_count++;
306 error = lookup(dir,basename,namelen,&inode);
307 if (!error)
308 break;
309 if (!(flag & O_CREAT)) {
310 iput(dir);
311 return error;
312 }
313 if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
314 iput(dir);
315 return -EACCES;
316 }
317 if (!dir->i_op || !dir->i_op->create) {
318 iput(dir);
319 return -EACCES;
320 }
321 if (IS_RDONLY(dir)) {
322 iput(dir);
323 return -EROFS;
324 }
325 dir->i_count++;
326 error = dir->i_op->create(dir,basename,namelen,mode,res_inode);
327 if (error != -EEXIST) {
328 iput(dir);
329 return error;
330 }
331 }
332 if (error) {
333 iput(dir);
334 return error;
335 }
336 if ((flag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
337 iput(dir);
338 iput(inode);
339 return -EEXIST;
340 }
341 error = follow_link(dir,inode,flag,mode,&inode);
342 if (error)
343 return error;
344 if (S_ISDIR(inode->i_mode) && (flag & 2)) {
345 iput(inode);
346 return -EISDIR;
347 }
348 if (!permission(inode,ACC_MODE(flag))) {
349 iput(inode);
350 return -EACCES;
351 }
352 if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
353 if (IS_NODEV(inode)) {
354 iput(inode);
355 return -EACCES;
356 }
357 } else {
358 if (IS_RDONLY(inode) && (flag & 2)) {
359 iput(inode);
360 return -EROFS;
361 }
362 }
363 if ((inode->i_count > 1) && (flag & 2))
364 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
365 if (!*p)
366 continue;
367 if (inode == (*p)->executable) {
368 iput(inode);
369 return -ETXTBSY;
370 }
371 for (i=0; i < (*p)->numlibraries; i++)
372 if (inode == (*p)->libraries[i].library) {
373 iput(inode);
374 return -ETXTBSY;
375 }
376 }
377 *res_inode = inode;
378 return 0;
379 }
380
381 int do_mknod(const char * filename, int mode, dev_t dev)
382 {
383 const char * basename;
384 int namelen, error;
385 struct inode * dir;
386
387 mode &= ~current->umask;
388 error = dir_namei(filename,&namelen,&basename, NULL, &dir);
389 if (error)
390 return error;
391 if (!namelen) {
392 iput(dir);
393 return -ENOENT;
394 }
395 if (IS_RDONLY(dir)) {
396 iput(dir);
397 return -EROFS;
398 }
399 if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
400 iput(dir);
401 return -EACCES;
402 }
403 if (!dir->i_op || !dir->i_op->mknod) {
404 iput(dir);
405 return -EPERM;
406 }
407 return dir->i_op->mknod(dir,basename,namelen,mode,dev);
408 }
409
410 int sys_mknod(const char * filename, int mode, dev_t dev)
411 {
412 int error;
413 char * tmp;
414
415 if (S_ISDIR(mode) || (!S_ISFIFO(mode) && !suser()))
416 return -EPERM;
417 error = getname(filename,&tmp);
418 if (!error) {
419 error = do_mknod(tmp,mode,dev);
420 putname(tmp);
421 }
422 return error;
423 }
424
425 static int do_mkdir(const char * pathname, int mode)
426 {
427 const char * basename;
428 int namelen, error;
429 struct inode * dir;
430
431 error = dir_namei(pathname,&namelen,&basename,NULL,&dir);
432 if (error)
433 return error;
434 if (!namelen) {
435 iput(dir);
436 return -ENOENT;
437 }
438 if (IS_RDONLY(dir)) {
439 iput(dir);
440 return -EROFS;
441 }
442 if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
443 iput(dir);
444 return -EACCES;
445 }
446 if (!dir->i_op || !dir->i_op->mkdir) {
447 iput(dir);
448 return -EPERM;
449 }
450 return dir->i_op->mkdir(dir,basename,namelen,mode);
451 }
452
453 int sys_mkdir(const char * pathname, int mode)
454 {
455 int error;
456 char * tmp;
457
458 error = getname(pathname,&tmp);
459 if (!error) {
460 error = do_mkdir(tmp,mode);
461 putname(tmp);
462 }
463 return error;
464 }
465
466 static int do_rmdir(const char * name)
467 {
468 const char * basename;
469 int namelen, error;
470 struct inode * dir;
471
472 error = dir_namei(name,&namelen,&basename,NULL,&dir);
473 if (error)
474 return error;
475 if (!namelen) {
476 iput(dir);
477 return -ENOENT;
478 }
479 if (IS_RDONLY(dir)) {
480 iput(dir);
481 return -EROFS;
482 }
483 if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
484 iput(dir);
485 return -EACCES;
486 }
487 if (!dir->i_op || !dir->i_op->rmdir) {
488 iput(dir);
489 return -EPERM;
490 }
491 return dir->i_op->rmdir(dir,basename,namelen);
492 }
493
494 int sys_rmdir(const char * pathname)
495 {
496 int error;
497 char * tmp;
498
499 error = getname(pathname,&tmp);
500 if (!error) {
501 error = do_rmdir(tmp);
502 putname(tmp);
503 }
504 return error;
505 }
506
507 static int do_unlink(const char * name)
508 {
509 const char * basename;
510 int namelen, error;
511 struct inode * dir;
512
513 error = dir_namei(name,&namelen,&basename,NULL,&dir);
514 if (error)
515 return error;
516 if (!namelen) {
517 iput(dir);
518 return -EPERM;
519 }
520 if (IS_RDONLY(dir)) {
521 iput(dir);
522 return -EROFS;
523 }
524 if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
525 iput(dir);
526 return -EACCES;
527 }
528 if (!dir->i_op || !dir->i_op->unlink) {
529 iput(dir);
530 return -EPERM;
531 }
532 return dir->i_op->unlink(dir,basename,namelen);
533 }
534
535 int sys_unlink(const char * pathname)
536 {
537 int error;
538 char * tmp;
539
540 error = getname(pathname,&tmp);
541 if (!error) {
542 error = do_unlink(tmp);
543 putname(tmp);
544 }
545 return error;
546 }
547
548 static int do_symlink(const char * oldname, const char * newname)
549 {
550 struct inode * dir;
551 const char * basename;
552 int namelen, error;
553
554 error = dir_namei(newname,&namelen,&basename,NULL,&dir);
555 if (error)
556 return error;
557 if (!namelen) {
558 iput(dir);
559 return -ENOENT;
560 }
561 if (IS_RDONLY(dir)) {
562 iput(dir);
563 return -EROFS;
564 }
565 if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
566 iput(dir);
567 return -EACCES;
568 }
569 if (!dir->i_op || !dir->i_op->symlink) {
570 iput(dir);
571 return -EPERM;
572 }
573 return dir->i_op->symlink(dir,basename,namelen,oldname);
574 }
575
576 int sys_symlink(const char * oldname, const char * newname)
577 {
578 int error;
579 char * old, * new;
580
581 error = getname(oldname,&old);
582 if (!error) {
583 error = getname(newname,&new);
584 if (!error) {
585 error = do_symlink(old,new);
586 putname(new);
587 }
588 putname(old);
589 }
590 return error;
591 }
592
593 static int do_link(struct inode * oldinode, const char * newname)
594 {
595 struct inode * dir;
596 const char * basename;
597 int namelen, error;
598
599 error = dir_namei(newname,&namelen,&basename,NULL,&dir);
600 if (error) {
601 iput(oldinode);
602 return error;
603 }
604 if (!namelen) {
605 iput(oldinode);
606 iput(dir);
607 return -EPERM;
608 }
609 if (IS_RDONLY(dir)) {
610 iput(oldinode);
611 iput(dir);
612 return -EROFS;
613 }
614 if (dir->i_dev != oldinode->i_dev) {
615 iput(dir);
616 iput(oldinode);
617 return -EXDEV;
618 }
619 if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
620 iput(dir);
621 iput(oldinode);
622 return -EACCES;
623 }
624 if (!dir->i_op || !dir->i_op->link) {
625 iput(dir);
626 iput(oldinode);
627 return -EPERM;
628 }
629 return dir->i_op->link(oldinode, dir, basename, namelen);
630 }
631
632 int sys_link(const char * oldname, const char * newname)
633 {
634 int error;
635 char * new;
636 struct inode * oldinode;
637
638 error = namei(oldname, &oldinode);
639 if (error)
640 return error;
641 error = getname(newname,&new);
642 if (!error) {
643 error = do_link(oldinode,new);
644 putname(new);
645 }
646 return error;
647 }
648
649 static int do_rename(const char * oldname, const char * newname)
650 {
651 struct inode * old_dir, * new_dir;
652 const char * old_base, * new_base;
653 int old_len, new_len, error;
654
655 error = dir_namei(oldname,&old_len,&old_base,NULL,&old_dir);
656 if (error)
657 return error;
658 if (!permission(old_dir,MAY_WRITE | MAY_EXEC)) {
659 iput(old_dir);
660 return -EACCES;
661 }
662 if (!old_len || (old_base[0] == '.' &&
663 (old_len == 1 || (old_base[1] == '.' &&
664 old_len == 2)))) {
665 iput(old_dir);
666 return -EPERM;
667 }
668 error = dir_namei(newname,&new_len,&new_base,NULL,&new_dir);
669 if (error) {
670 iput(old_dir);
671 return error;
672 }
673 if (!permission(new_dir,MAY_WRITE | MAY_EXEC)) {
674 iput(old_dir);
675 iput(new_dir);
676 return -EACCES;
677 }
678 if (!new_len || (new_base[0] == '.' &&
679 (new_len == 1 || (new_base[1] == '.' &&
680 new_len == 2)))) {
681 iput(old_dir);
682 iput(new_dir);
683 return -EPERM;
684 }
685 if (new_dir->i_dev != old_dir->i_dev) {
686 iput(old_dir);
687 iput(new_dir);
688 return -EXDEV;
689 }
690 if (IS_RDONLY(new_dir) || IS_RDONLY(old_dir)) {
691 iput(old_dir);
692 iput(new_dir);
693 return -EROFS;
694 }
695 if (!old_dir->i_op || !old_dir->i_op->rename) {
696 iput(old_dir);
697 iput(new_dir);
698 return -EPERM;
699 }
700 return old_dir->i_op->rename(old_dir, old_base, old_len,
701 new_dir, new_base, new_len);
702 }
703
704 int sys_rename(const char * oldname, const char * newname)
705 {
706 int error;
707 char * old, * new;
708
709 error = getname(oldname,&old);
710 if (!error) {
711 error = getname(newname,&new);
712 if (!error) {
713 error = do_rename(old,new);
714 putname(new);
715 }
716 putname(old);
717 }
718 return error;
719 }