Blame view
fs/hpfs/map.c
8.34 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
/* * 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" unsigned *hpfs_map_dnode_bitmap(struct super_block *s, struct quad_buffer_head *qbh) { return hpfs_map_4sectors(s, hpfs_sb(s)->sb_dmap, qbh, 0); } unsigned int *hpfs_map_bitmap(struct super_block *s, unsigned bmp_block, struct quad_buffer_head *qbh, char *id) { secno sec; if (hpfs_sb(s)->sb_chk) if (bmp_block * 16384 > hpfs_sb(s)->sb_fs_size) { hpfs_error(s, "hpfs_map_bitmap called with bad parameter: %08x at %s", bmp_block, id); return NULL; } |
0b69760be HPFS: Fix endiani... |
24 |
sec = le32_to_cpu(hpfs_sb(s)->sb_bmp_dir[bmp_block]); |
1da177e4c Linux-2.6.12-rc2 |
25 26 27 28 29 30 31 32 33 34 35 36 |
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; } return hpfs_map_4sectors(s, sec, qbh, 4); } /* * 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... |
37 |
unsigned char *hpfs_load_code_page(struct super_block *s, secno cps) |
1da177e4c Linux-2.6.12-rc2 |
38 39 40 41 42 43 44 45 46 47 |
{ 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... |
48 49 50 |
if (le32_to_cpu(cp->magic) != CP_DIR_MAGIC) { printk("HPFS: Code page directory magic doesn't match (magic = %08x) ", le32_to_cpu(cp->magic)); |
1da177e4c Linux-2.6.12-rc2 |
51 52 53 |
brelse(bh); return NULL; } |
0b69760be HPFS: Fix endiani... |
54 |
if (!le32_to_cpu(cp->n_code_pages)) { |
1da177e4c Linux-2.6.12-rc2 |
55 56 57 58 59 |
printk("HPFS: n_code_pages == 0 "); brelse(bh); return NULL; } |
0b69760be HPFS: Fix endiani... |
60 61 |
cpds = le32_to_cpu(cp->array[0].code_page_data); cpi = le16_to_cpu(cp->array[0].index); |
1da177e4c Linux-2.6.12-rc2 |
62 63 64 65 66 67 68 69 70 |
brelse(bh); if (cpi >= 3) { printk("HPFS: Code page index out of array "); return NULL; } if (!(cpd = hpfs_map_sector(s, cpds, &bh, 0))) return NULL; |
0b69760be HPFS: Fix endiani... |
71 |
if (le16_to_cpu(cpd->offs[cpi]) > 0x178) { |
1da177e4c Linux-2.6.12-rc2 |
72 73 74 75 76 |
printk("HPFS: Code page index out of sector "); brelse(bh); return NULL; } |
0b69760be HPFS: Fix endiani... |
77 |
ptr = (unsigned char *)cpd + le16_to_cpu(cpd->offs[cpi]) + 6; |
1da177e4c Linux-2.6.12-rc2 |
78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 |
if (!(cp_table = kmalloc(256, GFP_KERNEL))) { printk("HPFS: out of memory for code page table "); 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; } secno *hpfs_load_bitmap_directory(struct super_block *s, secno bmp) { struct buffer_head *bh; int n = (hpfs_sb(s)->sb_fs_size + 0x200000 - 1) >> 21; int i; secno *b; if (!(b = kmalloc(n * 512, GFP_KERNEL))) { printk("HPFS: can't allocate memory for bitmap directory "); return NULL; } for (i=0;i<n;i++) { secno *d = hpfs_map_sector(s, bmp+i, &bh, n - i - 1); if (!d) { kfree(b); return NULL; } memcpy((char *)b + 512 * i, d, 512); brelse(bh); } return b; } /* * 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... |
133 |
if (le32_to_cpu(fnode->magic) != FNODE_MAGIC) { |
18debbbcc [PATCH] hpfs: fix... |
134 135 |
hpfs_error(s, "bad magic on fnode %08lx", (unsigned long)ino); |
1da177e4c Linux-2.6.12-rc2 |
136 137 138 139 140 |
goto bail; } if (!fnode->dirflag) { if ((unsigned)fnode->btree.n_used_nodes + (unsigned)fnode->btree.n_free_nodes != (fnode->btree.internal ? 12 : 8)) { |
18debbbcc [PATCH] hpfs: fix... |
141 142 143 |
hpfs_error(s, "bad number of nodes in fnode %08lx", (unsigned long)ino); |
1da177e4c Linux-2.6.12-rc2 |
144 145 |
goto bail; } |
0b69760be HPFS: Fix endiani... |
146 |
if (le16_to_cpu(fnode->btree.first_free) != |
1da177e4c Linux-2.6.12-rc2 |
147 |
8 + fnode->btree.n_used_nodes * (fnode->btree.internal ? 8 : 12)) { |
18debbbcc [PATCH] hpfs: fix... |
148 149 150 |
hpfs_error(s, "bad first_free pointer in fnode %08lx", (unsigned long)ino); |
1da177e4c Linux-2.6.12-rc2 |
151 152 153 |
goto bail; } } |
0b69760be HPFS: Fix endiani... |
154 155 |
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... |
156 157 158 |
hpfs_error(s, "bad EA info in fnode %08lx: ea_offs == %04x ea_size_s == %04x", (unsigned long)ino, |
0b69760be HPFS: Fix endiani... |
159 |
le16_to_cpu(fnode->ea_offs), le16_to_cpu(fnode->ea_size_s)); |
1da177e4c Linux-2.6.12-rc2 |
160 161 162 163 164 165 |
goto bail; } ea = fnode_ea(fnode); ea_end = fnode_end_ea(fnode); while (ea != ea_end) { if (ea > ea_end) { |
18debbbcc [PATCH] hpfs: fix... |
166 167 |
hpfs_error(s, "bad EA in fnode %08lx", (unsigned long)ino); |
1da177e4c Linux-2.6.12-rc2 |
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
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... |
186 |
if (le32_to_cpu(anode->magic) != ANODE_MAGIC) { |
1da177e4c Linux-2.6.12-rc2 |
187 188 189 |
hpfs_error(s, "bad magic on anode %08x", ano); goto bail; } |
0b69760be HPFS: Fix endiani... |
190 191 192 193 |
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 |
194 195 196 197 198 |
if ((unsigned)anode->btree.n_used_nodes + (unsigned)anode->btree.n_free_nodes != (anode->btree.internal ? 60 : 40)) { hpfs_error(s, "bad number of nodes in anode %08x", ano); goto bail; } |
0b69760be HPFS: Fix endiani... |
199 |
if (le16_to_cpu(anode->btree.first_free) != |
1da177e4c Linux-2.6.12-rc2 |
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 |
8 + anode->btree.n_used_nodes * (anode->btree.internal ? 8 : 12)) { 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... |
229 |
unsigned char *d = (unsigned char *)dnode; |
1da177e4c Linux-2.6.12-rc2 |
230 |
int b = 0; |
0b69760be HPFS: Fix endiani... |
231 |
if (le32_to_cpu(dnode->magic) != DNODE_MAGIC) { |
1da177e4c Linux-2.6.12-rc2 |
232 233 234 |
hpfs_error(s, "bad magic on dnode %08x", secno); goto bail; } |
0b69760be HPFS: Fix endiani... |
235 236 |
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 |
237 238 |
/* Check dirents - bad dirents would cause infinite loops or shooting to memory */ |
0b69760be HPFS: Fix endiani... |
239 240 |
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 |
241 242 |
goto bail; } |
0b69760be HPFS: Fix endiani... |
243 |
for (p = 20; p < le32_to_cpu(dnode->first_free); p += d[p] + (d[p+1] << 8)) { |
1da177e4c Linux-2.6.12-rc2 |
244 |
struct hpfs_dirent *de = (struct hpfs_dirent *)((char *)dnode + p); |
0b69760be HPFS: Fix endiani... |
245 |
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 |
246 247 248 |
hpfs_error(s, "bad dirent size in dnode %08x, dirent %03x, last %03x", secno, p, pp); goto bail; } |
0b69760be HPFS: Fix endiani... |
249 250 |
if (((31 + de->namelen + de->down*4 + 3) & ~3) != le16_to_cpu(de->length)) { if (((31 + de->namelen + de->down*4 + 3) & ~3) < le16_to_cpu(de->length) && s->s_flags & MS_RDONLY) goto ok; |
1da177e4c Linux-2.6.12-rc2 |
251 252 253 254 255 256 257 258 259 260 261 262 |
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... |
263 |
if (p != le32_to_cpu(dnode->first_free)) { |
1da177e4c Linux-2.6.12-rc2 |
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 |
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; } if (b == 3) printk("HPFS: warning: unbalanced dnode tree, dnode %08x; see hpfs.txt 4 more info ", secno); } 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... |
289 |
dno = le32_to_cpu(fnode->u.external[0].disk_secno); |
1da177e4c Linux-2.6.12-rc2 |
290 291 292 |
brelse(bh); return dno; } |