|
|
1.1.1.2 root 1: /*
2: * linux/fs/namei.c
3: *
4: * (C) 1991 Linus Torvalds
5: */
6:
1.1.1.3 root 7: /*
8: * Some corrections by tytso.
9: */
10:
1.1 root 11: #include <linux/sched.h>
12: #include <linux/kernel.h>
13: #include <asm/segment.h>
14:
15: #include <string.h>
16: #include <fcntl.h>
17: #include <errno.h>
18: #include <const.h>
19: #include <sys/stat.h>
20:
1.1.1.4 ! root 21: static struct m_inode * _namei(const char * filename, struct m_inode * base,
! 22: int follow_links);
! 23:
1.1 root 24: #define ACC_MODE(x) ("\004\002\006\377"[(x)&O_ACCMODE])
25:
26: /*
27: * comment out this line if you want names > NAME_LEN chars to be
28: * truncated. Else they will be disallowed.
29: */
30: /* #define NO_TRUNCATE */
31:
32: #define MAY_EXEC 1
33: #define MAY_WRITE 2
34: #define MAY_READ 4
35:
36: /*
37: * permission()
38: *
39: * is used to check for read/write/execute permissions on a file.
40: * I don't know if we should look at just the euid or both euid and
41: * uid, but that should be easily changed.
42: */
43: static int permission(struct m_inode * inode,int mask)
44: {
45: int mode = inode->i_mode;
46:
47: /* special case: not even root can read/write a deleted file */
48: if (inode->i_dev && !inode->i_nlinks)
49: return 0;
1.1.1.2 root 50: else if (current->euid==inode->i_uid)
1.1 root 51: mode >>= 6;
1.1.1.4 ! root 52: else if (in_group_p(inode->i_gid))
1.1 root 53: mode >>= 3;
1.1.1.2 root 54: if (((mode & mask & 0007) == mask) || suser())
55: return 1;
56: return 0;
1.1 root 57: }
58:
59: /*
60: * ok, we cannot use strncmp, as the name is not in our data space.
61: * Thus we'll have to use match. No big problem. Match also makes
62: * some sanity tests.
63: *
64: * NOTE! unlike strncmp, match returns 1 for success, 0 for failure.
65: */
66: static int match(int len,const char * name,struct dir_entry * de)
67: {
68: register int same __asm__("ax");
69:
70: if (!de || !de->inode || len > NAME_LEN)
71: return 0;
1.1.1.4 ! root 72: /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
! 73: if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
! 74: return 1;
1.1 root 75: if (len < NAME_LEN && de->name[len])
76: return 0;
77: __asm__("cld\n\t"
78: "fs ; repe ; cmpsb\n\t"
79: "setz %%al"
80: :"=a" (same)
81: :"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
82: :"cx","di","si");
83: return same;
84: }
85:
86: /*
87: * find_entry()
88: *
1.1.1.3 root 89: * finds an entry in the specified directory with the wanted name. It
1.1 root 90: * returns the cache buffer in which the entry was found, and the entry
91: * itself (as a parameter - res_dir). It does NOT read the inode of the
92: * entry - you'll have to do that yourself if you want to.
1.1.1.2 root 93: *
94: * This also takes care of the few special cases due to '..'-traversal
95: * over a pseudo-root and a mount point.
1.1 root 96: */
1.1.1.2 root 97: static struct buffer_head * find_entry(struct m_inode ** dir,
1.1 root 98: const char * name, int namelen, struct dir_entry ** res_dir)
99: {
100: int entries;
101: int block,i;
102: struct buffer_head * bh;
103: struct dir_entry * de;
1.1.1.2 root 104: struct super_block * sb;
1.1 root 105:
106: #ifdef NO_TRUNCATE
107: if (namelen > NAME_LEN)
108: return NULL;
109: #else
110: if (namelen > NAME_LEN)
111: namelen = NAME_LEN;
112: #endif
1.1.1.2 root 113: entries = (*dir)->i_size / (sizeof (struct dir_entry));
1.1 root 114: *res_dir = NULL;
1.1.1.2 root 115: /* check for '..', as we might have to do some "magic" for it */
116: if (namelen==2 && get_fs_byte(name)=='.' && get_fs_byte(name+1)=='.') {
117: /* '..' in a pseudo-root results in a faked '.' (just change namelen) */
118: if ((*dir) == current->root)
119: namelen=1;
120: else if ((*dir)->i_num == ROOT_INO) {
121: /* '..' over a mount-point results in 'dir' being exchanged for the mounted
122: directory-inode. NOTE! We set mounted, so that we can iput the new dir */
123: sb=get_super((*dir)->i_dev);
124: if (sb->s_imount) {
125: iput(*dir);
126: (*dir)=sb->s_imount;
127: (*dir)->i_count++;
128: }
129: }
130: }
131: if (!(block = (*dir)->i_zone[0]))
1.1 root 132: return NULL;
1.1.1.2 root 133: if (!(bh = bread((*dir)->i_dev,block)))
1.1 root 134: return NULL;
135: i = 0;
136: de = (struct dir_entry *) bh->b_data;
137: while (i < entries) {
138: if ((char *)de >= BLOCK_SIZE+bh->b_data) {
139: brelse(bh);
140: bh = NULL;
1.1.1.2 root 141: if (!(block = bmap(*dir,i/DIR_ENTRIES_PER_BLOCK)) ||
142: !(bh = bread((*dir)->i_dev,block))) {
1.1 root 143: i += DIR_ENTRIES_PER_BLOCK;
144: continue;
145: }
146: de = (struct dir_entry *) bh->b_data;
147: }
148: if (match(namelen,name,de)) {
149: *res_dir = de;
150: return bh;
151: }
152: de++;
153: i++;
154: }
155: brelse(bh);
156: return NULL;
157: }
158:
159: /*
160: * add_entry()
161: *
162: * adds a file entry to the specified directory, using the same
163: * semantics as find_entry(). It returns NULL if it failed.
164: *
165: * NOTE!! The inode part of 'de' is left at 0 - which means you
166: * may not sleep between calling this and putting something into
167: * the entry, as someone else might have used it while you slept.
168: */
169: static struct buffer_head * add_entry(struct m_inode * dir,
170: const char * name, int namelen, struct dir_entry ** res_dir)
171: {
172: int block,i;
173: struct buffer_head * bh;
174: struct dir_entry * de;
175:
176: *res_dir = NULL;
177: #ifdef NO_TRUNCATE
178: if (namelen > NAME_LEN)
179: return NULL;
180: #else
181: if (namelen > NAME_LEN)
182: namelen = NAME_LEN;
183: #endif
184: if (!namelen)
185: return NULL;
186: if (!(block = dir->i_zone[0]))
187: return NULL;
188: if (!(bh = bread(dir->i_dev,block)))
189: return NULL;
190: i = 0;
191: de = (struct dir_entry *) bh->b_data;
192: while (1) {
193: if ((char *)de >= BLOCK_SIZE+bh->b_data) {
194: brelse(bh);
195: bh = NULL;
196: block = create_block(dir,i/DIR_ENTRIES_PER_BLOCK);
197: if (!block)
198: return NULL;
199: if (!(bh = bread(dir->i_dev,block))) {
200: i += DIR_ENTRIES_PER_BLOCK;
201: continue;
202: }
203: de = (struct dir_entry *) bh->b_data;
204: }
205: if (i*sizeof(struct dir_entry) >= dir->i_size) {
206: de->inode=0;
207: dir->i_size = (i+1)*sizeof(struct dir_entry);
208: dir->i_dirt = 1;
209: dir->i_ctime = CURRENT_TIME;
210: }
211: if (!de->inode) {
212: dir->i_mtime = CURRENT_TIME;
213: for (i=0; i < NAME_LEN ; i++)
214: de->name[i]=(i<namelen)?get_fs_byte(name+i):0;
215: bh->b_dirt = 1;
216: *res_dir = de;
217: return bh;
218: }
219: de++;
220: i++;
221: }
222: brelse(bh);
223: return NULL;
224: }
225:
1.1.1.4 ! root 226: static struct m_inode * follow_link(struct m_inode * dir, struct m_inode * inode)
! 227: {
! 228: unsigned short fs;
! 229: struct buffer_head * bh;
! 230:
! 231: if (!dir) {
! 232: dir = current->root;
! 233: dir->i_count++;
! 234: }
! 235: if (!inode) {
! 236: iput(dir);
! 237: return NULL;
! 238: }
! 239: if (!S_ISLNK(inode->i_mode)) {
! 240: iput(dir);
! 241: return inode;
! 242: }
! 243: __asm__("mov %%fs,%0":"=r" (fs));
! 244: if (fs != 0x17 || !inode->i_zone[0] ||
! 245: !(bh = bread(inode->i_dev, inode->i_zone[0]))) {
! 246: iput(dir);
! 247: iput(inode);
! 248: return NULL;
! 249: }
! 250: iput(inode);
! 251: __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
! 252: inode = _namei(bh->b_data,dir,0);
! 253: __asm__("mov %0,%%fs"::"r" (fs));
! 254: brelse(bh);
! 255: return inode;
! 256: }
! 257:
1.1 root 258: /*
259: * get_dir()
260: *
261: * Getdir traverses the pathname until it hits the topmost directory.
262: * It returns NULL on failure.
263: */
1.1.1.4 ! root 264: static struct m_inode * get_dir(const char * pathname, struct m_inode * inode)
1.1 root 265: {
266: char c;
267: const char * thisname;
268: struct buffer_head * bh;
1.1.1.4 ! root 269: int namelen,inr;
1.1 root 270: struct dir_entry * de;
1.1.1.4 ! root 271: struct m_inode * dir;
1.1 root 272:
1.1.1.4 ! root 273: if (!inode) {
! 274: inode = current->pwd;
! 275: inode->i_count++;
! 276: }
1.1 root 277: if ((c=get_fs_byte(pathname))=='/') {
1.1.1.4 ! root 278: iput(inode);
1.1 root 279: inode = current->root;
280: pathname++;
1.1.1.4 ! root 281: inode->i_count++;
! 282: }
1.1 root 283: while (1) {
284: thisname = pathname;
285: if (!S_ISDIR(inode->i_mode) || !permission(inode,MAY_EXEC)) {
286: iput(inode);
287: return NULL;
288: }
289: for(namelen=0;(c=get_fs_byte(pathname++))&&(c!='/');namelen++)
290: /* nothing */ ;
291: if (!c)
292: return inode;
1.1.1.2 root 293: if (!(bh = find_entry(&inode,thisname,namelen,&de))) {
1.1 root 294: iput(inode);
295: return NULL;
296: }
297: inr = de->inode;
298: brelse(bh);
1.1.1.4 ! root 299: dir = inode;
! 300: if (!(inode = iget(dir->i_dev,inr))) {
! 301: iput(dir);
! 302: return NULL;
! 303: }
! 304: if (!(inode = follow_link(dir,inode)))
1.1 root 305: return NULL;
306: }
307: }
308:
309: /*
310: * dir_namei()
311: *
312: * dir_namei() returns the inode of the directory of the
313: * specified name, and the name within that directory.
314: */
315: static struct m_inode * dir_namei(const char * pathname,
1.1.1.4 ! root 316: int * namelen, const char ** name, struct m_inode * base)
1.1 root 317: {
318: char c;
319: const char * basename;
320: struct m_inode * dir;
321:
1.1.1.4 ! root 322: if (!(dir = get_dir(pathname,base)))
1.1 root 323: return NULL;
324: basename = pathname;
325: while (c=get_fs_byte(pathname++))
326: if (c=='/')
327: basename=pathname;
328: *namelen = pathname-basename-1;
329: *name = basename;
330: return dir;
331: }
332:
1.1.1.4 ! root 333: struct m_inode * _namei(const char * pathname, struct m_inode * base,
! 334: int follow_links)
1.1 root 335: {
336: const char * basename;
1.1.1.4 ! root 337: int inr,namelen;
! 338: struct m_inode * inode;
1.1 root 339: struct buffer_head * bh;
340: struct dir_entry * de;
341:
1.1.1.4 ! root 342: if (!(base = dir_namei(pathname,&namelen,&basename,base)))
1.1 root 343: return NULL;
344: if (!namelen) /* special case: '/usr/' etc */
1.1.1.4 ! root 345: return base;
! 346: bh = find_entry(&base,basename,namelen,&de);
1.1 root 347: if (!bh) {
1.1.1.4 ! root 348: iput(base);
1.1 root 349: return NULL;
350: }
351: inr = de->inode;
352: brelse(bh);
1.1.1.4 ! root 353: if (!(inode = iget(base->i_dev,inr))) {
! 354: iput(base);
! 355: return NULL;
1.1 root 356: }
1.1.1.4 ! root 357: if (follow_links)
! 358: inode = follow_link(base,inode);
! 359: else
! 360: iput(base);
! 361: inode->i_atime=CURRENT_TIME;
! 362: inode->i_dirt=1;
! 363: return inode;
! 364: }
! 365:
! 366: struct m_inode * lnamei(const char * pathname)
! 367: {
! 368: return _namei(pathname, NULL, 0);
! 369: }
! 370:
! 371: /*
! 372: * namei()
! 373: *
! 374: * is used by most simple commands to get the inode of a specified name.
! 375: * Open, link etc use their own routines, but this is enough for things
! 376: * like 'chmod' etc.
! 377: */
! 378: struct m_inode * namei(const char * pathname)
! 379: {
! 380: return _namei(pathname,NULL,1);
1.1 root 381: }
382:
383: /*
384: * open_namei()
385: *
386: * namei for open - this is in fact almost the whole open-routine.
387: */
388: int open_namei(const char * pathname, int flag, int mode,
389: struct m_inode ** res_inode)
390: {
391: const char * basename;
392: int inr,dev,namelen;
393: struct m_inode * dir, *inode;
394: struct buffer_head * bh;
395: struct dir_entry * de;
396:
397: if ((flag & O_TRUNC) && !(flag & O_ACCMODE))
398: flag |= O_WRONLY;
399: mode &= 0777 & ~current->umask;
400: mode |= I_REGULAR;
1.1.1.4 ! root 401: if (!(dir = dir_namei(pathname,&namelen,&basename,NULL)))
1.1 root 402: return -ENOENT;
403: if (!namelen) { /* special case: '/usr/' etc */
404: if (!(flag & (O_ACCMODE|O_CREAT|O_TRUNC))) {
405: *res_inode=dir;
406: return 0;
407: }
408: iput(dir);
409: return -EISDIR;
410: }
1.1.1.2 root 411: bh = find_entry(&dir,basename,namelen,&de);
1.1 root 412: if (!bh) {
413: if (!(flag & O_CREAT)) {
414: iput(dir);
415: return -ENOENT;
416: }
417: if (!permission(dir,MAY_WRITE)) {
418: iput(dir);
419: return -EACCES;
420: }
421: inode = new_inode(dir->i_dev);
422: if (!inode) {
423: iput(dir);
424: return -ENOSPC;
425: }
1.1.1.2 root 426: inode->i_uid = current->euid;
1.1 root 427: inode->i_mode = mode;
428: inode->i_dirt = 1;
429: bh = add_entry(dir,basename,namelen,&de);
430: if (!bh) {
431: inode->i_nlinks--;
432: iput(inode);
433: iput(dir);
434: return -ENOSPC;
435: }
436: de->inode = inode->i_num;
437: bh->b_dirt = 1;
438: brelse(bh);
439: iput(dir);
440: *res_inode = inode;
441: return 0;
442: }
443: inr = de->inode;
444: dev = dir->i_dev;
445: brelse(bh);
1.1.1.4 ! root 446: if (flag & O_EXCL) {
! 447: iput(dir);
1.1 root 448: return -EEXIST;
1.1.1.4 ! root 449: }
! 450: if (!(inode = follow_link(dir,iget(dev,inr))))
1.1 root 451: return -EACCES;
452: if ((S_ISDIR(inode->i_mode) && (flag & O_ACCMODE)) ||
1.1.1.2 root 453: !permission(inode,ACC_MODE(flag))) {
1.1 root 454: iput(inode);
455: return -EPERM;
456: }
457: inode->i_atime = CURRENT_TIME;
458: if (flag & O_TRUNC)
459: truncate(inode);
460: *res_inode = inode;
461: return 0;
462: }
463:
1.1.1.2 root 464: int sys_mknod(const char * filename, int mode, int dev)
465: {
466: const char * basename;
467: int namelen;
468: struct m_inode * dir, * inode;
469: struct buffer_head * bh;
470: struct dir_entry * de;
471:
472: if (!suser())
473: return -EPERM;
1.1.1.4 ! root 474: if (!(dir = dir_namei(filename,&namelen,&basename, NULL)))
1.1.1.2 root 475: return -ENOENT;
476: if (!namelen) {
477: iput(dir);
478: return -ENOENT;
479: }
480: if (!permission(dir,MAY_WRITE)) {
481: iput(dir);
482: return -EPERM;
483: }
484: bh = find_entry(&dir,basename,namelen,&de);
485: if (bh) {
486: brelse(bh);
487: iput(dir);
488: return -EEXIST;
489: }
490: inode = new_inode(dir->i_dev);
491: if (!inode) {
492: iput(dir);
493: return -ENOSPC;
494: }
495: inode->i_mode = mode;
496: if (S_ISBLK(mode) || S_ISCHR(mode))
497: inode->i_zone[0] = dev;
498: inode->i_mtime = inode->i_atime = CURRENT_TIME;
499: inode->i_dirt = 1;
500: bh = add_entry(dir,basename,namelen,&de);
501: if (!bh) {
502: iput(dir);
503: inode->i_nlinks=0;
504: iput(inode);
505: return -ENOSPC;
506: }
507: de->inode = inode->i_num;
508: bh->b_dirt = 1;
509: iput(dir);
510: iput(inode);
511: brelse(bh);
512: return 0;
513: }
514:
1.1 root 515: int sys_mkdir(const char * pathname, int mode)
516: {
517: const char * basename;
518: int namelen;
519: struct m_inode * dir, * inode;
520: struct buffer_head * bh, *dir_block;
521: struct dir_entry * de;
522:
1.1.1.4 ! root 523: if (!(dir = dir_namei(pathname,&namelen,&basename, NULL)))
1.1 root 524: return -ENOENT;
525: if (!namelen) {
526: iput(dir);
527: return -ENOENT;
528: }
529: if (!permission(dir,MAY_WRITE)) {
530: iput(dir);
531: return -EPERM;
532: }
1.1.1.2 root 533: bh = find_entry(&dir,basename,namelen,&de);
1.1 root 534: if (bh) {
535: brelse(bh);
536: iput(dir);
537: return -EEXIST;
538: }
539: inode = new_inode(dir->i_dev);
540: if (!inode) {
541: iput(dir);
542: return -ENOSPC;
543: }
544: inode->i_size = 32;
545: inode->i_dirt = 1;
546: inode->i_mtime = inode->i_atime = CURRENT_TIME;
547: if (!(inode->i_zone[0]=new_block(inode->i_dev))) {
548: iput(dir);
549: inode->i_nlinks--;
550: iput(inode);
551: return -ENOSPC;
552: }
553: inode->i_dirt = 1;
554: if (!(dir_block=bread(inode->i_dev,inode->i_zone[0]))) {
555: iput(dir);
556: inode->i_nlinks--;
557: iput(inode);
558: return -ERROR;
559: }
560: de = (struct dir_entry *) dir_block->b_data;
561: de->inode=inode->i_num;
562: strcpy(de->name,".");
563: de++;
564: de->inode = dir->i_num;
565: strcpy(de->name,"..");
566: inode->i_nlinks = 2;
567: dir_block->b_dirt = 1;
568: brelse(dir_block);
569: inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask);
570: inode->i_dirt = 1;
571: bh = add_entry(dir,basename,namelen,&de);
572: if (!bh) {
573: iput(dir);
574: inode->i_nlinks=0;
575: iput(inode);
576: return -ENOSPC;
577: }
578: de->inode = inode->i_num;
579: bh->b_dirt = 1;
580: dir->i_nlinks++;
581: dir->i_dirt = 1;
582: iput(dir);
583: iput(inode);
584: brelse(bh);
585: return 0;
586: }
587:
588: /*
589: * routine to check that the specified directory is empty (for rmdir)
590: */
591: static int empty_dir(struct m_inode * inode)
592: {
593: int nr,block;
594: int len;
595: struct buffer_head * bh;
596: struct dir_entry * de;
597:
598: len = inode->i_size / sizeof (struct dir_entry);
599: if (len<2 || !inode->i_zone[0] ||
600: !(bh=bread(inode->i_dev,inode->i_zone[0]))) {
601: printk("warning - bad directory on dev %04x\n",inode->i_dev);
602: return 0;
603: }
604: de = (struct dir_entry *) bh->b_data;
605: if (de[0].inode != inode->i_num || !de[1].inode ||
606: strcmp(".",de[0].name) || strcmp("..",de[1].name)) {
607: printk("warning - bad directory on dev %04x\n",inode->i_dev);
608: return 0;
609: }
610: nr = 2;
611: de += 2;
612: while (nr<len) {
613: if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
614: brelse(bh);
615: block=bmap(inode,nr/DIR_ENTRIES_PER_BLOCK);
616: if (!block) {
617: nr += DIR_ENTRIES_PER_BLOCK;
618: continue;
619: }
620: if (!(bh=bread(inode->i_dev,block)))
621: return 0;
622: de = (struct dir_entry *) bh->b_data;
623: }
624: if (de->inode) {
625: brelse(bh);
626: return 0;
627: }
628: de++;
629: nr++;
630: }
631: brelse(bh);
632: return 1;
633: }
634:
635: int sys_rmdir(const char * name)
636: {
637: const char * basename;
638: int namelen;
639: struct m_inode * dir, * inode;
640: struct buffer_head * bh;
641: struct dir_entry * de;
642:
1.1.1.4 ! root 643: if (!(dir = dir_namei(name,&namelen,&basename, NULL)))
1.1 root 644: return -ENOENT;
645: if (!namelen) {
646: iput(dir);
647: return -ENOENT;
648: }
1.1.1.3 root 649: if (!permission(dir,MAY_WRITE)) {
650: iput(dir);
651: return -EPERM;
652: }
1.1.1.2 root 653: bh = find_entry(&dir,basename,namelen,&de);
1.1 root 654: if (!bh) {
655: iput(dir);
656: return -ENOENT;
657: }
1.1.1.3 root 658: if (!(inode = iget(dir->i_dev, de->inode))) {
1.1 root 659: iput(dir);
660: brelse(bh);
661: return -EPERM;
662: }
1.1.1.3 root 663: if ((dir->i_mode & S_ISVTX) && current->euid &&
664: inode->i_uid != current->euid) {
1.1 root 665: iput(dir);
1.1.1.3 root 666: iput(inode);
667: brelse(bh);
668: return -EPERM;
669: }
670: if (inode->i_dev != dir->i_dev || inode->i_count>1) {
671: iput(dir);
672: iput(inode);
1.1 root 673: brelse(bh);
674: return -EPERM;
675: }
676: if (inode == dir) { /* we may not delete ".", but "../dir" is ok */
677: iput(inode);
678: iput(dir);
679: brelse(bh);
680: return -EPERM;
681: }
682: if (!S_ISDIR(inode->i_mode)) {
683: iput(inode);
684: iput(dir);
685: brelse(bh);
686: return -ENOTDIR;
687: }
688: if (!empty_dir(inode)) {
689: iput(inode);
690: iput(dir);
691: brelse(bh);
692: return -ENOTEMPTY;
693: }
694: if (inode->i_nlinks != 2)
695: printk("empty directory has nlink!=2 (%d)",inode->i_nlinks);
696: de->inode = 0;
697: bh->b_dirt = 1;
698: brelse(bh);
699: inode->i_nlinks=0;
700: inode->i_dirt=1;
701: dir->i_nlinks--;
702: dir->i_ctime = dir->i_mtime = CURRENT_TIME;
703: dir->i_dirt=1;
704: iput(dir);
705: iput(inode);
706: return 0;
707: }
708:
709: int sys_unlink(const char * name)
710: {
711: const char * basename;
712: int namelen;
713: struct m_inode * dir, * inode;
714: struct buffer_head * bh;
715: struct dir_entry * de;
716:
1.1.1.4 ! root 717: if (!(dir = dir_namei(name,&namelen,&basename, NULL)))
1.1 root 718: return -ENOENT;
719: if (!namelen) {
720: iput(dir);
721: return -ENOENT;
722: }
723: if (!permission(dir,MAY_WRITE)) {
724: iput(dir);
725: return -EPERM;
726: }
1.1.1.2 root 727: bh = find_entry(&dir,basename,namelen,&de);
1.1 root 728: if (!bh) {
729: iput(dir);
730: return -ENOENT;
731: }
1.1.1.3 root 732: if (!(inode = iget(dir->i_dev, de->inode))) {
1.1 root 733: iput(dir);
734: brelse(bh);
735: return -ENOENT;
736: }
1.1.1.3 root 737: if ((dir->i_mode & S_ISVTX) && !suser() &&
738: current->euid != inode->i_uid &&
739: current->euid != dir->i_uid) {
1.1 root 740: iput(dir);
1.1.1.3 root 741: iput(inode);
1.1 root 742: brelse(bh);
743: return -EPERM;
744: }
1.1.1.3 root 745: if (S_ISDIR(inode->i_mode)) {
1.1.1.2 root 746: iput(inode);
747: iput(dir);
748: brelse(bh);
749: return -EPERM;
1.1.1.3 root 750: }
1.1 root 751: if (!inode->i_nlinks) {
752: printk("Deleting nonexistent file (%04x:%d), %d\n",
753: inode->i_dev,inode->i_num,inode->i_nlinks);
754: inode->i_nlinks=1;
755: }
756: de->inode = 0;
757: bh->b_dirt = 1;
758: brelse(bh);
759: inode->i_nlinks--;
760: inode->i_dirt = 1;
761: inode->i_ctime = CURRENT_TIME;
762: iput(inode);
763: iput(dir);
764: return 0;
765: }
766:
1.1.1.4 ! root 767: int sys_symlink(const char * oldname, const char * newname)
! 768: {
! 769: struct dir_entry * de;
! 770: struct m_inode * dir, * inode;
! 771: struct buffer_head * bh, * name_block;
! 772: const char * basename;
! 773: int namelen, i;
! 774: char c;
! 775:
! 776: dir = dir_namei(newname,&namelen,&basename, NULL);
! 777: if (!dir)
! 778: return -EACCES;
! 779: if (!namelen) {
! 780: iput(dir);
! 781: return -EPERM;
! 782: }
! 783: if (!permission(dir,MAY_WRITE)) {
! 784: iput(dir);
! 785: return -EACCES;
! 786: }
! 787: if (!(inode = new_inode(dir->i_dev))) {
! 788: iput(dir);
! 789: return -ENOSPC;
! 790: }
! 791: inode->i_mode = S_IFLNK | (0777 & ~current->umask);
! 792: inode->i_dirt = 1;
! 793: if (!(inode->i_zone[0]=new_block(inode->i_dev))) {
! 794: iput(dir);
! 795: inode->i_nlinks--;
! 796: iput(inode);
! 797: return -ENOSPC;
! 798: }
! 799: inode->i_dirt = 1;
! 800: if (!(name_block=bread(inode->i_dev,inode->i_zone[0]))) {
! 801: iput(dir);
! 802: inode->i_nlinks--;
! 803: iput(inode);
! 804: return -ERROR;
! 805: }
! 806: i = 0;
! 807: while (i < 1023 && (c=get_fs_byte(oldname++)))
! 808: name_block->b_data[i++] = c;
! 809: name_block->b_data[i] = 0;
! 810: name_block->b_dirt = 1;
! 811: brelse(name_block);
! 812: inode->i_size = i;
! 813: inode->i_dirt = 1;
! 814: bh = find_entry(&dir,basename,namelen,&de);
! 815: if (bh) {
! 816: inode->i_nlinks--;
! 817: iput(inode);
! 818: brelse(bh);
! 819: iput(dir);
! 820: return -EEXIST;
! 821: }
! 822: bh = add_entry(dir,basename,namelen,&de);
! 823: if (!bh) {
! 824: inode->i_nlinks--;
! 825: iput(inode);
! 826: iput(dir);
! 827: return -ENOSPC;
! 828: }
! 829: de->inode = inode->i_num;
! 830: bh->b_dirt = 1;
! 831: brelse(bh);
! 832: iput(dir);
! 833: iput(inode);
! 834: return 0;
! 835: }
! 836:
1.1 root 837: int sys_link(const char * oldname, const char * newname)
838: {
839: struct dir_entry * de;
840: struct m_inode * oldinode, * dir;
841: struct buffer_head * bh;
842: const char * basename;
843: int namelen;
844:
845: oldinode=namei(oldname);
846: if (!oldinode)
847: return -ENOENT;
1.1.1.2 root 848: if (S_ISDIR(oldinode->i_mode)) {
1.1 root 849: iput(oldinode);
850: return -EPERM;
851: }
1.1.1.4 ! root 852: dir = dir_namei(newname,&namelen,&basename, NULL);
1.1 root 853: if (!dir) {
854: iput(oldinode);
855: return -EACCES;
856: }
857: if (!namelen) {
858: iput(oldinode);
859: iput(dir);
860: return -EPERM;
861: }
862: if (dir->i_dev != oldinode->i_dev) {
863: iput(dir);
864: iput(oldinode);
865: return -EXDEV;
866: }
867: if (!permission(dir,MAY_WRITE)) {
868: iput(dir);
869: iput(oldinode);
870: return -EACCES;
871: }
1.1.1.2 root 872: bh = find_entry(&dir,basename,namelen,&de);
1.1 root 873: if (bh) {
874: brelse(bh);
875: iput(dir);
876: iput(oldinode);
877: return -EEXIST;
878: }
879: bh = add_entry(dir,basename,namelen,&de);
880: if (!bh) {
881: iput(dir);
882: iput(oldinode);
883: return -ENOSPC;
884: }
885: de->inode = oldinode->i_num;
886: bh->b_dirt = 1;
887: brelse(bh);
888: iput(dir);
889: oldinode->i_nlinks++;
890: oldinode->i_ctime = CURRENT_TIME;
891: oldinode->i_dirt = 1;
892: iput(oldinode);
893: return 0;
894: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.