|
|
1.1 root 1: /*
2: * linux/fs/minix/namei.c
3: *
4: * (C) 1991 Linus Torvalds
5: */
6:
7: #include <linux/sched.h>
8: #include <linux/minix_fs.h>
9: #include <linux/kernel.h>
1.1.1.4 root 10: #include <linux/string.h>
11: #include <linux/stat.h>
1.1.1.5 ! root 12: #include <linux/fcntl.h>
1.1 root 13: #include <asm/segment.h>
14:
15: #include <errno.h>
16: #include <const.h>
17:
18: /*
19: * comment out this line if you want names > MINIX_NAME_LEN chars to be
20: * truncated. Else they will be disallowed.
21: */
22: /* #define NO_TRUNCATE */
23:
24: /*
25: * ok, we cannot use strncmp, as the name is not in our data space.
26: * Thus we'll have to use minix_match. No big problem. Match also makes
27: * some sanity tests.
28: *
29: * NOTE! unlike strncmp, minix_match returns 1 for success, 0 for failure.
30: */
31: static int minix_match(int len,const char * name,struct minix_dir_entry * de)
32: {
33: register int same __asm__("ax");
34:
35: if (!de || !de->inode || len > MINIX_NAME_LEN)
36: return 0;
37: /* "" means "." ---> so paths like "/usr/lib//libc.a" work */
38: if (!len && (de->name[0]=='.') && (de->name[1]=='\0'))
39: return 1;
40: if (len < MINIX_NAME_LEN && de->name[len])
41: return 0;
42: __asm__("cld\n\t"
43: "fs ; repe ; cmpsb\n\t"
44: "setz %%al"
45: :"=a" (same)
46: :"0" (0),"S" ((long) name),"D" ((long) de->name),"c" (len)
47: :"cx","di","si");
48: return same;
49: }
50:
51: /*
52: * minix_find_entry()
53: *
54: * finds an entry in the specified directory with the wanted name. It
55: * returns the cache buffer in which the entry was found, and the entry
56: * itself (as a parameter - res_dir). It does NOT read the inode of the
57: * entry - you'll have to do that yourself if you want to.
58: */
59: static struct buffer_head * minix_find_entry(struct inode * dir,
60: const char * name, int namelen, struct minix_dir_entry ** res_dir)
61: {
62: int entries;
63: int block,i;
64: struct buffer_head * bh;
65: struct minix_dir_entry * de;
66:
67: *res_dir = NULL;
68: if (!dir)
69: return NULL;
70: #ifdef NO_TRUNCATE
71: if (namelen > MINIX_NAME_LEN)
72: return NULL;
73: #else
74: if (namelen > MINIX_NAME_LEN)
75: namelen = MINIX_NAME_LEN;
76: #endif
77: entries = dir->i_size / (sizeof (struct minix_dir_entry));
78: if (!(block = dir->i_data[0]))
79: return NULL;
80: if (!(bh = bread(dir->i_dev,block)))
81: return NULL;
82: i = 0;
83: de = (struct minix_dir_entry *) bh->b_data;
84: while (i < entries) {
85: if ((char *)de >= BLOCK_SIZE+bh->b_data) {
86: brelse(bh);
87: bh = NULL;
1.1.1.2 root 88: if (!(block = minix_bmap(dir,i/MINIX_DIR_ENTRIES_PER_BLOCK)) ||
1.1 root 89: !(bh = bread(dir->i_dev,block))) {
90: i += MINIX_DIR_ENTRIES_PER_BLOCK;
91: continue;
92: }
93: de = (struct minix_dir_entry *) bh->b_data;
94: }
95: if (minix_match(namelen,name,de)) {
96: *res_dir = de;
97: return bh;
98: }
99: de++;
100: i++;
101: }
102: brelse(bh);
103: return NULL;
104: }
105:
106: int minix_lookup(struct inode * dir,const char * name, int len,
107: struct inode ** result)
108: {
109: int ino;
110: struct minix_dir_entry * de;
111: struct buffer_head * bh;
112:
113: *result = NULL;
114: if (!dir)
115: return -ENOENT;
116: if (!S_ISDIR(dir->i_mode)) {
117: iput(dir);
118: return -ENOENT;
119: }
120: if (!(bh = minix_find_entry(dir,name,len,&de))) {
121: iput(dir);
122: return -ENOENT;
123: }
124: ino = de->inode;
125: brelse(bh);
126: if (!(*result = iget(dir->i_dev,ino))) {
127: iput(dir);
128: return -EACCES;
129: }
130: iput(dir);
131: return 0;
132: }
133:
134: /*
135: * minix_add_entry()
136: *
137: * adds a file entry to the specified directory, using the same
138: * semantics as minix_find_entry(). It returns NULL if it failed.
139: *
140: * NOTE!! The inode part of 'de' is left at 0 - which means you
141: * may not sleep between calling this and putting something into
142: * the entry, as someone else might have used it while you slept.
143: */
144: static struct buffer_head * minix_add_entry(struct inode * dir,
145: const char * name, int namelen, struct minix_dir_entry ** res_dir)
146: {
147: int block,i;
148: struct buffer_head * bh;
149: struct minix_dir_entry * de;
150:
151: *res_dir = NULL;
152: if (!dir)
153: return NULL;
154: #ifdef NO_TRUNCATE
155: if (namelen > MINIX_NAME_LEN)
156: return NULL;
157: #else
158: if (namelen > MINIX_NAME_LEN)
159: namelen = MINIX_NAME_LEN;
160: #endif
161: if (!namelen)
162: return NULL;
163: if (!(block = dir->i_data[0]))
164: return NULL;
165: if (!(bh = bread(dir->i_dev,block)))
166: return NULL;
167: i = 0;
168: de = (struct minix_dir_entry *) bh->b_data;
169: while (1) {
170: if ((char *)de >= BLOCK_SIZE+bh->b_data) {
171: brelse(bh);
172: bh = NULL;
173: block = minix_create_block(dir,i/MINIX_DIR_ENTRIES_PER_BLOCK);
174: if (!block)
175: return NULL;
176: if (!(bh = bread(dir->i_dev,block))) {
177: i += MINIX_DIR_ENTRIES_PER_BLOCK;
178: continue;
179: }
180: de = (struct minix_dir_entry *) bh->b_data;
181: }
182: if (i*sizeof(struct minix_dir_entry) >= dir->i_size) {
183: de->inode=0;
184: dir->i_size = (i+1)*sizeof(struct minix_dir_entry);
185: dir->i_dirt = 1;
186: dir->i_ctime = CURRENT_TIME;
187: }
188: if (!de->inode) {
189: dir->i_mtime = CURRENT_TIME;
190: for (i=0; i < MINIX_NAME_LEN ; i++)
191: de->name[i]=(i<namelen)?get_fs_byte(name+i):0;
192: bh->b_dirt = 1;
193: *res_dir = de;
194: return bh;
195: }
196: de++;
197: i++;
198: }
199: brelse(bh);
200: return NULL;
201: }
202:
203: int minix_create(struct inode * dir,const char * name, int len, int mode,
204: struct inode ** result)
205: {
206: struct inode * inode;
207: struct buffer_head * bh;
208: struct minix_dir_entry * de;
209:
210: *result = NULL;
211: if (!dir)
212: return -ENOENT;
213: inode = minix_new_inode(dir->i_dev);
214: if (!inode) {
215: iput(dir);
216: return -ENOSPC;
217: }
1.1.1.3 root 218: inode->i_op = &minix_file_inode_operations;
1.1 root 219: inode->i_mode = mode;
220: inode->i_dirt = 1;
221: bh = minix_add_entry(dir,name,len,&de);
222: if (!bh) {
223: inode->i_nlink--;
1.1.1.3 root 224: inode->i_dirt = 1;
1.1 root 225: iput(inode);
226: iput(dir);
227: return -ENOSPC;
228: }
229: de->inode = inode->i_ino;
230: bh->b_dirt = 1;
231: brelse(bh);
232: iput(dir);
233: *result = inode;
234: return 0;
235: }
236:
237: int minix_mknod(struct inode * dir, const char * name, int len, int mode, int rdev)
238: {
239: struct inode * inode;
240: struct buffer_head * bh;
241: struct minix_dir_entry * de;
242:
243: if (!dir)
244: return -ENOENT;
245: bh = minix_find_entry(dir,name,len,&de);
246: if (bh) {
247: brelse(bh);
248: iput(dir);
249: return -EEXIST;
250: }
251: inode = minix_new_inode(dir->i_dev);
252: if (!inode) {
253: iput(dir);
254: return -ENOSPC;
255: }
256: inode->i_uid = current->euid;
257: inode->i_mode = mode;
1.1.1.3 root 258: inode->i_op = NULL;
259: if (S_ISREG(inode->i_mode))
260: inode->i_op = &minix_file_inode_operations;
261: else if (S_ISDIR(inode->i_mode))
262: inode->i_op = &minix_dir_inode_operations;
263: else if (S_ISLNK(inode->i_mode))
264: inode->i_op = &minix_symlink_inode_operations;
265: else if (S_ISCHR(inode->i_mode))
266: inode->i_op = &minix_chrdev_inode_operations;
267: else if (S_ISBLK(inode->i_mode))
268: inode->i_op = &minix_blkdev_inode_operations;
1.1.1.5 ! root 269: else if (S_ISFIFO(inode->i_mode)) {
! 270: inode->i_op = &minix_fifo_inode_operations;
! 271: inode->i_size = 0;
! 272: inode->i_pipe = 1;
! 273: PIPE_HEAD(*inode) = PIPE_TAIL(*inode) = 0;
! 274: PIPE_READERS(*inode) = PIPE_WRITERS(*inode) = 0;
! 275: }
1.1 root 276: if (S_ISBLK(mode) || S_ISCHR(mode))
277: inode->i_rdev = rdev;
278: inode->i_mtime = inode->i_atime = CURRENT_TIME;
279: inode->i_dirt = 1;
280: bh = minix_add_entry(dir,name,len,&de);
281: if (!bh) {
282: inode->i_nlink--;
1.1.1.3 root 283: inode->i_dirt = 1;
1.1 root 284: iput(inode);
285: iput(dir);
286: return -ENOSPC;
287: }
288: de->inode = inode->i_ino;
289: bh->b_dirt = 1;
290: brelse(bh);
291: iput(dir);
292: iput(inode);
293: return 0;
294: }
295:
296: int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
297: {
298: struct inode * inode;
299: struct buffer_head * bh, *dir_block;
300: struct minix_dir_entry * de;
301:
302: bh = minix_find_entry(dir,name,len,&de);
303: if (bh) {
304: brelse(bh);
305: iput(dir);
306: return -EEXIST;
307: }
308: inode = minix_new_inode(dir->i_dev);
309: if (!inode) {
310: iput(dir);
311: return -ENOSPC;
312: }
1.1.1.3 root 313: inode->i_op = &minix_dir_inode_operations;
314: inode->i_size = 2 * sizeof (struct minix_dir_entry);
1.1 root 315: inode->i_mtime = inode->i_atime = CURRENT_TIME;
316: if (!(inode->i_data[0] = minix_new_block(inode->i_dev))) {
317: iput(dir);
318: inode->i_nlink--;
1.1.1.3 root 319: inode->i_dirt = 1;
1.1 root 320: iput(inode);
321: return -ENOSPC;
322: }
323: inode->i_dirt = 1;
324: if (!(dir_block = bread(inode->i_dev,inode->i_data[0]))) {
325: iput(dir);
326: inode->i_nlink--;
1.1.1.3 root 327: inode->i_dirt = 1;
1.1 root 328: iput(inode);
1.1.1.3 root 329: return -EIO;
1.1 root 330: }
331: de = (struct minix_dir_entry *) dir_block->b_data;
332: de->inode=inode->i_ino;
333: strcpy(de->name,".");
334: de++;
335: de->inode = dir->i_ino;
336: strcpy(de->name,"..");
337: inode->i_nlink = 2;
338: dir_block->b_dirt = 1;
339: brelse(dir_block);
340: inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask);
341: inode->i_dirt = 1;
342: bh = minix_add_entry(dir,name,len,&de);
343: if (!bh) {
344: iput(dir);
345: inode->i_nlink=0;
346: iput(inode);
347: return -ENOSPC;
348: }
349: de->inode = inode->i_ino;
350: bh->b_dirt = 1;
351: dir->i_nlink++;
352: dir->i_dirt = 1;
353: iput(dir);
354: iput(inode);
355: brelse(bh);
356: return 0;
357: }
358:
359: /*
360: * routine to check that the specified directory is empty (for rmdir)
361: */
362: static int empty_dir(struct inode * inode)
363: {
364: int nr,block;
365: int len;
366: struct buffer_head * bh;
367: struct minix_dir_entry * de;
368:
369: len = inode->i_size / sizeof (struct minix_dir_entry);
370: if (len<2 || !inode->i_data[0] ||
371: !(bh=bread(inode->i_dev,inode->i_data[0]))) {
372: printk("warning - bad directory on dev %04x\n",inode->i_dev);
373: return 0;
374: }
375: de = (struct minix_dir_entry *) bh->b_data;
376: if (de[0].inode != inode->i_ino || !de[1].inode ||
377: strcmp(".",de[0].name) || strcmp("..",de[1].name)) {
378: printk("warning - bad directory on dev %04x\n",inode->i_dev);
379: return 0;
380: }
381: nr = 2;
382: de += 2;
383: while (nr<len) {
384: if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
385: brelse(bh);
1.1.1.2 root 386: block = minix_bmap(inode,nr/MINIX_DIR_ENTRIES_PER_BLOCK);
1.1 root 387: if (!block) {
388: nr += MINIX_DIR_ENTRIES_PER_BLOCK;
389: continue;
390: }
391: if (!(bh=bread(inode->i_dev,block)))
392: return 0;
393: de = (struct minix_dir_entry *) bh->b_data;
394: }
395: if (de->inode) {
396: brelse(bh);
397: return 0;
398: }
399: de++;
400: nr++;
401: }
402: brelse(bh);
403: return 1;
404: }
405:
406: int minix_rmdir(struct inode * dir, const char * name, int len)
407: {
408: int retval;
409: struct inode * inode;
410: struct buffer_head * bh;
411: struct minix_dir_entry * de;
412:
413: inode = NULL;
414: bh = minix_find_entry(dir,name,len,&de);
415: retval = -ENOENT;
416: if (!bh)
417: goto end_rmdir;
418: retval = -EPERM;
419: if (!(inode = iget(dir->i_dev, de->inode)))
420: goto end_rmdir;
421: if ((dir->i_mode & S_ISVTX) && current->euid &&
422: inode->i_uid != current->euid)
423: goto end_rmdir;
424: if (inode->i_dev != dir->i_dev)
425: goto end_rmdir;
426: if (inode == dir) /* we may not delete ".", but "../dir" is ok */
427: goto end_rmdir;
428: if (!S_ISDIR(inode->i_mode)) {
429: retval = -ENOTDIR;
430: goto end_rmdir;
431: }
432: if (!empty_dir(inode)) {
433: retval = -ENOTEMPTY;
434: goto end_rmdir;
435: }
436: if (inode->i_count > 1) {
437: retval = -EBUSY;
438: goto end_rmdir;
439: }
440: if (inode->i_nlink != 2)
441: printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
442: de->inode = 0;
443: bh->b_dirt = 1;
444: inode->i_nlink=0;
445: inode->i_dirt=1;
446: dir->i_nlink--;
447: dir->i_ctime = dir->i_mtime = CURRENT_TIME;
448: dir->i_dirt=1;
449: retval = 0;
450: end_rmdir:
451: iput(dir);
452: iput(inode);
453: brelse(bh);
454: return retval;
455: }
456:
457: int minix_unlink(struct inode * dir, const char * name, int len)
458: {
459: int retval;
460: struct inode * inode;
461: struct buffer_head * bh;
462: struct minix_dir_entry * de;
463:
464: retval = -ENOENT;
465: inode = NULL;
466: bh = minix_find_entry(dir,name,len,&de);
467: if (!bh)
468: goto end_unlink;
469: if (!(inode = iget(dir->i_dev, de->inode)))
470: goto end_unlink;
471: retval = -EPERM;
472: if ((dir->i_mode & S_ISVTX) && !suser() &&
473: current->euid != inode->i_uid &&
474: current->euid != dir->i_uid)
475: goto end_unlink;
476: if (S_ISDIR(inode->i_mode))
477: goto end_unlink;
478: if (!inode->i_nlink) {
479: printk("Deleting nonexistent file (%04x:%d), %d\n",
480: inode->i_dev,inode->i_ino,inode->i_nlink);
481: inode->i_nlink=1;
482: }
483: de->inode = 0;
484: bh->b_dirt = 1;
485: inode->i_nlink--;
486: inode->i_dirt = 1;
487: inode->i_ctime = CURRENT_TIME;
488: retval = 0;
489: end_unlink:
490: brelse(bh);
491: iput(inode);
492: iput(dir);
493: return retval;
494: }
495:
496: int minix_symlink(struct inode * dir, const char * name, int len, const char * symname)
497: {
498: struct minix_dir_entry * de;
499: struct inode * inode = NULL;
500: struct buffer_head * bh = NULL, * name_block = NULL;
501: int i;
502: char c;
503:
504: if (!(inode = minix_new_inode(dir->i_dev))) {
505: iput(dir);
506: return -ENOSPC;
507: }
508: inode->i_mode = S_IFLNK | 0777;
1.1.1.3 root 509: inode->i_op = &minix_symlink_inode_operations;
1.1 root 510: if (!(inode->i_data[0] = minix_new_block(inode->i_dev))) {
511: iput(dir);
512: inode->i_nlink--;
1.1.1.3 root 513: inode->i_dirt = 1;
1.1 root 514: iput(inode);
515: return -ENOSPC;
516: }
517: inode->i_dirt = 1;
518: if (!(name_block = bread(inode->i_dev,inode->i_data[0]))) {
519: iput(dir);
520: inode->i_nlink--;
1.1.1.3 root 521: inode->i_dirt = 1;
1.1 root 522: iput(inode);
1.1.1.3 root 523: return -EIO;
1.1 root 524: }
525: i = 0;
526: while (i < 1023 && (c=get_fs_byte(symname++)))
527: name_block->b_data[i++] = c;
528: name_block->b_data[i] = 0;
529: name_block->b_dirt = 1;
530: brelse(name_block);
531: inode->i_size = i;
532: inode->i_dirt = 1;
533: bh = minix_find_entry(dir,name,len,&de);
534: if (bh) {
535: inode->i_nlink--;
1.1.1.3 root 536: inode->i_dirt = 1;
1.1 root 537: iput(inode);
538: brelse(bh);
539: iput(dir);
540: return -EEXIST;
541: }
542: bh = minix_add_entry(dir,name,len,&de);
543: if (!bh) {
544: inode->i_nlink--;
1.1.1.3 root 545: inode->i_dirt = 1;
1.1 root 546: iput(inode);
547: iput(dir);
548: return -ENOSPC;
549: }
550: de->inode = inode->i_ino;
551: bh->b_dirt = 1;
552: brelse(bh);
553: iput(dir);
554: iput(inode);
555: return 0;
556: }
557:
558: int minix_link(struct inode * oldinode, struct inode * dir, const char * name, int len)
559: {
560: struct minix_dir_entry * de;
561: struct buffer_head * bh;
562:
563: if (S_ISDIR(oldinode->i_mode)) {
564: iput(oldinode);
565: iput(dir);
566: return -EPERM;
567: }
568: bh = minix_find_entry(dir,name,len,&de);
569: if (bh) {
570: brelse(bh);
571: iput(dir);
572: iput(oldinode);
573: return -EEXIST;
574: }
575: bh = minix_add_entry(dir,name,len,&de);
576: if (!bh) {
577: iput(dir);
578: iput(oldinode);
579: return -ENOSPC;
580: }
581: de->inode = oldinode->i_ino;
582: bh->b_dirt = 1;
583: brelse(bh);
584: iput(dir);
585: oldinode->i_nlink++;
586: oldinode->i_ctime = CURRENT_TIME;
587: oldinode->i_dirt = 1;
588: iput(oldinode);
589: return 0;
590: }
591:
592: static int subdir(struct inode * new, struct inode * old)
593: {
594: unsigned short fs;
595: int ino;
596: int result;
597:
598: __asm__("mov %%fs,%0":"=r" (fs));
599: __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
600: new->i_count++;
601: result = 0;
602: for (;;) {
603: if (new == old) {
604: result = 1;
605: break;
606: }
607: if (new->i_dev != old->i_dev)
608: break;
609: ino = new->i_ino;
610: if (minix_lookup(new,"..",2,&new))
611: break;
612: if (new->i_ino == ino)
613: break;
614: }
615: iput(new);
616: __asm__("mov %0,%%fs"::"r" (fs));
617: return result;
618: }
619:
620: #define PARENT_INO(buffer) \
621: (((struct minix_dir_entry *) (buffer))[1].inode)
622:
623: #define PARENT_NAME(buffer) \
624: (((struct minix_dir_entry *) (buffer))[1].name)
625:
626: /*
627: * rename uses retrying to avoid race-conditions: at least they should be minimal.
628: * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
629: * checks fail, it tries to restart itself again. Very practical - no changes
630: * are done until we know everything works ok.. and then all the changes can be
631: * done in one fell swoop when we have claimed all the buffers needed.
632: *
633: * Anybody can rename anything with this: the permission checks are left to the
634: * higher-level routines.
635: */
636: static int do_minix_rename(struct inode * old_dir, const char * old_name, int old_len,
637: struct inode * new_dir, const char * new_name, int new_len)
638: {
639: struct inode * old_inode, * new_inode;
640: struct buffer_head * old_bh, * new_bh, * dir_bh;
641: struct minix_dir_entry * old_de, * new_de;
642: int retval;
643:
644: goto start_up;
645: try_again:
646: brelse(old_bh);
647: brelse(new_bh);
648: brelse(dir_bh);
649: iput(old_inode);
650: iput(new_inode);
651: current->counter = 0;
652: schedule();
653: start_up:
654: old_inode = new_inode = NULL;
655: old_bh = new_bh = dir_bh = NULL;
656: old_bh = minix_find_entry(old_dir,old_name,old_len,&old_de);
657: retval = -ENOENT;
658: if (!old_bh)
659: goto end_rename;
660: old_inode = iget(old_dir->i_dev, old_de->inode);
661: if (!old_inode)
662: goto end_rename;
1.1.1.3 root 663: if ((old_dir->i_mode & S_ISVTX) &&
664: current->euid != old_inode->i_uid &&
665: current->euid != old_dir->i_uid && !suser())
666: goto end_rename;
1.1 root 667: new_bh = minix_find_entry(new_dir,new_name,new_len,&new_de);
668: if (new_bh) {
669: new_inode = iget(new_dir->i_dev, new_de->inode);
670: if (!new_inode) {
671: brelse(new_bh);
672: new_bh = NULL;
673: }
674: }
675: if (new_inode == old_inode) {
676: retval = 0;
677: goto end_rename;
678: }
679: if (S_ISDIR(old_inode->i_mode)) {
680: retval = -EEXIST;
681: if (new_bh)
682: goto end_rename;
683: retval = -EACCES;
684: if (!permission(old_inode, MAY_WRITE))
685: goto end_rename;
686: retval = -EINVAL;
687: if (subdir(new_dir, old_inode))
688: goto end_rename;
689: retval = -EIO;
690: if (!old_inode->i_data[0])
691: goto end_rename;
692: if (!(dir_bh = bread(old_inode->i_dev, old_inode->i_data[0])))
693: goto end_rename;
694: if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
695: goto end_rename;
696: }
697: if (!new_bh)
698: new_bh = minix_add_entry(new_dir,new_name,new_len,&new_de);
699: retval = -ENOSPC;
700: if (!new_bh)
701: goto end_rename;
702: /* sanity checking before doing the rename - avoid races */
703: if (new_inode && (new_de->inode != new_inode->i_ino))
704: goto try_again;
705: if (new_de->inode && !new_inode)
706: goto try_again;
707: if (old_de->inode != old_inode->i_ino)
708: goto try_again;
709: /* ok, that's it */
710: old_de->inode = 0;
711: new_de->inode = old_inode->i_ino;
1.1.1.3 root 712: if (new_inode) {
1.1 root 713: new_inode->i_nlink--;
1.1.1.3 root 714: new_inode->i_dirt = 1;
715: }
1.1 root 716: old_bh->b_dirt = 1;
717: new_bh->b_dirt = 1;
718: if (dir_bh) {
719: PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
720: dir_bh->b_dirt = 1;
721: old_dir->i_nlink--;
722: new_dir->i_nlink++;
723: old_dir->i_dirt = 1;
724: new_dir->i_dirt = 1;
725: }
726: retval = 0;
727: end_rename:
728: brelse(dir_bh);
729: brelse(old_bh);
730: brelse(new_bh);
731: iput(old_inode);
732: iput(new_inode);
733: iput(old_dir);
734: iput(new_dir);
735: return retval;
736: }
737:
738: /*
739: * Ok, rename also locks out other renames, as they can change the parent of
740: * a directory, and we don't want any races. Other races are checked for by
741: * "do_rename()", which restarts if there are inconsistencies.
742: *
743: * Note that there is no race between different filesystems: it's only within
744: * the same device that races occur: many renames can happen at once, as long
745: * as they are on different partitions.
746: */
747: int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
748: struct inode * new_dir, const char * new_name, int new_len)
749: {
750: static struct task_struct * wait = NULL;
751: static int lock = 0;
752: int result;
753:
754: while (lock)
755: sleep_on(&wait);
756: lock = 1;
757: result = do_minix_rename(old_dir, old_name, old_len,
758: new_dir, new_name, new_len);
759: lock = 0;
760: wake_up(&wait);
761: return result;
762: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.