Blame view
fs/hpfs/map.c
9.79 KB
b24413180 License cleanup: ... |
1 |
// SPDX-License-Identifier: GPL-2.0 |
1da177e4c Linux-2.6.12-rc2 |
2 3 4 5 6 7 8 9 10 |
/* * linux/fs/hpfs/map.c * * Mikulas Patocka (mikulas@artax.karlin.mff.cuni.cz), 1998-1999 * * mapping structures to memory with some minimal checks */ #include "hpfs_fn.h" |
52576da35 hpfs: bitmaps are... |
11 |
__le32 *hpfs_map_dnode_bitmap(struct super_block *s, struct quad_buffer_head *qbh) |
1da177e4c Linux-2.6.12-rc2 |
12 13 14 |
{ return hpfs_map_4sectors(s, hpfs_sb(s)->sb_dmap, qbh, 0); } |
52576da35 hpfs: bitmaps are... |
15 |
__le32 *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block, |
1da177e4c Linux-2.6.12-rc2 |
16 17 18 |
struct quad_buffer_head *qbh, char *id) { secno sec; |
275f495db hpfs: implement p... |
19 |
__le32 *ret; |
3ebacb050 hpfs: better test... |
20 21 |
unsigned n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14; if (hpfs_sb(s)->sb_chk) if (bmp_block >= n_bands) { |
1da177e4c Linux-2.6.12-rc2 |
22 23 24 |
hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id); return NULL; } |
0b69760be HPFS: Fix endiani... |
25 |
sec = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block]); |
1da177e4c Linux-2.6.12-rc2 |
26 27 28 29 |
if (!sec || sec > hpfs_sb(s)->sb_fs_size-4) { hpfs_error(s, "invalid bitmap block pointer %08x -> %08x at %s", bmp_block, sec, id); return NULL; } |
275f495db hpfs: implement p... |
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
ret = hpfs_map_4sectors(s, sec, qbh, 4); if (ret) hpfs_prefetch_bitmap(s, bmp_block + 1); return ret; } void hpfs_prefetch_bitmap(struct super_block *s, unsigned bmp_block) { unsigned to_prefetch, next_prefetch; unsigned n_bands = (hpfs_sb(s)->sb_fs_size + 0x3fff) >> 14; if (unlikely(bmp_block >= n_bands)) return; to_prefetch = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block]); if (unlikely(bmp_block + 1 >= n_bands)) next_prefetch = 0; else next_prefetch = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block + 1]); hpfs_prefetch_sectors(s, to_prefetch, 4 + 4 * (to_prefetch + 4 == next_prefetch)); |
1da177e4c Linux-2.6.12-rc2 |
47 48 49 50 51 52 53 |
} /* * Load first code page into kernel memory, return pointer to 256-byte array, * first 128 bytes are uppercasing table for chars 128-255, next 128 bytes are * lowercasing table */ |
7e7742ee0 sanitize signedne... |
54 |
unsigned char *hpfs_load_code_page(struct super_block *s, secno cps) |
1da177e4c Linux-2.6.12-rc2 |
55 56 57 58 59 60 61 62 63 64 |
{ struct buffer_head *bh; secno cpds; unsigned cpi; unsigned char *ptr; unsigned char *cp_table; int i; struct code_page_data *cpd; struct code_page_directory *cp = hpfs_map_sector(s, cps, &bh, 0); if (!cp) return NULL; |
0b69760be HPFS: Fix endiani... |
65 |
if (le32_to_cpu(cp->magic) != CP_DIR_MAGIC) { |
a19189e55 fs/hpfs: increase... |
66 67 |
pr_err("Code page directory magic doesn't match (magic = %08x) ", |
b7cb1ce22 fs/hpfs: convert ... |
68 |
le32_to_cpu(cp->magic)); |
1da177e4c Linux-2.6.12-rc2 |
69 70 71 |
brelse(bh); return NULL; } |
0b69760be HPFS: Fix endiani... |
72 |
if (!le32_to_cpu(cp->n_code_pages)) { |
a19189e55 fs/hpfs: increase... |
73 74 |
pr_err("n_code_pages == 0 "); |
1da177e4c Linux-2.6.12-rc2 |
75 76 77 |
brelse(bh); return NULL; } |
0b69760be HPFS: Fix endiani... |
78 79 |
cpds = le32_to_cpu(cp->array[0].code_page_data); cpi = le16_to_cpu(cp->array[0].index); |
1da177e4c Linux-2.6.12-rc2 |
80 81 82 |
brelse(bh); if (cpi >= 3) { |
a19189e55 fs/hpfs: increase... |
83 84 |
pr_err("Code page index out of array "); |
1da177e4c Linux-2.6.12-rc2 |
85 86 87 88 |
return NULL; } if (!(cpd = hpfs_map_sector(s, cpds, &bh, 0))) return NULL; |
0b69760be HPFS: Fix endiani... |
89 |
if (le16_to_cpu(cpd->offs[cpi]) > 0x178) { |
a19189e55 fs/hpfs: increase... |
90 91 |
pr_err("Code page index out of sector "); |
1da177e4c Linux-2.6.12-rc2 |
92 93 94 |
brelse(bh); return NULL; } |
0b69760be HPFS: Fix endiani... |
95 |
ptr = (unsigned char *)cpd + le16_to_cpu(cpd->offs[cpi]) + 6; |
1da177e4c Linux-2.6.12-rc2 |
96 |
if (!(cp_table = kmalloc(256, GFP_KERNEL))) { |
a19189e55 fs/hpfs: increase... |
97 98 |
pr_err("out of memory for code page table "); |
1da177e4c Linux-2.6.12-rc2 |
99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
brelse(bh); return NULL; } memcpy(cp_table, ptr, 128); brelse(bh); /* Try to build lowercasing table from uppercasing one */ for (i=128; i<256; i++) cp_table[i]=i; for (i=128; i<256; i++) if (cp_table[i-128]!=i && cp_table[i-128]>=128) cp_table[cp_table[i-128]] = i; return cp_table; } |
28fe3c196 hpfs: assorted en... |
113 |
__le32 *hpfs_load_bitmap_directory(struct super_block *s, secno bmp) |
1da177e4c Linux-2.6.12-rc2 |
114 115 116 117 |
{ struct buffer_head *bh; int n = (hpfs_sb(s)->sb_fs_size + 0x200000 - 1) >> 21; int i; |
28fe3c196 hpfs: assorted en... |
118 |
__le32 *b; |
6da2ec560 treewide: kmalloc... |
119 |
if (!(b = kmalloc_array(n, 512, GFP_KERNEL))) { |
a19189e55 fs/hpfs: increase... |
120 121 |
pr_err("can't allocate memory for bitmap directory "); |
1da177e4c Linux-2.6.12-rc2 |
122 123 124 |
return NULL; } for (i=0;i<n;i++) { |
28fe3c196 hpfs: assorted en... |
125 |
__le32 *d = hpfs_map_sector(s, bmp+i, &bh, n - i - 1); |
1da177e4c Linux-2.6.12-rc2 |
126 127 128 129 130 131 132 133 134 |
if (!d) { kfree(b); return NULL; } memcpy((char *)b + 512 * i, d, 512); brelse(bh); } return b; } |
a64eefaac hpfs: support hot... |
135 136 137 |
void hpfs_load_hotfix_map(struct super_block *s, struct hpfs_spare_block *spareblock) { struct quad_buffer_head qbh; |
4e728cf8f hpfs: missing end... |
138 |
__le32 *directory; |
a64eefaac hpfs: support hot... |
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 |
u32 n_hotfixes, n_used_hotfixes; unsigned i; n_hotfixes = le32_to_cpu(spareblock->n_spares); n_used_hotfixes = le32_to_cpu(spareblock->n_spares_used); if (n_hotfixes > 256 || n_used_hotfixes > n_hotfixes) { hpfs_error(s, "invalid number of hotfixes: %u, used: %u", n_hotfixes, n_used_hotfixes); return; } if (!(directory = hpfs_map_4sectors(s, le32_to_cpu(spareblock->hotfix_map), &qbh, 0))) { hpfs_error(s, "can't load hotfix map"); return; } for (i = 0; i < n_used_hotfixes; i++) { hpfs_sb(s)->hotfix_from[i] = le32_to_cpu(directory[i]); hpfs_sb(s)->hotfix_to[i] = le32_to_cpu(directory[n_hotfixes + i]); } hpfs_sb(s)->n_hotfixes = n_used_hotfixes; hpfs_brelse4(&qbh); } |
1da177e4c Linux-2.6.12-rc2 |
160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
/* * Load fnode to memory */ struct fnode *hpfs_map_fnode(struct super_block *s, ino_t ino, struct buffer_head **bhp) { struct fnode *fnode; if (hpfs_sb(s)->sb_chk) if (hpfs_chk_sectors(s, ino, 1, "fnode")) { return NULL; } if ((fnode = hpfs_map_sector(s, ino, bhp, FNODE_RD_AHEAD))) { if (hpfs_sb(s)->sb_chk) { struct extended_attribute *ea; struct extended_attribute *ea_end; |
0b69760be HPFS: Fix endiani... |
174 |
if (le32_to_cpu(fnode->magic) != FNODE_MAGIC) { |
18debbbcc [PATCH] hpfs: fix... |
175 176 |
hpfs_error(s, "bad magic on fnode %08lx", (unsigned long)ino); |
1da177e4c Linux-2.6.12-rc2 |
177 178 |
goto bail; } |
c4c995430 hpfs: get rid of ... |
179 |
if (!fnode_is_dir(fnode)) { |
1da177e4c Linux-2.6.12-rc2 |
180 |
if ((unsigned)fnode->btree.n_used_nodes + (unsigned)fnode->btree.n_free_nodes != |
ddc19e6e0 hpfs: annotate bt... |
181 |
(bp_internal(&fnode->btree) ? 12 : 8)) { |
18debbbcc [PATCH] hpfs: fix... |
182 183 184 |
hpfs_error(s, "bad number of nodes in fnode %08lx", (unsigned long)ino); |
1da177e4c Linux-2.6.12-rc2 |
185 186 |
goto bail; } |
0b69760be HPFS: Fix endiani... |
187 |
if (le16_to_cpu(fnode->btree.first_free) != |
ddc19e6e0 hpfs: annotate bt... |
188 |
8 + fnode->btree.n_used_nodes * (bp_internal(&fnode->btree) ? 8 : 12)) { |
18debbbcc [PATCH] hpfs: fix... |
189 190 191 |
hpfs_error(s, "bad first_free pointer in fnode %08lx", (unsigned long)ino); |
1da177e4c Linux-2.6.12-rc2 |
192 193 194 |
goto bail; } } |
0b69760be HPFS: Fix endiani... |
195 196 |
if (le16_to_cpu(fnode->ea_size_s) && (le16_to_cpu(fnode->ea_offs) < 0xc4 || le16_to_cpu(fnode->ea_offs) + le16_to_cpu(fnode->acl_size_s) + le16_to_cpu(fnode->ea_size_s) > 0x200)) { |
18debbbcc [PATCH] hpfs: fix... |
197 198 199 |
hpfs_error(s, "bad EA info in fnode %08lx: ea_offs == %04x ea_size_s == %04x", (unsigned long)ino, |
0b69760be HPFS: Fix endiani... |
200 |
le16_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s)); |
1da177e4c Linux-2.6.12-rc2 |
201 202 203 204 205 206 |
goto bail; } ea = fnode_ea(fnode); ea_end = fnode_end_ea(fnode); while (ea != ea_end) { if (ea > ea_end) { |
18debbbcc [PATCH] hpfs: fix... |
207 208 |
hpfs_error(s, "bad EA in fnode %08lx", (unsigned long)ino); |
1da177e4c Linux-2.6.12-rc2 |
209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 |
goto bail; } ea = next_ea(ea); } } } return fnode; bail: brelse(*bhp); return NULL; } struct anode *hpfs_map_anode(struct super_block *s, anode_secno ano, struct buffer_head **bhp) { struct anode *anode; if (hpfs_sb(s)->sb_chk) if (hpfs_chk_sectors(s, ano, 1, "anode")) return NULL; if ((anode = hpfs_map_sector(s, ano, bhp, ANODE_RD_AHEAD))) if (hpfs_sb(s)->sb_chk) { |
0b69760be HPFS: Fix endiani... |
227 |
if (le32_to_cpu(anode->magic) != ANODE_MAGIC) { |
1da177e4c Linux-2.6.12-rc2 |
228 229 230 |
hpfs_error(s, "bad magic on anode %08x", ano); goto bail; } |
0b69760be HPFS: Fix endiani... |
231 232 233 234 |
if (le32_to_cpu(anode->self) != ano) { hpfs_error(s, "self pointer invalid on anode %08x", ano); goto bail; } |
1da177e4c Linux-2.6.12-rc2 |
235 |
if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes != |
ddc19e6e0 hpfs: annotate bt... |
236 |
(bp_internal(&anode->btree) ? 60 : 40)) { |
1da177e4c Linux-2.6.12-rc2 |
237 238 239 |
hpfs_error(s, "bad number of nodes in anode %08x", ano); goto bail; } |
0b69760be HPFS: Fix endiani... |
240 |
if (le16_to_cpu(anode->btree.first_free) != |
ddc19e6e0 hpfs: annotate bt... |
241 |
8 + anode->btree.n_used_nodes * (bp_internal(&anode->btree) ? 8 : 12)) { |
1da177e4c Linux-2.6.12-rc2 |
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
hpfs_error(s, "bad first_free pointer in anode %08x", ano); goto bail; } } return anode; bail: brelse(*bhp); return NULL; } /* * Load dnode to memory and do some checks */ struct dnode *hpfs_map_dnode(struct super_block *s, unsigned secno, struct quad_buffer_head *qbh) { struct dnode *dnode; if (hpfs_sb(s)->sb_chk) { if (hpfs_chk_sectors(s, secno, 4, "dnode")) return NULL; if (secno & 3) { hpfs_error(s, "dnode %08x not byte-aligned", secno); return NULL; } } if ((dnode = hpfs_map_4sectors(s, secno, qbh, DNODE_RD_AHEAD))) if (hpfs_sb(s)->sb_chk) { unsigned p, pp = 0; |
7e7742ee0 sanitize signedne... |
270 |
unsigned char *d = (unsigned char *)dnode; |
1da177e4c Linux-2.6.12-rc2 |
271 |
int b = 0; |
0b69760be HPFS: Fix endiani... |
272 |
if (le32_to_cpu(dnode->magic) != DNODE_MAGIC) { |
1da177e4c Linux-2.6.12-rc2 |
273 274 275 |
hpfs_error(s, "bad magic on dnode %08x", secno); goto bail; } |
0b69760be HPFS: Fix endiani... |
276 277 |
if (le32_to_cpu(dnode->self) != secno) hpfs_error(s, "bad self pointer on dnode %08x self = %08x", secno, le32_to_cpu(dnode->self)); |
1da177e4c Linux-2.6.12-rc2 |
278 279 |
/* Check dirents - bad dirents would cause infinite loops or shooting to memory */ |
0b69760be HPFS: Fix endiani... |
280 281 |
if (le32_to_cpu(dnode->first_free) > 2048) { hpfs_error(s, "dnode %08x has first_free == %08x", secno, le32_to_cpu(dnode->first_free)); |
1da177e4c Linux-2.6.12-rc2 |
282 283 |
goto bail; } |
0b69760be HPFS: Fix endiani... |
284 |
for (p = 20; p < le32_to_cpu(dnode->first_free); p += d[p] + (d[p+1] << 8)) { |
1da177e4c Linux-2.6.12-rc2 |
285 |
struct hpfs_dirent *de = (struct hpfs_dirent *)((char *)dnode + p); |
0b69760be HPFS: Fix endiani... |
286 |
if (le16_to_cpu(de->length) > 292 || (le16_to_cpu(de->length) < 32) || (le16_to_cpu(de->length) & 3) || p + le16_to_cpu(de->length) > 2048) { |
1da177e4c Linux-2.6.12-rc2 |
287 288 289 |
hpfs_error(s, "bad dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp); goto bail; } |
0b69760be HPFS: Fix endiani... |
290 |
if (((31 + de->namelen + de->down*4 + 3) & ~3) != le16_to_cpu(de->length)) { |
1751e8a6c Rename superblock... |
291 |
if (((31 + de->namelen + de->down*4 + 3) & ~3) < le16_to_cpu(de->length) && s->s_flags & SB_RDONLY) goto ok; |
1da177e4c Linux-2.6.12-rc2 |
292 293 294 295 296 297 298 299 300 301 302 303 |
hpfs_error(s, "namelen does not match dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp); goto bail; } ok: if (hpfs_sb(s)->sb_chk >= 2) b |= 1 << de->down; if (de->down) if (de_down_pointer(de) < 0x10) { hpfs_error(s, "bad down pointer in dnode %08x, dirent %03x, last %03x", secno, p, pp); goto bail; } pp = p; } |
0b69760be HPFS: Fix endiani... |
304 |
if (p != le32_to_cpu(dnode->first_free)) { |
1da177e4c Linux-2.6.12-rc2 |
305 306 307 308 309 310 311 |
hpfs_error(s, "size on last dirent does not match first_free; dnode %08x", secno); goto bail; } if (d[pp + 30] != 1 || d[pp + 31] != 255) { hpfs_error(s, "dnode %08x does not end with \\377 entry", secno); goto bail; } |
b7cb1ce22 fs/hpfs: convert ... |
312 |
if (b == 3) |
a19189e55 fs/hpfs: increase... |
313 314 |
pr_err("unbalanced dnode tree, dnode %08x; see hpfs.txt 4 more info ", |
b7cb1ce22 fs/hpfs: convert ... |
315 |
secno); |
1da177e4c Linux-2.6.12-rc2 |
316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 |
} return dnode; bail: hpfs_brelse4(qbh); return NULL; } dnode_secno hpfs_fnode_dno(struct super_block *s, ino_t ino) { struct buffer_head *bh; struct fnode *fnode; dnode_secno dno; fnode = hpfs_map_fnode(s, ino, &bh); if (!fnode) return 0; |
0b69760be HPFS: Fix endiani... |
332 |
dno = le32_to_cpu(fnode->u.external[0].disk_secno); |
1da177e4c Linux-2.6.12-rc2 |
333 334 335 |
brelse(bh); return dno; } |