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 ((char *) thisname)[len] = '\0';
187 error = lookup(base,thisname,len,&inode);
188 ((char *) thisname)[len] = c;
189 if (error) {
190 iput(base);
191 return error;
192 }
193 error = follow_link(base,inode,0,0,&base);
194 if (error)
195 return error;
196 }
197 if (!base->i_op || !base->i_op->lookup) {
198 iput(base);
199 return -ENOTDIR;
200 }
201 *name = thisname;
202 *namelen = len;
203 *res_inode = base;
204 return 0;
205 }
206
207 static int _namei(const char * pathname, struct inode * base,
208 int follow_links, struct inode ** res_inode)
209 {
210 const char * basename;
211 int namelen,error;
212 struct inode * inode;
213
214 *res_inode = NULL;
215 error = dir_namei(pathname,&namelen,&basename,base,&base);
216 if (error)
217 return error;
218 base->i_count++;
219 error = lookup(base,basename,namelen,&inode);
220 if (error) {
221 iput(base);
222 return error;
223 }
224 if (follow_links) {
225 error = follow_link(base,inode,0,0,&inode);
226 if (error)
227 return error;
228 } else
229 iput(base);
230 *res_inode = inode;
231 return 0;
232 }
233
234 int lnamei(const char * pathname, struct inode ** res_inode)
235 {
236 int error;
237 char * tmp;
238
239 error = getname(pathname,&tmp);
240 if (!error) {
241 error = _namei(tmp,NULL,0,res_inode);
242 putname(tmp);
243 }
244 return error;
245 }
246
247
248
249
250
251
252
253
254 int namei(const char * pathname, struct inode ** res_inode)
255 {
256 int error;
257 char * tmp;
258
259 error = getname(pathname,&tmp);
260 if (!error) {
261 error = _namei(tmp,NULL,1,res_inode);
262 putname(tmp);
263 }
264 return error;
265 }
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280 int open_namei(const char * pathname, int flag, int mode,
281 struct inode ** res_inode, struct inode * base)
282 {
283 const char * basename;
284 int namelen,error,i;
285 struct inode * dir, *inode;
286 struct task_struct ** p;
287
288 mode &= 07777 & ~current->umask;
289 mode |= S_IFREG;
290 error = dir_namei(pathname,&namelen,&basename,base,&dir);
291 if (error)
292 return error;
293 if (!namelen) {
294 if (flag & 2) {
295 iput(dir);
296 return -EISDIR;
297 }
298
299 if (!permission(dir,ACC_MODE(flag))) {
300 iput(dir);
301 return -EACCES;
302 }
303 *res_inode=dir;
304 return 0;
305 }
306 for (i = 0; i < 5; i++) {
307 dir->i_count++;
308 error = lookup(dir,basename,namelen,&inode);
309 if (!error)
310 break;
311 if (!(flag & O_CREAT)) {
312 iput(dir);
313 return error;
314 }
315 if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
316 iput(dir);
317 return -EACCES;
318 }
319 if (!dir->i_op || !dir->i_op->create) {
320 iput(dir);
321 return -EACCES;
322 }
323 if (IS_RDONLY(dir)) {
324 iput(dir);
325 return -EROFS;
326 }
327 dir->i_count++;
328 error = dir->i_op->create(dir,basename,namelen,mode,res_inode);
329 if (error != -EEXIST) {
330 iput(dir);
331 return error;
332 }
333 }
334 if (error) {
335 iput(dir);
336 return error;
337 }
338 if ((flag & (O_CREAT | O_EXCL)) == (O_CREAT | O_EXCL)) {
339 iput(dir);
340 iput(inode);
341 return -EEXIST;
342 }
343 error = follow_link(dir,inode,flag,mode,&inode);
344 if (error)
345 return error;
346 if (S_ISDIR(inode->i_mode) && (flag & 2)) {
347 iput(inode);
348 return -EISDIR;
349 }
350 if (!permission(inode,ACC_MODE(flag))) {
351 iput(inode);
352 return -EACCES;
353 }
354 if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
355 if (IS_NODEV(inode)) {
356 iput(inode);
357 return -EACCES;
358 }
359 } else {
360 if (IS_RDONLY(inode) && (flag & 2)) {
361 iput(inode);
362 return -EROFS;
363 }
364 }
365 if ((inode->i_count > 1) && (flag & 2))
366 for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
367 if (!*p)
368 continue;
369 if (inode == (*p)->executable) {
370 iput(inode);
371 return -ETXTBSY;
372 }
373 for (i=0; i < (*p)->numlibraries; i++)
374 if (inode == (*p)->libraries[i].library) {
375 iput(inode);
376 return -ETXTBSY;
377 }
378 }
379 *res_inode = inode;
380 return 0;
381 }
382
383 int do_mknod(const char * filename, int mode, dev_t dev)
384 {
385 const char * basename;
386 int namelen, error;
387 struct inode * dir;
388
389 mode &= ~current->umask;
390 error = dir_namei(filename,&namelen,&basename, NULL, &dir);
391 if (error)
392 return error;
393 if (!namelen) {
394 iput(dir);
395 return -ENOENT;
396 }
397 if (IS_RDONLY(dir)) {
398 iput(dir);
399 return -EROFS;
400 }
401 if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
402 iput(dir);
403 return -EACCES;
404 }
405 if (!dir->i_op || !dir->i_op->mknod) {
406 iput(dir);
407 return -EPERM;
408 }
409 return dir->i_op->mknod(dir,basename,namelen,mode,dev);
410 }
411
412 int sys_mknod(const char * filename, int mode, dev_t dev)
413 {
414 int error;
415 char * tmp;
416
417 if (S_ISDIR(mode) || (!S_ISFIFO(mode) && !suser()))
418 return -EPERM;
419 error = getname(filename,&tmp);
420 if (!error) {
421 error = do_mknod(tmp,mode,dev);
422 putname(tmp);
423 }
424 return error;
425 }
426
427 static int do_mkdir(const char * pathname, int mode)
428 {
429 const char * basename;
430 int namelen, error;
431 struct inode * dir;
432
433 error = dir_namei(pathname,&namelen,&basename,NULL,&dir);
434 if (error)
435 return error;
436 if (!namelen) {
437 iput(dir);
438 return -ENOENT;
439 }
440 if (IS_RDONLY(dir)) {
441 iput(dir);
442 return -EROFS;
443 }
444 if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
445 iput(dir);
446 return -EACCES;
447 }
448 if (!dir->i_op || !dir->i_op->mkdir) {
449 iput(dir);
450 return -EPERM;
451 }
452 return dir->i_op->mkdir(dir,basename,namelen,mode);
453 }
454
455 int sys_mkdir(const char * pathname, int mode)
456 {
457 int error;
458 char * tmp;
459
460 error = getname(pathname,&tmp);
461 if (!error) {
462 error = do_mkdir(tmp,mode);
463 putname(tmp);
464 }
465 return error;
466 }
467
468 static int do_rmdir(const char * name)
469 {
470 const char * basename;
471 int namelen, error;
472 struct inode * dir;
473
474 error = dir_namei(name,&namelen,&basename,NULL,&dir);
475 if (error)
476 return error;
477 if (!namelen) {
478 iput(dir);
479 return -ENOENT;
480 }
481 if (IS_RDONLY(dir)) {
482 iput(dir);
483 return -EROFS;
484 }
485 if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
486 iput(dir);
487 return -EACCES;
488 }
489 if (!dir->i_op || !dir->i_op->rmdir) {
490 iput(dir);
491 return -EPERM;
492 }
493 return dir->i_op->rmdir(dir,basename,namelen);
494 }
495
496 int sys_rmdir(const char * pathname)
497 {
498 int error;
499 char * tmp;
500
501 error = getname(pathname,&tmp);
502 if (!error) {
503 error = do_rmdir(tmp);
504 putname(tmp);
505 }
506 return error;
507 }
508
509 static int do_unlink(const char * name)
510 {
511 const char * basename;
512 int namelen, error;
513 struct inode * dir;
514
515 error = dir_namei(name,&namelen,&basename,NULL,&dir);
516 if (error)
517 return error;
518 if (!namelen) {
519 iput(dir);
520 return -EPERM;
521 }
522 if (IS_RDONLY(dir)) {
523 iput(dir);
524 return -EROFS;
525 }
526 if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
527 iput(dir);
528 return -EACCES;
529 }
530 if (!dir->i_op || !dir->i_op->unlink) {
531 iput(dir);
532 return -EPERM;
533 }
534 return dir->i_op->unlink(dir,basename,namelen);
535 }
536
537 int sys_unlink(const char * pathname)
538 {
539 int error;
540 char * tmp;
541
542 error = getname(pathname,&tmp);
543 if (!error) {
544 error = do_unlink(tmp);
545 putname(tmp);
546 }
547 return error;
548 }
549
550 static int do_symlink(const char * oldname, const char * newname)
551 {
552 struct inode * dir;
553 const char * basename;
554 int namelen, error;
555
556 error = dir_namei(newname,&namelen,&basename,NULL,&dir);
557 if (error)
558 return error;
559 if (!namelen) {
560 iput(dir);
561 return -ENOENT;
562 }
563 if (IS_RDONLY(dir)) {
564 iput(dir);
565 return -EROFS;
566 }
567 if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
568 iput(dir);
569 return -EACCES;
570 }
571 if (!dir->i_op || !dir->i_op->symlink) {
572 iput(dir);
573 return -EPERM;
574 }
575 return dir->i_op->symlink(dir,basename,namelen,oldname);
576 }
577
578 int sys_symlink(const char * oldname, const char * newname)
579 {
580 int error;
581 char * old, * new;
582
583 error = getname(oldname,&old);
584 if (!error) {
585 error = getname(newname,&new);
586 if (!error) {
587 error = do_symlink(old,new);
588 putname(new);
589 }
590 putname(old);
591 }
592 return error;
593 }
594
595 static int do_link(struct inode * oldinode, const char * newname)
596 {
597 struct inode * dir;
598 const char * basename;
599 int namelen, error;
600
601 error = dir_namei(newname,&namelen,&basename,NULL,&dir);
602 if (error) {
603 iput(oldinode);
604 return error;
605 }
606 if (!namelen) {
607 iput(oldinode);
608 iput(dir);
609 return -EPERM;
610 }
611 if (IS_RDONLY(dir)) {
612 iput(oldinode);
613 iput(dir);
614 return -EROFS;
615 }
616 if (dir->i_dev != oldinode->i_dev) {
617 iput(dir);
618 iput(oldinode);
619 return -EXDEV;
620 }
621 if (!permission(dir,MAY_WRITE | MAY_EXEC)) {
622 iput(dir);
623 iput(oldinode);
624 return -EACCES;
625 }
626 if (!dir->i_op || !dir->i_op->link) {
627 iput(dir);
628 iput(oldinode);
629 return -EPERM;
630 }
631 return dir->i_op->link(oldinode, dir, basename, namelen);
632 }
633
634 int sys_link(const char * oldname, const char * newname)
635 {
636 int error;
637 char * new;
638 struct inode * oldinode;
639
640 error = namei(oldname, &oldinode);
641 if (error)
642 return error;
643 error = getname(newname,&new);
644 if (!error) {
645 error = do_link(oldinode,new);
646 putname(new);
647 }
648 return error;
649 }
650
651 static int do_rename(const char * oldname, const char * newname)
652 {
653 struct inode * old_dir, * new_dir;
654 const char * old_base, * new_base;
655 int old_len, new_len, error;
656
657 error = dir_namei(oldname,&old_len,&old_base,NULL,&old_dir);
658 if (error)
659 return error;
660 if (!permission(old_dir,MAY_WRITE | MAY_EXEC)) {
661 iput(old_dir);
662 return -EACCES;
663 }
664 if (!old_len || (old_base[0] == '.' &&
665 (old_len == 1 || (old_base[1] == '.' &&
666 old_len == 2)))) {
667 iput(old_dir);
668 return -EPERM;
669 }
670 error = dir_namei(newname,&new_len,&new_base,NULL,&new_dir);
671 if (error) {
672 iput(old_dir);
673 return error;
674 }
675 if (!permission(new_dir,MAY_WRITE | MAY_EXEC)) {
676 iput(old_dir);
677 iput(new_dir);
678 return -EACCES;
679 }
680 if (!new_len || (new_base[0] == '.' &&
681 (new_len == 1 || (new_base[1] == '.' &&
682 new_len == 2)))) {
683 iput(old_dir);
684 iput(new_dir);
685 return -EPERM;
686 }
687 if (new_dir->i_dev != old_dir->i_dev) {
688 iput(old_dir);
689 iput(new_dir);
690 return -EXDEV;
691 }
692 if (IS_RDONLY(new_dir) || IS_RDONLY(old_dir)) {
693 iput(old_dir);
694 iput(new_dir);
695 return -EROFS;
696 }
697 if (!old_dir->i_op || !old_dir->i_op->rename) {
698 iput(old_dir);
699 iput(new_dir);
700 return -EPERM;
701 }
702 return old_dir->i_op->rename(old_dir, old_base, old_len,
703 new_dir, new_base, new_len);
704 }
705
706 int sys_rename(const char * oldname, const char * newname)
707 {
708 int error;
709 char * old, * new;
710
711 error = getname(oldname,&old);
712 if (!error) {
713 error = getname(newname,&new);
714 if (!error) {
715 error = do_rename(old,new);
716 putname(new);
717 }
718 putname(old);
719 }
720 return error;
721 }