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