1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2002 Juli Mallett. All rights reserved. 5 * 6 * This software was written by Juli Mallett <jmallett@FreeBSD.org> for the 7 * FreeBSD project. Redistribution and use in source and binary forms, with 8 * or without modification, are permitted provided that the following 9 * conditions are met: 10 * 11 * 1. Redistribution of source code must retain the above copyright notice, 12 * this list of conditions and the following disclaimer. 13 * 2. Redistribution in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 26 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 27 * POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include <sys/cdefs.h> 31 __FBSDID("$FreeBSD$"); 32 33 #include <sys/param.h> 34 #include <sys/mount.h> 35 #include <sys/disklabel.h> 36 #include <sys/stat.h> 37 38 #include <ufs/ufs/extattr.h> 39 #include <ufs/ufs/quota.h> 40 #include <ufs/ufs/ufsmount.h> 41 #include <ufs/ufs/dinode.h> 42 #include <ufs/ffs/fs.h> 43 44 #include <errno.h> 45 #include <stdio.h> 46 #include <string.h> 47 #include <stdlib.h> 48 #include <unistd.h> 49 50 #include <libufs.h> 51 52 int 53 sbread(struct uufsd *disk) 54 { 55 struct fs *fs; 56 57 ERROR(disk, NULL); 58 59 if ((errno = sbget(disk->d_fd, &fs, STDSB)) != 0) { 60 switch (errno) { 61 case EIO: 62 ERROR(disk, "non-existent or truncated superblock"); 63 break; 64 case ENOENT: 65 ERROR(disk, "no usable known superblock found"); 66 break; 67 case ENOSPC: 68 ERROR(disk, "failed to allocate space for superblock " 69 "information"); 70 break; 71 case EINVAL: 72 ERROR(disk, "The previous newfs operation on this " 73 "volume did not complete.\nYou must complete " 74 "newfs before using this volume."); 75 break; 76 default: 77 ERROR(disk, "unknown superblock read error"); 78 errno = EIO; 79 break; 80 } 81 disk->d_ufs = 0; 82 return (-1); 83 } 84 memcpy(&disk->d_fs, fs, fs->fs_sbsize); 85 free(fs); 86 fs = &disk->d_fs; 87 if (fs->fs_magic == FS_UFS1_MAGIC) 88 disk->d_ufs = 1; 89 if (fs->fs_magic == FS_UFS2_MAGIC) 90 disk->d_ufs = 2; 91 disk->d_bsize = fs->fs_fsize / fsbtodb(fs, 1); 92 disk->d_sblock = fs->fs_sblockloc / disk->d_bsize; 93 disk->d_si = fs->fs_si; 94 return (0); 95 } 96 97 int 98 sbwrite(struct uufsd *disk, int all) 99 { 100 struct fs *fs; 101 int rv; 102 103 ERROR(disk, NULL); 104 105 rv = ufs_disk_write(disk); 106 if (rv == -1) { 107 ERROR(disk, "failed to open disk for writing"); 108 return (-1); 109 } 110 111 fs = &disk->d_fs; 112 if ((errno = sbput(disk->d_fd, fs, all ? fs->fs_ncg : 0)) != 0) { 113 switch (errno) { 114 case EIO: 115 ERROR(disk, "failed to write superblock"); 116 break; 117 default: 118 ERROR(disk, "unknown superblock write error"); 119 errno = EIO; 120 break; 121 } 122 return (-1); 123 } 124 return (0); 125 } 126 127 /* 128 * These are the low-level functions that actually read and write 129 * the superblock and its associated data. The actual work is done by 130 * the functions ffs_sbget and ffs_sbput in /sys/ufs/ffs/ffs_subr.c. 131 */ 132 static int use_pread(void *devfd, off_t loc, void **bufp, int size); 133 static int use_pwrite(void *devfd, off_t loc, void *buf, int size); 134 135 /* 136 * Read a superblock from the devfd device allocating memory returned 137 * in fsp. Also read the superblock summary information. 138 */ 139 int 140 sbget(int devfd, struct fs **fsp, off_t sblockloc) 141 { 142 143 return (ffs_sbget(&devfd, fsp, sblockloc, "user", use_pread)); 144 } 145 146 /* 147 * A read function for use by user-level programs using libufs. 148 */ 149 static int 150 use_pread(void *devfd, off_t loc, void **bufp, int size) 151 { 152 int fd; 153 154 fd = *(int *)devfd; 155 if ((*bufp = malloc(size)) == NULL) 156 return (ENOSPC); 157 if (pread(fd, *bufp, size, loc) != size) 158 return (EIO); 159 return (0); 160 } 161 162 /* 163 * Write a superblock to the devfd device from the memory pointed to by fs. 164 * Also write out the superblock summary information but do not free the 165 * summary information memory. 166 * 167 * Additionally write out numaltwrite of the alternate superblocks. Use 168 * fs->fs_ncg to write out all of the alternate superblocks. 169 */ 170 int 171 sbput(int devfd, struct fs *fs, int numaltwrite) 172 { 173 struct csum *savedcsp; 174 off_t savedactualloc; 175 int i, error; 176 177 if ((error = ffs_sbput(&devfd, fs, fs->fs_sblockactualloc, 178 use_pwrite)) != 0) 179 return (error); 180 if (numaltwrite == 0) 181 return (0); 182 savedactualloc = fs->fs_sblockactualloc; 183 savedcsp = fs->fs_csp; 184 fs->fs_csp = NULL; 185 for (i = 0; i < numaltwrite; i++) { 186 fs->fs_sblockactualloc = dbtob(fsbtodb(fs, cgsblock(fs, i))); 187 if ((error = ffs_sbput(&devfd, fs, fs->fs_sblockactualloc, 188 use_pwrite)) != 0) { 189 fs->fs_sblockactualloc = savedactualloc; 190 fs->fs_csp = savedcsp; 191 return (error); 192 } 193 } 194 fs->fs_sblockactualloc = savedactualloc; 195 fs->fs_csp = savedcsp; 196 return (0); 197 } 198 199 /* 200 * A write function for use by user-level programs using sbput in libufs. 201 */ 202 static int 203 use_pwrite(void *devfd, off_t loc, void *buf, int size) 204 { 205 int fd; 206 207 fd = *(int *)devfd; 208 if (pwrite(fd, buf, size, loc) != size) 209 return (EIO); 210 return (0); 211 } 212