/* vi:set tabstop=2 cindent shiftwidth=2: */ /* * libvxfs - library for reading Veritas Journaled FileSystem (VxFS) * Copyright (c) 1999 Martin Hinner * * bmap.c: Maps extents to blocks * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id$ */ #include #include #include int vxbmap_ext4 (struct vxfs_inode *ino, int block) { int i; int size; int blk; __u32 *ind; if (ino->orgtype != VXFS_ORG_EXT4) { if (vxverbose) fprintf (stderr, "vxbmap_ext4: Organisation type is not EXT4 !\n"); return -1; } /* * Try direct blocks */ size = 0; for (i = 0; i < VXFS_NDADDR; i++) { if (block >= size && block < (size + ino->org.ext4.direct[i].size)) return (block - size) + ino->org.ext4.direct[i].extent; size += ino->org.ext4.direct[i].size; } /* * Try indirect blocks */ block -= size; if (block / (ino->org.ext4.indsize * (ino->org.ext4.indsize * (vxbsize / 4))) == 0) { ind = (__u32 *) vxread (ino->org.ext4.indirect, ino->org.ext4.indsize); blk = ind[(block / ino->org.ext4.indsize) % (ino->org.ext4.indsize * vxbsize)] + (block % ino->org.ext4.indsize); free (ind); return blk; } /* * Try double indirect blocks */ if (vxverbose) printf ("vxbmap_ext4: Double indirect extents are not supported yet.\n"); return -1; } int vxbmap_typed (struct vxfs_inode *ino, int block) { int i, blk; if (ino->orgtype != VXFS_ORG_TYPED) { if (vxverbose) fprintf (stderr, "vxbmap_typed: Organisation type is not TYPED !\n"); return -1; } for (i=0;i= (ino->org.typed[i].hdr & VXFS_TYPED_OFFSETMASK)) { switch(ino->org.typed[i].hdr>>VXFS_TYPED_TYPESHIFT) { case VXFS_TYPED_INDIRECT: blk = vxbmap_typedindir(ino->org.typed[i].block, ino->org.typed[i].size, block - (ino->org.typed[i].hdr & VXFS_TYPED_OFFSETMASK)); if (blk != -2) return blk; break; case VXFS_TYPED_DATA: if (block - (ino->org.typed[i].hdr & VXFS_TYPED_OFFSETMASK) < ino->org.typed[i].size ) return ino->org.typed[i].block + block - (ino->org.typed[i].hdr & VXFS_TYPED_OFFSETMASK); break; } } } if (vxverbose) fprintf(stderr,"vxbmap_typed: Block %u exceeded all typed extents!\n", block); return -1; } /* * Return: -1: Error * -2: block is not inside this indirect block * >=0: Block number */ int vxbmap_typedindir(int indirblock, int size, int block) { int i,j, blk; struct vxfs_typed *typed; /* printf("vxbmap_typeindir(indirblock=%u, size=%u, block=%u)\n", indirblock,size,block); */ typed = (struct vxfs_typed *) vxread (indirblock,size); for (i=0;i>VXFS_TYPED_TYPESHIFT); printf("offset=%lx ",typed[i].hdr & VXFS_TYPED_OFFSETMASK); printf("block=%x ",typed[i].block); printf("size=%x\n",typed[i].size); #endif if (block >= (typed[i].hdr & VXFS_TYPED_OFFSETMASK)) { switch(typed[i].hdr>>VXFS_TYPED_TYPESHIFT) { case VXFS_TYPED_INDIRECT: blk = vxbmap_typedindir(typed[i].block, typed[i].size, block - (typed[i].hdr & VXFS_TYPED_OFFSETMASK)); if (blk != -2) { free(typed); return blk; } break; case VXFS_TYPED_DATA: if (block - (typed[i].hdr & VXFS_TYPED_OFFSETMASK) < typed[i].size ) { blk = typed[i].block + block - (typed[i].hdr & VXFS_TYPED_OFFSETMASK); free(typed); return blk; } break; } } } free(typed); return -1; } int vxbmap_typeddev4 (struct vxfs_inode *ino, int block) { printf("Typed4 (dev) extens are not supported yet\n"); return -1; }