diff options
Diffstat (limited to 'fs/msdos/namei.c')
-rw-r--r-- | fs/msdos/namei.c | 56 |
1 files changed, 27 insertions, 29 deletions
diff --git a/fs/msdos/namei.c b/fs/msdos/namei.c index 05ff4f1d7026..e844b9809d27 100644 --- a/fs/msdos/namei.c +++ b/fs/msdos/namei.c | |||
@@ -14,12 +14,7 @@ | |||
14 | 14 | ||
15 | /* Characters that are undesirable in an MS-DOS file name */ | 15 | /* Characters that are undesirable in an MS-DOS file name */ |
16 | static unsigned char bad_chars[] = "*?<>|\""; | 16 | static unsigned char bad_chars[] = "*?<>|\""; |
17 | static unsigned char bad_if_strict_pc[] = "+=,; "; | 17 | static unsigned char bad_if_strict[] = "+=,; "; |
18 | /* GEMDOS is less restrictive */ | ||
19 | static unsigned char bad_if_strict_atari[] = " "; | ||
20 | |||
21 | #define bad_if_strict(opts) \ | ||
22 | ((opts)->atari ? bad_if_strict_atari : bad_if_strict_pc) | ||
23 | 18 | ||
24 | /***** Formats an MS-DOS file name. Rejects invalid names. */ | 19 | /***** Formats an MS-DOS file name. Rejects invalid names. */ |
25 | static int msdos_format_name(const unsigned char *name, int len, | 20 | static int msdos_format_name(const unsigned char *name, int len, |
@@ -40,21 +35,20 @@ static int msdos_format_name(const unsigned char *name, int len, | |||
40 | /* Get rid of dot - test for it elsewhere */ | 35 | /* Get rid of dot - test for it elsewhere */ |
41 | name++; | 36 | name++; |
42 | len--; | 37 | len--; |
43 | } else if (!opts->atari) | 38 | } else |
44 | return -EINVAL; | 39 | return -EINVAL; |
45 | } | 40 | } |
46 | /* | 41 | /* |
47 | * disallow names that _really_ start with a dot for MS-DOS, | 42 | * disallow names that _really_ start with a dot |
48 | * GEMDOS does not care | ||
49 | */ | 43 | */ |
50 | space = !opts->atari; | 44 | space = 1; |
51 | c = 0; | 45 | c = 0; |
52 | for (walk = res; len && walk - res < 8; walk++) { | 46 | for (walk = res; len && walk - res < 8; walk++) { |
53 | c = *name++; | 47 | c = *name++; |
54 | len--; | 48 | len--; |
55 | if (opts->name_check != 'r' && strchr(bad_chars, c)) | 49 | if (opts->name_check != 'r' && strchr(bad_chars, c)) |
56 | return -EINVAL; | 50 | return -EINVAL; |
57 | if (opts->name_check == 's' && strchr(bad_if_strict(opts), c)) | 51 | if (opts->name_check == 's' && strchr(bad_if_strict, c)) |
58 | return -EINVAL; | 52 | return -EINVAL; |
59 | if (c >= 'A' && c <= 'Z' && opts->name_check == 's') | 53 | if (c >= 'A' && c <= 'Z' && opts->name_check == 's') |
60 | return -EINVAL; | 54 | return -EINVAL; |
@@ -94,7 +88,7 @@ static int msdos_format_name(const unsigned char *name, int len, | |||
94 | if (opts->name_check != 'r' && strchr(bad_chars, c)) | 88 | if (opts->name_check != 'r' && strchr(bad_chars, c)) |
95 | return -EINVAL; | 89 | return -EINVAL; |
96 | if (opts->name_check == 's' && | 90 | if (opts->name_check == 's' && |
97 | strchr(bad_if_strict(opts), c)) | 91 | strchr(bad_if_strict, c)) |
98 | return -EINVAL; | 92 | return -EINVAL; |
99 | if (c < ' ' || c == ':' || c == '\\') | 93 | if (c < ' ' || c == ':' || c == '\\') |
100 | return -EINVAL; | 94 | return -EINVAL; |
@@ -214,7 +208,7 @@ static struct dentry *msdos_lookup(struct inode *dir, struct dentry *dentry, | |||
214 | 208 | ||
215 | dentry->d_op = &msdos_dentry_operations; | 209 | dentry->d_op = &msdos_dentry_operations; |
216 | 210 | ||
217 | lock_kernel(); | 211 | lock_super(sb); |
218 | res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo); | 212 | res = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo); |
219 | if (res == -ENOENT) | 213 | if (res == -ENOENT) |
220 | goto add; | 214 | goto add; |
@@ -232,7 +226,7 @@ add: | |||
232 | if (dentry) | 226 | if (dentry) |
233 | dentry->d_op = &msdos_dentry_operations; | 227 | dentry->d_op = &msdos_dentry_operations; |
234 | out: | 228 | out: |
235 | unlock_kernel(); | 229 | unlock_super(sb); |
236 | if (!res) | 230 | if (!res) |
237 | return dentry; | 231 | return dentry; |
238 | return ERR_PTR(res); | 232 | return ERR_PTR(res); |
@@ -243,6 +237,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name, | |||
243 | int is_dir, int is_hid, int cluster, | 237 | int is_dir, int is_hid, int cluster, |
244 | struct timespec *ts, struct fat_slot_info *sinfo) | 238 | struct timespec *ts, struct fat_slot_info *sinfo) |
245 | { | 239 | { |
240 | struct msdos_sb_info *sbi = MSDOS_SB(dir->i_sb); | ||
246 | struct msdos_dir_entry de; | 241 | struct msdos_dir_entry de; |
247 | __le16 time, date; | 242 | __le16 time, date; |
248 | int err; | 243 | int err; |
@@ -252,7 +247,7 @@ static int msdos_add_entry(struct inode *dir, const unsigned char *name, | |||
252 | if (is_hid) | 247 | if (is_hid) |
253 | de.attr |= ATTR_HIDDEN; | 248 | de.attr |= ATTR_HIDDEN; |
254 | de.lcase = 0; | 249 | de.lcase = 0; |
255 | fat_date_unix2dos(ts->tv_sec, &time, &date); | 250 | fat_date_unix2dos(ts->tv_sec, &time, &date, sbi->options.tz_utc); |
256 | de.cdate = de.adate = 0; | 251 | de.cdate = de.adate = 0; |
257 | de.ctime = 0; | 252 | de.ctime = 0; |
258 | de.ctime_cs = 0; | 253 | de.ctime_cs = 0; |
@@ -286,7 +281,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode, | |||
286 | unsigned char msdos_name[MSDOS_NAME]; | 281 | unsigned char msdos_name[MSDOS_NAME]; |
287 | int err, is_hid; | 282 | int err, is_hid; |
288 | 283 | ||
289 | lock_kernel(); | 284 | lock_super(sb); |
290 | 285 | ||
291 | err = msdos_format_name(dentry->d_name.name, dentry->d_name.len, | 286 | err = msdos_format_name(dentry->d_name.name, dentry->d_name.len, |
292 | msdos_name, &MSDOS_SB(sb)->options); | 287 | msdos_name, &MSDOS_SB(sb)->options); |
@@ -315,7 +310,7 @@ static int msdos_create(struct inode *dir, struct dentry *dentry, int mode, | |||
315 | 310 | ||
316 | d_instantiate(dentry, inode); | 311 | d_instantiate(dentry, inode); |
317 | out: | 312 | out: |
318 | unlock_kernel(); | 313 | unlock_super(sb); |
319 | if (!err) | 314 | if (!err) |
320 | err = fat_flush_inodes(sb, dir, inode); | 315 | err = fat_flush_inodes(sb, dir, inode); |
321 | return err; | 316 | return err; |
@@ -324,11 +319,12 @@ out: | |||
324 | /***** Remove a directory */ | 319 | /***** Remove a directory */ |
325 | static int msdos_rmdir(struct inode *dir, struct dentry *dentry) | 320 | static int msdos_rmdir(struct inode *dir, struct dentry *dentry) |
326 | { | 321 | { |
322 | struct super_block *sb = dir->i_sb; | ||
327 | struct inode *inode = dentry->d_inode; | 323 | struct inode *inode = dentry->d_inode; |
328 | struct fat_slot_info sinfo; | 324 | struct fat_slot_info sinfo; |
329 | int err; | 325 | int err; |
330 | 326 | ||
331 | lock_kernel(); | 327 | lock_super(sb); |
332 | /* | 328 | /* |
333 | * Check whether the directory is not in use, then check | 329 | * Check whether the directory is not in use, then check |
334 | * whether it is empty. | 330 | * whether it is empty. |
@@ -349,9 +345,9 @@ static int msdos_rmdir(struct inode *dir, struct dentry *dentry) | |||
349 | inode->i_ctime = CURRENT_TIME_SEC; | 345 | inode->i_ctime = CURRENT_TIME_SEC; |
350 | fat_detach(inode); | 346 | fat_detach(inode); |
351 | out: | 347 | out: |
352 | unlock_kernel(); | 348 | unlock_super(sb); |
353 | if (!err) | 349 | if (!err) |
354 | err = fat_flush_inodes(inode->i_sb, dir, inode); | 350 | err = fat_flush_inodes(sb, dir, inode); |
355 | 351 | ||
356 | return err; | 352 | return err; |
357 | } | 353 | } |
@@ -366,7 +362,7 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
366 | struct timespec ts; | 362 | struct timespec ts; |
367 | int err, is_hid, cluster; | 363 | int err, is_hid, cluster; |
368 | 364 | ||
369 | lock_kernel(); | 365 | lock_super(sb); |
370 | 366 | ||
371 | err = msdos_format_name(dentry->d_name.name, dentry->d_name.len, | 367 | err = msdos_format_name(dentry->d_name.name, dentry->d_name.len, |
372 | msdos_name, &MSDOS_SB(sb)->options); | 368 | msdos_name, &MSDOS_SB(sb)->options); |
@@ -404,14 +400,14 @@ static int msdos_mkdir(struct inode *dir, struct dentry *dentry, int mode) | |||
404 | 400 | ||
405 | d_instantiate(dentry, inode); | 401 | d_instantiate(dentry, inode); |
406 | 402 | ||
407 | unlock_kernel(); | 403 | unlock_super(sb); |
408 | fat_flush_inodes(sb, dir, inode); | 404 | fat_flush_inodes(sb, dir, inode); |
409 | return 0; | 405 | return 0; |
410 | 406 | ||
411 | out_free: | 407 | out_free: |
412 | fat_free_clusters(dir, cluster); | 408 | fat_free_clusters(dir, cluster); |
413 | out: | 409 | out: |
414 | unlock_kernel(); | 410 | unlock_super(sb); |
415 | return err; | 411 | return err; |
416 | } | 412 | } |
417 | 413 | ||
@@ -419,10 +415,11 @@ out: | |||
419 | static int msdos_unlink(struct inode *dir, struct dentry *dentry) | 415 | static int msdos_unlink(struct inode *dir, struct dentry *dentry) |
420 | { | 416 | { |
421 | struct inode *inode = dentry->d_inode; | 417 | struct inode *inode = dentry->d_inode; |
418 | struct super_block *sb= inode->i_sb; | ||
422 | struct fat_slot_info sinfo; | 419 | struct fat_slot_info sinfo; |
423 | int err; | 420 | int err; |
424 | 421 | ||
425 | lock_kernel(); | 422 | lock_super(sb); |
426 | err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo); | 423 | err = msdos_find(dir, dentry->d_name.name, dentry->d_name.len, &sinfo); |
427 | if (err) | 424 | if (err) |
428 | goto out; | 425 | goto out; |
@@ -434,9 +431,9 @@ static int msdos_unlink(struct inode *dir, struct dentry *dentry) | |||
434 | inode->i_ctime = CURRENT_TIME_SEC; | 431 | inode->i_ctime = CURRENT_TIME_SEC; |
435 | fat_detach(inode); | 432 | fat_detach(inode); |
436 | out: | 433 | out: |
437 | unlock_kernel(); | 434 | unlock_super(sb); |
438 | if (!err) | 435 | if (!err) |
439 | err = fat_flush_inodes(inode->i_sb, dir, inode); | 436 | err = fat_flush_inodes(sb, dir, inode); |
440 | 437 | ||
441 | return err; | 438 | return err; |
442 | } | 439 | } |
@@ -618,10 +615,11 @@ error_inode: | |||
618 | static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry, | 615 | static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry, |
619 | struct inode *new_dir, struct dentry *new_dentry) | 616 | struct inode *new_dir, struct dentry *new_dentry) |
620 | { | 617 | { |
618 | struct super_block *sb = old_dir->i_sb; | ||
621 | unsigned char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME]; | 619 | unsigned char old_msdos_name[MSDOS_NAME], new_msdos_name[MSDOS_NAME]; |
622 | int err, is_hid; | 620 | int err, is_hid; |
623 | 621 | ||
624 | lock_kernel(); | 622 | lock_super(sb); |
625 | 623 | ||
626 | err = msdos_format_name(old_dentry->d_name.name, | 624 | err = msdos_format_name(old_dentry->d_name.name, |
627 | old_dentry->d_name.len, old_msdos_name, | 625 | old_dentry->d_name.len, old_msdos_name, |
@@ -640,9 +638,9 @@ static int msdos_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
640 | err = do_msdos_rename(old_dir, old_msdos_name, old_dentry, | 638 | err = do_msdos_rename(old_dir, old_msdos_name, old_dentry, |
641 | new_dir, new_msdos_name, new_dentry, is_hid); | 639 | new_dir, new_msdos_name, new_dentry, is_hid); |
642 | out: | 640 | out: |
643 | unlock_kernel(); | 641 | unlock_super(sb); |
644 | if (!err) | 642 | if (!err) |
645 | err = fat_flush_inodes(old_dir->i_sb, old_dir, new_dir); | 643 | err = fat_flush_inodes(sb, old_dir, new_dir); |
646 | return err; | 644 | return err; |
647 | } | 645 | } |
648 | 646 | ||