1 /* $OpenBSD: disksubr.c,v 1.2 2021/05/12 01:20:52 jsg Exp $ */
2
3 /*
4 * Copyright (c) 1996 Theo de Raadt
5 * Copyright (c) 1982, 1986, 1988 Regents of the University of California.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions 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 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33 #include <sys/param.h>
34 #include <sys/buf.h>
35 #include <sys/disklabel.h>
36 #include <sys/disk.h>
37
38 /*
39 * Attempt to read a disk label from a device
40 * using the indicated strategy routine.
41 * The label must be partly set up before this:
42 * secpercyl, secsize and anything required for a block i/o read
43 * operation in the driver's strategy/start routines
44 * must be filled in before calling us.
45 *
46 * If dos partition table requested, attempt to load it and
47 * find disklabel inside a DOS partition.
48 *
49 * We would like to check if each MBR has a valid DOSMBR_SIGNATURE, but
50 * we cannot because it doesn't always exist. So.. we assume the
51 * MBR is valid.
52 */
53 int
readdisklabel(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp,int spoofonly)54 readdisklabel(dev_t dev, void (*strat)(struct buf *),
55 struct disklabel *lp, int spoofonly)
56 {
57 struct buf *bp = NULL;
58 int error;
59
60 if ((error = initdisklabel(lp)))
61 goto done;
62
63 /* get a buffer and initialize it */
64 bp = geteblk(lp->d_secsize);
65 bp->b_dev = dev;
66
67 error = readdoslabel(bp, strat, lp, NULL, spoofonly);
68 if (error == 0)
69 goto done;
70
71 #if defined(CD9660)
72 error = iso_disklabelspoof(dev, strat, lp);
73 if (error == 0)
74 goto done;
75 #endif
76 #if defined(UDF)
77 error = udf_disklabelspoof(dev, strat, lp);
78 if (error == 0)
79 goto done;
80 #endif
81
82 done:
83 if (bp) {
84 bp->b_flags |= B_INVAL;
85 brelse(bp);
86 }
87 disk_change = 1;
88 return (error);
89 }
90
91 /*
92 * Write disk label back to device after modification.
93 */
94 int
writedisklabel(dev_t dev,void (* strat)(struct buf *),struct disklabel * lp)95 writedisklabel(dev_t dev, void (*strat)(struct buf *), struct disklabel *lp)
96 {
97 daddr_t partoff = -1;
98 int error = EIO;
99 int offset;
100 struct disklabel *dlp;
101 struct buf *bp = NULL;
102
103 /* get a buffer and initialize it */
104 bp = geteblk(lp->d_secsize);
105 bp->b_dev = dev;
106
107 if (readdoslabel(bp, strat, lp, &partoff, 1) != 0)
108 goto done;
109
110 /* Read it in, slap the new label in, and write it back out */
111 error = readdisksector(bp, strat, lp, DL_BLKTOSEC(lp, partoff +
112 DOS_LABELSECTOR));
113 if (error)
114 goto done;
115 offset = DL_BLKOFFSET(lp, partoff + DOS_LABELSECTOR);
116
117 dlp = (struct disklabel *)(bp->b_data + offset);
118 *dlp = *lp;
119 CLR(bp->b_flags, B_READ | B_WRITE | B_DONE);
120 SET(bp->b_flags, B_BUSY | B_WRITE | B_RAW);
121 (*strat)(bp);
122 error = biowait(bp);
123
124 done:
125 if (bp) {
126 bp->b_flags |= B_INVAL;
127 brelse(bp);
128 }
129 disk_change = 1;
130 return (error);
131 }
132