|
|
1.1.1.2 root 1: /*
2: * linux/fs/namei.c
3: *
1.1.1.10 root 4: * Copyright (C) 1991, 1992 Linus Torvalds
1.1.1.2 root 5: */
6:
1.1.1.3 root 7: /*
8: * Some corrections by tytso.
9: */
10:
1.1 root 11: #include <asm/segment.h>
12:
1.1.1.10 root 13: #include <linux/errno.h>
1.1.1.9 root 14: #include <linux/sched.h>
15: #include <linux/kernel.h>
1.1.1.7 root 16: #include <linux/string.h>
1.1.1.9 root 17: #include <linux/fcntl.h>
1.1.1.8 root 18: #include <linux/stat.h>
1.1 root 19:
1.1.1.11! root 20: #define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
1.1 root 21:
22: /*
1.1.1.5 root 23: * comment out this line if you want names > MINIX_NAME_LEN chars to be
1.1 root 24: * truncated. Else they will be disallowed.
25: */
26: /* #define NO_TRUNCATE */
27:
28: /*
29: * permission()
30: *
31: * is used to check for read/write/execute permissions on a file.
32: * I don't know if we should look at just the euid or both euid and
33: * uid, but that should be easily changed.
34: */
1.1.1.5 root 35: int permission(struct inode * inode,int mask)
1.1 root 36: {
37: int mode = inode->i_mode;
38:
39: /* special case: not even root can read/write a deleted file */
1.1.1.5 root 40: if (inode->i_dev && !inode->i_nlink)
1.1 root 41: return 0;
1.1.1.5 root 42: else if (current->euid == inode->i_uid)
1.1 root 43: mode >>= 6;
1.1.1.4 root 44: else if (in_group_p(inode->i_gid))
1.1 root 45: mode >>= 3;
1.1.1.2 root 46: if (((mode & mask & 0007) == mask) || suser())
47: return 1;
48: return 0;
1.1 root 49: }
50:
51: /*
1.1.1.5 root 52: * lookup() looks up one part of a pathname, using the fs-dependent
53: * routines (currently minix_lookup) for it. It also checks for
54: * fathers (pseudo-roots, mount-points)
1.1 root 55: */
1.1.1.5 root 56: int lookup(struct inode * dir,const char * name, int len,
57: struct inode ** result)
1.1 root 58: {
1.1.1.2 root 59: struct super_block * sb;
1.1 root 60:
1.1.1.5 root 61: *result = NULL;
62: if (len==2 && get_fs_byte(name)=='.' && get_fs_byte(name+1)=='.') {
63: if (dir == current->root)
64: len = 1;
65: else if ((sb = dir->i_sb) && (dir == sb->s_mounted)) {
66: sb = dir->i_sb;
67: iput(dir);
68: if (dir = sb->s_covered)
69: dir->i_count++;
1.1.1.2 root 70: }
71: }
1.1.1.5 root 72: if (!dir)
73: return -ENOENT;
74: if (!permission(dir,MAY_EXEC)) {
75: iput(dir);
76: return -EACCES;
1.1 root 77: }
1.1.1.5 root 78: if (!len) {
79: *result = dir;
80: return 0;
81: }
82: if (!dir->i_op || !dir->i_op->lookup) {
83: iput(dir);
84: return -ENOENT;
1.1 root 85: }
1.1.1.5 root 86: return dir->i_op->lookup(dir,name,len,result);
1.1 root 87: }
88:
1.1.1.11! root 89: int follow_link(struct inode * dir, struct inode * inode,
! 90: int flag, int mode, struct inode ** res_inode)
1.1.1.4 root 91: {
1.1.1.5 root 92: if (!dir || !inode) {
1.1.1.4 root 93: iput(dir);
1.1.1.5 root 94: iput(inode);
1.1.1.11! root 95: *res_inode = NULL;
! 96: return -ENOENT;
1.1.1.4 root 97: }
1.1.1.5 root 98: if (!inode->i_op || !inode->i_op->follow_link) {
1.1.1.4 root 99: iput(dir);
1.1.1.11! root 100: *res_inode = inode;
! 101: return 0;
1.1.1.4 root 102: }
1.1.1.11! root 103: return inode->i_op->follow_link(dir,inode,flag,mode,res_inode);
1.1.1.4 root 104: }
105:
1.1 root 106: /*
1.1.1.5 root 107: * dir_namei()
1.1 root 108: *
1.1.1.5 root 109: * dir_namei() returns the inode of the directory of the
110: * specified name, and the name within that directory.
1.1 root 111: */
1.1.1.11! root 112: static int dir_namei(const char * pathname, int * namelen, const char ** name,
! 113: struct inode * base, struct inode ** res_inode)
1.1 root 114: {
115: char c;
116: const char * thisname;
1.1.1.5 root 117: int len,error;
118: struct inode * inode;
119:
1.1.1.11! root 120: *res_inode = NULL;
1.1.1.5 root 121: if (!base) {
122: base = current->pwd;
123: base->i_count++;
1.1.1.4 root 124: }
1.1 root 125: if ((c=get_fs_byte(pathname))=='/') {
1.1.1.5 root 126: iput(base);
127: base = current->root;
1.1 root 128: pathname++;
1.1.1.5 root 129: base->i_count++;
1.1.1.4 root 130: }
1.1 root 131: while (1) {
132: thisname = pathname;
1.1.1.5 root 133: for(len=0;(c=get_fs_byte(pathname++))&&(c!='/');len++)
1.1 root 134: /* nothing */ ;
135: if (!c)
1.1.1.5 root 136: break;
137: base->i_count++;
138: error = lookup(base,thisname,len,&inode);
139: if (error) {
140: iput(base);
1.1.1.11! root 141: return error;
1.1.1.4 root 142: }
1.1.1.11! root 143: error = follow_link(base,inode,0,0,&base);
! 144: if (error)
! 145: return error;
1.1 root 146: }
1.1.1.5 root 147: *name = thisname;
148: *namelen = len;
1.1.1.11! root 149: *res_inode = base;
! 150: return 0;
1.1 root 151: }
152:
1.1.1.11! root 153: static int _namei(const char * pathname, struct inode * base,
! 154: int follow_links, struct inode ** res_inode)
1.1 root 155: {
156: const char * basename;
1.1.1.5 root 157: int namelen,error;
158: struct inode * inode;
1.1 root 159:
1.1.1.11! root 160: *res_inode = NULL;
! 161: error = dir_namei(pathname,&namelen,&basename,base,&base);
! 162: if (error)
! 163: return error;
1.1.1.5 root 164: base->i_count++; /* lookup uses up base */
165: error = lookup(base,basename,namelen,&inode);
166: if (error) {
1.1.1.4 root 167: iput(base);
1.1.1.11! root 168: return error;
1.1 root 169: }
1.1.1.11! root 170: if (follow_links) {
! 171: error = follow_link(base,inode,0,0,&inode);
! 172: if (error)
! 173: return error;
! 174: } else
1.1.1.4 root 175: iput(base);
1.1.1.11! root 176: *res_inode = inode;
! 177: return 0;
1.1.1.4 root 178: }
179:
1.1.1.11! root 180: int lnamei(const char * pathname, struct inode ** res_inode)
1.1.1.4 root 181: {
1.1.1.11! root 182: return _namei(pathname,NULL,0,res_inode);
1.1.1.4 root 183: }
184:
185: /*
186: * namei()
187: *
188: * is used by most simple commands to get the inode of a specified name.
189: * Open, link etc use their own routines, but this is enough for things
190: * like 'chmod' etc.
191: */
1.1.1.11! root 192: int namei(const char * pathname, struct inode ** res_inode)
1.1.1.4 root 193: {
1.1.1.11! root 194: return _namei(pathname,NULL,1,res_inode);
1.1 root 195: }
196:
197: /*
198: * open_namei()
199: *
200: * namei for open - this is in fact almost the whole open-routine.
1.1.1.11! root 201: *
! 202: * Note that the low bits of "flag" aren't the same asin the open
! 203: * system call - they are 00 - no permissions needed
! 204: * 01 - read permission needed
! 205: * 10 - write permission needed
! 206: * 11 - read/write permissions needed
! 207: * which is a lot more logical, and also allows the "no perm" needed
! 208: * for symlinks (where the permissions are checked later).
1.1 root 209: */
210: int open_namei(const char * pathname, int flag, int mode,
1.1.1.11! root 211: struct inode ** res_inode, struct inode * base)
1.1 root 212: {
213: const char * basename;
1.1.1.10 root 214: int namelen,error,i;
1.1.1.5 root 215: struct inode * dir, *inode;
1.1.1.10 root 216: struct task_struct ** p;
1.1 root 217:
1.1.1.8 root 218: mode &= 07777 & ~current->umask;
1.1.1.11! root 219: mode |= S_IFREG;
! 220: error = dir_namei(pathname,&namelen,&basename,base,&dir);
! 221: if (error)
! 222: return error;
1.1 root 223: if (!namelen) { /* special case: '/usr/' etc */
1.1.1.11! root 224: if (!(flag & 2)) {
1.1 root 225: *res_inode=dir;
226: return 0;
227: }
228: iput(dir);
229: return -EISDIR;
230: }
1.1.1.5 root 231: dir->i_count++; /* lookup eats the dir */
232: error = lookup(dir,basename,namelen,&inode);
233: if (error) {
1.1 root 234: if (!(flag & O_CREAT)) {
235: iput(dir);
1.1.1.5 root 236: return error;
1.1 root 237: }
238: if (!permission(dir,MAY_WRITE)) {
239: iput(dir);
240: return -EACCES;
241: }
1.1.1.5 root 242: if (!dir->i_op || !dir->i_op->create) {
1.1 root 243: iput(dir);
1.1.1.5 root 244: return -EACCES;
1.1 root 245: }
1.1.1.10 root 246: if (IS_RDONLY(dir)) {
247: iput(dir);
248: return -EROFS;
249: }
1.1.1.5 root 250: return dir->i_op->create(dir,basename,namelen,mode,res_inode);
1.1 root 251: }
1.1.1.4 root 252: if (flag & O_EXCL) {
253: iput(dir);
1.1.1.5 root 254: iput(inode);
1.1 root 255: return -EEXIST;
1.1.1.4 root 256: }
1.1.1.11! root 257: if (error = follow_link(dir,inode,flag,mode,&inode))
! 258: return error;
! 259: if (S_ISDIR(inode->i_mode) && (flag & 2)) {
! 260: iput(inode);
! 261: return -EPERM;
! 262: }
! 263: if (!permission(inode,ACC_MODE(flag))) {
! 264: iput(inode);
! 265: return -EACCES;
! 266: }
1.1.1.10 root 267: if (S_ISBLK(inode->i_mode) || S_ISCHR(inode->i_mode)) {
268: if (IS_NODEV(inode)) {
269: iput(inode);
270: return -EACCES;
271: }
272: } else {
1.1.1.11! root 273: if (IS_RDONLY(inode) && (flag & 2)) {
1.1.1.10 root 274: iput(inode);
275: return -EROFS;
276: }
277: }
1.1.1.11! root 278: if ((inode->i_count > 1) && (flag & 2))
1.1.1.10 root 279: for (p = &LAST_TASK ; p > &FIRST_TASK ; --p) {
280: if (!*p)
281: continue;
282: if (inode == (*p)->executable) {
283: iput(inode);
284: return -ETXTBSY;
285: }
286: for (i=0; i < (*p)->numlibraries; i++)
287: if (inode == (*p)->libraries[i].library) {
288: iput(inode);
289: return -ETXTBSY;
290: }
291: }
1.1 root 292: *res_inode = inode;
293: return 0;
294: }
295:
1.1.1.8 root 296: int do_mknod(const char * filename, int mode, int dev)
1.1.1.2 root 297: {
298: const char * basename;
1.1.1.11! root 299: int namelen, error;
1.1.1.5 root 300: struct inode * dir;
1.1.1.11! root 301:
! 302: error = dir_namei(filename,&namelen,&basename, NULL, &dir);
! 303: if (error)
! 304: return error;
1.1.1.2 root 305: if (!namelen) {
306: iput(dir);
307: return -ENOENT;
308: }
1.1.1.10 root 309: if (IS_RDONLY(dir)) {
310: iput(dir);
311: return -EROFS;
312: }
1.1.1.2 root 313: if (!permission(dir,MAY_WRITE)) {
314: iput(dir);
1.1.1.6 root 315: return -EACCES;
1.1.1.2 root 316: }
1.1.1.5 root 317: if (!dir->i_op || !dir->i_op->mknod) {
1.1.1.2 root 318: iput(dir);
1.1.1.5 root 319: return -EPERM;
1.1.1.2 root 320: }
1.1.1.5 root 321: return dir->i_op->mknod(dir,basename,namelen,mode,dev);
1.1.1.2 root 322: }
323:
1.1.1.8 root 324: int sys_mknod(const char * filename, int mode, int dev)
325: {
1.1.1.9 root 326: if (S_ISFIFO(mode) || suser())
1.1.1.8 root 327: return do_mknod(filename,mode,dev);
328: return -EPERM;
329: }
330:
1.1 root 331: int sys_mkdir(const char * pathname, int mode)
332: {
333: const char * basename;
1.1.1.11! root 334: int namelen, error;
1.1.1.5 root 335: struct inode * dir;
1.1 root 336:
1.1.1.11! root 337: error = dir_namei(pathname,&namelen,&basename,NULL,&dir);
! 338: if (error)
! 339: return error;
1.1 root 340: if (!namelen) {
341: iput(dir);
342: return -ENOENT;
343: }
1.1.1.10 root 344: if (IS_RDONLY(dir)) {
345: iput(dir);
346: return -EROFS;
347: }
1.1 root 348: if (!permission(dir,MAY_WRITE)) {
349: iput(dir);
1.1.1.6 root 350: return -EACCES;
1.1 root 351: }
1.1.1.5 root 352: if (!dir->i_op || !dir->i_op->mkdir) {
1.1 root 353: iput(dir);
1.1.1.5 root 354: return -EPERM;
1.1 root 355: }
1.1.1.5 root 356: return dir->i_op->mkdir(dir,basename,namelen,mode);
1.1 root 357: }
358:
359: int sys_rmdir(const char * name)
360: {
361: const char * basename;
1.1.1.11! root 362: int namelen, error;
1.1.1.5 root 363: struct inode * dir;
1.1 root 364:
1.1.1.11! root 365: error = dir_namei(name,&namelen,&basename,NULL,&dir);
! 366: if (error)
! 367: return error;
1.1 root 368: if (!namelen) {
369: iput(dir);
370: return -ENOENT;
371: }
1.1.1.10 root 372: if (IS_RDONLY(dir)) {
373: iput(dir);
374: return -EROFS;
375: }
1.1.1.3 root 376: if (!permission(dir,MAY_WRITE)) {
377: iput(dir);
1.1.1.6 root 378: return -EACCES;
1.1.1.3 root 379: }
1.1.1.5 root 380: if (!dir->i_op || !dir->i_op->rmdir) {
1.1 root 381: iput(dir);
382: return -EPERM;
383: }
1.1.1.5 root 384: return dir->i_op->rmdir(dir,basename,namelen);
1.1 root 385: }
386:
387: int sys_unlink(const char * name)
388: {
389: const char * basename;
1.1.1.11! root 390: int namelen, error;
1.1.1.5 root 391: struct inode * dir;
1.1 root 392:
1.1.1.11! root 393: error = dir_namei(name,&namelen,&basename,NULL,&dir);
! 394: if (error)
! 395: return error;
1.1 root 396: if (!namelen) {
397: iput(dir);
1.1.1.6 root 398: return -EPERM;
1.1 root 399: }
1.1.1.10 root 400: if (IS_RDONLY(dir)) {
401: iput(dir);
402: return -EROFS;
403: }
1.1 root 404: if (!permission(dir,MAY_WRITE)) {
405: iput(dir);
1.1.1.6 root 406: return -EACCES;
1.1 root 407: }
1.1.1.5 root 408: if (!dir->i_op || !dir->i_op->unlink) {
1.1.1.2 root 409: iput(dir);
410: return -EPERM;
1.1.1.3 root 411: }
1.1.1.5 root 412: return dir->i_op->unlink(dir,basename,namelen);
1.1 root 413: }
414:
1.1.1.4 root 415: int sys_symlink(const char * oldname, const char * newname)
416: {
1.1.1.5 root 417: struct inode * dir;
1.1.1.4 root 418: const char * basename;
1.1.1.11! root 419: int namelen, error;
1.1.1.4 root 420:
1.1.1.11! root 421: error = dir_namei(newname,&namelen,&basename,NULL,&dir);
! 422: if (error)
! 423: return error;
1.1.1.4 root 424: if (!namelen) {
425: iput(dir);
1.1.1.6 root 426: return -ENOENT;
1.1.1.4 root 427: }
1.1.1.10 root 428: if (IS_RDONLY(dir)) {
429: iput(dir);
430: return -EROFS;
431: }
1.1.1.4 root 432: if (!permission(dir,MAY_WRITE)) {
433: iput(dir);
1.1.1.6 root 434: return -EACCES;
1.1.1.4 root 435: }
1.1.1.5 root 436: if (!dir->i_op || !dir->i_op->symlink) {
1.1.1.4 root 437: iput(dir);
1.1.1.5 root 438: return -EPERM;
1.1.1.4 root 439: }
1.1.1.5 root 440: return dir->i_op->symlink(dir,basename,namelen,oldname);
1.1.1.4 root 441: }
442:
1.1 root 443: int sys_link(const char * oldname, const char * newname)
444: {
1.1.1.5 root 445: struct inode * oldinode, * dir;
1.1 root 446: const char * basename;
1.1.1.11! root 447: int namelen, error;
1.1 root 448:
1.1.1.11! root 449: error = namei(oldname, &oldinode);
! 450: if (error)
! 451: return error;
! 452: error = dir_namei(newname,&namelen,&basename,NULL,&dir);
! 453: if (error) {
1.1 root 454: iput(oldinode);
1.1.1.11! root 455: return error;
1.1 root 456: }
457: if (!namelen) {
458: iput(oldinode);
459: iput(dir);
460: return -EPERM;
461: }
1.1.1.10 root 462: if (IS_RDONLY(dir)) {
463: iput(oldinode);
464: iput(dir);
465: return -EROFS;
466: }
1.1 root 467: if (dir->i_dev != oldinode->i_dev) {
468: iput(dir);
469: iput(oldinode);
470: return -EXDEV;
471: }
472: if (!permission(dir,MAY_WRITE)) {
473: iput(dir);
474: iput(oldinode);
475: return -EACCES;
476: }
1.1.1.5 root 477: if (!dir->i_op || !dir->i_op->link) {
1.1 root 478: iput(dir);
479: iput(oldinode);
1.1.1.5 root 480: return -EPERM;
1.1 root 481: }
1.1.1.5 root 482: return dir->i_op->link(oldinode, dir, basename, namelen);
483: }
484:
485: int sys_rename(const char * oldname, const char * newname)
486: {
487: struct inode * old_dir, * new_dir;
488: const char * old_base, * new_base;
1.1.1.11! root 489: int old_len, new_len, error;
1.1.1.5 root 490:
1.1.1.11! root 491: error = dir_namei(oldname,&old_len,&old_base,NULL,&old_dir);
! 492: if (error)
! 493: return error;
1.1.1.5 root 494: if (!permission(old_dir,MAY_WRITE)) {
495: iput(old_dir);
496: return -EACCES;
1.1 root 497: }
1.1.1.5 root 498: if (!old_len || (get_fs_byte(old_base) == '.' &&
499: (old_len == 1 || (get_fs_byte(old_base+1) == '.' &&
500: old_len == 2)))) {
501: iput(old_dir);
502: return -EPERM;
503: }
1.1.1.11! root 504: error = dir_namei(newname,&new_len,&new_base,NULL,&new_dir);
! 505: if (error) {
1.1.1.5 root 506: iput(old_dir);
1.1.1.11! root 507: return error;
1.1.1.5 root 508: }
509: if (!permission(new_dir,MAY_WRITE)) {
510: iput(old_dir);
511: iput(new_dir);
512: return -EACCES;
513: }
514: if (!new_len || (get_fs_byte(new_base) == '.' &&
515: (new_len == 1 || (get_fs_byte(new_base+1) == '.' &&
516: new_len == 2)))) {
517: iput(old_dir);
518: iput(new_dir);
519: return -EPERM;
520: }
521: if (new_dir->i_dev != old_dir->i_dev) {
522: iput(old_dir);
523: iput(new_dir);
524: return -EXDEV;
525: }
1.1.1.10 root 526: if (IS_RDONLY(new_dir) || IS_RDONLY(old_dir)) {
527: iput(old_dir);
528: iput(new_dir);
529: return -EROFS;
530: }
1.1.1.5 root 531: if (!old_dir->i_op || !old_dir->i_op->rename) {
532: iput(old_dir);
533: iput(new_dir);
534: return -EPERM;
535: }
536: return old_dir->i_op->rename(old_dir, old_base, old_len,
537: new_dir, new_base, new_len);
1.1 root 538: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.