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