diff options
-rw-r--r-- | Documentation/filesystems/affs.txt | 9 | ||||
-rw-r--r-- | fs/affs/affs.h | 20 | ||||
-rw-r--r-- | fs/affs/amigaffs.c | 23 | ||||
-rw-r--r-- | fs/affs/namei.c | 32 | ||||
-rw-r--r-- | fs/affs/super.c | 6 |
5 files changed, 57 insertions, 33 deletions
diff --git a/Documentation/filesystems/affs.txt b/Documentation/filesystems/affs.txt index 81ac488e3758..71b63c2b9841 100644 --- a/Documentation/filesystems/affs.txt +++ b/Documentation/filesystems/affs.txt | |||
@@ -49,6 +49,10 @@ mode=mode Sets the mode flags to the given (octal) value, regardless | |||
49 | This is useful since most of the plain AmigaOS files | 49 | This is useful since most of the plain AmigaOS files |
50 | will map to 600. | 50 | will map to 600. |
51 | 51 | ||
52 | nofilenametruncate | ||
53 | The file system will return an error when filename exceeds | ||
54 | standard maximum filename length (30 characters). | ||
55 | |||
52 | reserved=num Sets the number of reserved blocks at the start of the | 56 | reserved=num Sets the number of reserved blocks at the start of the |
53 | partition to num. You should never need this option. | 57 | partition to num. You should never need this option. |
54 | Default is 2. | 58 | Default is 2. |
@@ -181,9 +185,8 @@ tested, though several hundred MB have been read and written using | |||
181 | this fs. For a most up-to-date list of bugs please consult | 185 | this fs. For a most up-to-date list of bugs please consult |
182 | fs/affs/Changes. | 186 | fs/affs/Changes. |
183 | 187 | ||
184 | Filenames are truncated to 30 characters without warning (this | 188 | By default, filenames are truncated to 30 characters without warning. |
185 | can be changed by setting the compile-time option AFFS_NO_TRUNCATE | 189 | 'nofilenametruncate' mount option can change that behavior. |
186 | in include/linux/amigaffs.h). | ||
187 | 190 | ||
188 | Case is ignored by the affs in filename matching, but Linux shells | 191 | Case is ignored by the affs in filename matching, but Linux shells |
189 | do care about the case. Example (with /wb being an affs mounted fs): | 192 | do care about the case. Example (with /wb being an affs mounted fs): |
diff --git a/fs/affs/affs.h b/fs/affs/affs.h index 3952121f2f28..25b23b1e7f22 100644 --- a/fs/affs/affs.h +++ b/fs/affs/affs.h | |||
@@ -5,14 +5,6 @@ | |||
5 | #include <linux/mutex.h> | 5 | #include <linux/mutex.h> |
6 | #include <linux/workqueue.h> | 6 | #include <linux/workqueue.h> |
7 | 7 | ||
8 | /* AmigaOS allows file names with up to 30 characters length. | ||
9 | * Names longer than that will be silently truncated. If you | ||
10 | * want to disallow this, comment out the following #define. | ||
11 | * Creating filesystem objects with longer names will then | ||
12 | * result in an error (ENAMETOOLONG). | ||
13 | */ | ||
14 | /*#define AFFS_NO_TRUNCATE */ | ||
15 | |||
16 | /* Ugly macros make the code more pretty. */ | 8 | /* Ugly macros make the code more pretty. */ |
17 | 9 | ||
18 | #define GET_END_PTR(st,p,sz) ((st *)((char *)(p)+((sz)-sizeof(st)))) | 10 | #define GET_END_PTR(st,p,sz) ((st *)((char *)(p)+((sz)-sizeof(st)))) |
@@ -28,7 +20,6 @@ | |||
28 | 20 | ||
29 | #define AFFS_CACHE_SIZE PAGE_SIZE | 21 | #define AFFS_CACHE_SIZE PAGE_SIZE |
30 | 22 | ||
31 | #define AFFS_MAX_PREALLOC 32 | ||
32 | #define AFFS_LC_SIZE (AFFS_CACHE_SIZE/sizeof(u32)/2) | 23 | #define AFFS_LC_SIZE (AFFS_CACHE_SIZE/sizeof(u32)/2) |
33 | #define AFFS_AC_SIZE (AFFS_CACHE_SIZE/sizeof(struct affs_ext_key)/2) | 24 | #define AFFS_AC_SIZE (AFFS_CACHE_SIZE/sizeof(struct affs_ext_key)/2) |
34 | #define AFFS_AC_MASK (AFFS_AC_SIZE-1) | 25 | #define AFFS_AC_MASK (AFFS_AC_SIZE-1) |
@@ -118,6 +109,7 @@ struct affs_sb_info { | |||
118 | #define SF_OFS 0x0200 /* Old filesystem */ | 109 | #define SF_OFS 0x0200 /* Old filesystem */ |
119 | #define SF_PREFIX 0x0400 /* Buffer for prefix is allocated */ | 110 | #define SF_PREFIX 0x0400 /* Buffer for prefix is allocated */ |
120 | #define SF_VERBOSE 0x0800 /* Talk about fs when mounting */ | 111 | #define SF_VERBOSE 0x0800 /* Talk about fs when mounting */ |
112 | #define SF_NO_TRUNCATE 0x1000 /* Don't truncate filenames */ | ||
121 | 113 | ||
122 | /* short cut to get to the affs specific sb data */ | 114 | /* short cut to get to the affs specific sb data */ |
123 | static inline struct affs_sb_info *AFFS_SB(struct super_block *sb) | 115 | static inline struct affs_sb_info *AFFS_SB(struct super_block *sb) |
@@ -137,9 +129,13 @@ extern void affs_fix_checksum(struct super_block *sb, struct buffer_head *bh); | |||
137 | extern void secs_to_datestamp(time_t secs, struct affs_date *ds); | 129 | extern void secs_to_datestamp(time_t secs, struct affs_date *ds); |
138 | extern umode_t prot_to_mode(u32 prot); | 130 | extern umode_t prot_to_mode(u32 prot); |
139 | extern void mode_to_prot(struct inode *inode); | 131 | extern void mode_to_prot(struct inode *inode); |
140 | extern void affs_error(struct super_block *sb, const char *function, const char *fmt, ...); | 132 | extern void affs_error(struct super_block *sb, const char *function, |
141 | extern void affs_warning(struct super_block *sb, const char *function, const char *fmt, ...); | 133 | const char *fmt, ...); |
142 | extern int affs_check_name(const unsigned char *name, int len); | 134 | extern void affs_warning(struct super_block *sb, const char *function, |
135 | const char *fmt, ...); | ||
136 | extern bool affs_nofilenametruncate(const struct dentry *dentry); | ||
137 | extern int affs_check_name(const unsigned char *name, int len, | ||
138 | bool notruncate); | ||
143 | extern int affs_copy_name(unsigned char *bstr, struct dentry *dentry); | 139 | extern int affs_copy_name(unsigned char *bstr, struct dentry *dentry); |
144 | 140 | ||
145 | /* bitmap. c */ | 141 | /* bitmap. c */ |
diff --git a/fs/affs/amigaffs.c b/fs/affs/amigaffs.c index d9a43674cb94..533a322c41c0 100644 --- a/fs/affs/amigaffs.c +++ b/fs/affs/amigaffs.c | |||
@@ -471,20 +471,27 @@ affs_warning(struct super_block *sb, const char *function, const char *fmt, ...) | |||
471 | function,ErrorBuffer); | 471 | function,ErrorBuffer); |
472 | } | 472 | } |
473 | 473 | ||
474 | bool | ||
475 | affs_nofilenametruncate(const struct dentry *dentry) | ||
476 | { | ||
477 | struct inode *inode = dentry->d_inode; | ||
478 | return AFFS_SB(inode->i_sb)->s_flags & SF_NO_TRUNCATE; | ||
479 | |||
480 | } | ||
481 | |||
474 | /* Check if the name is valid for a affs object. */ | 482 | /* Check if the name is valid for a affs object. */ |
475 | 483 | ||
476 | int | 484 | int |
477 | affs_check_name(const unsigned char *name, int len) | 485 | affs_check_name(const unsigned char *name, int len, bool notruncate) |
478 | { | 486 | { |
479 | int i; | 487 | int i; |
480 | 488 | ||
481 | if (len > 30) | 489 | if (len > 30) { |
482 | #ifdef AFFS_NO_TRUNCATE | 490 | if (notruncate) |
483 | return -ENAMETOOLONG; | 491 | return -ENAMETOOLONG; |
484 | #else | 492 | else |
485 | len = 30; | 493 | len = 30; |
486 | #endif | 494 | } |
487 | |||
488 | for (i = 0; i < len; i++) { | 495 | for (i = 0; i < len; i++) { |
489 | if (name[i] < ' ' || name[i] == ':' | 496 | if (name[i] < ' ' || name[i] == ':' |
490 | || (name[i] > 0x7e && name[i] < 0xa0)) | 497 | || (name[i] > 0x7e && name[i] < 0xa0)) |
diff --git a/fs/affs/namei.c b/fs/affs/namei.c index c36cbb4537a2..6dae1ccd176d 100644 --- a/fs/affs/namei.c +++ b/fs/affs/namei.c | |||
@@ -60,13 +60,13 @@ affs_get_toupper(struct super_block *sb) | |||
60 | * Note: the dentry argument is the parent dentry. | 60 | * Note: the dentry argument is the parent dentry. |
61 | */ | 61 | */ |
62 | static inline int | 62 | static inline int |
63 | __affs_hash_dentry(struct qstr *qstr, toupper_t toupper) | 63 | __affs_hash_dentry(struct qstr *qstr, toupper_t toupper, bool notruncate) |
64 | { | 64 | { |
65 | const u8 *name = qstr->name; | 65 | const u8 *name = qstr->name; |
66 | unsigned long hash; | 66 | unsigned long hash; |
67 | int i; | 67 | int i; |
68 | 68 | ||
69 | i = affs_check_name(qstr->name, qstr->len); | 69 | i = affs_check_name(qstr->name, qstr->len, notruncate); |
70 | if (i) | 70 | if (i) |
71 | return i; | 71 | return i; |
72 | 72 | ||
@@ -82,16 +82,22 @@ __affs_hash_dentry(struct qstr *qstr, toupper_t toupper) | |||
82 | static int | 82 | static int |
83 | affs_hash_dentry(const struct dentry *dentry, struct qstr *qstr) | 83 | affs_hash_dentry(const struct dentry *dentry, struct qstr *qstr) |
84 | { | 84 | { |
85 | return __affs_hash_dentry(qstr, affs_toupper); | 85 | return __affs_hash_dentry(qstr, affs_toupper, |
86 | affs_nofilenametruncate(dentry)); | ||
87 | |||
86 | } | 88 | } |
89 | |||
87 | static int | 90 | static int |
88 | affs_intl_hash_dentry(const struct dentry *dentry, struct qstr *qstr) | 91 | affs_intl_hash_dentry(const struct dentry *dentry, struct qstr *qstr) |
89 | { | 92 | { |
90 | return __affs_hash_dentry(qstr, affs_intl_toupper); | 93 | return __affs_hash_dentry(qstr, affs_intl_toupper, |
94 | affs_nofilenametruncate(dentry)); | ||
95 | |||
91 | } | 96 | } |
92 | 97 | ||
93 | static inline int __affs_compare_dentry(unsigned int len, | 98 | static inline int __affs_compare_dentry(unsigned int len, |
94 | const char *str, const struct qstr *name, toupper_t toupper) | 99 | const char *str, const struct qstr *name, toupper_t toupper, |
100 | bool notruncate) | ||
95 | { | 101 | { |
96 | const u8 *aname = str; | 102 | const u8 *aname = str; |
97 | const u8 *bname = name->name; | 103 | const u8 *bname = name->name; |
@@ -101,7 +107,7 @@ static inline int __affs_compare_dentry(unsigned int len, | |||
101 | * must be valid. 'name' must be validated first. | 107 | * must be valid. 'name' must be validated first. |
102 | */ | 108 | */ |
103 | 109 | ||
104 | if (affs_check_name(name->name, name->len)) | 110 | if (affs_check_name(name->name, name->len, notruncate)) |
105 | return 1; | 111 | return 1; |
106 | 112 | ||
107 | /* | 113 | /* |
@@ -126,13 +132,18 @@ static int | |||
126 | affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry, | 132 | affs_compare_dentry(const struct dentry *parent, const struct dentry *dentry, |
127 | unsigned int len, const char *str, const struct qstr *name) | 133 | unsigned int len, const char *str, const struct qstr *name) |
128 | { | 134 | { |
129 | return __affs_compare_dentry(len, str, name, affs_toupper); | 135 | |
136 | return __affs_compare_dentry(len, str, name, affs_toupper, | ||
137 | affs_nofilenametruncate(parent)); | ||
130 | } | 138 | } |
139 | |||
131 | static int | 140 | static int |
132 | affs_intl_compare_dentry(const struct dentry *parent, const struct dentry *dentry, | 141 | affs_intl_compare_dentry(const struct dentry *parent, const struct dentry *dentry, |
133 | unsigned int len, const char *str, const struct qstr *name) | 142 | unsigned int len, const char *str, const struct qstr *name) |
134 | { | 143 | { |
135 | return __affs_compare_dentry(len, str, name, affs_intl_toupper); | 144 | return __affs_compare_dentry(len, str, name, affs_intl_toupper, |
145 | affs_nofilenametruncate(parent)); | ||
146 | |||
136 | } | 147 | } |
137 | 148 | ||
138 | /* | 149 | /* |
@@ -411,7 +422,10 @@ affs_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
411 | (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name, | 422 | (u32)old_dir->i_ino, (int)old_dentry->d_name.len, old_dentry->d_name.name, |
412 | (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name); | 423 | (u32)new_dir->i_ino, (int)new_dentry->d_name.len, new_dentry->d_name.name); |
413 | 424 | ||
414 | retval = affs_check_name(new_dentry->d_name.name,new_dentry->d_name.len); | 425 | retval = affs_check_name(new_dentry->d_name.name, |
426 | new_dentry->d_name.len, | ||
427 | affs_nofilenametruncate(old_dentry)); | ||
428 | |||
415 | if (retval) | 429 | if (retval) |
416 | return retval; | 430 | return retval; |
417 | 431 | ||
diff --git a/fs/affs/super.c b/fs/affs/super.c index 4fad16adbe7b..6d589f28bf9b 100644 --- a/fs/affs/super.c +++ b/fs/affs/super.c | |||
@@ -163,7 +163,7 @@ static const struct super_operations affs_sops = { | |||
163 | }; | 163 | }; |
164 | 164 | ||
165 | enum { | 165 | enum { |
166 | Opt_bs, Opt_mode, Opt_mufs, Opt_prefix, Opt_protect, | 166 | Opt_bs, Opt_mode, Opt_mufs, Opt_notruncate, Opt_prefix, Opt_protect, |
167 | Opt_reserved, Opt_root, Opt_setgid, Opt_setuid, | 167 | Opt_reserved, Opt_root, Opt_setgid, Opt_setuid, |
168 | Opt_verbose, Opt_volume, Opt_ignore, Opt_err, | 168 | Opt_verbose, Opt_volume, Opt_ignore, Opt_err, |
169 | }; | 169 | }; |
@@ -172,6 +172,7 @@ static const match_table_t tokens = { | |||
172 | {Opt_bs, "bs=%u"}, | 172 | {Opt_bs, "bs=%u"}, |
173 | {Opt_mode, "mode=%o"}, | 173 | {Opt_mode, "mode=%o"}, |
174 | {Opt_mufs, "mufs"}, | 174 | {Opt_mufs, "mufs"}, |
175 | {Opt_notruncate, "nofilenametruncate"}, | ||
175 | {Opt_prefix, "prefix=%s"}, | 176 | {Opt_prefix, "prefix=%s"}, |
176 | {Opt_protect, "protect"}, | 177 | {Opt_protect, "protect"}, |
177 | {Opt_reserved, "reserved=%u"}, | 178 | {Opt_reserved, "reserved=%u"}, |
@@ -233,6 +234,9 @@ parse_options(char *options, kuid_t *uid, kgid_t *gid, int *mode, int *reserved, | |||
233 | case Opt_mufs: | 234 | case Opt_mufs: |
234 | *mount_opts |= SF_MUFS; | 235 | *mount_opts |= SF_MUFS; |
235 | break; | 236 | break; |
237 | case Opt_notruncate: | ||
238 | *mount_opts |= SF_NO_TRUNCATE; | ||
239 | break; | ||
236 | case Opt_prefix: | 240 | case Opt_prefix: |
237 | *prefix = match_strdup(&args[0]); | 241 | *prefix = match_strdup(&args[0]); |
238 | if (!*prefix) | 242 | if (!*prefix) |