sblock.c revision 105740
1214082Sdim/* 2214634Sdim * Copyright (c) 2002 Juli Mallett. All rights reserved. 3214082Sdim * 4214082Sdim * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the 5214082Sdim * FreeBSD project. Redistribution and use in source and binary forms, with 6214082Sdim * or without modification, are permitted provided that the following 7214082Sdim * conditions are met: 8214082Sdim * 9214082Sdim * 1. Redistribution of source code must retain the above copyright notice, 10214082Sdim * this list of conditions and the following disclaimer. 11214082Sdim * 2. Redistribution in binary form must reproduce the above copyright 12214082Sdim * notice, this list of conditions and the following disclaimer in the 13214082Sdim * documentation and/or other materials provided with the distribution. 14214082Sdim * 15214082Sdim * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 16214082Sdim * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 17214082Sdim * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18214082Sdim * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 19214082Sdim * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 20214082Sdim * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21214082Sdim * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22214634Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 23214634Sdim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 24214634Sdim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25214634Sdim * POSSIBILITY OF SUCH DAMAGE. 26214634Sdim */ 27214082Sdim 28214082Sdim#include <sys/cdefs.h> 29214082Sdim__FBSDID("$FreeBSD: head/lib/libufs/sblock.c 105740 2002-10-22 19:36:10Z jmallett $"); 30214082Sdim 31214082Sdim#include <sys/param.h> 32214082Sdim#include <sys/mount.h> 33214082Sdim#include <sys/disklabel.h> 34214082Sdim#include <sys/stat.h> 35214082Sdim 36214082Sdim#include <ufs/ufs/ufsmount.h> 37214082Sdim#include <ufs/ufs/dinode.h> 38214082Sdim#include <ufs/ffs/fs.h> 39214082Sdim 40214082Sdim#include <errno.h> 41214082Sdim#include <fcntl.h> 42214082Sdim#include <stdio.h> 43214082Sdim#include <string.h> 44214082Sdim#include <unistd.h> 45214082Sdim 46214082Sdim#include <libufs.h> 47214082Sdim 48214082Sdimstatic int superblocks[] = SBLOCKSEARCH; 49214082Sdim 50214082Sdimint 51214082Sdimsbread(struct uufsd *disk) 52214082Sdim{ 53214082Sdim struct fs *fs; 54214082Sdim int sb, superblock; 55214082Sdim 56214082Sdim DEBUG(NULL); 57214082Sdim 58214082Sdim fs = &disk->d_fs; 59214082Sdim superblock = superblocks[0]; 60214082Sdim 61214082Sdim for (sb = 0; (superblock = superblocks[sb]) != -1; sb++) { 62214082Sdim if (bread(disk, superblock, disk->d_sb, SBLOCKSIZE) == -1) { 63214082Sdim disk->d_error = "non-existent or truncated superblock"; 64214082Sdim DEBUG(NULL); 65214082Sdim return -1; 66214082Sdim } 67214082Sdim if (fs->fs_magic == FS_UFS1_MAGIC) 68214082Sdim disk->d_ufs = 1; 69214082Sdim if ((fs->fs_magic == FS_UFS2_MAGIC) && 70214082Sdim (fs->fs_sblockloc == numfrags(fs, superblock))) 71214082Sdim disk->d_ufs = 2; 72214082Sdim if ((fs->fs_bsize <= MAXBSIZE) && 73214082Sdim (fs->fs_bsize >= sizeof(*fs))) { 74214082Sdim if (disk->d_ufs) 75214082Sdim break; 76214082Sdim } 77214082Sdim disk->d_ufs = 0; 78214082Sdim } 79214082Sdim if (superblock == -1 || disk->d_ufs == 0) { 80214082Sdim /* 81214082Sdim * Other error cases will result in errno being set, here we 82214082Sdim * must set it to indicate no superblock could be found with 83214082Sdim * which to associate this disk/filesystem. 84214082Sdim */ 85214082Sdim DEBUG("no superblock found"); 86214082Sdim disk->d_error = "no superblock found"; 87214082Sdim errno = ENOENT; 88214082Sdim return -1; 89214082Sdim } 90214082Sdim disk->d_bsize = fs->fs_fsize / fsbtodb(fs, 1); 91214082Sdim disk->d_sblock = superblock / disk->d_bsize; 92214082Sdim return 0; 93214082Sdim} 94214082Sdim 95214082Sdimint 96214082Sdimsbwrite(struct uufsd *disk, int all) 97214082Sdim{ 98214082Sdim struct fs *fs; 99214082Sdim int i, rofd; 100214082Sdim 101214082Sdim DEBUG(NULL); 102214082Sdim 103214082Sdim fs = &disk->d_fs; 104214082Sdim 105214082Sdim rofd = disk->d_fd; 106214082Sdim disk->d_fd = open(disk->d_name, O_WRONLY); 107214082Sdim if (disk->d_fd < 0) { 108214082Sdim DEBUG("open"); 109214082Sdim disk->d_error = "failed to open disk"; 110214082Sdim return -1; 111214082Sdim } 112214082Sdim if (bwrite(disk, disk->d_sblock, fs, SBLOCKSIZE) == -1) { 113214082Sdim DEBUG(NULL); 114214082Sdim disk->d_error = "failed to write superblock"; 115214082Sdim return -1; 116214082Sdim } 117214082Sdim if (all) { 118214082Sdim for (i = 0; i < fs->fs_ncg; i++) 119214082Sdim if (bwrite(disk, fsbtodb(fs, cgsblock(fs, i)), 120214082Sdim fs, SBLOCKSIZE) == -1) { 121214082Sdim DEBUG(NULL); 122214082Sdim disk->d_error = "failed to update a superblock"; 123214082Sdim return -1; 124214082Sdim } 125214082Sdim } 126214082Sdim close(disk->d_fd); 127214082Sdim disk->d_fd = rofd; 128214082Sdim return 0; 129214082Sdim} 130214082Sdim