|
|
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 root 12: #include <asm/segment.h>
13:
14: #include <fcntl.h>
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 root 269: if (S_ISBLK(mode) || S_ISCHR(mode))
270: inode->i_rdev = rdev;
271: inode->i_mtime = inode->i_atime = CURRENT_TIME;
272: inode->i_dirt = 1;
273: bh = minix_add_entry(dir,name,len,&de);
274: if (!bh) {
275: inode->i_nlink--;
1.1.1.3 root 276: inode->i_dirt = 1;
1.1 root 277: iput(inode);
278: iput(dir);
279: return -ENOSPC;
280: }
281: de->inode = inode->i_ino;
282: bh->b_dirt = 1;
283: brelse(bh);
284: iput(dir);
285: iput(inode);
286: return 0;
287: }
288:
289: int minix_mkdir(struct inode * dir, const char * name, int len, int mode)
290: {
291: struct inode * inode;
292: struct buffer_head * bh, *dir_block;
293: struct minix_dir_entry * de;
294:
295: bh = minix_find_entry(dir,name,len,&de);
296: if (bh) {
297: brelse(bh);
298: iput(dir);
299: return -EEXIST;
300: }
301: inode = minix_new_inode(dir->i_dev);
302: if (!inode) {
303: iput(dir);
304: return -ENOSPC;
305: }
1.1.1.3 root 306: inode->i_op = &minix_dir_inode_operations;
307: inode->i_size = 2 * sizeof (struct minix_dir_entry);
1.1 root 308: inode->i_mtime = inode->i_atime = CURRENT_TIME;
309: if (!(inode->i_data[0] = minix_new_block(inode->i_dev))) {
310: iput(dir);
311: inode->i_nlink--;
1.1.1.3 root 312: inode->i_dirt = 1;
1.1 root 313: iput(inode);
314: return -ENOSPC;
315: }
316: inode->i_dirt = 1;
317: if (!(dir_block = bread(inode->i_dev,inode->i_data[0]))) {
318: iput(dir);
319: inode->i_nlink--;
1.1.1.3 root 320: inode->i_dirt = 1;
1.1 root 321: iput(inode);
1.1.1.3 root 322: return -EIO;
1.1 root 323: }
324: de = (struct minix_dir_entry *) dir_block->b_data;
325: de->inode=inode->i_ino;
326: strcpy(de->name,".");
327: de++;
328: de->inode = dir->i_ino;
329: strcpy(de->name,"..");
330: inode->i_nlink = 2;
331: dir_block->b_dirt = 1;
332: brelse(dir_block);
333: inode->i_mode = I_DIRECTORY | (mode & 0777 & ~current->umask);
334: inode->i_dirt = 1;
335: bh = minix_add_entry(dir,name,len,&de);
336: if (!bh) {
337: iput(dir);
338: inode->i_nlink=0;
339: iput(inode);
340: return -ENOSPC;
341: }
342: de->inode = inode->i_ino;
343: bh->b_dirt = 1;
344: dir->i_nlink++;
345: dir->i_dirt = 1;
346: iput(dir);
347: iput(inode);
348: brelse(bh);
349: return 0;
350: }
351:
352: /*
353: * routine to check that the specified directory is empty (for rmdir)
354: */
355: static int empty_dir(struct inode * inode)
356: {
357: int nr,block;
358: int len;
359: struct buffer_head * bh;
360: struct minix_dir_entry * de;
361:
362: len = inode->i_size / sizeof (struct minix_dir_entry);
363: if (len<2 || !inode->i_data[0] ||
364: !(bh=bread(inode->i_dev,inode->i_data[0]))) {
365: printk("warning - bad directory on dev %04x\n",inode->i_dev);
366: return 0;
367: }
368: de = (struct minix_dir_entry *) bh->b_data;
369: if (de[0].inode != inode->i_ino || !de[1].inode ||
370: strcmp(".",de[0].name) || strcmp("..",de[1].name)) {
371: printk("warning - bad directory on dev %04x\n",inode->i_dev);
372: return 0;
373: }
374: nr = 2;
375: de += 2;
376: while (nr<len) {
377: if ((void *) de >= (void *) (bh->b_data+BLOCK_SIZE)) {
378: brelse(bh);
1.1.1.2 root 379: block = minix_bmap(inode,nr/MINIX_DIR_ENTRIES_PER_BLOCK);
1.1 root 380: if (!block) {
381: nr += MINIX_DIR_ENTRIES_PER_BLOCK;
382: continue;
383: }
384: if (!(bh=bread(inode->i_dev,block)))
385: return 0;
386: de = (struct minix_dir_entry *) bh->b_data;
387: }
388: if (de->inode) {
389: brelse(bh);
390: return 0;
391: }
392: de++;
393: nr++;
394: }
395: brelse(bh);
396: return 1;
397: }
398:
399: int minix_rmdir(struct inode * dir, const char * name, int len)
400: {
401: int retval;
402: struct inode * inode;
403: struct buffer_head * bh;
404: struct minix_dir_entry * de;
405:
406: inode = NULL;
407: bh = minix_find_entry(dir,name,len,&de);
408: retval = -ENOENT;
409: if (!bh)
410: goto end_rmdir;
411: retval = -EPERM;
412: if (!(inode = iget(dir->i_dev, de->inode)))
413: goto end_rmdir;
414: if ((dir->i_mode & S_ISVTX) && current->euid &&
415: inode->i_uid != current->euid)
416: goto end_rmdir;
417: if (inode->i_dev != dir->i_dev)
418: goto end_rmdir;
419: if (inode == dir) /* we may not delete ".", but "../dir" is ok */
420: goto end_rmdir;
421: if (!S_ISDIR(inode->i_mode)) {
422: retval = -ENOTDIR;
423: goto end_rmdir;
424: }
425: if (!empty_dir(inode)) {
426: retval = -ENOTEMPTY;
427: goto end_rmdir;
428: }
429: if (inode->i_count > 1) {
430: retval = -EBUSY;
431: goto end_rmdir;
432: }
433: if (inode->i_nlink != 2)
434: printk("empty directory has nlink!=2 (%d)\n",inode->i_nlink);
435: de->inode = 0;
436: bh->b_dirt = 1;
437: inode->i_nlink=0;
438: inode->i_dirt=1;
439: dir->i_nlink--;
440: dir->i_ctime = dir->i_mtime = CURRENT_TIME;
441: dir->i_dirt=1;
442: retval = 0;
443: end_rmdir:
444: iput(dir);
445: iput(inode);
446: brelse(bh);
447: return retval;
448: }
449:
450: int minix_unlink(struct inode * dir, const char * name, int len)
451: {
452: int retval;
453: struct inode * inode;
454: struct buffer_head * bh;
455: struct minix_dir_entry * de;
456:
457: retval = -ENOENT;
458: inode = NULL;
459: bh = minix_find_entry(dir,name,len,&de);
460: if (!bh)
461: goto end_unlink;
462: if (!(inode = iget(dir->i_dev, de->inode)))
463: goto end_unlink;
464: retval = -EPERM;
465: if ((dir->i_mode & S_ISVTX) && !suser() &&
466: current->euid != inode->i_uid &&
467: current->euid != dir->i_uid)
468: goto end_unlink;
469: if (S_ISDIR(inode->i_mode))
470: goto end_unlink;
471: if (!inode->i_nlink) {
472: printk("Deleting nonexistent file (%04x:%d), %d\n",
473: inode->i_dev,inode->i_ino,inode->i_nlink);
474: inode->i_nlink=1;
475: }
476: de->inode = 0;
477: bh->b_dirt = 1;
478: inode->i_nlink--;
479: inode->i_dirt = 1;
480: inode->i_ctime = CURRENT_TIME;
481: retval = 0;
482: end_unlink:
483: brelse(bh);
484: iput(inode);
485: iput(dir);
486: return retval;
487: }
488:
489: int minix_symlink(struct inode * dir, const char * name, int len, const char * symname)
490: {
491: struct minix_dir_entry * de;
492: struct inode * inode = NULL;
493: struct buffer_head * bh = NULL, * name_block = NULL;
494: int i;
495: char c;
496:
497: if (!(inode = minix_new_inode(dir->i_dev))) {
498: iput(dir);
499: return -ENOSPC;
500: }
501: inode->i_mode = S_IFLNK | 0777;
1.1.1.3 root 502: inode->i_op = &minix_symlink_inode_operations;
1.1 root 503: if (!(inode->i_data[0] = minix_new_block(inode->i_dev))) {
504: iput(dir);
505: inode->i_nlink--;
1.1.1.3 root 506: inode->i_dirt = 1;
1.1 root 507: iput(inode);
508: return -ENOSPC;
509: }
510: inode->i_dirt = 1;
511: if (!(name_block = bread(inode->i_dev,inode->i_data[0]))) {
512: iput(dir);
513: inode->i_nlink--;
1.1.1.3 root 514: inode->i_dirt = 1;
1.1 root 515: iput(inode);
1.1.1.3 root 516: return -EIO;
1.1 root 517: }
518: i = 0;
519: while (i < 1023 && (c=get_fs_byte(symname++)))
520: name_block->b_data[i++] = c;
521: name_block->b_data[i] = 0;
522: name_block->b_dirt = 1;
523: brelse(name_block);
524: inode->i_size = i;
525: inode->i_dirt = 1;
526: bh = minix_find_entry(dir,name,len,&de);
527: if (bh) {
528: inode->i_nlink--;
1.1.1.3 root 529: inode->i_dirt = 1;
1.1 root 530: iput(inode);
531: brelse(bh);
532: iput(dir);
533: return -EEXIST;
534: }
535: bh = minix_add_entry(dir,name,len,&de);
536: if (!bh) {
537: inode->i_nlink--;
1.1.1.3 root 538: inode->i_dirt = 1;
1.1 root 539: iput(inode);
540: iput(dir);
541: return -ENOSPC;
542: }
543: de->inode = inode->i_ino;
544: bh->b_dirt = 1;
545: brelse(bh);
546: iput(dir);
547: iput(inode);
548: return 0;
549: }
550:
551: int minix_link(struct inode * oldinode, struct inode * dir, const char * name, int len)
552: {
553: struct minix_dir_entry * de;
554: struct buffer_head * bh;
555:
556: if (S_ISDIR(oldinode->i_mode)) {
557: iput(oldinode);
558: iput(dir);
559: return -EPERM;
560: }
561: bh = minix_find_entry(dir,name,len,&de);
562: if (bh) {
563: brelse(bh);
564: iput(dir);
565: iput(oldinode);
566: return -EEXIST;
567: }
568: bh = minix_add_entry(dir,name,len,&de);
569: if (!bh) {
570: iput(dir);
571: iput(oldinode);
572: return -ENOSPC;
573: }
574: de->inode = oldinode->i_ino;
575: bh->b_dirt = 1;
576: brelse(bh);
577: iput(dir);
578: oldinode->i_nlink++;
579: oldinode->i_ctime = CURRENT_TIME;
580: oldinode->i_dirt = 1;
581: iput(oldinode);
582: return 0;
583: }
584:
585: static int subdir(struct inode * new, struct inode * old)
586: {
587: unsigned short fs;
588: int ino;
589: int result;
590:
591: __asm__("mov %%fs,%0":"=r" (fs));
592: __asm__("mov %0,%%fs"::"r" ((unsigned short) 0x10));
593: new->i_count++;
594: result = 0;
595: for (;;) {
596: if (new == old) {
597: result = 1;
598: break;
599: }
600: if (new->i_dev != old->i_dev)
601: break;
602: ino = new->i_ino;
603: if (minix_lookup(new,"..",2,&new))
604: break;
605: if (new->i_ino == ino)
606: break;
607: }
608: iput(new);
609: __asm__("mov %0,%%fs"::"r" (fs));
610: return result;
611: }
612:
613: #define PARENT_INO(buffer) \
614: (((struct minix_dir_entry *) (buffer))[1].inode)
615:
616: #define PARENT_NAME(buffer) \
617: (((struct minix_dir_entry *) (buffer))[1].name)
618:
619: /*
620: * rename uses retrying to avoid race-conditions: at least they should be minimal.
621: * it tries to allocate all the blocks, then sanity-checks, and if the sanity-
622: * checks fail, it tries to restart itself again. Very practical - no changes
623: * are done until we know everything works ok.. and then all the changes can be
624: * done in one fell swoop when we have claimed all the buffers needed.
625: *
626: * Anybody can rename anything with this: the permission checks are left to the
627: * higher-level routines.
628: */
629: static int do_minix_rename(struct inode * old_dir, const char * old_name, int old_len,
630: struct inode * new_dir, const char * new_name, int new_len)
631: {
632: struct inode * old_inode, * new_inode;
633: struct buffer_head * old_bh, * new_bh, * dir_bh;
634: struct minix_dir_entry * old_de, * new_de;
635: int retval;
636:
637: goto start_up;
638: try_again:
639: brelse(old_bh);
640: brelse(new_bh);
641: brelse(dir_bh);
642: iput(old_inode);
643: iput(new_inode);
644: current->counter = 0;
645: schedule();
646: start_up:
647: old_inode = new_inode = NULL;
648: old_bh = new_bh = dir_bh = NULL;
649: old_bh = minix_find_entry(old_dir,old_name,old_len,&old_de);
650: retval = -ENOENT;
651: if (!old_bh)
652: goto end_rename;
653: old_inode = iget(old_dir->i_dev, old_de->inode);
654: if (!old_inode)
655: goto end_rename;
1.1.1.3 root 656: if ((old_dir->i_mode & S_ISVTX) &&
657: current->euid != old_inode->i_uid &&
658: current->euid != old_dir->i_uid && !suser())
659: goto end_rename;
1.1 root 660: new_bh = minix_find_entry(new_dir,new_name,new_len,&new_de);
661: if (new_bh) {
662: new_inode = iget(new_dir->i_dev, new_de->inode);
663: if (!new_inode) {
664: brelse(new_bh);
665: new_bh = NULL;
666: }
667: }
668: if (new_inode == old_inode) {
669: retval = 0;
670: goto end_rename;
671: }
672: if (S_ISDIR(old_inode->i_mode)) {
673: retval = -EEXIST;
674: if (new_bh)
675: goto end_rename;
676: retval = -EACCES;
677: if (!permission(old_inode, MAY_WRITE))
678: goto end_rename;
679: retval = -EINVAL;
680: if (subdir(new_dir, old_inode))
681: goto end_rename;
682: retval = -EIO;
683: if (!old_inode->i_data[0])
684: goto end_rename;
685: if (!(dir_bh = bread(old_inode->i_dev, old_inode->i_data[0])))
686: goto end_rename;
687: if (PARENT_INO(dir_bh->b_data) != old_dir->i_ino)
688: goto end_rename;
689: }
690: if (!new_bh)
691: new_bh = minix_add_entry(new_dir,new_name,new_len,&new_de);
692: retval = -ENOSPC;
693: if (!new_bh)
694: goto end_rename;
695: /* sanity checking before doing the rename - avoid races */
696: if (new_inode && (new_de->inode != new_inode->i_ino))
697: goto try_again;
698: if (new_de->inode && !new_inode)
699: goto try_again;
700: if (old_de->inode != old_inode->i_ino)
701: goto try_again;
702: /* ok, that's it */
703: old_de->inode = 0;
704: new_de->inode = old_inode->i_ino;
1.1.1.3 root 705: if (new_inode) {
1.1 root 706: new_inode->i_nlink--;
1.1.1.3 root 707: new_inode->i_dirt = 1;
708: }
1.1 root 709: old_bh->b_dirt = 1;
710: new_bh->b_dirt = 1;
711: if (dir_bh) {
712: PARENT_INO(dir_bh->b_data) = new_dir->i_ino;
713: dir_bh->b_dirt = 1;
714: old_dir->i_nlink--;
715: new_dir->i_nlink++;
716: old_dir->i_dirt = 1;
717: new_dir->i_dirt = 1;
718: }
719: retval = 0;
720: end_rename:
721: brelse(dir_bh);
722: brelse(old_bh);
723: brelse(new_bh);
724: iput(old_inode);
725: iput(new_inode);
726: iput(old_dir);
727: iput(new_dir);
728: return retval;
729: }
730:
731: /*
732: * Ok, rename also locks out other renames, as they can change the parent of
733: * a directory, and we don't want any races. Other races are checked for by
734: * "do_rename()", which restarts if there are inconsistencies.
735: *
736: * Note that there is no race between different filesystems: it's only within
737: * the same device that races occur: many renames can happen at once, as long
738: * as they are on different partitions.
739: */
740: int minix_rename(struct inode * old_dir, const char * old_name, int old_len,
741: struct inode * new_dir, const char * new_name, int new_len)
742: {
743: static struct task_struct * wait = NULL;
744: static int lock = 0;
745: int result;
746:
747: while (lock)
748: sleep_on(&wait);
749: lock = 1;
750: result = do_minix_rename(old_dir, old_name, old_len,
751: new_dir, new_name, new_len);
752: lock = 0;
753: wake_up(&wait);
754: return result;
755: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.