/* * Copyright (c) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2009, 2013 * The President and Fellows of Harvard College. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE UNIVERSITY AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include #include #include #include #include #include "compat.h" #include #include "disk.h" #include "utils.h" #include "ibmacros.h" #include "sfs.h" #include "main.h" //////////////////////////////////////////////////////////// // global setup void sfs_setup(void) { assert(sizeof(struct sfs_superblock)==SFS_BLOCKSIZE); assert(sizeof(struct sfs_dinode)==SFS_BLOCKSIZE); assert(SFS_BLOCKSIZE % sizeof(struct sfs_direntry) == 0); } //////////////////////////////////////////////////////////// // byte-swap functions static void swapsb(struct sfs_superblock *sb) { sb->sb_magic = SWAP32(sb->sb_magic); sb->sb_nblocks = SWAP32(sb->sb_nblocks); } static void swapbits(uint8_t *bits) { /* nothing to do */ (void)bits; } static void swapinode(struct sfs_dinode *sfi) { int i; sfi->sfi_size = SWAP32(sfi->sfi_size); sfi->sfi_type = SWAP16(sfi->sfi_type); sfi->sfi_linkcount = SWAP16(sfi->sfi_linkcount); for (i=0; isfd_ino = SWAP32(sfd->sfd_ino); } static void swapindir(uint32_t *entries) { int i; for (i=0; i 1) { uint32_t index = offset / entrysize; offset %= entrysize; return ibmap(entries[index], offset, entrysize/SFS_DBPERIDB); } else { assert(offset < SFS_DBPERIDB); return entries[offset]; } } /* * bmap() for SFS. * * Given an inode and a file block, returns a disk block. */ static uint32_t bmap(const struct sfs_dinode *sfi, uint32_t fileblock) { uint32_t iblock, offset; if (fileblock < INOMAX_D) { return GET_D(sfi, fileblock); } else if (fileblock < INOMAX_I) { iblock = (fileblock - INOMAX_D) / RANGE_I; offset = (fileblock - INOMAX_D) % RANGE_I; return ibmap(GET_I(sfi, iblock), offset, RANGE_D); } else if (fileblock < INOMAX_II) { iblock = (fileblock - INOMAX_I) / RANGE_II; offset = (fileblock - INOMAX_I) % RANGE_II; return ibmap(GET_II(sfi, iblock), offset, RANGE_I); } else if (fileblock < INOMAX_III) { iblock = (fileblock - INOMAX_II) / RANGE_III; offset = (fileblock - INOMAX_II) % RANGE_III; return ibmap(GET_III(sfi, iblock), offset, RANGE_II); } return 0; } //////////////////////////////////////////////////////////// // superblock, free block bitmap, and inode I/O /* * superblock - blocknum is a disk block number. */ void sfs_readsb(uint32_t blocknum, struct sfs_superblock *sb) { diskread(sb, blocknum); swapsb(sb); } void sfs_writesb(uint32_t blocknum, struct sfs_superblock *sb) { swapsb(sb); diskwrite(sb, blocknum); swapsb(sb); } /* * freemap blocks - whichblock is a block number within the free block * bitmap. */ void sfs_readfreemapblock(uint32_t whichblock, uint8_t *bits) { diskread(bits, SFS_FREEMAP_START + whichblock); swapbits(bits); } void sfs_writefreemapblock(uint32_t whichblock, uint8_t *bits) { swapbits(bits); diskwrite(bits, SFS_FREEMAP_START + whichblock); swapbits(bits); } /* * inodes - ino is an inode number, which is a disk block number. */ void sfs_readinode(uint32_t ino, struct sfs_dinode *sfi) { diskread(sfi, ino); swapinode(sfi); } void sfs_writeinode(uint32_t ino, struct sfs_dinode *sfi) { swapinode(sfi); diskwrite(sfi, ino); swapinode(sfi); } /* * indirect blocks - blocknum is a disk block number. */ void sfs_readindirect(uint32_t blocknum, uint32_t *entries) { diskread(entries, blocknum); swapindir(entries); } void sfs_writeindirect(uint32_t blocknum, uint32_t *entries) { swapindir(entries); diskwrite(entries, blocknum); swapindir(entries); } //////////////////////////////////////////////////////////// // directory I/O /* * Read the directory block at DISKBLOCK into D. */ static void sfs_readdirblock(struct sfs_direntry *d, uint32_t diskblock) { const unsigned atonce = SFS_BLOCKSIZE/sizeof(struct sfs_direntry); unsigned j; if (diskblock != 0) { diskread(d, diskblock); for (j=0; jsfd_ino == SFS_NOINO && bd->sfd_ino == SFS_NOINO) { return 0; } if (ad->sfd_ino == SFS_NOINO) { return 1; } if (bd->sfd_ino == SFS_NOINO) { return -1; } return strcmp(ad->sfd_name, bd->sfd_name); } /* * Sort the directory contents in D (with ND entries) by producing a * permutation vector into VECTOR, which should be allocated to hold * ND ints. */ void sfsdir_sort(struct sfs_direntry *d, unsigned nd, int *vector) { unsigned i; for (i=0; i