1 /* 2 * Copyright (c) 2002 Juli Mallett. All rights reserved. 3 * 4 * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the 5 * FreeBSD project. Redistribution and use in source and binary forms, with 6 * or without modification, are permitted provided that the following 7 * conditions are met: 8 * 9 * 1. Redistribution of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 2. Redistribution in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 24 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 * POSSIBILITY OF SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include <sys/param.h> 32 #include <sys/mount.h> 33 #include <sys/disklabel.h> 34 #include <sys/stat.h> 35 36 #include <ufs/ufs/ufsmount.h> 37 #include <ufs/ufs/dinode.h> 38 #include <ufs/ffs/fs.h> 39 40 #include <errno.h> 41 #include <stdio.h> 42 #include <string.h> 43 #include <stdlib.h> 44 #include <unistd.h> 45 46 #include <libufs.h> 47 48 static int superblocks[] = SBLOCKSEARCH; 49 50 int 51 sbread(struct uufsd *disk) 52 { 53 uint8_t block[MAXBSIZE]; 54 struct fs *fs; 55 int sb, superblock; 56 int i, size, blks; 57 uint8_t *space; 58 59 ERROR(disk, NULL); 60 61 fs = &disk->d_fs; 62 superblock = superblocks[0]; 63 64 for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) { 65 if (bread(disk, superblock, disk->d_sb, SBLOCKSIZE) == -1) { 66 ERROR(disk, "non-existent or truncated superblock"); 67 return (-1); 68 } 69 if (fs->fs_magic == FS_UFS1_MAGIC) 70 disk->d_ufs = 1; 71 if (fs->fs_magic == FS_UFS2_MAGIC && 72 fs->fs_sblockloc == superblock) 73 disk->d_ufs = 2; 74 if (fs->fs_bsize <= MAXBSIZE && 75 (size_t)fs->fs_bsize >= sizeof(*fs)) { 76 if (disk->d_ufs) 77 break; 78 } 79 disk->d_ufs = 0; 80 } 81 if (superblock == -1 || disk->d_ufs == 0) { 82 /* 83 * Other error cases will result in errno being set, here we 84 * must set it to indicate no superblock could be found with 85 * which to associate this disk/filesystem. 86 */ 87 ERROR(disk, "no usable known superblock found"); 88 errno = ENOENT; 89 return (-1); 90 } 91 disk->d_bsize = fs->fs_fsize / fsbtodb(fs, 1); 92 disk->d_sblock = superblock / disk->d_bsize; 93 /* 94 * Read in the superblock summary information. 95 */ 96 size = fs->fs_cssize; 97 blks = howmany(size, fs->fs_fsize); 98 size += fs->fs_ncg * sizeof(int32_t); 99 space = malloc(size); 100 if (space == NULL) { 101 ERROR(disk, "failed to allocate space for summary information"); 102 return (-1); 103 } 104 fs->fs_csp = (struct csum *)space; 105 for (i = 0; i < blks; i += fs->fs_frag) { 106 size = fs->fs_bsize; 107 if (i + fs->fs_frag > blks) 108 size = (blks - i) * fs->fs_fsize; 109 if (bread(disk, fsbtodb(fs, fs->fs_csaddr + i), block, size) 110 == -1) { 111 ERROR(disk, "Failed to read sb summary information"); 112 free(fs->fs_csp); 113 return (-1); 114 } 115 bcopy(block, space, size); 116 space += size; 117 } 118 fs->fs_maxcluster = (uint32_t *)space; 119 disk->d_sbcsum = fs->fs_csp; 120 121 return (0); 122 } 123 124 int 125 sbwrite(struct uufsd *disk, int all) 126 { 127 struct fs *fs; 128 int blks, size; 129 uint8_t *space; 130 unsigned i; 131 132 ERROR(disk, NULL); 133 134 fs = &disk->d_fs; 135 136 if (!disk->d_sblock) { 137 disk->d_sblock = disk->d_fs.fs_sblockloc / disk->d_bsize; 138 } 139 140 if (bwrite(disk, disk->d_sblock, fs, SBLOCKSIZE) == -1) { 141 ERROR(disk, "failed to write superblock"); 142 return (-1); 143 } 144 /* 145 * Write superblock summary information. 146 */ 147 blks = howmany(fs->fs_cssize, fs->fs_fsize); 148 space = (uint8_t *)disk->d_sbcsum; 149 for (i = 0; i < blks; i += fs->fs_frag) { 150 size = fs->fs_bsize; 151 if (i + fs->fs_frag > blks) 152 size = (blks - i) * fs->fs_fsize; 153 if (bwrite(disk, fsbtodb(fs, fs->fs_csaddr + i), space, size) 154 == -1) { 155 ERROR(disk, "Failed to write sb summary information"); 156 return (-1); 157 } 158 space += size; 159 } 160 if (all) { 161 for (i = 0; i < fs->fs_ncg; i++) 162 if (bwrite(disk, fsbtodb(fs, cgsblock(fs, i)), 163 fs, SBLOCKSIZE) == -1) { 164 ERROR(disk, "failed to update a superblock"); 165 return (-1); 166 } 167 } 168 return (0); 169 } 170