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 (!(*result)->i_sb ||
181 ((*result)->i_sb->s_magic != MSDOS_SUPER_MAGIC)) {
182
183 iput(dir);
184 return 0;
185 }
186 if (MSDOS_I(*result)->i_busy) {
187 iput(*result);
188 iput(dir);
189 return -ENOENT;
190 }
191 PRINTK (("msdos_lookup 6\n"));
192 while (MSDOS_I(*result)->i_old) {
193 next = MSDOS_I(*result)->i_old;
194 iput(*result);
195 if (!(*result = iget(next->i_sb,next->i_ino))) {
196 fs_panic(dir->i_sb,"msdos_lookup: Can't happen");
197 iput(dir);
198 return -ENOENT;
199 }
200 }
201 PRINTK (("msdos_lookup 7\n"));
202 iput(dir);
203 PRINTK (("msdos_lookup 8\n"));
204 return 0;
205 }
206
207
208
209 static int msdos_create_entry(struct inode *dir, const char *name,
210 int is_dir, int is_hid, struct inode **result)
211 {
212 struct super_block *sb = dir->i_sb;
213 struct buffer_head *bh;
214 struct msdos_dir_entry *de;
215 int res,ino;
216
217 if ((res = msdos_scan(dir,NULL,&bh,&de,&ino,SCAN_ANY)) < 0) {
218 if (res != -ENOENT) return res;
219 if (dir->i_ino == MSDOS_ROOT_INO) return -ENOSPC;
220 if ((res = msdos_add_cluster(dir)) < 0) return res;
221 if ((res = msdos_scan(dir,NULL,&bh,&de,&ino,SCAN_ANY)) < 0) return res;
222 }
223
224
225
226 dir->i_ctime = dir->i_mtime = CURRENT_TIME;
227 dir->i_dirt = 1;
228 memcpy(de->name,name,MSDOS_NAME);
229 memset(de->unused, 0, sizeof(de->unused));
230 de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;
231 de->attr = is_hid ? (de->attr|ATTR_HIDDEN) : (de->attr&~ATTR_HIDDEN);
232 de->start = 0;
233 date_unix2dos(dir->i_mtime,&de->time,&de->date);
234 de->size = 0;
235 mark_buffer_dirty(bh, 1);
236 if ((*result = iget(dir->i_sb,ino)) != NULL)
237 msdos_read_inode(*result);
238 brelse(bh);
239 if (!*result) return -EIO;
240 (*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =
241 CURRENT_TIME;
242 (*result)->i_dirt = 1;
243 return 0;
244 }
245
246
247 int msdos_create(struct inode *dir,const char *name,int len,int mode,
248 struct inode **result)
249 {
250 struct super_block *sb = dir->i_sb;
251 struct buffer_head *bh;
252 struct msdos_dir_entry *de;
253 char msdos_name[MSDOS_NAME];
254 int ino,res,is_hid;
255
256 if (!dir) return -ENOENT;
257 if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
258 msdos_name,0,MSDOS_SB(dir->i_sb)->dotsOK)) < 0) {
259 iput(dir);
260 return res;
261 }
262 is_hid = (name[0]=='.') && (msdos_name[0]!='.');
263 lock_creation();
264
265
266
267
268 if (msdos_scan(dir,msdos_name,&bh,&de,&ino,SCAN_HID) >= 0) {
269 unlock_creation();
270 brelse(bh);
271 iput(dir);
272 return is_hid ? -EEXIST : -EINVAL;
273 }
274 if (msdos_scan(dir,msdos_name,&bh,&de,&ino,SCAN_NOTHID) >= 0) {
275 unlock_creation();
276 brelse(bh);
277 iput(dir);
278 return is_hid ? -EINVAL : -EEXIST;
279 }
280 res = msdos_create_entry(dir,msdos_name,S_ISDIR(mode),is_hid,result);
281 unlock_creation();
282 iput(dir);
283 return res;
284 }
285
286
287 #ifdef DEBUG
288
289 static void dump_fat(struct super_block *sb,int start)
290 {
291 printk("[");
292 while (start) {
293 printk("%d ",start);
294 start = fat_access(sb,start,-1);
295 if (!start) {
296 printk("ERROR");
297 break;
298 }
299 if (start == -1) break;
300 }
301 printk("]\n");
302 }
303
304 #endif
305
306
307 int msdos_mkdir(struct inode *dir,const char *name,int len,int mode)
308 {
309 struct super_block *sb = dir->i_sb;
310 struct buffer_head *bh;
311 struct msdos_dir_entry *de;
312 struct inode *inode,*dot;
313 char msdos_name[MSDOS_NAME];
314 int ino,res,is_hid;
315
316 if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len,
317 msdos_name,0,MSDOS_SB(dir->i_sb)->dotsOK)) < 0) {
318 iput(dir);
319 return res;
320 }
321 is_hid = (name[0]=='.') && (msdos_name[0]!='.');
322 lock_creation();
323 if (msdos_scan(dir,msdos_name,&bh,&de,&ino,SCAN_ANY) >= 0) {
324 unlock_creation();
325 brelse(bh);
326 iput(dir);
327 return -EEXIST;
328 }
329 if ((res = msdos_create_entry(dir,msdos_name,1,is_hid,&inode)) < 0) {
330 unlock_creation();
331 iput(dir);
332 return res;
333 }
334 dir->i_nlink++;
335 inode->i_nlink = 2;
336 MSDOS_I(inode)->i_busy = 1;
337 if ((res = msdos_add_cluster(inode)) < 0) goto mkdir_error;
338 if ((res = msdos_create_entry(inode,MSDOS_DOT,1,0,&dot)) < 0)
339 goto mkdir_error;
340 dot->i_size = inode->i_size;
341 MSDOS_I(dot)->i_start = MSDOS_I(inode)->i_start;
342 dot->i_nlink = inode->i_nlink;
343 dot->i_dirt = 1;
344 iput(dot);
345 if ((res = msdos_create_entry(inode,MSDOS_DOTDOT,1,0,&dot)) < 0)
346 goto mkdir_error;
347 unlock_creation();
348 dot->i_size = dir->i_size;
349 MSDOS_I(dot)->i_start = MSDOS_I(dir)->i_start;
350 dot->i_nlink = dir->i_nlink;
351 dot->i_dirt = 1;
352 MSDOS_I(inode)->i_busy = 0;
353 iput(dot);
354 iput(inode);
355 iput(dir);
356 return 0;
357 mkdir_error:
358 iput(inode);
359 if (msdos_rmdir(dir,name,len) < 0)
360 fs_panic(dir->i_sb,"rmdir in mkdir failed");
361 unlock_creation();
362 return res;
363 }
364
365
366 static int msdos_empty(struct inode *dir)
367 {
368 struct super_block *sb = dir->i_sb;
369 loff_t pos;
370 struct buffer_head *bh;
371 struct msdos_dir_entry *de;
372
373 if (dir->i_count > 1)
374 return -EBUSY;
375 if (MSDOS_I(dir)->i_start) {
376 pos = 0;
377 bh = NULL;
378 while (msdos_get_entry(dir,&pos,&bh,&de) > -1)
379 if (!IS_FREE(de->name) && strncmp(de->name,MSDOS_DOT,
380 MSDOS_NAME) && strncmp(de->name,MSDOS_DOTDOT,
381 MSDOS_NAME)) {
382 brelse(bh);
383 return -ENOTEMPTY;
384 }
385 if (bh)
386 brelse(bh);
387 }
388 return 0;
389 }
390
391
392 int msdos_rmdir(struct inode *dir,const char *name,int len)
393 {
394 struct super_block *sb = dir->i_sb;
395 int res,ino;
396 struct buffer_head *bh;
397 struct msdos_dir_entry *de;
398 struct inode *inode;
399
400 bh = NULL;
401 inode = NULL;
402 res = -EPERM;
403 if (name[0] == '.' && (len == 1 || (len == 2 && name[1] == '.')))
404 goto rmdir_done;
405 if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) goto rmdir_done;
406 res = -ENOENT;
407 if (!(inode = iget(dir->i_sb,ino))) goto rmdir_done;
408 res = -ENOTDIR;
409 if (!S_ISDIR(inode->i_mode)) goto rmdir_done;
410 res = -EBUSY;
411 if (dir->i_dev != inode->i_dev || dir == inode)
412 goto rmdir_done;
413 res = msdos_empty(inode);
414 if (res)
415 goto rmdir_done;
416 inode->i_nlink = 0;
417 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
418 dir->i_nlink--;
419 inode->i_dirt = dir->i_dirt = 1;
420 de->name[0] = DELETED_FLAG;
421 mark_buffer_dirty(bh, 1);
422 res = 0;
423 rmdir_done:
424 brelse(bh);
425 iput(dir);
426 iput(inode);
427 return res;
428 }
429
430
431 static int msdos_unlinkx(
432 struct inode *dir,
433 const char *name,
434 int len,
435 int nospc)
436 {
437 struct super_block *sb = dir->i_sb;
438 int res,ino;
439 struct buffer_head *bh;
440 struct msdos_dir_entry *de;
441 struct inode *inode;
442
443 bh = NULL;
444 inode = NULL;
445 if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0)
446 goto unlink_done;
447 if (!(inode = iget(dir->i_sb,ino))) {
448 res = -ENOENT;
449 goto unlink_done;
450 }
451 if (!S_ISREG(inode->i_mode) && nospc){
452 res = -EPERM;
453 goto unlink_done;
454 }
455 if (IS_IMMUTABLE(inode)){
456 res = -EPERM;
457 goto unlink_done;
458 }
459 inode->i_nlink = 0;
460 inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
461 MSDOS_I(inode)->i_busy = 1;
462 inode->i_dirt = dir->i_dirt = 1;
463 de->name[0] = DELETED_FLAG;
464 mark_buffer_dirty(bh, 1);
465 unlink_done:
466 brelse(bh);
467 iput(inode);
468 iput(dir);
469 return res;
470 }
471
472
473 int msdos_unlink(struct inode *dir,const char *name,int len)
474 {
475 return msdos_unlinkx (dir,name,len,1);
476 }
477
478
479 int msdos_unlink_umsdos(struct inode *dir,const char *name,int len)
480 {
481 return msdos_unlinkx (dir,name,len,0);
482 }
483
484
485 static int rename_same_dir(struct inode *old_dir,char *old_name,
486 struct inode *new_dir,char *new_name,struct buffer_head *old_bh,
487 struct msdos_dir_entry *old_de,int old_ino,int is_hid)
488 {
489 struct super_block *sb = old_dir->i_sb;
490 struct buffer_head *new_bh;
491 struct msdos_dir_entry *new_de;
492 struct inode *new_inode,*old_inode;
493 int new_ino,exists,error;
494
495 if (!strncmp(old_name,new_name,MSDOS_NAME)) goto set_hid;
496 exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino,SCAN_ANY) >= 0;
497 if (*(unsigned char *) old_de->name == DELETED_FLAG) {
498 if (exists) brelse(new_bh);
499 return -ENOENT;
500 }
501 if (exists) {
502 if (!(new_inode = iget(new_dir->i_sb,new_ino))) {
503 brelse(new_bh);
504 return -EIO;
505 }
506 error = S_ISDIR(new_inode->i_mode)
507 ? (old_de->attr & ATTR_DIR)
508 ? msdos_empty(new_inode)
509 : -EPERM
510 : (old_de->attr & ATTR_DIR)
511 ? -EPERM
512 : 0;
513 if (!error && (old_de->attr & ATTR_SYS)) error = -EPERM;
514 if (error) {
515 iput(new_inode);
516 brelse(new_bh);
517 return error;
518 }
519 if (S_ISDIR(new_inode->i_mode)) {
520 new_dir->i_nlink--;
521 new_dir->i_dirt = 1;
522 }
523 new_inode->i_nlink = 0;
524 MSDOS_I(new_inode)->i_busy = 1;
525 new_inode->i_dirt = 1;
526 new_de->name[0] = DELETED_FLAG;
527 mark_buffer_dirty(new_bh, 1);
528 iput(new_inode);
529 brelse(new_bh);
530 }
531 memcpy(old_de->name,new_name,MSDOS_NAME);
532 set_hid:
533 old_de->attr = is_hid
534 ? (old_de->attr | ATTR_HIDDEN)
535 : (old_de->attr &~ ATTR_HIDDEN);
536 mark_buffer_dirty(old_bh, 1);
537
538 if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) {
539 msdos_read_inode(old_inode);
540 MSDOS_I(old_inode)->i_attrs = is_hid
541 ? (MSDOS_I(old_inode)->i_attrs | ATTR_HIDDEN)
542 : (MSDOS_I(old_inode)->i_attrs &~ ATTR_HIDDEN);
543 iput(old_inode);
544 }
545 return 0;
546 }
547
548
549 static int rename_diff_dir(struct inode *old_dir,char *old_name,
550 struct inode *new_dir,char *new_name,struct buffer_head *old_bh,
551 struct msdos_dir_entry *old_de,int old_ino,int is_hid)
552 {
553 struct super_block *sb = old_dir->i_sb;
554 struct buffer_head *new_bh,*free_bh,*dotdot_bh;
555 struct msdos_dir_entry *new_de,*free_de,*dotdot_de;
556 struct inode *old_inode,*new_inode,*free_inode,*dotdot_inode,*walk;
557 int new_ino,free_ino,dotdot_ino;
558 int error,exists,ino;
559
560 if (old_dir->i_dev != new_dir->i_dev) return -EINVAL;
561 if (old_ino == new_dir->i_ino) return -EINVAL;
562 if (!(walk = iget(new_dir->i_sb,new_dir->i_ino))) return -EIO;
563
564 while (walk->i_ino != MSDOS_ROOT_INO) {
565 ino = msdos_parent_ino(walk,1);
566 iput(walk);
567 if (ino < 0) return ino;
568 if (ino == old_ino) return -EINVAL;
569 if (!(walk = iget(new_dir->i_sb,ino))) return -EIO;
570 }
571 iput(walk);
572
573 while ((error = msdos_scan(new_dir,NULL,&free_bh,&free_de,&free_ino,
574 SCAN_ANY)) < 0) {
575 if (error != -ENOENT) return error;
576 error = msdos_add_cluster(new_dir);
577 if (error) return error;
578 }
579 exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino,SCAN_ANY) >= 0;
580 if (!(old_inode = iget(old_dir->i_sb,old_ino))) {
581 brelse(free_bh);
582 if (exists) brelse(new_bh);
583 return -EIO;
584 }
585 if (*(unsigned char *) old_de->name == DELETED_FLAG) {
586 iput(old_inode);
587 brelse(free_bh);
588 if (exists) brelse(new_bh);
589 return -ENOENT;
590 }
591 new_inode = NULL;
592 if (exists) {
593 if (!(new_inode = iget(new_dir->i_sb,new_ino))) {
594 iput(old_inode);
595 brelse(new_bh);
596 return -EIO;
597 }
598 error = S_ISDIR(new_inode->i_mode)
599 ? (old_de->attr & ATTR_DIR)
600 ? msdos_empty(new_inode)
601 : -EPERM
602 : (old_de->attr & ATTR_DIR)
603 ? -EPERM
604 : 0;
605 if (!error && (old_de->attr & ATTR_SYS)) error = -EPERM;
606 if (error) {
607 iput(new_inode);
608 iput(old_inode);
609 brelse(new_bh);
610 return error;
611 }
612 new_inode->i_nlink = 0;
613 MSDOS_I(new_inode)->i_busy = 1;
614 new_inode->i_dirt = 1;
615 new_de->name[0] = DELETED_FLAG;
616 mark_buffer_dirty(new_bh, 1);
617 }
618 memcpy(free_de,old_de,sizeof(struct msdos_dir_entry));
619 memcpy(free_de->name,new_name,MSDOS_NAME);
620 free_de->attr = is_hid
621 ? (free_de->attr|ATTR_HIDDEN)
622 : (free_de->attr&~ATTR_HIDDEN);
623 if (!(free_inode = iget(new_dir->i_sb,free_ino))) {
624 free_de->name[0] = DELETED_FLAG;
625
626 brelse(free_bh);
627 if (exists) {
628 iput(new_inode);
629 brelse(new_bh);
630 }
631 return -EIO;
632 }
633 if (exists && S_ISDIR(new_inode->i_mode)) {
634 new_dir->i_nlink--;
635 new_dir->i_dirt = 1;
636 }
637 msdos_read_inode(free_inode);
638 MSDOS_I(old_inode)->i_busy = 1;
639 cache_inval_inode(old_inode);
640 old_inode->i_dirt = 1;
641 old_de->name[0] = DELETED_FLAG;
642 mark_buffer_dirty(old_bh, 1);
643 mark_buffer_dirty(free_bh, 1);
644 if (!exists) iput(free_inode);
645 else {
646 MSDOS_I(new_inode)->i_depend = free_inode;
647 MSDOS_I(free_inode)->i_old = new_inode;
648
649 iput(new_inode);
650 brelse(new_bh);
651 }
652 if (S_ISDIR(old_inode->i_mode)) {
653 if ((error = msdos_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh,
654 &dotdot_de,&dotdot_ino,SCAN_ANY)) < 0) goto rename_done;
655 if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) {
656 brelse(dotdot_bh);
657 error = -EIO;
658 goto rename_done;
659 }
660 dotdot_de->start = MSDOS_I(dotdot_inode)->i_start =
661 MSDOS_I(new_dir)->i_start;
662 dotdot_inode->i_dirt = 1;
663 mark_buffer_dirty(dotdot_bh, 1);
664 old_dir->i_nlink--;
665 new_dir->i_nlink++;
666
667 dotdot_inode->i_nlink = new_dir->i_nlink;
668 iput(dotdot_inode);
669 brelse(dotdot_bh);
670 }
671 error = 0;
672 rename_done:
673 brelse(free_bh);
674 iput(old_inode);
675 return error;
676 }
677
678
679 int msdos_rename(struct inode *old_dir,const char *old_name,int old_len,
680 struct inode *new_dir,const char *new_name,int new_len)
681 {
682 struct super_block *sb = old_dir->i_sb;
683 char old_msdos_name[MSDOS_NAME],new_msdos_name[MSDOS_NAME];
684 struct buffer_head *old_bh;
685 struct msdos_dir_entry *old_de;
686 int old_ino,error;
687 int is_hid,old_hid;
688
689 if ((error = msdos_format_name(MSDOS_SB(old_dir->i_sb)->name_check,
690 old_name,old_len,old_msdos_name,1,MSDOS_SB(old_dir->i_sb)->dotsOK))
691 < 0) goto rename_done;
692 if ((error = msdos_format_name(MSDOS_SB(new_dir->i_sb)->name_check,
693 new_name,new_len,new_msdos_name,0,MSDOS_SB(new_dir->i_sb)->dotsOK))
694 < 0) goto rename_done;
695 is_hid = (new_name[0]=='.') && (new_msdos_name[0]!='.');
696 old_hid = (old_name[0]=='.') && (old_msdos_name[0]!='.');
697 if ((error = msdos_scan(old_dir,old_msdos_name,&old_bh,&old_de,
698 &old_ino,old_hid?SCAN_HID:SCAN_NOTHID)) < 0) goto rename_done;
699 lock_creation();
700 if (old_dir == new_dir)
701 error = rename_same_dir(old_dir,old_msdos_name,new_dir,
702 new_msdos_name,old_bh,old_de,old_ino,is_hid);
703 else error = rename_diff_dir(old_dir,old_msdos_name,new_dir,
704 new_msdos_name,old_bh,old_de,old_ino,is_hid);
705 unlock_creation();
706 brelse(old_bh);
707 rename_done:
708 iput(old_dir);
709 iput(new_dir);
710 return error;
711 }