15e53a4f9SPedro F. Giffuni /*- 25e53a4f9SPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 35e53a4f9SPedro F. Giffuni * 420938dbfSJuli Mallett * Copyright (c) 2002 Juli Mallett. All rights reserved. 520938dbfSJuli Mallett * 620938dbfSJuli Mallett * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the 720938dbfSJuli Mallett * FreeBSD project. Redistribution and use in source and binary forms, with 820938dbfSJuli Mallett * or without modification, are permitted provided that the following 920938dbfSJuli Mallett * conditions are met: 1020938dbfSJuli Mallett * 1120938dbfSJuli Mallett * 1. Redistribution of source code must retain the above copyright notice, 1220938dbfSJuli Mallett * this list of conditions and the following disclaimer. 1320938dbfSJuli Mallett * 2. Redistribution in binary form must reproduce the above copyright 1420938dbfSJuli Mallett * notice, this list of conditions and the following disclaimer in the 1520938dbfSJuli Mallett * documentation and/or other materials provided with the distribution. 1620938dbfSJuli Mallett * 1720938dbfSJuli Mallett * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1820938dbfSJuli Mallett * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 1920938dbfSJuli Mallett * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 2020938dbfSJuli Mallett * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 2120938dbfSJuli Mallett * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 2220938dbfSJuli Mallett * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 2320938dbfSJuli Mallett * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2420938dbfSJuli Mallett * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 2520938dbfSJuli Mallett * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 2620938dbfSJuli Mallett * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 2720938dbfSJuli Mallett * POSSIBILITY OF SUCH DAMAGE. 2820938dbfSJuli Mallett */ 2920938dbfSJuli Mallett 3020938dbfSJuli Mallett #include <sys/cdefs.h> 3120938dbfSJuli Mallett __FBSDID("$FreeBSD$"); 3220938dbfSJuli Mallett 3320938dbfSJuli Mallett #include <sys/param.h> 3420938dbfSJuli Mallett #include <sys/mount.h> 3520938dbfSJuli Mallett #include <sys/disklabel.h> 3620938dbfSJuli Mallett #include <sys/stat.h> 3720938dbfSJuli Mallett 38d485c77fSKonstantin Belousov #include <ufs/ufs/extattr.h> 39d485c77fSKonstantin Belousov #include <ufs/ufs/quota.h> 4020938dbfSJuli Mallett #include <ufs/ufs/ufsmount.h> 4120938dbfSJuli Mallett #include <ufs/ufs/dinode.h> 4220938dbfSJuli Mallett #include <ufs/ffs/fs.h> 4320938dbfSJuli Mallett 4420938dbfSJuli Mallett #include <errno.h> 4520938dbfSJuli Mallett #include <stdio.h> 4620938dbfSJuli Mallett #include <string.h> 47113db2ddSJeff Roberson #include <stdlib.h> 4820938dbfSJuli Mallett #include <unistd.h> 4920938dbfSJuli Mallett 5020938dbfSJuli Mallett #include <libufs.h> 5120938dbfSJuli Mallett 5282e72f1dSKirk McKusick static int handle_disk_read(struct uufsd *, struct fs *, int); 5382e72f1dSKirk McKusick 5482e72f1dSKirk McKusick /* 5582e72f1dSKirk McKusick * Read the standard superblock. 56*b21582eeSKirk McKusick * 57*b21582eeSKirk McKusick * The following option flags can be or'ed into disk->d_lookupflags: 58*b21582eeSKirk McKusick * 59*b21582eeSKirk McKusick * UFS_NOMSG indicates that superblock inconsistency error messages 60*b21582eeSKirk McKusick * should not be printed. 61*b21582eeSKirk McKusick * 62*b21582eeSKirk McKusick * UFS_NOCSUM causes only the superblock itself to be returned, but does 63*b21582eeSKirk McKusick * not read in any auxillary data structures like the cylinder group 64*b21582eeSKirk McKusick * summary information. 6582e72f1dSKirk McKusick */ 6620938dbfSJuli Mallett int 6720938dbfSJuli Mallett sbread(struct uufsd *disk) 6820938dbfSJuli Mallett { 6920938dbfSJuli Mallett struct fs *fs; 7082e72f1dSKirk McKusick int error; 7182e72f1dSKirk McKusick 72*b21582eeSKirk McKusick error = sbget(disk->d_fd, &fs, disk->d_sblockloc, disk->d_lookupflags); 7382e72f1dSKirk McKusick return (handle_disk_read(disk, fs, error)); 7482e72f1dSKirk McKusick } 7582e72f1dSKirk McKusick 7682e72f1dSKirk McKusick static int 7782e72f1dSKirk McKusick handle_disk_read(struct uufsd *disk, struct fs *fs, int error) 7882e72f1dSKirk McKusick { 7920938dbfSJuli Mallett 8049b2a686SJuli Mallett ERROR(disk, NULL); 8182e72f1dSKirk McKusick if (error != 0) { 8282e72f1dSKirk McKusick switch (error) { 83dffce215SKirk McKusick case EIO: 8449b2a686SJuli Mallett ERROR(disk, "non-existent or truncated superblock"); 85dffce215SKirk McKusick break; 86dffce215SKirk McKusick case ENOENT: 87dffce215SKirk McKusick ERROR(disk, "no usable known superblock found"); 88dffce215SKirk McKusick break; 8982e72f1dSKirk McKusick case EINTEGRITY: 9082e72f1dSKirk McKusick ERROR(disk, "superblock check-hash failure"); 9182e72f1dSKirk McKusick break; 92dffce215SKirk McKusick case ENOSPC: 93dffce215SKirk McKusick ERROR(disk, "failed to allocate space for superblock " 94dffce215SKirk McKusick "information"); 95dffce215SKirk McKusick break; 96dffce215SKirk McKusick case EINVAL: 97dffce215SKirk McKusick ERROR(disk, "The previous newfs operation on this " 98dffce215SKirk McKusick "volume did not complete.\nYou must complete " 99dffce215SKirk McKusick "newfs before using this volume."); 100dffce215SKirk McKusick break; 101dffce215SKirk McKusick default: 102dffce215SKirk McKusick ERROR(disk, "unknown superblock read error"); 103dffce215SKirk McKusick errno = EIO; 10420938dbfSJuli Mallett break; 10520938dbfSJuli Mallett } 10620938dbfSJuli Mallett disk->d_ufs = 0; 1071081253fSJuli Mallett return (-1); 10820938dbfSJuli Mallett } 109dffce215SKirk McKusick memcpy(&disk->d_fs, fs, fs->fs_sbsize); 110dffce215SKirk McKusick free(fs); 111dffce215SKirk McKusick fs = &disk->d_fs; 112dffce215SKirk McKusick if (fs->fs_magic == FS_UFS1_MAGIC) 113dffce215SKirk McKusick disk->d_ufs = 1; 114dffce215SKirk McKusick if (fs->fs_magic == FS_UFS2_MAGIC) 115dffce215SKirk McKusick disk->d_ufs = 2; 11620938dbfSJuli Mallett disk->d_bsize = fs->fs_fsize / fsbtodb(fs, 1); 117dffce215SKirk McKusick disk->d_sblock = fs->fs_sblockloc / disk->d_bsize; 11892c839a1SKirk McKusick disk->d_si = fs->fs_si; 1191081253fSJuli Mallett return (0); 12020938dbfSJuli Mallett } 12120938dbfSJuli Mallett 12220938dbfSJuli Mallett int 12320938dbfSJuli Mallett sbwrite(struct uufsd *disk, int all) 12420938dbfSJuli Mallett { 12520938dbfSJuli Mallett struct fs *fs; 1268a9493deSKirk McKusick int rv; 12720938dbfSJuli Mallett 12849b2a686SJuli Mallett ERROR(disk, NULL); 129585e5402SJuli Mallett 1308a9493deSKirk McKusick rv = ufs_disk_write(disk); 1318a9493deSKirk McKusick if (rv == -1) { 1328a9493deSKirk McKusick ERROR(disk, "failed to open disk for writing"); 1338a9493deSKirk McKusick return (-1); 1348a9493deSKirk McKusick } 1358a9493deSKirk McKusick 13620938dbfSJuli Mallett fs = &disk->d_fs; 137dffce215SKirk McKusick if ((errno = sbput(disk->d_fd, fs, all ? fs->fs_ncg : 0)) != 0) { 138dffce215SKirk McKusick switch (errno) { 139dffce215SKirk McKusick case EIO: 14049b2a686SJuli Mallett ERROR(disk, "failed to write superblock"); 141dffce215SKirk McKusick break; 142dffce215SKirk McKusick default: 143dffce215SKirk McKusick ERROR(disk, "unknown superblock write error"); 144dffce215SKirk McKusick errno = EIO; 145dffce215SKirk McKusick break; 146dffce215SKirk McKusick } 1471081253fSJuli Mallett return (-1); 14820938dbfSJuli Mallett } 149dffce215SKirk McKusick return (0); 150dffce215SKirk McKusick } 151dffce215SKirk McKusick 152113db2ddSJeff Roberson /* 153dffce215SKirk McKusick * These are the low-level functions that actually read and write 154dffce215SKirk McKusick * the superblock and its associated data. The actual work is done by 155dffce215SKirk McKusick * the functions ffs_sbget and ffs_sbput in /sys/ufs/ffs/ffs_subr.c. 156113db2ddSJeff Roberson */ 157dffce215SKirk McKusick static int use_pread(void *devfd, off_t loc, void **bufp, int size); 158dffce215SKirk McKusick static int use_pwrite(void *devfd, off_t loc, void *buf, int size); 159dffce215SKirk McKusick 160dffce215SKirk McKusick /* 161*b21582eeSKirk McKusick * The following two functions read a superblock. Their flags 162*b21582eeSKirk McKusick * parameter are made up of the following or'ed together options: 163*b21582eeSKirk McKusick * 164*b21582eeSKirk McKusick * UFS_NOMSG indicates that superblock inconsistency error messages 165*b21582eeSKirk McKusick * should not be printed. 166*b21582eeSKirk McKusick * 167*b21582eeSKirk McKusick * UFS_NOCSUM causes only the superblock itself to be returned, but does 168*b21582eeSKirk McKusick * not read in any auxillary data structures like the cylinder group 169*b21582eeSKirk McKusick * summary information. 170*b21582eeSKirk McKusick * 171dffce215SKirk McKusick * Read a superblock from the devfd device allocating memory returned 172*b21582eeSKirk McKusick * in fsp. 173dffce215SKirk McKusick */ 174dffce215SKirk McKusick int 175*b21582eeSKirk McKusick sbget(int devfd, struct fs **fsp, off_t sblockloc, int flags) 176dffce215SKirk McKusick { 177dffce215SKirk McKusick 178*b21582eeSKirk McKusick return (ffs_sbget(&devfd, fsp, sblockloc, flags, "user", use_pread)); 179113db2ddSJeff Roberson } 180dffce215SKirk McKusick 181dffce215SKirk McKusick /* 182dffce215SKirk McKusick * A read function for use by user-level programs using libufs. 183dffce215SKirk McKusick */ 184dffce215SKirk McKusick static int 185dffce215SKirk McKusick use_pread(void *devfd, off_t loc, void **bufp, int size) 186dffce215SKirk McKusick { 187dffce215SKirk McKusick int fd; 188dffce215SKirk McKusick 189dffce215SKirk McKusick fd = *(int *)devfd; 190dffce215SKirk McKusick if ((*bufp = malloc(size)) == NULL) 191dffce215SKirk McKusick return (ENOSPC); 192dffce215SKirk McKusick if (pread(fd, *bufp, size, loc) != size) 193dffce215SKirk McKusick return (EIO); 194dffce215SKirk McKusick return (0); 195113db2ddSJeff Roberson } 196dffce215SKirk McKusick 197dffce215SKirk McKusick /* 198dffce215SKirk McKusick * Write a superblock to the devfd device from the memory pointed to by fs. 199dffce215SKirk McKusick * Also write out the superblock summary information but do not free the 200dffce215SKirk McKusick * summary information memory. 201dffce215SKirk McKusick * 202dffce215SKirk McKusick * Additionally write out numaltwrite of the alternate superblocks. Use 203dffce215SKirk McKusick * fs->fs_ncg to write out all of the alternate superblocks. 204dffce215SKirk McKusick */ 205dffce215SKirk McKusick int 206dffce215SKirk McKusick sbput(int devfd, struct fs *fs, int numaltwrite) 207dffce215SKirk McKusick { 208dffce215SKirk McKusick struct csum *savedcsp; 209dffce215SKirk McKusick off_t savedactualloc; 210dffce215SKirk McKusick int i, error; 211dffce215SKirk McKusick 212dffce215SKirk McKusick if ((error = ffs_sbput(&devfd, fs, fs->fs_sblockactualloc, 213dffce215SKirk McKusick use_pwrite)) != 0) 214dffce215SKirk McKusick return (error); 215dffce215SKirk McKusick if (numaltwrite == 0) 216dffce215SKirk McKusick return (0); 217dffce215SKirk McKusick savedactualloc = fs->fs_sblockactualloc; 218*b21582eeSKirk McKusick if (fs->fs_si != NULL) { 219dffce215SKirk McKusick savedcsp = fs->fs_csp; 220dffce215SKirk McKusick fs->fs_csp = NULL; 221*b21582eeSKirk McKusick } 222dffce215SKirk McKusick for (i = 0; i < numaltwrite; i++) { 223dffce215SKirk McKusick fs->fs_sblockactualloc = dbtob(fsbtodb(fs, cgsblock(fs, i))); 224dffce215SKirk McKusick if ((error = ffs_sbput(&devfd, fs, fs->fs_sblockactualloc, 225dffce215SKirk McKusick use_pwrite)) != 0) { 226dffce215SKirk McKusick fs->fs_sblockactualloc = savedactualloc; 227dffce215SKirk McKusick fs->fs_csp = savedcsp; 22885ee267aSKirk McKusick return (error); 22920938dbfSJuli Mallett } 23020938dbfSJuli Mallett } 231dffce215SKirk McKusick fs->fs_sblockactualloc = savedactualloc; 232*b21582eeSKirk McKusick if (fs->fs_si != NULL) 233dffce215SKirk McKusick fs->fs_csp = savedcsp; 234dffce215SKirk McKusick return (0); 235dffce215SKirk McKusick } 236dffce215SKirk McKusick 237dffce215SKirk McKusick /* 238dffce215SKirk McKusick * A write function for use by user-level programs using sbput in libufs. 239dffce215SKirk McKusick */ 240dffce215SKirk McKusick static int 241dffce215SKirk McKusick use_pwrite(void *devfd, off_t loc, void *buf, int size) 242dffce215SKirk McKusick { 243dffce215SKirk McKusick int fd; 244dffce215SKirk McKusick 245dffce215SKirk McKusick fd = *(int *)devfd; 246dffce215SKirk McKusick if (pwrite(fd, buf, size, loc) != size) 247dffce215SKirk McKusick return (EIO); 2481081253fSJuli Mallett return (0); 24920938dbfSJuli Mallett } 250