]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - lib/libufs/sblock.c
usr.bin/bc: update to version 5.3.1
[FreeBSD/FreeBSD.git] / lib / libufs / sblock.c
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 }