199193Sjmallett/* 299193Sjmallett * Copyright (c) 2002 Juli Mallett. All rights reserved. 399193Sjmallett * 499193Sjmallett * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the 599193Sjmallett * FreeBSD project. Redistribution and use in source and binary forms, with 699193Sjmallett * or without modification, are permitted provided that the following 799193Sjmallett * conditions are met: 899193Sjmallett * 999193Sjmallett * 1. Redistribution of source code must retain the above copyright notice, 1099193Sjmallett * this list of conditions and the following disclaimer. 1199193Sjmallett * 2. Redistribution in binary form must reproduce the above copyright 1299193Sjmallett * notice, this list of conditions and the following disclaimer in the 1399193Sjmallett * documentation and/or other materials provided with the distribution. 1499193Sjmallett * 1599193Sjmallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1699193Sjmallett * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1799193Sjmallett * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 1899193Sjmallett * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 1999193Sjmallett * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2099193Sjmallett * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2199193Sjmallett * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2299193Sjmallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2399193Sjmallett * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 2499193Sjmallett * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2599193Sjmallett * POSSIBILITY OF SUCH DAMAGE. 2699193Sjmallett */ 2799193Sjmallett 2899193Sjmallett#include <sys/cdefs.h> 2999193Sjmallett__FBSDID("$FreeBSD$"); 3099193Sjmallett 3199193Sjmallett#include <sys/param.h> 3299193Sjmallett#include <sys/mount.h> 3399193Sjmallett#include <sys/disklabel.h> 3499193Sjmallett#include <sys/stat.h> 3599193Sjmallett 3699193Sjmallett#include <ufs/ufs/ufsmount.h> 3799193Sjmallett#include <ufs/ufs/dinode.h> 3899193Sjmallett#include <ufs/ffs/fs.h> 3999193Sjmallett 4099193Sjmallett#include <errno.h> 4199193Sjmallett#include <stdio.h> 4299193Sjmallett#include <string.h> 43207141Sjeff#include <stdlib.h> 4499193Sjmallett#include <unistd.h> 4599193Sjmallett 4699193Sjmallett#include <libufs.h> 4799193Sjmallett 4899193Sjmallettstatic int superblocks[] = SBLOCKSEARCH; 4999193Sjmallett 5099193Sjmallettint 5199193Sjmallettsbread(struct uufsd *disk) 5299193Sjmallett{ 53207141Sjeff uint8_t block[MAXBSIZE]; 5499193Sjmallett struct fs *fs; 5599193Sjmallett int sb, superblock; 56207141Sjeff int i, size, blks; 57207141Sjeff uint8_t *space; 5899193Sjmallett 59109462Sjmallett ERROR(disk, NULL); 6099193Sjmallett 6199193Sjmallett fs = &disk->d_fs; 6299193Sjmallett superblock = superblocks[0]; 6399193Sjmallett 6499193Sjmallett for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) { 6599193Sjmallett if (bread(disk, superblock, disk->d_sb, SBLOCKSIZE) == -1) { 66109462Sjmallett ERROR(disk, "non-existent or truncated superblock"); 67116084Sjmallett return (-1); 6899193Sjmallett } 6999193Sjmallett if (fs->fs_magic == FS_UFS1_MAGIC) 7099193Sjmallett disk->d_ufs = 1; 71111111Sjmallett if (fs->fs_magic == FS_UFS2_MAGIC && 72111111Sjmallett fs->fs_sblockloc == superblock) 7399193Sjmallett disk->d_ufs = 2; 74111111Sjmallett if (fs->fs_bsize <= MAXBSIZE && 75111111Sjmallett (size_t)fs->fs_bsize >= sizeof(*fs)) { 7699193Sjmallett if (disk->d_ufs) 7799193Sjmallett break; 7899193Sjmallett } 7999193Sjmallett disk->d_ufs = 0; 8099193Sjmallett } 8199193Sjmallett if (superblock == -1 || disk->d_ufs == 0) { 8299193Sjmallett /* 8399193Sjmallett * Other error cases will result in errno being set, here we 8499193Sjmallett * must set it to indicate no superblock could be found with 8599193Sjmallett * which to associate this disk/filesystem. 8699193Sjmallett */ 87109462Sjmallett ERROR(disk, "no usable known superblock found"); 8899193Sjmallett errno = ENOENT; 89116084Sjmallett return (-1); 9099193Sjmallett } 9199193Sjmallett disk->d_bsize = fs->fs_fsize / fsbtodb(fs, 1); 9299193Sjmallett disk->d_sblock = superblock / disk->d_bsize; 93207141Sjeff /* 94207141Sjeff * Read in the superblock summary information. 95207141Sjeff */ 96207141Sjeff size = fs->fs_cssize; 97207141Sjeff blks = howmany(size, fs->fs_fsize); 98207141Sjeff size += fs->fs_ncg * sizeof(int32_t); 99207141Sjeff space = malloc(size); 100207141Sjeff if (space == NULL) { 101207141Sjeff ERROR(disk, "failed to allocate space for summary information"); 102207141Sjeff return (-1); 103207141Sjeff } 104207141Sjeff fs->fs_csp = (struct csum *)space; 105207141Sjeff for (i = 0; i < blks; i += fs->fs_frag) { 106207141Sjeff size = fs->fs_bsize; 107207141Sjeff if (i + fs->fs_frag > blks) 108207141Sjeff size = (blks - i) * fs->fs_fsize; 109207141Sjeff if (bread(disk, fsbtodb(fs, fs->fs_csaddr + i), block, size) 110207141Sjeff == -1) { 111207141Sjeff ERROR(disk, "Failed to read sb summary information"); 112207141Sjeff free(fs->fs_csp); 113207141Sjeff return (-1); 114207141Sjeff } 115207141Sjeff bcopy(block, space, size); 116207141Sjeff space += size; 117207141Sjeff } 118207141Sjeff fs->fs_maxcluster = (uint32_t *)space; 119207141Sjeff disk->d_sbcsum = fs->fs_csp; 120207141Sjeff 121116084Sjmallett return (0); 12299193Sjmallett} 12399193Sjmallett 12499193Sjmallettint 12599193Sjmallettsbwrite(struct uufsd *disk, int all) 12699193Sjmallett{ 12799193Sjmallett struct fs *fs; 128207141Sjeff int blks, size; 129207141Sjeff uint8_t *space; 130203782Simp unsigned i; 13199193Sjmallett 132109462Sjmallett ERROR(disk, NULL); 13399222Sjmallett 13499193Sjmallett fs = &disk->d_fs; 13599193Sjmallett 136109913Sjmallett if (!disk->d_sblock) { 137109913Sjmallett disk->d_sblock = disk->d_fs.fs_sblockloc / disk->d_bsize; 138109913Sjmallett } 139109913Sjmallett 14099193Sjmallett if (bwrite(disk, disk->d_sblock, fs, SBLOCKSIZE) == -1) { 141109462Sjmallett ERROR(disk, "failed to write superblock"); 142116084Sjmallett return (-1); 14399193Sjmallett } 144207141Sjeff /* 145207141Sjeff * Write superblock summary information. 146207141Sjeff */ 147207141Sjeff blks = howmany(fs->fs_cssize, fs->fs_fsize); 148207141Sjeff space = (uint8_t *)disk->d_sbcsum; 149207141Sjeff for (i = 0; i < blks; i += fs->fs_frag) { 150207141Sjeff size = fs->fs_bsize; 151207141Sjeff if (i + fs->fs_frag > blks) 152207141Sjeff size = (blks - i) * fs->fs_fsize; 153207141Sjeff if (bwrite(disk, fsbtodb(fs, fs->fs_csaddr + i), space, size) 154207141Sjeff == -1) { 155207141Sjeff ERROR(disk, "Failed to write sb summary information"); 156207141Sjeff return (-1); 157207141Sjeff } 158207141Sjeff space += size; 159207141Sjeff } 16099193Sjmallett if (all) { 16199193Sjmallett for (i = 0; i < fs->fs_ncg; i++) 16299193Sjmallett if (bwrite(disk, fsbtodb(fs, cgsblock(fs, i)), 16399193Sjmallett fs, SBLOCKSIZE) == -1) { 164109462Sjmallett ERROR(disk, "failed to update a superblock"); 165116084Sjmallett return (-1); 16699193Sjmallett } 16799193Sjmallett } 168116084Sjmallett return (0); 16999193Sjmallett} 170