diff options
Diffstat (limited to 'fs/romfs/storage.c')
-rw-r--r-- | fs/romfs/storage.c | 68 |
1 files changed, 50 insertions, 18 deletions
diff --git a/fs/romfs/storage.c b/fs/romfs/storage.c index 7e3e1e12a081..b3208adf8e71 100644 --- a/fs/romfs/storage.c +++ b/fs/romfs/storage.c | |||
@@ -67,26 +67,35 @@ static ssize_t romfs_mtd_strnlen(struct super_block *sb, | |||
67 | * compare a string to one in a romfs image on MTD | 67 | * compare a string to one in a romfs image on MTD |
68 | * - return 1 if matched, 0 if differ, -ve if error | 68 | * - return 1 if matched, 0 if differ, -ve if error |
69 | */ | 69 | */ |
70 | static int romfs_mtd_strncmp(struct super_block *sb, unsigned long pos, | 70 | static int romfs_mtd_strcmp(struct super_block *sb, unsigned long pos, |
71 | const char *str, size_t size) | 71 | const char *str, size_t size) |
72 | { | 72 | { |
73 | u_char buf[16]; | 73 | u_char buf[17]; |
74 | size_t len, segment; | 74 | size_t len, segment; |
75 | int ret; | 75 | int ret; |
76 | 76 | ||
77 | /* scan the string up to 16 bytes at a time */ | 77 | /* scan the string up to 16 bytes at a time, and attempt to grab the |
78 | * trailing NUL whilst we're at it */ | ||
79 | buf[0] = 0xff; | ||
80 | |||
78 | while (size > 0) { | 81 | while (size > 0) { |
79 | segment = min_t(size_t, size, 16); | 82 | segment = min_t(size_t, size + 1, 17); |
80 | ret = ROMFS_MTD_READ(sb, pos, segment, &len, buf); | 83 | ret = ROMFS_MTD_READ(sb, pos, segment, &len, buf); |
81 | if (ret < 0) | 84 | if (ret < 0) |
82 | return ret; | 85 | return ret; |
86 | len--; | ||
83 | if (memcmp(buf, str, len) != 0) | 87 | if (memcmp(buf, str, len) != 0) |
84 | return 0; | 88 | return 0; |
89 | buf[0] = buf[len]; | ||
85 | size -= len; | 90 | size -= len; |
86 | pos += len; | 91 | pos += len; |
87 | str += len; | 92 | str += len; |
88 | } | 93 | } |
89 | 94 | ||
95 | /* check the trailing NUL was */ | ||
96 | if (buf[0]) | ||
97 | return 0; | ||
98 | |||
90 | return 1; | 99 | return 1; |
91 | } | 100 | } |
92 | #endif /* CONFIG_ROMFS_ON_MTD */ | 101 | #endif /* CONFIG_ROMFS_ON_MTD */ |
@@ -111,6 +120,7 @@ static int romfs_blk_read(struct super_block *sb, unsigned long pos, | |||
111 | return -EIO; | 120 | return -EIO; |
112 | memcpy(buf, bh->b_data + offset, segment); | 121 | memcpy(buf, bh->b_data + offset, segment); |
113 | brelse(bh); | 122 | brelse(bh); |
123 | buf += segment; | ||
114 | buflen -= segment; | 124 | buflen -= segment; |
115 | pos += segment; | 125 | pos += segment; |
116 | } | 126 | } |
@@ -154,28 +164,48 @@ static ssize_t romfs_blk_strnlen(struct super_block *sb, | |||
154 | * compare a string to one in a romfs image on a block device | 164 | * compare a string to one in a romfs image on a block device |
155 | * - return 1 if matched, 0 if differ, -ve if error | 165 | * - return 1 if matched, 0 if differ, -ve if error |
156 | */ | 166 | */ |
157 | static int romfs_blk_strncmp(struct super_block *sb, unsigned long pos, | 167 | static int romfs_blk_strcmp(struct super_block *sb, unsigned long pos, |
158 | const char *str, size_t size) | 168 | const char *str, size_t size) |
159 | { | 169 | { |
160 | struct buffer_head *bh; | 170 | struct buffer_head *bh; |
161 | unsigned long offset; | 171 | unsigned long offset; |
162 | size_t segment; | 172 | size_t segment; |
163 | bool x; | 173 | bool matched, terminated = false; |
164 | 174 | ||
165 | /* scan the string up to 16 bytes at a time */ | 175 | /* compare string up to a block at a time */ |
166 | while (size > 0) { | 176 | while (size > 0) { |
167 | offset = pos & (ROMBSIZE - 1); | 177 | offset = pos & (ROMBSIZE - 1); |
168 | segment = min_t(size_t, size, ROMBSIZE - offset); | 178 | segment = min_t(size_t, size, ROMBSIZE - offset); |
169 | bh = sb_bread(sb, pos >> ROMBSBITS); | 179 | bh = sb_bread(sb, pos >> ROMBSBITS); |
170 | if (!bh) | 180 | if (!bh) |
171 | return -EIO; | 181 | return -EIO; |
172 | x = (memcmp(bh->b_data + offset, str, segment) != 0); | 182 | matched = (memcmp(bh->b_data + offset, str, segment) == 0); |
173 | brelse(bh); | 183 | |
174 | if (x) | ||
175 | return 0; | ||
176 | size -= segment; | 184 | size -= segment; |
177 | pos += segment; | 185 | pos += segment; |
178 | str += segment; | 186 | str += segment; |
187 | if (matched && size == 0 && offset + segment < ROMBSIZE) { | ||
188 | if (!bh->b_data[offset + segment]) | ||
189 | terminated = true; | ||
190 | else | ||
191 | matched = false; | ||
192 | } | ||
193 | brelse(bh); | ||
194 | if (!matched) | ||
195 | return 0; | ||
196 | } | ||
197 | |||
198 | if (!terminated) { | ||
199 | /* the terminating NUL must be on the first byte of the next | ||
200 | * block */ | ||
201 | BUG_ON((pos & (ROMBSIZE - 1)) != 0); | ||
202 | bh = sb_bread(sb, pos >> ROMBSBITS); | ||
203 | if (!bh) | ||
204 | return -EIO; | ||
205 | matched = !bh->b_data[0]; | ||
206 | brelse(bh); | ||
207 | if (!matched) | ||
208 | return 0; | ||
179 | } | 209 | } |
180 | 210 | ||
181 | return 1; | 211 | return 1; |
@@ -234,10 +264,12 @@ ssize_t romfs_dev_strnlen(struct super_block *sb, | |||
234 | 264 | ||
235 | /* | 265 | /* |
236 | * compare a string to one in romfs | 266 | * compare a string to one in romfs |
267 | * - the string to be compared to, str, may not be NUL-terminated; instead the | ||
268 | * string is of the specified size | ||
237 | * - return 1 if matched, 0 if differ, -ve if error | 269 | * - return 1 if matched, 0 if differ, -ve if error |
238 | */ | 270 | */ |
239 | int romfs_dev_strncmp(struct super_block *sb, unsigned long pos, | 271 | int romfs_dev_strcmp(struct super_block *sb, unsigned long pos, |
240 | const char *str, size_t size) | 272 | const char *str, size_t size) |
241 | { | 273 | { |
242 | size_t limit; | 274 | size_t limit; |
243 | 275 | ||
@@ -246,16 +278,16 @@ int romfs_dev_strncmp(struct super_block *sb, unsigned long pos, | |||
246 | return -EIO; | 278 | return -EIO; |
247 | if (size > ROMFS_MAXFN) | 279 | if (size > ROMFS_MAXFN) |
248 | return -ENAMETOOLONG; | 280 | return -ENAMETOOLONG; |
249 | if (size > limit - pos) | 281 | if (size + 1 > limit - pos) |
250 | return -EIO; | 282 | return -EIO; |
251 | 283 | ||
252 | #ifdef CONFIG_ROMFS_ON_MTD | 284 | #ifdef CONFIG_ROMFS_ON_MTD |
253 | if (sb->s_mtd) | 285 | if (sb->s_mtd) |
254 | return romfs_mtd_strncmp(sb, pos, str, size); | 286 | return romfs_mtd_strcmp(sb, pos, str, size); |
255 | #endif | 287 | #endif |
256 | #ifdef CONFIG_ROMFS_ON_BLOCK | 288 | #ifdef CONFIG_ROMFS_ON_BLOCK |
257 | if (sb->s_bdev) | 289 | if (sb->s_bdev) |
258 | return romfs_blk_strncmp(sb, pos, str, size); | 290 | return romfs_blk_strcmp(sb, pos, str, size); |
259 | #endif | 291 | #endif |
260 | return -EIO; | 292 | return -EIO; |
261 | } | 293 | } |