This source file includes following definitions.
- msdos_format_name
- msdos_find
- msdos_lookup
- msdos_create_entry
- msdos_create
- dump_fat
- msdos_mkdir
- msdos_empty
- msdos_rmdir
- msdos_unlinkx
- msdos_unlink
- msdos_unlink_umsdos
- rename_same_dir
- rename_diff_dir
- msdos_rename
1
2
3
4
5
6
7
8 #include <linux/sched.h>
9 #include <linux/msdos_fs.h>
10 #include <linux/kernel.h>
11 #include <linux/errno.h>
12 #include <linux/string.h>
13 #include <linux/stat.h>
14
15 #include <asm/segment.h>
16
17 #include "msbuffer.h"
18
19 #define PRINTK(x)
20
21
22
23 static const char *reserved_names[] = {
24 "CON ","PRN ","NUL ","AUX ",
25 "LPT1 ","LPT2 ","LPT3 ","LPT4 ",
26 "COM1 ","COM2 ","COM3 ","COM4 ",
27 NULL };
28
29
30
31
32 static char bad_chars[] = "*?<>|\"";
33 static char bad_if_strict[] = "+=,; ";
34
35
36
37 static int msdos_format_name(char conv,const char *name,int len,
38 char *res,int dot_dirs,char dotsOK)
39
40
41
42
43 {
44 char *walk;
45 const char **reserved;
46 unsigned char c;
47 int space;
48
49 if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.'))) {
50 if (!dot_dirs) return -EEXIST;
51 memset(res+1,' ',10);
52 while (len--) *res++ = '.';
53 return 0;
54 }
55 if (name[0] == '.') {
56 if (!dotsOK) return -EINVAL;
57
58 name++; len--;
59 }
60 space = 1;
61 c = 0;
62 for (walk = res; len && walk-res < 8; walk++) {
63 c = *name++;
64 len--;
65 if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;
66 if (conv == 's' && strchr(bad_if_strict,c)) return -EINVAL;
67 if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;
68 if (c < ' ' || c == ':' || c == '\\') return -EINVAL;
69
70
71
72
73 if((res==walk) && (c==0xE5)) c=0x05;
74 if (c == '.') break;
75 space = (c == ' ');
76 *walk = (c >= 'a' && c <= 'z') ? c-32 : c;
77 }
78 if (space) return -EINVAL;
79 if (conv == 's' && len && c != '.') {
80 c = *name++;
81 len--;
82 if (c != '.') return -EINVAL;
83 }
84 while (c != '.' && len--) c = *name++;
85 if (c == '.') {
86 while (walk-res < 8) *walk++ = ' ';
87 while (len > 0 && walk-res < MSDOS_NAME) {
88 c = *name++;
89 len--;
90 if (conv != 'r' && strchr(bad_chars,c)) return -EINVAL;
91 if (conv == 's' && strchr(bad_if_strict,c))
92 return -EINVAL;
93 if (c < ' ' || c == ':' || c == '\\' || c == '.')
94 return -EINVAL;
95 if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL;
96 space = c == ' ';
97 *walk++ = c >= 'a' && c <= 'z' ? c-32 : c;
98 }
99 if (space) return -EINVAL;
100 if (conv == 's' && len) return -EINVAL;
101 }
102 while (walk-res < MSDOS_NAME) *walk++ = ' ';
103 for (reserved = reserved_names; *reserved; reserved++)
104 if (!strncmp(res,*reserved,8)) return -EINVAL;
105 return 0;
106 }
107
108
109
110 static int msdos_find(struct inode *dir,const char *name,int len,
111 struct buffer_head **bh,struct msdos_dir_entry **de,int *ino)
112 {
113 char msdos_name[MSDOS_NAME];
114 int res;
115 char dotsOK;
116 char scantype;
117
118 dotsOK = MSDOS_SB(dir->i_sb)->dotsOK;
119 res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,
120 name,len, msdos_name,1,dotsOK);
121 if (res < 0)
122 return -ENOENT;
123 if((name[0]=='.') && dotsOK){
124 switch(len){
125 case 0: panic("Empty name in msdos_find!");
126 case 1: scantype = SCAN_ANY; break;
127 case 2: scantype = ((name[1]=='.')?SCAN_ANY:SCAN_HID); break;
128 default: scantype = SCAN_HID;
129 }
130 } else {
131 scantype = (dotsOK ? SCAN_NOTHID : SCAN_ANY);
132 }
133 return msdos_scan(dir,msdos_name,bh,de,ino,scantype);
134 }
135
136
137 int msdos_lookup(struct inode *dir,const char *name,int len,
138 struct inode **result)
139 {
140 struct super_block *sb = dir->i_sb;
141 int ino,res;
142 struct msdos_dir_entry *de;
143 struct buffer_head *bh;
144 struct inode *next;
145
146 PRINTK (("msdos_lookup\n"));
147
148 *result = NULL;
149 if (!dir) return -ENOENT;
150 if (!S_ISDIR(dir->i_mode)) {
151 iput(dir);
152 return -ENOENT;
153 }
154 PRINTK (("msdos_lookup 2\n"));
155 if (len == 1 && name[0] == '.') {
156 *result = dir;
157 return 0;
158 }
159 if (len == 2 && name[0] == '.' && name[1] == '.') {
160 ino = msdos_parent_ino(dir,0);
161 iput(dir);
162 if (ino < 0) return ino;
163 if (!(*result = iget(dir->i_sb,ino))) return -EACCES;
164 return 0;
165 }
166 PRINTK (("msdos_lookup 3\n"));
167 if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) {
168 iput(dir);
169 return res;
170 }
171 PRINTK (("msdos_lookup 4\n"));
172 if (bh) brelse(bh);
173 PRINTK (("msdos_lookup 4.5\n"));
174
175 if (!(*result = iget(dir->i_sb,ino))) {
176 iput(dir);
177 return -EACCES;
178 }
179 PRINTK (("msdos_lookup 5\n"));
180 if (MSDOS_I(*result)->i_busy) {
181 iput(*result);
182 iput(dir);
183 return -ENOENT;
184 }
185 PRINTK (("msdos_lookup 6\n"));
186 while (MSDOS_I(*result)->i_old) {
187 next = MSDOS_I(*result)->i_old;
188 iput(*result);
189 if (!(*result = iget(next->i_sb,next->i_ino))) {
190 fs_panic(dir->i_sb,"msdos_lookup: Can't happen");
191 iput(dir);
192 return -ENOENT;
193 }
194 }
195 PRINTK (("msdos_lookup 7\n"));
196 iput(dir);
197 PRINTK (("msdos_lookup 8\n"));
198 return 0;
199 }
200
201
202
203 static int msdos_create_entry(struct inode *dir, const char *name,
204 int is_dir, int is_hid, struct inode **result)
205 {
206 struct super_block *sb = dir->i_sb;
207 struct buffer_head *bh;
208 struct msdos_dir_entry *de;
209 int res,ino;
210
211 if ((res = msdos_scan(dir,NULL,&bh,&de,&ino,SCAN_ANY)) < 0) {
212 if (res != -ENOENT) return res;
213 if (dir->i_ino == MSDOS_ROOT_INO) return -ENOSPC;
214 if ((res = msdos_add_cluster(dir)) < 0) return res;
215 if ((res = msdos_scan(dir,NULL,&bh,&de,&ino,SCAN_ANY)) < 0) return res;
216 }
217
218
219
220 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
221 dir->i_dirt = 1;
222 memcpy(de->name,name,MSDOS_NAME);
223 memset(de->unused, 0, sizeof(de->unused));
224 de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
225 de->attr = is_hid ? (de->attr|ATTR_HIDDEN) : (de->attr&~ATTR_HIDDEN);
226 de->start = 0;
227 date_unix2dos(dir->i_mtime,&de->time,&de->date);
228 de->size = 0;
229 mark_buffer_dirty(bh, 1);
230 if ((*result = iget(dir->i_sb,ino)) != NULL)
231 msdos_read_inode(*result);
232 brelse(bh);
233 if (!*result) return -EIO;
234 (*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
235 CURRENT_TIME;
236 (*result)->i_dirt = 1;
237 return 0;
238 }
239
240
241 int msdos_create(struct inode *dir,const char *name,int len,int mode,
242 struct inode **result)
243 {
244 struct super_block *sb = dir->i_sb;
245 struct buffer_head *bh;
246 struct msdos_dir_entry *de;
247 char msdos_name[MSDOS_NAME];
248 int ino,res,is_hid;
249
250 if (!dir) return -ENOENT;
251 if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
252 msdos_name,0,MSDOS_SB(dir->i_sb)->dotsOK)) < 0) {
253 iput(dir);
254 return res;
255 }
256 is_hid = (name[0]=='.') && (msdos_name[0]!='.');
257 lock_creation();
258
259
260
261
262 if (msdos_scan(dir,msdos_name,&bh,&de,&ino,SCAN_HID) >= 0) {
263 unlock_creation();
264 brelse(bh);
265 iput(dir);
266 return is_hid ? -EEXIST : -EINVAL;
267 }
268 if (msdos_scan(dir,msdos_name,&bh,&de,&ino,SCAN_NOTHID) >= 0) {
269 unlock_creation();
270 brelse(bh);
271 iput(dir);
272 return is_hid ? -EINVAL : -EEXIST;
273 }
274 res = msdos_create_entry(dir,msdos_name,S_ISDIR(mode),is_hid,result);
275 unlock_creation();
276 iput(dir);
277 return res;
278 }
279
280
281 #ifdef DEBUG
282
283 static void dump_fat(struct super_block *sb,int start)
284 {
285 printk("[");
286 while (start) {
287 printk("%d ",start);
288 start = fat_access(sb,start,-1);
289 if (!start) {
290 printk("ERROR");
291 break;
292 }
293 if (start == -1) break;
294 }
295 printk("]\n");
296 }
297
298 #endif
299
300
301 int msdos_mkdir(struct inode *dir,const char *name,int len,int mode)
302 {
303 struct super_block *sb = dir->i_sb;
304 struct buffer_head *bh;
305 struct msdos_dir_entry *de;
306 struct inode *inode,*dot;
307 char msdos_name[MSDOS_NAME];
308 int ino,res,is_hid;
309
310 if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
311 msdos_name,0,MSDOS_SB(dir->i_sb)->dotsOK)) < 0) {
312 iput(dir);
313 return res;
314 }
315 is_hid = (name[0]=='.') && (msdos_name[0]!='.');
316 lock_creation();
317 if (msdos_scan(dir,msdos_name,&bh,&de,&ino,SCAN_ANY) >= 0) {
318 unlock_creation();
319 brelse(bh);
320 iput(dir);
321 return -EEXIST;
322 }
323 if ((res = msdos_create_entry(dir,msdos_name,1,is_hid,&inode)) < 0) {
324 unlock_creation();
325 iput(dir);
326 return res;
327 }
328 dir->i_nlink++;
329 inode->i_nlink = 2;
330 MSDOS_I(inode)->i_busy = 1;
331 if ((res = msdos_add_cluster(inode)) < 0) goto mkdir_error;
332 if ((res = msdos_create_entry(inode,MSDOS_DOT,1,0,&dot)) < 0)
333 goto mkdir_error;
334 dot->i_size = inode->i_size;
335 MSDOS_I(dot)->i_start = MSDOS_I(inode)->i_start;
336 dot->i_nlink = inode->i_nlink;
337 dot->i_dirt = 1;
338 iput(dot);
339 if ((res = msdos_create_entry(inode,MSDOS_DOTDOT,1,0,&dot)) < 0)
340 goto mkdir_error;
341 unlock_creation();
342 dot->i_size = dir->i_size;
343 MSDOS_I(dot)->i_start = MSDOS_I(dir)->i_start;
344 dot->i_nlink = dir->i_nlink;
345 dot->i_dirt = 1;
346 MSDOS_I(inode)->i_busy = 0;
347 iput(dot);
348 iput(inode);
349 iput(dir);
350 return 0;
351 mkdir_error:
352 iput(inode);
353 if (msdos_rmdir(dir,name,len) < 0)
354 fs_panic(dir->i_sb,"rmdir in mkdir failed");
355 unlock_creation();
356 return res;
357 }
358
359
360 static int msdos_empty(struct inode *dir)
361 {
362 struct super_block *sb = dir->i_sb;
363 loff_t pos;
364 struct buffer_head *bh;
365 struct msdos_dir_entry *de;
366
367 if (dir->i_count > 1)
368 return -EBUSY;
369 if (MSDOS_I(dir)->i_start) {
370 pos = 0;
371 bh = NULL;
372 while (msdos_get_entry(dir,&pos,&bh,&de) > -1)
373 if (!IS_FREE(de->name) && strncmp(de->name,MSDOS_DOT,
374 MSDOS_NAME) && strncmp(de->name,MSDOS_DOTDOT,
375 MSDOS_NAME)) {
376 brelse(bh);
377 return -ENOTEMPTY;
378 }
379 if (bh)
380 brelse(bh);
381 }
382 return 0;
383 }
384
385
386 int msdos_rmdir(struct inode *dir,const char *name,int len)
387 {
388 struct super_block *sb = dir->i_sb;
389 int res,ino;
390 struct buffer_head *bh;
391 struct msdos_dir_entry *de;
392 struct inode *inode;
393
394 bh = NULL;
395 inode = NULL;
396 res = -EPERM;
397 if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.')))
398 goto rmdir_done;
399 if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) goto rmdir_done;
400 res = -ENOENT;
401 if (!(inode = iget(dir->i_sb,ino))) goto rmdir_done;
402 res = -ENOTDIR;
403 if (!S_ISDIR(inode->i_mode)) goto rmdir_done;
404 res = -EBUSY;
405 if (dir->i_dev != inode->i_dev || dir == inode)
406 goto rmdir_done;
407 res = msdos_empty(inode);
408 if (res)
409 goto rmdir_done;
410 inode->i_nlink = 0;
411 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
412 dir->i_nlink--;
413 inode->i_dirt = dir->i_dirt = 1;
414 de->name[0] = DELETED_FLAG;
415 mark_buffer_dirty(bh, 1);
416 res = 0;
417 rmdir_done:
418 brelse(bh);
419 iput(dir);
420 iput(inode);
421 return res;
422 }
423
424
425 static int msdos_unlinkx(
426 struct inode *dir,
427 const char *name,
428 int len,
429 int nospc)
430 {
431 struct super_block *sb = dir->i_sb;
432 int res,ino;
433 struct buffer_head *bh;
434 struct msdos_dir_entry *de;
435 struct inode *inode;
436
437 bh = NULL;
438 inode = NULL;
439 if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0)
440 goto unlink_done;
441 if (!(inode = iget(dir->i_sb,ino))) {
442 res = -ENOENT;
443 goto unlink_done;
444 }
445 if (!S_ISREG(inode->i_mode) && nospc){
446 res = -EPERM;
447 goto unlink_done;
448 }
449 if (MSDOS_I(inode)->i_attrs & ATTR_SYS){
450 res = -EPERM;
451 goto unlink_done;
452 }
453 inode->i_nlink = 0;
454 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
455 MSDOS_I(inode)->i_busy = 1;
456 inode->i_dirt = dir->i_dirt = 1;
457 de->name[0] = DELETED_FLAG;
458 mark_buffer_dirty(bh, 1);
459 unlink_done:
460 brelse(bh);
461 iput(inode);
462 iput(dir);
463 return res;
464 }
465
466
467 int msdos_unlink(struct inode *dir,const char *name,int len)
468 {
469 return msdos_unlinkx (dir,name,len,1);
470 }
471
472
473 int msdos_unlink_umsdos(struct inode *dir,const char *name,int len)
474 {
475 return msdos_unlinkx (dir,name,len,0);
476 }
477
478
479 static int rename_same_dir(struct inode *old_dir,char *old_name,
480 struct inode *new_dir,char *new_name,struct buffer_head *old_bh,
481 struct msdos_dir_entry *old_de,int old_ino,int is_hid)
482 {
483 struct super_block *sb = old_dir->i_sb;
484 struct buffer_head *new_bh;
485 struct msdos_dir_entry *new_de;
486 struct inode *new_inode,*old_inode;
487 int new_ino,exists,error;
488
489 if (!strncmp(old_name,new_name,MSDOS_NAME)) goto set_hid;
490 exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino,SCAN_ANY) >= 0;
491 if (*(unsigned char *) old_de->name == DELETED_FLAG) {
492 if (exists) brelse(new_bh);
493 return -ENOENT;
494 }
495 if (exists) {
496 if (!(new_inode = iget(new_dir->i_sb,new_ino))) {
497 brelse(new_bh);
498 return -EIO;
499 }
500 error = S_ISDIR(new_inode->i_mode)
501 ? (old_de->attr & ATTR_DIR)
502 ? msdos_empty(new_inode)
503 : -EPERM
504 : (old_de->attr & ATTR_DIR)
505 ? -EPERM
506 : 0;
507 if (!error && (old_de->attr & ATTR_SYS)) error = -EPERM;
508 if (error) {
509 iput(new_inode);
510 brelse(new_bh);
511 return error;
512 }
513 if (S_ISDIR(new_inode->i_mode)) {
514 new_dir->i_nlink--;
515 new_dir->i_dirt = 1;
516 }
517 new_inode->i_nlink = 0;
518 MSDOS_I(new_inode)->i_busy = 1;
519 new_inode->i_dirt = 1;
520 new_de->name[0] = DELETED_FLAG;
521 mark_buffer_dirty(new_bh, 1);
522 iput(new_inode);
523 brelse(new_bh);
524 }
525 memcpy(old_de->name,new_name,MSDOS_NAME);
526 set_hid:
527 old_de->attr = is_hid
528 ? (old_de->attr | ATTR_HIDDEN)
529 : (old_de->attr &~ ATTR_HIDDEN);
530 mark_buffer_dirty(old_bh, 1);
531
532 if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) {
533 msdos_read_inode(old_inode);
534 MSDOS_I(old_inode)->i_attrs = is_hid
535 ? (MSDOS_I(old_inode)->i_attrs | ATTR_HIDDEN)
536 : (MSDOS_I(old_inode)->i_attrs &~ ATTR_HIDDEN);
537 iput(old_inode);
538 }
539 return 0;
540 }
541
542
543 static int rename_diff_dir(struct inode *old_dir,char *old_name,
544 struct inode *new_dir,char *new_name,struct buffer_head *old_bh,
545 struct msdos_dir_entry *old_de,int old_ino,int is_hid)
546 {
547 struct super_block *sb = old_dir->i_sb;
548 struct buffer_head *new_bh,*free_bh,*dotdot_bh;
549 struct msdos_dir_entry *new_de,*free_de,*dotdot_de;
550 struct inode *old_inode,*new_inode,*free_inode,*dotdot_inode,*walk;
551 int new_ino,free_ino,dotdot_ino;
552 int error,exists,ino;
553
554 if (old_dir->i_dev != new_dir->i_dev) return -EINVAL;
555 if (old_ino == new_dir->i_ino) return -EINVAL;
556 if (!(walk = iget(new_dir->i_sb,new_dir->i_ino))) return -EIO;
557
558 while (walk->i_ino != MSDOS_ROOT_INO) {
559 ino = msdos_parent_ino(walk,1);
560 iput(walk);
561 if (ino < 0) return ino;
562 if (ino == old_ino) return -EINVAL;
563 if (!(walk = iget(new_dir->i_sb,ino))) return -EIO;
564 }
565 iput(walk);
566
567 while ((error = msdos_scan(new_dir,NULL,&free_bh,&free_de,&free_ino,
568 SCAN_ANY)) < 0) {
569 if (error != -ENOENT) return error;
570 error = msdos_add_cluster(new_dir);
571 if (error) return error;
572 }
573 exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino,SCAN_ANY) >= 0;
574 if (!(old_inode = iget(old_dir->i_sb,old_ino))) {
575 brelse(free_bh);
576 if (exists) brelse(new_bh);
577 return -EIO;
578 }
579 if (*(unsigned char *) old_de->name == DELETED_FLAG) {
580 iput(old_inode);
581 brelse(free_bh);
582 if (exists) brelse(new_bh);
583 return -ENOENT;
584 }
585 new_inode = NULL;
586 if (exists) {
587 if (!(new_inode = iget(new_dir->i_sb,new_ino))) {
588 iput(old_inode);
589 brelse(new_bh);
590 return -EIO;
591 }
592 error = S_ISDIR(new_inode->i_mode)
593 ? (old_de->attr & ATTR_DIR)
594 ? msdos_empty(new_inode)
595 : -EPERM
596 : (old_de->attr & ATTR_DIR)
597 ? -EPERM
598 : 0;
599 if (!error && (old_de->attr & ATTR_SYS)) error = -EPERM;
600 if (error) {
601 iput(new_inode);
602 iput(old_inode);
603 brelse(new_bh);
604 return error;
605 }
606 new_inode->i_nlink = 0;
607 MSDOS_I(new_inode)->i_busy = 1;
608 new_inode->i_dirt = 1;
609 new_de->name[0] = DELETED_FLAG;
610 mark_buffer_dirty(new_bh, 1);
611 }
612 memcpy(free_de,old_de,sizeof(struct msdos_dir_entry));
613 memcpy(free_de->name,new_name,MSDOS_NAME);
614 free_de->attr = is_hid
615 ? (free_de->attr|ATTR_HIDDEN)
616 : (free_de->attr&~ATTR_HIDDEN);
617 if (!(free_inode = iget(new_dir->i_sb,free_ino))) {
618 free_de->name[0] = DELETED_FLAG;
619
620 brelse(free_bh);
621 if (exists) {
622 iput(new_inode);
623 brelse(new_bh);
624 }
625 return -EIO;
626 }
627 if (exists && S_ISDIR(new_inode->i_mode)) {
628 new_dir->i_nlink--;
629 new_dir->i_dirt = 1;
630 }
631 msdos_read_inode(free_inode);
632 MSDOS_I(old_inode)->i_busy = 1;
633 cache_inval_inode(old_inode);
634 old_inode->i_dirt = 1;
635 old_de->name[0] = DELETED_FLAG;
636 mark_buffer_dirty(old_bh, 1);
637 mark_buffer_dirty(free_bh, 1);
638 if (!exists) iput(free_inode);
639 else {
640 MSDOS_I(new_inode)->i_depend = free_inode;
641 MSDOS_I(free_inode)->i_old = new_inode;
642
643 iput(new_inode);
644 brelse(new_bh);
645 }
646 if (S_ISDIR(old_inode->i_mode)) {
647 if ((error = msdos_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
648 &dotdot_de,&dotdot_ino,SCAN_ANY)) < 0) goto rename_done;
649 if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) {
650 brelse(dotdot_bh);
651 error = -EIO;
652 goto rename_done;
653 }
654 dotdot_de->start = MSDOS_I(dotdot_inode)->i_start =
655 MSDOS_I(new_dir)->i_start;
656 dotdot_inode->i_dirt = 1;
657 mark_buffer_dirty(dotdot_bh, 1);
658 old_dir->i_nlink--;
659 new_dir->i_nlink++;
660
661 dotdot_inode->i_nlink = new_dir->i_nlink;
662 iput(dotdot_inode);
663 brelse(dotdot_bh);
664 }
665 error = 0;
666 rename_done:
667 brelse(free_bh);
668 iput(old_inode);
669 return error;
670 }
671
672
673 int msdos_rename(struct inode *old_dir,const char *old_name,int old_len,
674 struct inode *new_dir,const char *new_name,int new_len)
675 {
676 struct super_block *sb = old_dir->i_sb;
677 char old_msdos_name[MSDOS_NAME],new_msdos_name[MSDOS_NAME];
678 struct buffer_head *old_bh;
679 struct msdos_dir_entry *old_de;
680 int old_ino,error;
681 int is_hid,old_hid;
682
683 if ((error = msdos_format_name(MSDOS_SB(old_dir->i_sb)->name_check,
684 old_name,old_len,old_msdos_name,1,MSDOS_SB(old_dir->i_sb)->dotsOK))
685 < 0) goto rename_done;
686 if ((error = msdos_format_name(MSDOS_SB(new_dir->i_sb)->name_check,
687 new_name,new_len,new_msdos_name,0,MSDOS_SB(new_dir->i_sb)->dotsOK))
688 < 0) goto rename_done;
689 is_hid = (new_name[0]=='.') && (new_msdos_name[0]!='.');
690 old_hid = (old_name[0]=='.') && (old_msdos_name[0]!='.');
691 if ((error = msdos_scan(old_dir,old_msdos_name,&old_bh,&old_de,
692 &old_ino,old_hid?SCAN_HID:SCAN_NOTHID)) < 0) goto rename_done;
693 lock_creation();
694 if (old_dir == new_dir)
695 error = rename_same_dir(old_dir,old_msdos_name,new_dir,
696 new_msdos_name,old_bh,old_de,old_ino,is_hid);
697 else error = rename_diff_dir(old_dir,old_msdos_name,new_dir,
698 new_msdos_name,old_bh,old_de,old_ino,is_hid);
699 unlock_creation();
700 brelse(old_bh);
701 rename_done:
702 iput(old_dir);
703 iput(new_dir);
704 return error;
705 }