| @@ -1,1575 +1,1575 @@ | | | @@ -1,1575 +1,1575 @@ |
1 | /* $NetBSD: main.c,v 1.29 2013/05/03 16:05:12 matt Exp $ */ | | 1 | /* $NetBSD: main.c,v 1.30 2013/05/03 16:39:00 matt Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 2006 The NetBSD Foundation, Inc. | | 4 | * Copyright (c) 2006 The NetBSD Foundation, Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * This code is derived from software contributed to The NetBSD Foundation | | 7 | * This code is derived from software contributed to The NetBSD Foundation |
8 | * by Julio M. Merino Vidal. | | 8 | * by Julio M. Merino Vidal. |
9 | * | | 9 | * |
10 | * Redistribution and use in source and binary forms, with or without | | 10 | * Redistribution and use in source and binary forms, with or without |
11 | * modification, are permitted provided that the following conditions | | 11 | * modification, are permitted provided that the following conditions |
12 | * are met: | | 12 | * are met: |
13 | * 1. Redistributions of source code must retain the above copyright | | 13 | * 1. Redistributions of source code must retain the above copyright |
14 | * notice, this list of conditions and the following disclaimer. | | 14 | * notice, this list of conditions and the following disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above copyright | | 15 | * 2. Redistributions in binary form must reproduce the above copyright |
16 | * notice, this list of conditions and the following disclaimer in the | | 16 | * notice, this list of conditions and the following disclaimer in the |
17 | * documentation and/or other materials provided with the distribution. | | 17 | * documentation and/or other materials provided with the distribution. |
18 | * | | 18 | * |
19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS | | 19 | * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS |
20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED | | 20 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED |
21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | | 21 | * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS | | 22 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS |
23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 23 | * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 24 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 25 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 26 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 27 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | | 28 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
29 | * POSSIBILITY OF SUCH DAMAGE. | | 29 | * POSSIBILITY OF SUCH DAMAGE. |
30 | */ | | 30 | */ |
31 | | | 31 | |
32 | /* | | 32 | /* |
33 | * Copyright (c) 1987, 1993 | | 33 | * Copyright (c) 1987, 1993 |
34 | * The Regents of the University of California. All rights reserved. | | 34 | * The Regents of the University of California. All rights reserved. |
35 | * | | 35 | * |
36 | * This code is derived from software contributed to Berkeley by | | 36 | * This code is derived from software contributed to Berkeley by |
37 | * Symmetric Computer Systems. | | 37 | * Symmetric Computer Systems. |
38 | * | | 38 | * |
39 | * Redistribution and use in source and binary forms, with or without | | 39 | * Redistribution and use in source and binary forms, with or without |
40 | * modification, are permitted provided that the following conditions | | 40 | * modification, are permitted provided that the following conditions |
41 | * are met: | | 41 | * are met: |
42 | * 1. Redistributions of source code must retain the above copyright | | 42 | * 1. Redistributions of source code must retain the above copyright |
43 | * notice, this list of conditions and the following disclaimer. | | 43 | * notice, this list of conditions and the following disclaimer. |
44 | * 2. Redistributions in binary form must reproduce the above copyright | | 44 | * 2. Redistributions in binary form must reproduce the above copyright |
45 | * notice, this list of conditions and the following disclaimer in the | | 45 | * notice, this list of conditions and the following disclaimer in the |
46 | * documentation and/or other materials provided with the distribution. | | 46 | * documentation and/or other materials provided with the distribution. |
47 | * 3. Neither the name of the University nor the names of its contributors | | 47 | * 3. Neither the name of the University nor the names of its contributors |
48 | * may be used to endorse or promote products derived from this software | | 48 | * may be used to endorse or promote products derived from this software |
49 | * without specific prior written permission. | | 49 | * without specific prior written permission. |
50 | * | | 50 | * |
51 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | | 51 | * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND |
52 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 52 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
53 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 53 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
54 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | | 54 | * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE |
55 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | | 55 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
56 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | | 56 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
57 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | | 57 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | | 58 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
59 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | | 59 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
60 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | | 60 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
61 | * SUCH DAMAGE. | | 61 | * SUCH DAMAGE. |
62 | */ | | 62 | */ |
63 | | | 63 | |
64 | #if HAVE_NBTOOL_CONFIG_H | | 64 | #if HAVE_NBTOOL_CONFIG_H |
65 | #include "nbtool_config.h" | | 65 | #include "nbtool_config.h" |
66 | #endif | | 66 | #endif |
67 | | | 67 | |
68 | #include <sys/cdefs.h> | | 68 | #include <sys/cdefs.h> |
69 | #ifndef lint | | 69 | #ifndef lint |
70 | __COPYRIGHT("@(#) Copyright (c) 1987, 1993\ | | 70 | __COPYRIGHT("@(#) Copyright (c) 1987, 1993\ |
71 | The Regents of the University of California. All rights reserved."); | | 71 | The Regents of the University of California. All rights reserved."); |
72 | #endif /* not lint */ | | 72 | #endif /* not lint */ |
73 | | | 73 | |
74 | #ifndef lint | | 74 | #ifndef lint |
75 | #if 0 | | 75 | #if 0 |
76 | static char sccsid[] = "@(#)disklabel.c 8.4 (Berkeley) 5/4/95"; | | 76 | static char sccsid[] = "@(#)disklabel.c 8.4 (Berkeley) 5/4/95"; |
77 | /* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ | | 77 | /* from static char sccsid[] = "@(#)disklabel.c 1.2 (Symmetric) 11/28/85"; */ |
78 | #else | | 78 | #else |
79 | __RCSID("$NetBSD: main.c,v 1.29 2013/05/03 16:05:12 matt Exp $"); | | 79 | __RCSID("$NetBSD: main.c,v 1.30 2013/05/03 16:39:00 matt Exp $"); |
80 | #endif | | 80 | #endif |
81 | #endif /* not lint */ | | 81 | #endif /* not lint */ |
82 | | | 82 | |
83 | #include <sys/param.h> | | 83 | #include <sys/param.h> |
84 | #include <sys/file.h> | | 84 | #include <sys/file.h> |
85 | #include <sys/stat.h> | | 85 | #include <sys/stat.h> |
86 | #include <sys/wait.h> | | 86 | #include <sys/wait.h> |
87 | #define DKTYPENAMES | | 87 | #define DKTYPENAMES |
88 | #define FSTYPENAMES | | 88 | #define FSTYPENAMES |
89 | | | 89 | |
90 | #include <ctype.h> | | 90 | #include <ctype.h> |
91 | #include <err.h> | | 91 | #include <err.h> |
92 | #include <errno.h> | | 92 | #include <errno.h> |
93 | #include <signal.h> | | 93 | #include <signal.h> |
94 | #include <string.h> | | 94 | #include <string.h> |
95 | #include <stdio.h> | | 95 | #include <stdio.h> |
96 | #include <stdlib.h> | | 96 | #include <stdlib.h> |
97 | #include <limits.h> | | 97 | #include <limits.h> |
98 | #include <unistd.h> | | 98 | #include <unistd.h> |
99 | | | 99 | |
100 | #include <ufs/ufs/dinode.h> | | 100 | #include <ufs/ufs/dinode.h> |
101 | #include <ufs/ffs/fs.h> | | 101 | #include <ufs/ffs/fs.h> |
102 | | | 102 | |
103 | #if HAVE_NBTOOL_CONFIG_H | | 103 | #if HAVE_NBTOOL_CONFIG_H |
104 | #include <nbinclude/sys/disklabel.h> | | 104 | #include <nbinclude/sys/disklabel.h> |
105 | #include <nbinclude/sys/disklabel_acorn.h> | | 105 | #include <nbinclude/sys/disklabel_acorn.h> |
106 | #include <nbinclude/sys/bootblock.h> | | 106 | #include <nbinclude/sys/bootblock.h> |
107 | #include "../../include/disktab.h" | | 107 | #include "../../include/disktab.h" |
108 | #else | | 108 | #else |
109 | #include <sys/ioctl.h> | | 109 | #include <sys/ioctl.h> |
110 | #include <sys/disklabel.h> | | 110 | #include <sys/disklabel.h> |
111 | #include <sys/disklabel_acorn.h> | | 111 | #include <sys/disklabel_acorn.h> |
112 | #include <sys/bootblock.h> | | 112 | #include <sys/bootblock.h> |
113 | #include <util.h> | | 113 | #include <util.h> |
114 | #include <disktab.h> | | 114 | #include <disktab.h> |
115 | #endif /* HAVE_NBTOOL_CONFIG_H */ | | 115 | #endif /* HAVE_NBTOOL_CONFIG_H */ |
116 | | | 116 | |
117 | #include "pathnames.h" | | 117 | #include "pathnames.h" |
118 | #include "extern.h" | | 118 | #include "extern.h" |
119 | #include "dkcksum.h" | | 119 | #include "dkcksum.h" |
120 | #include "bswap.h" | | 120 | #include "bswap.h" |
121 | | | 121 | |
122 | /* | | 122 | /* |
123 | * Disklabel: read and write disklabels. | | 123 | * Disklabel: read and write disklabels. |
124 | * The label is usually placed on one of the first sectors of the disk. | | 124 | * The label is usually placed on one of the first sectors of the disk. |
125 | * Many machines also place a bootstrap in the same area, | | 125 | * Many machines also place a bootstrap in the same area, |
126 | * in which case the label is embedded in the bootstrap. | | 126 | * in which case the label is embedded in the bootstrap. |
127 | * The bootstrap source must leave space at the proper offset | | 127 | * The bootstrap source must leave space at the proper offset |
128 | * for the label on such machines. | | 128 | * for the label on such machines. |
129 | */ | | 129 | */ |
130 | | | 130 | |
131 | #ifndef BBSIZE | | 131 | #ifndef BBSIZE |
132 | #define BBSIZE 8192 /* size of boot area, with label */ | | 132 | #define BBSIZE 8192 /* size of boot area, with label */ |
133 | #endif | | 133 | #endif |
134 | | | 134 | |
135 | #define DISKMAGIC_REV bswap32(DISKMAGIC) | | 135 | #define DISKMAGIC_REV bswap32(DISKMAGIC) |
136 | /* To delete a label, we just invert the magic numbers */ | | 136 | /* To delete a label, we just invert the magic numbers */ |
137 | #define DISKMAGIC_DELETED (~DISKMAGIC) | | 137 | #define DISKMAGIC_DELETED (~DISKMAGIC) |
138 | #define DISKMAGIC_DELETED_REV bswap32(~DISKMAGIC) | | 138 | #define DISKMAGIC_DELETED_REV bswap32(~DISKMAGIC) |
139 | | | 139 | |
140 | #define DEFEDITOR _PATH_VI | | 140 | #define DEFEDITOR _PATH_VI |
141 | | | 141 | |
142 | char specname[MAXPATHLEN]; | | 142 | char specname[MAXPATHLEN]; |
143 | | | 143 | |
144 | /* Some global data, all too hard to pass about */ | | 144 | /* Some global data, all too hard to pass about */ |
145 | char bootarea[BBSIZE]; /* Buffer matching part of disk */ | | 145 | char bootarea[BBSIZE]; /* Buffer matching part of disk */ |
146 | int bootarea_len; /* Number of bytes we actually read */ | | 146 | int bootarea_len; /* Number of bytes we actually read */ |
147 | static struct disklabel lab; /* The label we have updated */ | | 147 | static struct disklabel lab; /* The label we have updated */ |
148 | | | 148 | |
149 | static int Aflag; /* Action all labels */ | | 149 | static int Aflag; /* Action all labels */ |
150 | static int Fflag; /* Read/write from file */ | | 150 | static int Fflag; /* Read/write from file */ |
151 | static int rflag; /* Read/write direct from disk */ | | 151 | static int rflag; /* Read/write direct from disk */ |
152 | static int tflag; /* Format output as disktab */ | | 152 | static int tflag; /* Format output as disktab */ |
153 | int Cflag; /* CHS format output */ | | 153 | int Cflag; /* CHS format output */ |
154 | static int Dflag; /* Delete old labels (use with write) */ | | 154 | static int Dflag; /* Delete old labels (use with write) */ |
155 | static int Iflag; /* Read/write direct, but default if absent */ | | 155 | static int Iflag; /* Read/write direct, but default if absent */ |
156 | static int lflag; /* List all known file system types and exit */ | | 156 | static int lflag; /* List all known file system types and exit */ |
157 | static int mflag; /* Expect disk to contain an MBR */ | | 157 | static int mflag; /* Expect disk to contain an MBR */ |
158 | static int verbose; | | 158 | static int verbose; |
159 | static int read_all; /* set if op = READ && Aflag */ | | 159 | static int read_all; /* set if op = READ && Aflag */ |
160 | | | 160 | |
161 | static int write_label(int); | | 161 | static int write_label(int); |
162 | static int readlabel_direct(int); | | 162 | static int readlabel_direct(int); |
163 | static void writelabel_direct(int); | | 163 | static void writelabel_direct(int); |
164 | static int update_label(int, u_int, u_int); | | 164 | static int update_label(int, u_int, u_int); |
165 | static struct disklabel *find_label(int, u_int); | | 165 | static struct disklabel *find_label(int, u_int); |
166 | static void getmachineparams(const char *); | | 166 | static void getmachineparams(const char *); |
167 | | | 167 | |
168 | static void makedisktab(FILE *, struct disklabel *); | | 168 | static void makedisktab(FILE *, struct disklabel *); |
169 | static void makelabel(const char *, const char *); | | 169 | static void makelabel(const char *, const char *); |
170 | static void l_perror(const char *); | | 170 | static void l_perror(const char *); |
171 | static void readlabel(int); | | 171 | static void readlabel(int); |
172 | static int edit(int); | | 172 | static int edit(int); |
173 | static int editit(const char *); | | 173 | static int editit(const char *); |
174 | static char *skip(char *); | | 174 | static char *skip(char *); |
175 | static char *word(char *); | | 175 | static char *word(char *); |
176 | static int getasciilabel(FILE *, struct disklabel *); | | 176 | static int getasciilabel(FILE *, struct disklabel *); |
177 | __dead static void usage(void); | | 177 | __dead static void usage(void); |
178 | static int qsort_strcmp(const void *, const void *); | | 178 | static int qsort_strcmp(const void *, const void *); |
179 | static int getulong(const char *, char, char **, | | 179 | static int getulong(const char *, char, char **, |
180 | unsigned long *, unsigned long); | | 180 | unsigned long *, unsigned long); |
181 | #define GETNUM32(a, v) getulong(a, '\0', NULL, v, UINT32_MAX) | | 181 | #define GETNUM32(a, v) getulong(a, '\0', NULL, v, UINT32_MAX) |
182 | #define GETNUM16(a, v) getulong(a, '\0', NULL, v, UINT16_MAX) | | 182 | #define GETNUM16(a, v) getulong(a, '\0', NULL, v, UINT16_MAX) |
183 | #define GETNUM8(a, v) getulong(a, '\0', NULL, v, UINT8_MAX) | | 183 | #define GETNUM8(a, v) getulong(a, '\0', NULL, v, UINT8_MAX) |
184 | | | 184 | |
185 | static int set_writable_fd = -1; | | 185 | static int set_writable_fd = -1; |
186 | | | 186 | |
187 | static u_int labeloffset; | | 187 | static u_int labeloffset; |
188 | static u_int labelsector; | | 188 | static u_int labelsector; |
189 | static int labelusesmbr; | | 189 | static int labelusesmbr; |
190 | u_int maxpartitions; | | 190 | u_int maxpartitions; |
191 | static int byteorder; | | 191 | static int byteorder; |
192 | | | 192 | |
193 | static int biendian_p; | | 193 | static int biendian_p; |
194 | #ifndef HAVE_NBTOOL_CONFIG_H | | 194 | #ifndef HAVE_NBTOOL_CONFIG_H |
195 | static int native_p = 1; | | 195 | static int native_p = 1; |
196 | #endif | | 196 | #endif |
197 | int bswap_p; | | 197 | int bswap_p; |
198 | | | 198 | |
199 | static const struct disklabel_params { | | 199 | static const struct disklabel_params { |
200 | const char *machine; | | 200 | const char *machine; |
201 | int labelusesmbr; | | 201 | int labelusesmbr; |
202 | u_int labelsector; | | 202 | u_int labelsector; |
203 | u_int labeloffset; | | 203 | u_int labeloffset; |
204 | u_int maxpartitions; | | 204 | u_int maxpartitions; |
205 | u_int raw_part; | | 205 | u_int raw_part; |
206 | u_int oldmaxpartitions; | | 206 | u_int oldmaxpartitions; |
207 | int byteorder; | | 207 | int byteorder; |
208 | } disklabel_params[] = { | | 208 | } disklabel_params[] = { |
209 | { "mvme68k", 0, 0, 0, 8, 2, 0, BIG_ENDIAN }, /* m68k */ | | 209 | { "mvme68k", 0, 0, 0, 8, 2, 0, BIG_ENDIAN }, /* m68k */ |
210 | { "next68k", 0, 0, 0, 8, 2, 0, BIG_ENDIAN }, /* m68k */ | | 210 | { "next68k", 0, 0, 0, 8, 2, 0, BIG_ENDIAN }, /* m68k */ |
211 | | | 211 | |
212 | { "algor", 0, 0, 64, 8, 2, 0, LITTLE_ENDIAN }, /* mips */ | | 212 | { "algor", 0, 0, 64, 8, 2, 0, LITTLE_ENDIAN }, /* mips */ |
213 | { "alpha", 0, 0, 64, 8, 2, 0, LITTLE_ENDIAN }, /* alpha */ | | 213 | { "alpha", 0, 0, 64, 8, 2, 0, LITTLE_ENDIAN }, /* alpha */ |
214 | { "luna68k", 0, 0, 64, 8, 2, 0, BIG_ENDIAN }, /* m68k */ | | 214 | { "luna68k", 0, 0, 64, 8, 2, 0, BIG_ENDIAN }, /* m68k */ |
215 | { "mac68k", 0, 0, 64, 8, 2, 0, BIG_ENDIAN }, /* m68k */ | | 215 | { "mac68k", 0, 0, 64, 8, 2, 0, BIG_ENDIAN }, /* m68k */ |
216 | { "news68k", 0, 0, 64, 8, 2, 0, BIG_ENDIAN }, /* m68k */ | | 216 | { "news68k", 0, 0, 64, 8, 2, 0, BIG_ENDIAN }, /* m68k */ |
217 | { "newsmips", 0, 0, 64, 8, 2, 0, BIG_ENDIAN }, /* mips */ | | 217 | { "newsmips", 0, 0, 64, 8, 2, 0, BIG_ENDIAN }, /* mips */ |
218 | { "pmax", 0, 0, 64, 8, 2, 0, LITTLE_ENDIAN }, /* mips */ | | 218 | { "pmax", 0, 0, 64, 8, 2, 0, LITTLE_ENDIAN }, /* mips */ |
219 | { "sun2", 0, 0, 64, 8, 2, 0, BIG_ENDIAN }, /* m68k */ | | 219 | { "sun2", 0, 0, 64, 8, 2, 0, BIG_ENDIAN }, /* m68k */ |
220 | { "sun68k", 0, 0, 64, 8, 2, 0, BIG_ENDIAN }, /* m68010 */ | | 220 | { "sun68k", 0, 0, 64, 8, 2, 0, BIG_ENDIAN }, /* m68010 */ |
221 | { "x68k", 0, 0, 64, 8, 2, 0, BIG_ENDIAN }, /* m68010 */ | | 221 | { "x68k", 0, 0, 64, 8, 2, 0, BIG_ENDIAN }, /* m68010 */ |
222 | | | 222 | |
223 | { "vax", 0, 0, 64, 12, 2, 8, LITTLE_ENDIAN }, /* vax */ | | 223 | { "vax", 0, 0, 64, 12, 2, 8, LITTLE_ENDIAN }, /* vax */ |
224 | | | 224 | |
225 | { "amiga", 0, 0, 64, 16, 2, 0, BIG_ENDIAN }, /* m68k */ | | 225 | { "amiga", 0, 0, 64, 16, 2, 0, BIG_ENDIAN }, /* m68k */ |
226 | { "amigappc", 0, 0, 64, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ | | 226 | { "amigappc", 0, 0, 64, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ |
227 | { "evbmips", 0, 0, 64, 16, 2, 0, 0 }, /* mips */ | | 227 | { "evbmips", 0, 0, 64, 16, 2, 0, 0 }, /* mips */ |
228 | { "evbppc", 0, 0, 64, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ | | 228 | { "evbppc", 0, 0, 64, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ |
229 | | | 229 | |
230 | { "sparc", 0, 0, 128, 8, 2, 0, BIG_ENDIAN }, /* sun */ | | 230 | { "sparc", 0, 0, 128, 8, 2, 0, BIG_ENDIAN }, /* sun */ |
231 | { "sparc64", 0, 0, 128, 8, 2, 0, BIG_ENDIAN }, /* sun */ | | 231 | { "sparc64", 0, 0, 128, 8, 2, 0, BIG_ENDIAN }, /* sun */ |
232 | { "sun3", 0, 0, 128, 8, 2, 0, BIG_ENDIAN }, /* sun */ | | 232 | { "sun3", 0, 0, 128, 8, 2, 0, BIG_ENDIAN }, /* sun */ |
233 | | | 233 | |
234 | { "atari", 0, 0, 516, 16, 2, 0, BIG_ENDIAN }, /* m68k */ | | 234 | { "atari", 0, 0, 516, 16, 2, 0, BIG_ENDIAN }, /* m68k */ |
235 | | | 235 | |
236 | { "mipsco", 0, 1, 0, 8, 2, 0, BIG_ENDIAN }, /* mips */ | | 236 | { "mipsco", 0, 1, 0, 8, 2, 0, BIG_ENDIAN }, /* mips */ |
237 | { "mvmeppc", 0, 1, 0, 8, 3, 0, BIG_ENDIAN }, /* powerpc */ | | 237 | { "mvmeppc", 0, 1, 0, 8, 3, 0, BIG_ENDIAN }, /* powerpc */ |
238 | | | 238 | |
239 | { "bebox", 0, 1, 0, 8, 3, 0, BIG_ENDIAN }, /* powerpc */ | | 239 | { "bebox", 0, 1, 0, 8, 3, 0, BIG_ENDIAN }, /* powerpc */ |
240 | | | 240 | |
241 | { "emips", 0, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* mips */ | | 241 | { "emips", 0, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* mips */ |
242 | { "hp700", 0, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* hppa */ | | 242 | { "hp700", 0, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* hppa */ |
243 | { "ibmnws", 0, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ | | 243 | { "ibmnws", 0, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ |
244 | { "ofppc", 0, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ | | 244 | { "ofppc", 0, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ |
245 | { "rs6000", 0, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ | | 245 | { "rs6000", 0, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ |
246 | { "sandpoint", 0, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ | | 246 | { "sandpoint", 0, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ |
247 | { "sgimips", 0, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* mips */ | | 247 | { "sgimips", 0, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* mips */ |
248 | | | 248 | |
249 | { "sbmips", 0, 1, 0, 16, 3, 0, 0 }, /* mips */ | | 249 | { "sbmips", 0, 1, 0, 16, 3, 0, 0 }, /* mips */ |
250 | | | 250 | |
251 | { "cesfic", 0, 2, 0, 8, 2, 0, BIG_ENDIAN }, /* m68k */ | | 251 | { "cesfic", 0, 2, 0, 8, 2, 0, BIG_ENDIAN }, /* m68k */ |
252 | { "hp300", 0, 2, 0, 8, 2, 0, BIG_ENDIAN }, /* m68k */ | | 252 | { "hp300", 0, 2, 0, 8, 2, 0, BIG_ENDIAN }, /* m68k */ |
253 | | | 253 | |
254 | { "ews4800mips",0, 9, 0, 16, 15, 0, BIG_ENDIAN }, /* mips */ | | 254 | { "ews4800mips",0, 9, 0, 16, 15, 0, BIG_ENDIAN }, /* mips */ |
255 | | | 255 | |
256 | { "macppc", 1, 0, 64, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ | | 256 | { "macppc", 1, 0, 64, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ |
257 | { "pmon", 1, 0, 64, 16, 2, 0, 0 }, /* evbmips */ | | 257 | { "pmon", 1, 0, 64, 16, 2, 0, 0 }, /* evbmips */ |
258 | | | 258 | |
259 | { "prep", 1, 1, 0, 8, 2, 0, BIG_ENDIAN }, /* powerpc */ | | 259 | { "prep", 1, 1, 0, 8, 2, 0, BIG_ENDIAN }, /* powerpc */ |
260 | | | 260 | |
261 | { "dreadmcast", 1, 1, 0, 16, 2, 0, LITTLE_ENDIAN }, /* sh3 */ | | 261 | { "dreadmcast", 1, 1, 0, 16, 2, 0, LITTLE_ENDIAN }, /* sh3 */ |
262 | { "evbsh3", 1, 1, 0, 16, 2, 0, 0 }, /* sh3 */ | | 262 | { "evbsh3", 1, 1, 0, 16, 2, 0, 0 }, /* sh3 */ |
263 | { "hpcsh", 1, 1, 0, 16, 2, 0, LITTLE_ENDIAN }, /* sh3 */ | | 263 | { "hpcsh", 1, 1, 0, 16, 2, 0, LITTLE_ENDIAN }, /* sh3 */ |
264 | { "evbppc-mbr", 1, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ | | 264 | { "evbppc-mbr", 1, 1, 0, 16, 2, 0, BIG_ENDIAN }, /* powerpc */ |
265 | { "mmeye", 1, 1, 0, 16, 2, 0, 0 }, /* sh3 */ | | 265 | { "mmeye", 1, 1, 0, 16, 2, 0, 0 }, /* sh3 */ |
266 | | | 266 | |
267 | { "acorn26", 1, 1, 0, 16, 2, 8, LITTLE_ENDIAN }, /* arm */ | | 267 | { "acorn26", 1, 1, 0, 16, 2, 8, LITTLE_ENDIAN }, /* arm */ |
268 | { "acorn32", 1, 1, 0, 16, 2, 8, LITTLE_ENDIAN }, /* arm */ | | 268 | { "acorn32", 1, 1, 0, 16, 2, 8, LITTLE_ENDIAN }, /* arm */ |
269 | { "cats", 1, 1, 0, 16, 2, 8, LITTLE_ENDIAN }, /* arm */ | | 269 | { "cats", 1, 1, 0, 16, 2, 8, LITTLE_ENDIAN }, /* arm */ |
270 | { "evbarm", 1, 1, 0, 16, 2, 8, 0 }, /* arm */ | | 270 | { "evbarm", 1, 1, 0, 16, 2, 8, 0 }, /* arm */ |
271 | { "iyonix", 1, 1, 0, 16, 2, 8, LITTLE_ENDIAN }, /* arm */ | | 271 | { "iyonix", 1, 1, 0, 16, 2, 8, LITTLE_ENDIAN }, /* arm */ |
272 | { "netwinder", 1, 1, 0, 16, 2, 8, LITTLE_ENDIAN }, /* arm */ | | 272 | { "netwinder", 1, 1, 0, 16, 2, 8, LITTLE_ENDIAN }, /* arm */ |
273 | { "shark", 1, 1, 0, 16, 2, 8, LITTLE_ENDIAN }, /* arm */ | | 273 | { "shark", 1, 1, 0, 16, 2, 8, LITTLE_ENDIAN }, /* arm */ |
274 | | | 274 | |
275 | { "amd64", 1, 1, 0, 16, 3, 0, LITTLE_ENDIAN }, /* x86 */ | | 275 | { "amd64", 1, 1, 0, 16, 3, 0, LITTLE_ENDIAN }, /* x86 */ |
276 | { "arc", 1, 1, 0, 16, 3, 0, LITTLE_ENDIAN }, /* mips */ | | 276 | { "arc", 1, 1, 0, 16, 3, 0, LITTLE_ENDIAN }, /* mips */ |
277 | { "cobalt", 1, 1, 0, 16, 3, 0, LITTLE_ENDIAN }, /* mips */ | | 277 | { "cobalt", 1, 1, 0, 16, 3, 0, LITTLE_ENDIAN }, /* mips */ |
278 | { "landisk", 1, 1, 0, 16, 3, 0, LITTLE_ENDIAN }, /* sh3 */ | | 278 | { "landisk", 1, 1, 0, 16, 3, 0, LITTLE_ENDIAN }, /* sh3 */ |
279 | | | 279 | |
280 | { "epoc32", 1, 1, 0, 16, 3, 8, LITTLE_ENDIAN }, /* arm */ | | 280 | { "epoc32", 1, 1, 0, 16, 3, 8, LITTLE_ENDIAN }, /* arm */ |
281 | { "hpcarm", 1, 1, 0, 16, 3, 8, LITTLE_ENDIAN }, /* arm */ | | 281 | { "hpcarm", 1, 1, 0, 16, 3, 8, LITTLE_ENDIAN }, /* arm */ |
282 | { "hpcmips", 1, 1, 0, 16, 3, 8, LITTLE_ENDIAN }, /* mips */ | | 282 | { "hpcmips", 1, 1, 0, 16, 3, 8, LITTLE_ENDIAN }, /* mips */ |
283 | { "i386", 1, 1, 0, 16, 3, 8, LITTLE_ENDIAN }, /* x86 */ | | 283 | { "i386", 1, 1, 0, 16, 3, 8, LITTLE_ENDIAN }, /* x86 */ |
284 | { "ia64", 1, 1, 0, 16, 3, 8, LITTLE_ENDIAN }, /* x86 */ | | 284 | { "ia64", 1, 1, 0, 16, 3, 8, LITTLE_ENDIAN }, /* x86 */ |
285 | { "zaurus", 1, 1, 0, 16, 3, 8, LITTLE_ENDIAN }, /* arm */ | | 285 | { "zaurus", 1, 1, 0, 16, 3, 8, LITTLE_ENDIAN }, /* arm */ |
286 | | | 286 | |
287 | { NULL, 0, 0, 0, 0, 0, 0, 0 }, /* must be last */ | | 287 | { NULL, 0, 0, 0, 0, 0, 0, 0 }, /* must be last */ |
288 | }; | | 288 | }; |
289 | | | 289 | |
290 | #ifndef HAVE_NBTOOL_CONFIG_H | | 290 | #ifndef HAVE_NBTOOL_CONFIG_H |
291 | static struct disklabel_params native_params; | | 291 | static struct disklabel_params native_params; |
292 | #endif | | 292 | #endif |
293 | | | 293 | |
294 | static const struct arch_endian { | | 294 | static const struct arch_endian { |
295 | int byteorder; | | 295 | int byteorder; |
296 | const char *arch; | | 296 | const char *arch; |
297 | } arch_endians[] = { | | 297 | } arch_endians[] = { |
298 | { LITTLE_ENDIAN, "alpha" }, | | 298 | { LITTLE_ENDIAN, "alpha" }, |
299 | { LITTLE_ENDIAN, "arm" }, | | 299 | { LITTLE_ENDIAN, "arm" }, |
300 | { LITTLE_ENDIAN, "earm" }, | | 300 | { LITTLE_ENDIAN, "earm" }, |
301 | { LITTLE_ENDIAN, "earmhf" }, | | 301 | { LITTLE_ENDIAN, "earmhf" }, |
302 | { LITTLE_ENDIAN, "i386" }, | | 302 | { LITTLE_ENDIAN, "i386" }, |
303 | { LITTLE_ENDIAN, "ia64" }, | | 303 | { LITTLE_ENDIAN, "ia64" }, |
304 | { LITTLE_ENDIAN, "mipsel" }, | | 304 | { LITTLE_ENDIAN, "mipsel" }, |
305 | { LITTLE_ENDIAN, "mips64el" }, | | 305 | { LITTLE_ENDIAN, "mips64el" }, |
306 | { LITTLE_ENDIAN, "sh3el" }, | | 306 | { LITTLE_ENDIAN, "sh3el" }, |
307 | { LITTLE_ENDIAN, "vax" }, | | 307 | { LITTLE_ENDIAN, "vax" }, |
308 | | | 308 | |
309 | { BIG_ENDIAN, "armeb" }, | | 309 | { BIG_ENDIAN, "armeb" }, |
310 | { BIG_ENDIAN, "earmeb" }, | | 310 | { BIG_ENDIAN, "earmeb" }, |
311 | { BIG_ENDIAN, "earmhfeb" }, | | 311 | { BIG_ENDIAN, "earmhfeb" }, |
312 | { BIG_ENDIAN, "hppa" }, | | 312 | { BIG_ENDIAN, "hppa" }, |
313 | { BIG_ENDIAN, "m68k" }, | | 313 | { BIG_ENDIAN, "m68k" }, |
314 | { BIG_ENDIAN, "mipseb" }, | | 314 | { BIG_ENDIAN, "mipseb" }, |
315 | { BIG_ENDIAN, "mips64eb" }, | | 315 | { BIG_ENDIAN, "mips64eb" }, |
316 | { BIG_ENDIAN, "powerpc" }, | | 316 | { BIG_ENDIAN, "powerpc" }, |
317 | { BIG_ENDIAN, "sh3eb" }, | | 317 | { BIG_ENDIAN, "sh3eb" }, |
318 | { BIG_ENDIAN, "sparc" }, | | 318 | { BIG_ENDIAN, "sparc" }, |
319 | { BIG_ENDIAN, "sparc64" }, | | 319 | { BIG_ENDIAN, "sparc64" }, |
320 | | | 320 | |
321 | { 0, NULL }, | | 321 | { 0, NULL }, |
322 | }; | | 322 | }; |
323 | | | 323 | |
324 | /* Default location for label - only used if we don't find one to update */ | | 324 | /* Default location for label - only used if we don't find one to update */ |
325 | #define LABEL_OFFSET (dklabel_getlabelsector() * DEV_BSIZE + dklabel_getlabeloffset()) | | 325 | #define LABEL_OFFSET (dklabel_getlabelsector() * DEV_BSIZE + dklabel_getlabeloffset()) |
326 | | | 326 | |
327 | /* | | 327 | /* |
328 | * For portability it doesn't make sense to use any other value.... | | 328 | * For portability it doesn't make sense to use any other value.... |
329 | * Except, maybe, the size of a physical sector. | | 329 | * Except, maybe, the size of a physical sector. |
330 | * This value is used if we have to write a label to the start of an mbr ptn. | | 330 | * This value is used if we have to write a label to the start of an mbr ptn. |
331 | */ | | 331 | */ |
332 | #ifndef LABELOFFSET_MBR | | 332 | #ifndef LABELOFFSET_MBR |
333 | #define LABELOFFSET_MBR 512 | | 333 | #define LABELOFFSET_MBR 512 |
334 | #endif | | 334 | #endif |
335 | | | 335 | |
336 | #if HAVE_NBTOOL_CONFIG_H | | 336 | #if HAVE_NBTOOL_CONFIG_H |
337 | static int | | 337 | static int |
338 | opendisk(const char *path, int flags, char *buf, int buflen, int cooked) | | 338 | opendisk(const char *path, int flags, char *buf, int buflen, int cooked) |
339 | { | | 339 | { |
340 | int f; | | 340 | int f; |
341 | f = open(path, flags, 0); | | 341 | f = open(path, flags, 0); |
342 | strlcpy(buf, path, buflen); | | 342 | strlcpy(buf, path, buflen); |
343 | return f; | | 343 | return f; |
344 | } | | 344 | } |
345 | #endif /* HAVE_NBTOOL_CONFIG_H */ | | 345 | #endif /* HAVE_NBTOOL_CONFIG_H */ |
346 | | | 346 | |
347 | static void | | 347 | static void |
348 | setbyteorder(int new_byteorder) | | 348 | setbyteorder(int new_byteorder) |
349 | { | | 349 | { |
350 | static int set_p; | | 350 | static int set_p; |
351 | | | 351 | |
352 | if ((!biendian_p || set_p) | | 352 | if ((!biendian_p || set_p) |
353 | && byteorder != 0 | | 353 | && byteorder != 0 |
354 | && byteorder != new_byteorder) { | | 354 | && byteorder != new_byteorder) { |
355 | warn("changing %s byteorder to %s", | | 355 | warn("changing %s byteorder to %s", |
356 | byteorder == LITTLE_ENDIAN ? "le" : "be", | | 356 | byteorder == LITTLE_ENDIAN ? "le" : "be", |
357 | new_byteorder == LITTLE_ENDIAN ? "le" : "be"); | | 357 | new_byteorder == LITTLE_ENDIAN ? "le" : "be"); |
358 | } | | 358 | } |
359 | byteorder = new_byteorder; | | 359 | byteorder = new_byteorder; |
360 | biendian_p = 0; | | 360 | biendian_p = 0; |
361 | set_p = 1; | | 361 | set_p = 1; |
362 | } | | 362 | } |
363 | | | 363 | |
364 | static void | | 364 | static void |
365 | getmachineparams(const char *mach) | | 365 | getmachineparams(const char *mach) |
366 | { | | 366 | { |
367 | const struct disklabel_params *dp = disklabel_params; | | 367 | const struct disklabel_params *dp = disklabel_params; |
368 | for (; dp->machine != NULL; dp++) { | | 368 | for (; dp->machine != NULL; dp++) { |
369 | if (!strcmp(mach, dp->machine)) { | | 369 | if (!strcmp(mach, dp->machine)) { |
370 | labelusesmbr = dp->labelusesmbr; | | 370 | labelusesmbr = dp->labelusesmbr; |
371 | labelsector = dp->labelsector; | | 371 | labelsector = dp->labelsector; |
372 | labeloffset = dp->labeloffset; | | 372 | labeloffset = dp->labeloffset; |
373 | maxpartitions = dp->maxpartitions; | | 373 | maxpartitions = dp->maxpartitions; |
374 | biendian_p = (dp->byteorder == 0); | | 374 | biendian_p = (dp->byteorder == 0); |
375 | if (!biendian_p) | | 375 | if (!biendian_p) |
376 | setbyteorder(dp->byteorder); | | 376 | setbyteorder(dp->byteorder); |
377 | return; | | 377 | return; |
378 | } | | 378 | } |
379 | } | | 379 | } |
380 | errx(1, "%s: unknown machine type", mach); | | 380 | errx(1, "%s: unknown machine type", mach); |
381 | } | | 381 | } |
382 | | | 382 | |
383 | static void | | 383 | static void |
384 | getarchbyteorder(const char *arch) | | 384 | getarchbyteorder(const char *arch) |
385 | { | | 385 | { |
386 | const struct arch_endian *p = arch_endians; | | 386 | const struct arch_endian *p = arch_endians; |
387 | for (; p->arch != NULL; p++) { | | 387 | for (; p->arch != NULL; p++) { |
388 | if (!strcmp(arch, p->arch)) { | | 388 | if (!strcmp(arch, p->arch)) { |
389 | setbyteorder(p->byteorder); | | 389 | setbyteorder(p->byteorder); |
390 | return; | | 390 | return; |
391 | } | | 391 | } |
392 | } | | 392 | } |
393 | errx(1, "%s: unknown arch", arch); | | 393 | errx(1, "%s: unknown arch", arch); |
394 | } | | 394 | } |
395 | | | 395 | |
396 | static daddr_t | | 396 | static daddr_t |
397 | dklabel_getlabelsector(void) | | 397 | dklabel_getlabelsector(void) |
398 | { | | 398 | { |
399 | unsigned long int nval; | | 399 | unsigned long int nval; |
400 | char *end; | | 400 | char *end; |
401 | const char *val; | | 401 | const char *val; |
402 | | | 402 | |
403 | if ((val = getenv("DISKLABELSECTOR")) == NULL) | | 403 | if ((val = getenv("DISKLABELSECTOR")) == NULL) |
404 | return labelsector; | | 404 | return labelsector; |
405 | if ((nval = strtoul(val, &end, 10)) == ULONG_MAX && errno == ERANGE) | | 405 | if ((nval = strtoul(val, &end, 10)) == ULONG_MAX && errno == ERANGE) |
406 | err(EXIT_FAILURE, "DISKLABELSECTOR in environment"); | | 406 | err(EXIT_FAILURE, "DISKLABELSECTOR in environment"); |
407 | return nval; | | 407 | return nval; |
408 | } | | 408 | } |
409 | | | 409 | |
410 | static off_t | | 410 | static off_t |
411 | dklabel_getlabeloffset(void) | | 411 | dklabel_getlabeloffset(void) |
412 | { | | 412 | { |
413 | unsigned long int nval; | | 413 | unsigned long int nval; |
414 | char *end; | | 414 | char *end; |
415 | const char *val; | | 415 | const char *val; |
416 | | | 416 | |
417 | if ((val = getenv("DISKLABELOFFSET")) == NULL) | | 417 | if ((val = getenv("DISKLABELOFFSET")) == NULL) |
418 | return labeloffset; | | 418 | return labeloffset; |
419 | if ((nval = strtoul(val, &end, 10)) == ULONG_MAX && errno == ERANGE) | | 419 | if ((nval = strtoul(val, &end, 10)) == ULONG_MAX && errno == ERANGE) |
420 | err(EXIT_FAILURE, "DISKLABELOFFSET in environment"); | | 420 | err(EXIT_FAILURE, "DISKLABELOFFSET in environment"); |
421 | return nval; | | 421 | return nval; |
422 | } | | 422 | } |
423 | | | 423 | |
424 | static void | | 424 | static void |
425 | clear_writable(void) | | 425 | clear_writable(void) |
426 | { | | 426 | { |
427 | static int zero = 0; | | 427 | static int zero = 0; |
428 | dk_ioctl(set_writable_fd, DIOCWLABEL, &zero); | | 428 | dk_ioctl(set_writable_fd, DIOCWLABEL, &zero); |
429 | } | | 429 | } |
430 | | | 430 | |
431 | int | | 431 | int |
432 | main(int argc, char *argv[]) | | 432 | main(int argc, char *argv[]) |
433 | { | | 433 | { |
434 | FILE *t; | | 434 | FILE *t; |
435 | int ch, f, error; | | 435 | int ch, f, error; |
436 | char *dkname; | | 436 | char *dkname; |
437 | char *cp; | | 437 | char *cp; |
438 | struct stat sb; | | 438 | struct stat sb; |
439 | int writable; | | 439 | int writable; |
440 | enum { | | 440 | enum { |
441 | UNSPEC, EDIT, READ, RESTORE, SETWRITABLE, SETREADONLY, | | 441 | UNSPEC, EDIT, READ, RESTORE, SETWRITABLE, SETREADONLY, |
442 | WRITE, INTERACT, DELETE | | 442 | WRITE, INTERACT, DELETE |
443 | } op = UNSPEC, old_op; | | 443 | } op = UNSPEC, old_op; |
444 | | | 444 | |
445 | #ifndef HAVE_NBTOOL_CONFIG_H | | 445 | #ifndef HAVE_NBTOOL_CONFIG_H |
446 | labeloffset = native_params.labeloffset = getlabeloffset(); | | 446 | labeloffset = native_params.labeloffset = getlabeloffset(); |
447 | labelsector = native_params.labelsector = getlabelsector(); | | 447 | labelsector = native_params.labelsector = getlabelsector(); |
448 | labelusesmbr = native_params.labelusesmbr = getlabelusesmbr(); | | 448 | labelusesmbr = native_params.labelusesmbr = getlabelusesmbr(); |
449 | maxpartitions = native_params.maxpartitions = getmaxpartitions(); | | 449 | maxpartitions = native_params.maxpartitions = getmaxpartitions(); |
450 | native_params.byteorder = BYTE_ORDER; | | 450 | native_params.byteorder = BYTE_ORDER; |
451 | #endif | | 451 | #endif |
452 | | | 452 | |
453 | if ((cp = getenv("MACHINE")) != NULL) { | | 453 | if ((cp = getenv("MACHINE")) != NULL) { |
454 | getmachineparams(cp); | | 454 | getmachineparams(cp); |
455 | } | | 455 | } |
456 | | | 456 | |
457 | if ((cp = getenv("MACHINE_ARCH")) != NULL) { | | 457 | if ((cp = getenv("MACHINE_ARCH")) != NULL) { |
458 | getarchbyteorder(cp); | | 458 | getarchbyteorder(cp); |
459 | } | | 459 | } |
460 | | | 460 | |
461 | mflag = labelusesmbr; | | 461 | mflag = labelusesmbr; |
462 | if (mflag < 0) { | | 462 | if (mflag < 0) { |
463 | #if HAVE_NBTOOL_CONFIG_H | | 463 | #if HAVE_NBTOOL_CONFIG_H |
464 | warn("getlabelusesmbr() failed"); | | 464 | warn("getlabelusesmbr() failed"); |
465 | #else | | 465 | #else |
466 | warn("getlabelusesmbr() failed"); | | 466 | warn("getlabelusesmbr() failed"); |
467 | mflag = LABELUSESMBR; | | 467 | mflag = LABELUSESMBR; |
468 | #endif | | 468 | #endif |
469 | } | | 469 | } |
470 | #if HAVE_NBTOOL_CONFIG_H | | 470 | #if HAVE_NBTOOL_CONFIG_H |
471 | /* We must avoid doing any ioctl requests */ | | 471 | /* We must avoid doing any ioctl requests */ |
472 | Fflag = rflag = 1; | | 472 | Fflag = rflag = 1; |
473 | #endif | | 473 | #endif |
474 | | | 474 | |
475 | error = 0; | | 475 | error = 0; |
476 | while ((ch = getopt(argc, argv, "AB:CDFIM:NRWef:ilmrtvw")) != -1) { | | 476 | while ((ch = getopt(argc, argv, "AB:CDFIM:NRWef:ilmrtvw")) != -1) { |
477 | old_op = op; | | 477 | old_op = op; |
478 | switch (ch) { | | 478 | switch (ch) { |
479 | case 'A': /* Action all labels */ | | 479 | case 'A': /* Action all labels */ |
480 | Aflag = 1; | | 480 | Aflag = 1; |
481 | rflag = 1; | | 481 | rflag = 1; |
482 | break; | | 482 | break; |
483 | case 'C': /* Display in CHS format */ | | 483 | case 'C': /* Display in CHS format */ |
484 | Cflag = 1; | | 484 | Cflag = 1; |
485 | break; | | 485 | break; |
486 | case 'D': /* Delete all existing labels */ | | 486 | case 'D': /* Delete all existing labels */ |
487 | Dflag = 1; | | 487 | Dflag = 1; |
488 | rflag = 1; | | 488 | rflag = 1; |
489 | break; | | 489 | break; |
490 | case 'F': /* Treat 'disk' as a regular file */ | | 490 | case 'F': /* Treat 'disk' as a regular file */ |
491 | Fflag = 1; | | 491 | Fflag = 1; |
492 | rflag = 1; /* Force direct access */ | | 492 | rflag = 1; /* Force direct access */ |
493 | break; | | 493 | break; |
494 | case 'I': /* Use default label if none found */ | | 494 | case 'I': /* Use default label if none found */ |
495 | Iflag = 1; | | 495 | Iflag = 1; |
496 | rflag = 1; /* Implies direct access */ | | 496 | rflag = 1; /* Implies direct access */ |
497 | break; | | 497 | break; |
498 | case 'R': /* Restore label from text file */ | | 498 | case 'R': /* Restore label from text file */ |
499 | op = RESTORE; | | 499 | op = RESTORE; |
500 | break; | | 500 | break; |
501 | case 'B': /* byteorder */ | | 501 | case 'B': /* byteorder */ |
502 | if (!strcmp(optarg, "be")) { | | 502 | if (!strcmp(optarg, "be")) { |
503 | setbyteorder(BIG_ENDIAN); | | 503 | setbyteorder(BIG_ENDIAN); |
504 | } else if (!strcmp(optarg, "le")) { | | 504 | } else if (!strcmp(optarg, "le")) { |
505 | setbyteorder(LITTLE_ENDIAN); | | 505 | setbyteorder(LITTLE_ENDIAN); |
506 | } else { | | 506 | } else { |
507 | errx(1, "%s: not be or le", optarg); | | 507 | errx(1, "%s: not be or le", optarg); |
508 | } | | 508 | } |
509 | break; | | 509 | break; |
510 | case 'M': /* machine type */ | | 510 | case 'M': /* machine type */ |
511 | getmachineparams(optarg); | | 511 | getmachineparams(optarg); |
512 | break; | | 512 | break; |
513 | case 'N': /* Disallow writes to label sector */ | | 513 | case 'N': /* Disallow writes to label sector */ |
514 | op = SETREADONLY; | | 514 | op = SETREADONLY; |
515 | break; | | 515 | break; |
516 | case 'W': /* Allow writes to label sector */ | | 516 | case 'W': /* Allow writes to label sector */ |
517 | op = SETWRITABLE; | | 517 | op = SETWRITABLE; |
518 | break; | | 518 | break; |
519 | case 'e': /* Edit label with $EDITOR */ | | 519 | case 'e': /* Edit label with $EDITOR */ |
520 | op = EDIT; | | 520 | op = EDIT; |
521 | break; | | 521 | break; |
522 | case 'f': /* Name of disktab file */ | | 522 | case 'f': /* Name of disktab file */ |
523 | if (setdisktab(optarg) == -1) | | 523 | if (setdisktab(optarg) == -1) |
524 | usage(); | | 524 | usage(); |
525 | break; | | 525 | break; |
526 | case 'i': /* Edit using built-in editor */ | | 526 | case 'i': /* Edit using built-in editor */ |
527 | op = INTERACT; | | 527 | op = INTERACT; |
528 | break; | | 528 | break; |
529 | case 'l': /* List all known file system types and exit */ | | 529 | case 'l': /* List all known file system types and exit */ |
530 | lflag = 1; | | 530 | lflag = 1; |
531 | break; | | 531 | break; |
532 | case 'm': /* Expect disk to have an MBR */ | | 532 | case 'm': /* Expect disk to have an MBR */ |
533 | mflag ^= 1; | | 533 | mflag ^= 1; |
534 | break; | | 534 | break; |
535 | case 'r': /* Read/write label directly from disk */ | | 535 | case 'r': /* Read/write label directly from disk */ |
536 | rflag = 1; | | 536 | rflag = 1; |
537 | break; | | 537 | break; |
538 | case 't': /* Format output as a disktab entry */ | | 538 | case 't': /* Format output as a disktab entry */ |
539 | tflag = 1; | | 539 | tflag = 1; |
540 | break; | | 540 | break; |
541 | case 'v': /* verbose/diag output */ | | 541 | case 'v': /* verbose/diag output */ |
542 | verbose++; | | 542 | verbose++; |
543 | break; | | 543 | break; |
544 | case 'w': /* Write label based on disktab entry */ | | 544 | case 'w': /* Write label based on disktab entry */ |
545 | op = WRITE; | | 545 | op = WRITE; |
546 | break; | | 546 | break; |
547 | case '?': | | 547 | case '?': |
548 | default: | | 548 | default: |
549 | usage(); | | 549 | usage(); |
550 | } | | 550 | } |
551 | if (old_op != UNSPEC && old_op != op) | | 551 | if (old_op != UNSPEC && old_op != op) |
552 | usage(); | | 552 | usage(); |
553 | } | | 553 | } |
554 | | | 554 | |
555 | if (maxpartitions == 0) { | | 555 | if (maxpartitions == 0) { |
556 | errx(1, "unknown label: use -M/-B and $MACHINE/$MACHINE_ARCH"); | | 556 | errx(1, "unknown label: use -M/-B and $MACHINE/$MACHINE_ARCH"); |
557 | } | | 557 | } |
558 | if (byteorder != BIG_ENDIAN && byteorder != LITTLE_ENDIAN) { | | 558 | if (byteorder != BIG_ENDIAN && byteorder != LITTLE_ENDIAN) { |
559 | errx(1, "unknown byteorder"); | | 559 | errx(1, "unknown byteorder"); |
560 | } | | 560 | } |
561 | bswap_p = (byteorder != BYTE_ORDER); | | 561 | bswap_p = (byteorder != BYTE_ORDER); |
562 | #ifdef DEBUG | | 562 | #ifdef DEBUG |
563 | printf("labelusesmbr=%d labelsector=%u labeloffset=%u maxparitions=%u\n", | | 563 | printf("labelusesmbr=%d labelsector=%u labeloffset=%u maxpartitions=%u\n", |
564 | labelusesmbr, labelsector, labeloffset, maxpartitions); | | 564 | labelusesmbr, labelsector, labeloffset, maxpartitions); |
565 | printf("byteorder=%d bswap_p=%d\n", byteorder, bswap_p); | | 565 | printf("byteorder=%d bswap_p=%d\n", byteorder, bswap_p); |
566 | #endif | | 566 | #endif |
567 | #ifndef HAVE_NBTOOL_CONFIG_H | | 567 | #ifndef HAVE_NBTOOL_CONFIG_H |
568 | /* | | 568 | /* |
569 | * If the disklabel has the same location as the native disklabel and | | 569 | * If the disklabel has the same location as the native disklabel and |
570 | * fewer or equal paritions, we can use the native ioctls. Otherwise | | 570 | * fewer or equal paritions, we can use the native ioctls. Otherwise |
571 | * force file/raw access. | | 571 | * force file/raw access. |
572 | */ | | 572 | */ |
573 | native_p = native_params.labelusesmbr == labelusesmbr | | 573 | native_p = native_params.labelusesmbr == labelusesmbr |
574 | && native_params.labelsector == labelsector | | 574 | && native_params.labelsector == labelsector |
575 | && native_params.labeloffset == labeloffset | | 575 | && native_params.labeloffset == labeloffset |
576 | && maxparitions <= native_params.maxpartitions | | 576 | && maxpartitions <= native_params.maxpartitions |
577 | && !bswap_p; | | 577 | && !bswap_p; |
578 | if (!native_p) | | 578 | if (!native_p) |
579 | Fflag = rflag = 1; | | 579 | Fflag = rflag = 1; |
580 | #endif | | 580 | #endif |
581 | | | 581 | |
582 | argc -= optind; | | 582 | argc -= optind; |
583 | argv += optind; | | 583 | argv += optind; |
584 | | | 584 | |
585 | if (lflag) | | 585 | if (lflag) |
586 | exit(list_fs_types() ? EXIT_SUCCESS : EXIT_FAILURE); | | 586 | exit(list_fs_types() ? EXIT_SUCCESS : EXIT_FAILURE); |
587 | | | 587 | |
588 | if (op == UNSPEC) | | 588 | if (op == UNSPEC) |
589 | op = Dflag ? DELETE : READ; | | 589 | op = Dflag ? DELETE : READ; |
590 | | | 590 | |
591 | if (argc < 1) | | 591 | if (argc < 1) |
592 | usage(); | | 592 | usage(); |
593 | | | 593 | |
594 | if (Iflag && op != EDIT && op != INTERACT) | | 594 | if (Iflag && op != EDIT && op != INTERACT) |
595 | usage(); | | 595 | usage(); |
596 | | | 596 | |
597 | dkname = argv[0]; | | 597 | dkname = argv[0]; |
598 | f = opendisk(dkname, op == READ ? O_RDONLY : O_RDWR, | | 598 | f = opendisk(dkname, op == READ ? O_RDONLY : O_RDWR, |
599 | specname, sizeof specname, 0); | | 599 | specname, sizeof specname, 0); |
600 | if (f < 0) | | 600 | if (f < 0) |
601 | err(4, "%s", specname); | | 601 | err(4, "%s", specname); |
602 | | | 602 | |
603 | if (!Fflag && fstat(f, &sb) == 0 && S_ISREG(sb.st_mode)) | | 603 | if (!Fflag && fstat(f, &sb) == 0 && S_ISREG(sb.st_mode)) |
604 | Fflag = rflag = 1; | | 604 | Fflag = rflag = 1; |
605 | | | 605 | |
606 | switch (op) { | | 606 | switch (op) { |
607 | | | 607 | |
608 | case DELETE: /* Remove all existing labels */ | | 608 | case DELETE: /* Remove all existing labels */ |
609 | if (argc != 1) | | 609 | if (argc != 1) |
610 | usage(); | | 610 | usage(); |
611 | Dflag = 2; | | 611 | Dflag = 2; |
612 | writelabel_direct(f); | | 612 | writelabel_direct(f); |
613 | break; | | 613 | break; |
614 | | | 614 | |
615 | case EDIT: | | 615 | case EDIT: |
616 | if (argc != 1) | | 616 | if (argc != 1) |
617 | usage(); | | 617 | usage(); |
618 | readlabel(f); | | 618 | readlabel(f); |
619 | error = edit(f); | | 619 | error = edit(f); |
620 | break; | | 620 | break; |
621 | | | 621 | |
622 | case INTERACT: | | 622 | case INTERACT: |
623 | if (argc != 1) | | 623 | if (argc != 1) |
624 | usage(); | | 624 | usage(); |
625 | readlabel(f); | | 625 | readlabel(f); |
626 | /* | | 626 | /* |
627 | * XXX: Fill some default values so checklabel does not fail | | 627 | * XXX: Fill some default values so checklabel does not fail |
628 | */ | | 628 | */ |
629 | if (lab.d_bbsize == 0) | | 629 | if (lab.d_bbsize == 0) |
630 | lab.d_bbsize = BBSIZE; | | 630 | lab.d_bbsize = BBSIZE; |
631 | if (lab.d_sbsize == 0) | | 631 | if (lab.d_sbsize == 0) |
632 | lab.d_sbsize = SBLOCKSIZE; | | 632 | lab.d_sbsize = SBLOCKSIZE; |
633 | interact(&lab, f); | | 633 | interact(&lab, f); |
634 | break; | | 634 | break; |
635 | | | 635 | |
636 | case READ: | | 636 | case READ: |
637 | if (argc != 1) | | 637 | if (argc != 1) |
638 | usage(); | | 638 | usage(); |
639 | read_all = Aflag; | | 639 | read_all = Aflag; |
640 | readlabel(f); | | 640 | readlabel(f); |
641 | if (read_all) | | 641 | if (read_all) |
642 | /* Label got printed in the bowels of readlabel */ | | 642 | /* Label got printed in the bowels of readlabel */ |
643 | break; | | 643 | break; |
644 | if (tflag) | | 644 | if (tflag) |
645 | makedisktab(stdout, &lab); | | 645 | makedisktab(stdout, &lab); |
646 | else { | | 646 | else { |
647 | showinfo(stdout, &lab, specname); | | 647 | showinfo(stdout, &lab, specname); |
648 | showpartitions(stdout, &lab, Cflag); | | 648 | showpartitions(stdout, &lab, Cflag); |
649 | } | | 649 | } |
650 | error = checklabel(&lab); | | 650 | error = checklabel(&lab); |
651 | if (error) | | 651 | if (error) |
652 | error += 100; | | 652 | error += 100; |
653 | break; | | 653 | break; |
654 | | | 654 | |
655 | case RESTORE: | | 655 | case RESTORE: |
656 | if (argc != 2) | | 656 | if (argc != 2) |
657 | usage(); | | 657 | usage(); |
658 | if (!(t = fopen(argv[1], "r"))) | | 658 | if (!(t = fopen(argv[1], "r"))) |
659 | err(4, "%s", argv[1]); | | 659 | err(4, "%s", argv[1]); |
660 | if (getasciilabel(t, &lab)) | | 660 | if (getasciilabel(t, &lab)) |
661 | error = write_label(f); | | 661 | error = write_label(f); |
662 | else | | 662 | else |
663 | error = 1; | | 663 | error = 1; |
664 | break; | | 664 | break; |
665 | | | 665 | |
666 | case SETREADONLY: | | 666 | case SETREADONLY: |
667 | writable = 0; | | 667 | writable = 0; |
668 | goto do_diocwlabel; | | 668 | goto do_diocwlabel; |
669 | case SETWRITABLE: | | 669 | case SETWRITABLE: |
670 | writable = 1; | | 670 | writable = 1; |
671 | do_diocwlabel: | | 671 | do_diocwlabel: |
672 | if (argc != 1) | | 672 | if (argc != 1) |
673 | usage(); | | 673 | usage(); |
674 | if (dk_ioctl(f, DIOCWLABEL, &writable) < 0) | | 674 | if (dk_ioctl(f, DIOCWLABEL, &writable) < 0) |
675 | err(4, "ioctl DIOCWLABEL"); | | 675 | err(4, "ioctl DIOCWLABEL"); |
676 | break; | | 676 | break; |
677 | | | 677 | |
678 | case WRITE: /* Create label from /etc/disktab entry & write */ | | 678 | case WRITE: /* Create label from /etc/disktab entry & write */ |
679 | if (argc < 2 || argc > 3) | | 679 | if (argc < 2 || argc > 3) |
680 | usage(); | | 680 | usage(); |
681 | makelabel(argv[1], argv[2]); | | 681 | makelabel(argv[1], argv[2]); |
682 | if (checklabel(&lab) == 0) | | 682 | if (checklabel(&lab) == 0) |
683 | error = write_label(f); | | 683 | error = write_label(f); |
684 | else | | 684 | else |
685 | error = 1; | | 685 | error = 1; |
686 | break; | | 686 | break; |
687 | | | 687 | |
688 | case UNSPEC: | | 688 | case UNSPEC: |
689 | usage(); | | 689 | usage(); |
690 | | | 690 | |
691 | } | | 691 | } |
692 | exit(error); | | 692 | exit(error); |
693 | } | | 693 | } |
694 | | | 694 | |
695 | /* | | 695 | /* |
696 | * Construct a prototype disklabel from /etc/disktab. | | 696 | * Construct a prototype disklabel from /etc/disktab. |
697 | */ | | 697 | */ |
698 | static void | | 698 | static void |
699 | makelabel(const char *type, const char *name) | | 699 | makelabel(const char *type, const char *name) |
700 | { | | 700 | { |
701 | struct disklabel *dp; | | 701 | struct disklabel *dp; |
702 | | | 702 | |
703 | dp = getdiskbyname(type); | | 703 | dp = getdiskbyname(type); |
704 | if (dp == NULL) | | 704 | if (dp == NULL) |
705 | errx(1, "unknown disk type: %s", type); | | 705 | errx(1, "unknown disk type: %s", type); |
706 | lab = *dp; | | 706 | lab = *dp; |
707 | | | 707 | |
708 | /* d_packname is union d_boot[01], so zero */ | | 708 | /* d_packname is union d_boot[01], so zero */ |
709 | (void)memset(lab.d_packname, 0, sizeof(lab.d_packname)); | | 709 | (void)memset(lab.d_packname, 0, sizeof(lab.d_packname)); |
710 | if (name) | | 710 | if (name) |
711 | (void)strncpy(lab.d_packname, name, sizeof(lab.d_packname)); | | 711 | (void)strncpy(lab.d_packname, name, sizeof(lab.d_packname)); |
712 | } | | 712 | } |
713 | | | 713 | |
714 | static int | | 714 | static int |
715 | write_label(int f) | | 715 | write_label(int f) |
716 | { | | 716 | { |
717 | int writable; | | 717 | int writable; |
718 | | | 718 | |
719 | lab.d_magic = DISKMAGIC; | | 719 | lab.d_magic = DISKMAGIC; |
720 | lab.d_magic2 = DISKMAGIC; | | 720 | lab.d_magic2 = DISKMAGIC; |
721 | lab.d_checksum = 0; | | 721 | lab.d_checksum = 0; |
722 | lab.d_checksum = dkcksum(&lab); | | 722 | lab.d_checksum = dkcksum(&lab); |
723 | | | 723 | |
724 | if (rflag) { | | 724 | if (rflag) { |
725 | /* Write the label directly to the disk */ | | 725 | /* Write the label directly to the disk */ |
726 | | | 726 | |
727 | /* | | 727 | /* |
728 | * First set the kernel disk label, | | 728 | * First set the kernel disk label, |
729 | * then write a label to the raw disk. | | 729 | * then write a label to the raw disk. |
730 | * If the SDINFO ioctl fails because it is unimplemented, | | 730 | * If the SDINFO ioctl fails because it is unimplemented, |
731 | * keep going; otherwise, the kernel consistency checks | | 731 | * keep going; otherwise, the kernel consistency checks |
732 | * may prevent us from changing the current (in-core) | | 732 | * may prevent us from changing the current (in-core) |
733 | * label. | | 733 | * label. |
734 | */ | | 734 | */ |
735 | if (!Fflag && dk_ioctl(f, DIOCSDINFO, &lab) < 0 && | | 735 | if (!Fflag && dk_ioctl(f, DIOCSDINFO, &lab) < 0 && |
736 | errno != ENODEV && errno != ENOTTY) { | | 736 | errno != ENODEV && errno != ENOTTY) { |
737 | l_perror("ioctl DIOCSDINFO"); | | 737 | l_perror("ioctl DIOCSDINFO"); |
738 | return (1); | | 738 | return (1); |
739 | } | | 739 | } |
740 | /* | | 740 | /* |
741 | * write enable label sector before write (if necessary), | | 741 | * write enable label sector before write (if necessary), |
742 | * disable after writing. | | 742 | * disable after writing. |
743 | */ | | 743 | */ |
744 | writable = 1; | | 744 | writable = 1; |
745 | if (!Fflag) { | | 745 | if (!Fflag) { |
746 | if (dk_ioctl(f, DIOCWLABEL, &writable) < 0) | | 746 | if (dk_ioctl(f, DIOCWLABEL, &writable) < 0) |
747 | perror("ioctl DIOCWLABEL"); | | 747 | perror("ioctl DIOCWLABEL"); |
748 | set_writable_fd = f; | | 748 | set_writable_fd = f; |
749 | atexit(clear_writable); | | 749 | atexit(clear_writable); |
750 | } | | 750 | } |
751 | | | 751 | |
752 | writelabel_direct(f); | | 752 | writelabel_direct(f); |
753 | | | 753 | |
754 | /* | | 754 | /* |
755 | * Now issue a DIOCWDINFO. This will let the kernel convert the | | 755 | * Now issue a DIOCWDINFO. This will let the kernel convert the |
756 | * disklabel to some machdep format if needed. | | 756 | * disklabel to some machdep format if needed. |
757 | */ | | 757 | */ |
758 | /* XXX: This is stupid! */ | | 758 | /* XXX: This is stupid! */ |
759 | if (!Fflag && dk_ioctl(f, DIOCWDINFO, &lab) < 0) { | | 759 | if (!Fflag && dk_ioctl(f, DIOCWDINFO, &lab) < 0) { |
760 | l_perror("ioctl DIOCWDINFO"); | | 760 | l_perror("ioctl DIOCWDINFO"); |
761 | return (1); | | 761 | return (1); |
762 | } | | 762 | } |
763 | } else { | | 763 | } else { |
764 | /* Get the kernel to write the label */ | | 764 | /* Get the kernel to write the label */ |
765 | if (dk_ioctl(f, DIOCWDINFO, &lab) < 0) { | | 765 | if (dk_ioctl(f, DIOCWDINFO, &lab) < 0) { |
766 | l_perror("ioctl DIOCWDINFO"); | | 766 | l_perror("ioctl DIOCWDINFO"); |
767 | return (1); | | 767 | return (1); |
768 | } | | 768 | } |
769 | } | | 769 | } |
770 | | | 770 | |
771 | #ifdef VAX_ALTLABELS | | 771 | #ifdef VAX_ALTLABELS |
772 | if (lab.d_type == DTYPE_SMD && lab.d_flags & D_BADSECT && | | 772 | if (lab.d_type == DTYPE_SMD && lab.d_flags & D_BADSECT && |
773 | lab.d_secsize == 512) { | | 773 | lab.d_secsize == 512) { |
774 | /* Write the label to the odd sectors of the last track! */ | | 774 | /* Write the label to the odd sectors of the last track! */ |
775 | daddr_t alt; | | 775 | daddr_t alt; |
776 | int i; | | 776 | int i; |
777 | uint8_t sec0[512]; | | 777 | uint8_t sec0[512]; |
778 | | | 778 | |
779 | if (pread(f, sec0, 512, 0) < 512) { | | 779 | if (pread(f, sec0, 512, 0) < 512) { |
780 | warn("read master label to write alternates"); | | 780 | warn("read master label to write alternates"); |
781 | return 0; | | 781 | return 0; |
782 | } | | 782 | } |
783 | | | 783 | |
784 | alt = lab.d_ncylinders * lab.d_secpercyl - lab.d_nsectors; | | 784 | alt = lab.d_ncylinders * lab.d_secpercyl - lab.d_nsectors; |
785 | for (i = 1; i < 11 && (uint32_t)i < lab.d_nsectors; i += 2) { | | 785 | for (i = 1; i < 11 && (uint32_t)i < lab.d_nsectors; i += 2) { |
786 | if (pwrite(f, sec0, 512, (off_t)(alt + i) * 512) < 512) | | 786 | if (pwrite(f, sec0, 512, (off_t)(alt + i) * 512) < 512) |
787 | warn("alternate label %d write", i/2); | | 787 | warn("alternate label %d write", i/2); |
788 | } | | 788 | } |
789 | } | | 789 | } |
790 | #endif /* VAX_ALTLABELS */ | | 790 | #endif /* VAX_ALTLABELS */ |
791 | | | 791 | |
792 | return 0; | | 792 | return 0; |
793 | } | | 793 | } |
794 | | | 794 | |
795 | int | | 795 | int |
796 | writelabel(int f, struct disklabel *lp) | | 796 | writelabel(int f, struct disklabel *lp) |
797 | { | | 797 | { |
798 | if (lp != &lab) | | 798 | if (lp != &lab) |
799 | lab = *lp; | | 799 | lab = *lp; |
800 | return write_label(f); | | 800 | return write_label(f); |
801 | } | | 801 | } |
802 | | | 802 | |
803 | static void | | 803 | static void |
804 | l_perror(const char *s) | | 804 | l_perror(const char *s) |
805 | { | | 805 | { |
806 | | | 806 | |
807 | switch (errno) { | | 807 | switch (errno) { |
808 | | | 808 | |
809 | case ESRCH: | | 809 | case ESRCH: |
810 | warnx("%s: No disk label on disk;\n" | | 810 | warnx("%s: No disk label on disk;\n" |
811 | "use \"disklabel -I\" to install initial label", s); | | 811 | "use \"disklabel -I\" to install initial label", s); |
812 | break; | | 812 | break; |
813 | | | 813 | |
814 | case EINVAL: | | 814 | case EINVAL: |
815 | warnx("%s: Label magic number or checksum is wrong!\n" | | 815 | warnx("%s: Label magic number or checksum is wrong!\n" |
816 | "(disklabel or kernel is out of date?)", s); | | 816 | "(disklabel or kernel is out of date?)", s); |
817 | break; | | 817 | break; |
818 | | | 818 | |
819 | case EBUSY: | | 819 | case EBUSY: |
820 | warnx("%s: Open partition would move or shrink", s); | | 820 | warnx("%s: Open partition would move or shrink", s); |
821 | break; | | 821 | break; |
822 | | | 822 | |
823 | case EXDEV: | | 823 | case EXDEV: |
824 | warnx("%s: Labeled partition or 'a' partition must start" | | 824 | warnx("%s: Labeled partition or 'a' partition must start" |
825 | " at beginning of disk", s); | | 825 | " at beginning of disk", s); |
826 | break; | | 826 | break; |
827 | | | 827 | |
828 | default: | | 828 | default: |
829 | warn("%s", s); | | 829 | warn("%s", s); |
830 | break; | | 830 | break; |
831 | } | | 831 | } |
832 | } | | 832 | } |
833 | | | 833 | |
834 | #ifdef NO_MBR_SUPPORT | | 834 | #ifdef NO_MBR_SUPPORT |
835 | #define process_mbr(f, action) 1 | | 835 | #define process_mbr(f, action) 1 |
836 | #else | | 836 | #else |
837 | /* | | 837 | /* |
838 | * Scan DOS/MBR partition table and extended partition list for NetBSD ptns. | | 838 | * Scan DOS/MBR partition table and extended partition list for NetBSD ptns. |
839 | */ | | 839 | */ |
840 | static int | | 840 | static int |
841 | process_mbr(int f, int (*action)(int, u_int)) | | 841 | process_mbr(int f, int (*action)(int, u_int)) |
842 | { | | 842 | { |
843 | struct mbr_partition *dp; | | 843 | struct mbr_partition *dp; |
844 | struct mbr_sector mbr; | | 844 | struct mbr_sector mbr; |
845 | int rval = 1, res; | | 845 | int rval = 1, res; |
846 | int part; | | 846 | int part; |
847 | u_int ext_base, next_ext, this_ext, start; | | 847 | u_int ext_base, next_ext, this_ext, start; |
848 | | | 848 | |
849 | ext_base = 0; | | 849 | ext_base = 0; |
850 | next_ext = 0; | | 850 | next_ext = 0; |
851 | for (;;) { | | 851 | for (;;) { |
852 | this_ext = next_ext; | | 852 | this_ext = next_ext; |
853 | next_ext = 0; | | 853 | next_ext = 0; |
854 | if (verbose > 1) | | 854 | if (verbose > 1) |
855 | warnx("reading mbr sector %u", this_ext); | | 855 | warnx("reading mbr sector %u", this_ext); |
856 | if (pread(f, &mbr, sizeof mbr, this_ext * (off_t)DEV_BSIZE) | | 856 | if (pread(f, &mbr, sizeof mbr, this_ext * (off_t)DEV_BSIZE) |
857 | != sizeof(mbr)) { | | 857 | != sizeof(mbr)) { |
858 | if (verbose) | | 858 | if (verbose) |
859 | warn("Can't read master boot record %u", | | 859 | warn("Can't read master boot record %u", |
860 | this_ext); | | 860 | this_ext); |
861 | break; | | 861 | break; |
862 | } | | 862 | } |
863 | | | 863 | |
864 | /* Check if table is valid. */ | | 864 | /* Check if table is valid. */ |
865 | if (mbr.mbr_magic != htole16(MBR_MAGIC)) { | | 865 | if (mbr.mbr_magic != htole16(MBR_MAGIC)) { |
866 | if (verbose) | | 866 | if (verbose) |
867 | warnx("Invalid signature in mbr record %u", | | 867 | warnx("Invalid signature in mbr record %u", |
868 | this_ext); | | 868 | this_ext); |
869 | break; | | 869 | break; |
870 | } | | 870 | } |
871 | | | 871 | |
872 | dp = &mbr.mbr_parts[0]; | | 872 | dp = &mbr.mbr_parts[0]; |
873 | | | 873 | |
874 | /* Find NetBSD partition(s). */ | | 874 | /* Find NetBSD partition(s). */ |
875 | for (part = 0; part < MBR_PART_COUNT; dp++, part++) { | | 875 | for (part = 0; part < MBR_PART_COUNT; dp++, part++) { |
876 | start = le32toh(dp->mbrp_start); | | 876 | start = le32toh(dp->mbrp_start); |
877 | switch (dp->mbrp_type) { | | 877 | switch (dp->mbrp_type) { |
878 | #ifdef COMPAT_386BSD_MBRPART | | 878 | #ifdef COMPAT_386BSD_MBRPART |
879 | case MBR_PTYPE_386BSD: | | 879 | case MBR_PTYPE_386BSD: |
880 | if (ext_base != 0) | | 880 | if (ext_base != 0) |
881 | break; | | 881 | break; |
882 | /* FALLTHROUGH */ | | 882 | /* FALLTHROUGH */ |
883 | #endif | | 883 | #endif |
884 | case MBR_PTYPE_NETBSD: | | 884 | case MBR_PTYPE_NETBSD: |
885 | res = action(f, this_ext + start); | | 885 | res = action(f, this_ext + start); |
886 | if (res <= 0) | | 886 | if (res <= 0) |
887 | /* Found or failure */ | | 887 | /* Found or failure */ |
888 | return res; | | 888 | return res; |
889 | if (res > rval) | | 889 | if (res > rval) |
890 | /* Keep largest value */ | | 890 | /* Keep largest value */ |
891 | rval = res; | | 891 | rval = res; |
892 | break; | | 892 | break; |
893 | case MBR_PTYPE_EXT: | | 893 | case MBR_PTYPE_EXT: |
894 | case MBR_PTYPE_EXT_LBA: | | 894 | case MBR_PTYPE_EXT_LBA: |
895 | case MBR_PTYPE_EXT_LNX: | | 895 | case MBR_PTYPE_EXT_LNX: |
896 | next_ext = start; | | 896 | next_ext = start; |
897 | break; | | 897 | break; |
898 | default: | | 898 | default: |
899 | break; | | 899 | break; |
900 | } | | 900 | } |
901 | } | | 901 | } |
902 | if (next_ext == 0) | | 902 | if (next_ext == 0) |
903 | /* No more extended partitions */ | | 903 | /* No more extended partitions */ |
904 | break; | | 904 | break; |
905 | next_ext += ext_base; | | 905 | next_ext += ext_base; |
906 | if (ext_base == 0) | | 906 | if (ext_base == 0) |
907 | ext_base = next_ext; | | 907 | ext_base = next_ext; |
908 | | | 908 | |
909 | if (next_ext <= this_ext) { | | 909 | if (next_ext <= this_ext) { |
910 | if (verbose) | | 910 | if (verbose) |
911 | warnx("Invalid extended chain %x <= %x", | | 911 | warnx("Invalid extended chain %x <= %x", |
912 | next_ext, this_ext); | | 912 | next_ext, this_ext); |
913 | break; | | 913 | break; |
914 | } | | 914 | } |
915 | /* Maybe we should check against the disk size... */ | | 915 | /* Maybe we should check against the disk size... */ |
916 | } | | 916 | } |
917 | | | 917 | |
918 | return rval; | | 918 | return rval; |
919 | } | | 919 | } |
920 | | | 920 | |
921 | static int | | 921 | static int |
922 | readlabel_mbr(int f, u_int sector) | | 922 | readlabel_mbr(int f, u_int sector) |
923 | { | | 923 | { |
924 | struct disklabel *disk_lp; | | 924 | struct disklabel *disk_lp; |
925 | | | 925 | |
926 | disk_lp = find_label(f, sector); | | 926 | disk_lp = find_label(f, sector); |
927 | if (disk_lp == NULL) | | 927 | if (disk_lp == NULL) |
928 | return 1; | | 928 | return 1; |
929 | targettohlabel(&lab, disk_lp); | | 929 | targettohlabel(&lab, disk_lp); |
930 | return 0; | | 930 | return 0; |
931 | } | | 931 | } |
932 | | | 932 | |
933 | static int | | 933 | static int |
934 | writelabel_mbr(int f, u_int sector) | | 934 | writelabel_mbr(int f, u_int sector) |
935 | { | | 935 | { |
936 | return update_label(f, sector, mflag ? LABELOFFSET_MBR : ~0U) ? 2 : 0; | | 936 | return update_label(f, sector, mflag ? LABELOFFSET_MBR : ~0U) ? 2 : 0; |
937 | } | | 937 | } |
938 | | | 938 | |
939 | #endif /* !NO_MBR_SUPPORT */ | | 939 | #endif /* !NO_MBR_SUPPORT */ |
940 | | | 940 | |
941 | #ifndef USE_ACORN | | 941 | #ifndef USE_ACORN |
942 | #define get_filecore_partition(f) 0 | | 942 | #define get_filecore_partition(f) 0 |
943 | #else | | 943 | #else |
944 | /* | | 944 | /* |
945 | * static int filecore_checksum(u_char *bootblock) | | 945 | * static int filecore_checksum(u_char *bootblock) |
946 | * | | 946 | * |
947 | * Calculates the filecore boot block checksum. This is used to validate | | 947 | * Calculates the filecore boot block checksum. This is used to validate |
948 | * a filecore boot block on the disk. If a boot block is validated then | | 948 | * a filecore boot block on the disk. If a boot block is validated then |
949 | * it is used to locate the partition table. If the boot block is not | | 949 | * it is used to locate the partition table. If the boot block is not |
950 | * validated, it is assumed that the whole disk is NetBSD. | | 950 | * validated, it is assumed that the whole disk is NetBSD. |
951 | * | | 951 | * |
952 | * The basic algorithm is: | | 952 | * The basic algorithm is: |
953 | * | | 953 | * |
954 | * for (each byte in block, excluding checksum) { | | 954 | * for (each byte in block, excluding checksum) { |
955 | * sum += byte; | | 955 | * sum += byte; |
956 | * if (sum > 255) | | 956 | * if (sum > 255) |
957 | * sum -= 255; | | 957 | * sum -= 255; |
958 | * } | | 958 | * } |
959 | * | | 959 | * |
960 | * That's equivalent to summing all of the bytes in the block | | 960 | * That's equivalent to summing all of the bytes in the block |
961 | * (excluding the checksum byte, of course), then calculating the | | 961 | * (excluding the checksum byte, of course), then calculating the |
962 | * checksum as "cksum = sum - ((sum - 1) / 255) * 255)". That | | 962 | * checksum as "cksum = sum - ((sum - 1) / 255) * 255)". That |
963 | * expression may or may not yield a faster checksum function, | | 963 | * expression may or may not yield a faster checksum function, |
964 | * but it's easier to reason about. | | 964 | * but it's easier to reason about. |
965 | * | | 965 | * |
966 | * Note that if you have a block filled with bytes of a single | | 966 | * Note that if you have a block filled with bytes of a single |
967 | * value "X" (regardless of that value!) and calculate the cksum | | 967 | * value "X" (regardless of that value!) and calculate the cksum |
968 | * of the block (excluding the checksum byte), you will _always_ | | 968 | * of the block (excluding the checksum byte), you will _always_ |
969 | * end up with a checksum of X. (Do the math; that can be derived | | 969 | * end up with a checksum of X. (Do the math; that can be derived |
970 | * from the checksum calculation function!) That means that | | 970 | * from the checksum calculation function!) That means that |
971 | * blocks which contain bytes which all have the same value will | | 971 | * blocks which contain bytes which all have the same value will |
972 | * always checksum properly. That's a _very_ unlikely occurence | | 972 | * always checksum properly. That's a _very_ unlikely occurence |
973 | * (probably impossible, actually) for a valid filecore boot block, | | 973 | * (probably impossible, actually) for a valid filecore boot block, |
974 | * so we treat such blocks as invalid. | | 974 | * so we treat such blocks as invalid. |
975 | */ | | 975 | */ |
976 | static int | | 976 | static int |
977 | filecore_checksum(u_char *bootblock) | | 977 | filecore_checksum(u_char *bootblock) |
978 | { | | 978 | { |
979 | u_char byte0, accum_diff; | | 979 | u_char byte0, accum_diff; |
980 | u_int sum; | | 980 | u_int sum; |
981 | int i; | | 981 | int i; |
982 | | | 982 | |
983 | sum = 0; | | 983 | sum = 0; |
984 | accum_diff = 0; | | 984 | accum_diff = 0; |
985 | byte0 = bootblock[0]; | | 985 | byte0 = bootblock[0]; |
986 | | | 986 | |
987 | /* | | 987 | /* |
988 | * Sum the contents of the block, keeping track of whether | | 988 | * Sum the contents of the block, keeping track of whether |
989 | * or not all bytes are the same. If 'accum_diff' ends up | | 989 | * or not all bytes are the same. If 'accum_diff' ends up |
990 | * being zero, all of the bytes are, in fact, the same. | | 990 | * being zero, all of the bytes are, in fact, the same. |
991 | */ | | 991 | */ |
992 | for (i = 0; i < 511; ++i) { | | 992 | for (i = 0; i < 511; ++i) { |
993 | sum += bootblock[i]; | | 993 | sum += bootblock[i]; |
994 | accum_diff |= bootblock[i] ^ byte0; | | 994 | accum_diff |= bootblock[i] ^ byte0; |
995 | } | | 995 | } |
996 | | | 996 | |
997 | /* | | 997 | /* |
998 | * Check to see if the checksum byte is the same as the | | 998 | * Check to see if the checksum byte is the same as the |
999 | * rest of the bytes, too. (Note that if all of the bytes | | 999 | * rest of the bytes, too. (Note that if all of the bytes |
1000 | * are the same except the checksum, a checksum compare | | 1000 | * are the same except the checksum, a checksum compare |
1001 | * won't succeed, but that's not our problem.) | | 1001 | * won't succeed, but that's not our problem.) |
1002 | */ | | 1002 | */ |
1003 | accum_diff |= bootblock[i] ^ byte0; | | 1003 | accum_diff |= bootblock[i] ^ byte0; |
1004 | | | 1004 | |
1005 | /* All bytes in block are the same; call it invalid. */ | | 1005 | /* All bytes in block are the same; call it invalid. */ |
1006 | if (accum_diff == 0) | | 1006 | if (accum_diff == 0) |
1007 | return (-1); | | 1007 | return (-1); |
1008 | | | 1008 | |
1009 | return (sum - ((sum - 1) / 255) * 255); | | 1009 | return (sum - ((sum - 1) / 255) * 255); |
1010 | } | | 1010 | } |
1011 | | | 1011 | |
1012 | /* | | 1012 | /* |
1013 | * Check for the presence of a RiscOS filecore boot block | | 1013 | * Check for the presence of a RiscOS filecore boot block |
1014 | * indicating an ADFS file system on the disc. | | 1014 | * indicating an ADFS file system on the disc. |
1015 | * Return the offset to the NetBSD part of the disc if | | 1015 | * Return the offset to the NetBSD part of the disc if |
1016 | * this can be determined. | | 1016 | * this can be determined. |
1017 | * This routine will terminate disklabel if the disc | | 1017 | * This routine will terminate disklabel if the disc |
1018 | * is found to be ADFS only. | | 1018 | * is found to be ADFS only. |
1019 | */ | | 1019 | */ |
1020 | static u_int | | 1020 | static u_int |
1021 | get_filecore_partition(int f) | | 1021 | get_filecore_partition(int f) |
1022 | { | | 1022 | { |
1023 | struct filecore_bootblock *fcbb; | | 1023 | struct filecore_bootblock *fcbb; |
1024 | static u_char bb[DEV_BSIZE]; | | 1024 | static u_char bb[DEV_BSIZE]; |
1025 | u_int offset; | | 1025 | u_int offset; |
1026 | struct riscix_partition_table *riscix_part; | | 1026 | struct riscix_partition_table *riscix_part; |
1027 | int loop; | | 1027 | int loop; |
1028 | | | 1028 | |
1029 | if (pread(f, bb, sizeof(bb), (off_t)FILECORE_BOOT_SECTOR * DEV_BSIZE) != sizeof(bb)) | | 1029 | if (pread(f, bb, sizeof(bb), (off_t)FILECORE_BOOT_SECTOR * DEV_BSIZE) != sizeof(bb)) |
1030 | err(4, "can't read filecore boot block"); | | 1030 | err(4, "can't read filecore boot block"); |
1031 | fcbb = (struct filecore_bootblock *)bb; | | 1031 | fcbb = (struct filecore_bootblock *)bb; |
1032 | | | 1032 | |
1033 | /* Check if table is valid. */ | | 1033 | /* Check if table is valid. */ |
1034 | if (filecore_checksum(bb) != fcbb->checksum) | | 1034 | if (filecore_checksum(bb) != fcbb->checksum) |
1035 | return (0); | | 1035 | return (0); |
1036 | | | 1036 | |
1037 | /* | | 1037 | /* |
1038 | * Check for NetBSD/arm32 (RiscBSD) partition marker. | | 1038 | * Check for NetBSD/arm32 (RiscBSD) partition marker. |
1039 | * If found the NetBSD disklabel location is easy. | | 1039 | * If found the NetBSD disklabel location is easy. |
1040 | */ | | 1040 | */ |
1041 | offset = (fcbb->partition_cyl_low + (fcbb->partition_cyl_high << 8)) | | 1041 | offset = (fcbb->partition_cyl_low + (fcbb->partition_cyl_high << 8)) |
1042 | * fcbb->heads * fcbb->secspertrack; | | 1042 | * fcbb->heads * fcbb->secspertrack; |
1043 | | | 1043 | |
1044 | switch (fcbb->partition_type) { | | 1044 | switch (fcbb->partition_type) { |
1045 | | | 1045 | |
1046 | case PARTITION_FORMAT_RISCBSD: | | 1046 | case PARTITION_FORMAT_RISCBSD: |
1047 | return (offset); | | 1047 | return (offset); |
1048 | | | 1048 | |
1049 | case PARTITION_FORMAT_RISCIX: | | 1049 | case PARTITION_FORMAT_RISCIX: |
1050 | /* | | 1050 | /* |
1051 | * Read the RISCiX partition table and search for the | | 1051 | * Read the RISCiX partition table and search for the |
1052 | * first partition named "RiscBSD", "NetBSD", or "Empty:" | | 1052 | * first partition named "RiscBSD", "NetBSD", or "Empty:" |
1053 | * | | 1053 | * |
1054 | * XXX is use of 'Empty:' really desirable?! -- cgd | | 1054 | * XXX is use of 'Empty:' really desirable?! -- cgd |
1055 | */ | | 1055 | */ |
1056 | | | 1056 | |
1057 | if (pread(f, bb, sizeof(bb), (off_t)offset * DEV_BSIZE) != sizeof(bb)) | | 1057 | if (pread(f, bb, sizeof(bb), (off_t)offset * DEV_BSIZE) != sizeof(bb)) |
1058 | err(4, "can't read riscix partition table"); | | 1058 | err(4, "can't read riscix partition table"); |
1059 | riscix_part = (struct riscix_partition_table *)bb; | | 1059 | riscix_part = (struct riscix_partition_table *)bb; |
1060 | | | 1060 | |
1061 | for (loop = 0; loop < NRISCIX_PARTITIONS; ++loop) { | | 1061 | for (loop = 0; loop < NRISCIX_PARTITIONS; ++loop) { |
1062 | if (strcmp((char *)riscix_part->partitions[loop].rp_name, | | 1062 | if (strcmp((char *)riscix_part->partitions[loop].rp_name, |
1063 | "RiscBSD") == 0 || | | 1063 | "RiscBSD") == 0 || |
1064 | strcmp((char *)riscix_part->partitions[loop].rp_name, | | 1064 | strcmp((char *)riscix_part->partitions[loop].rp_name, |
1065 | "NetBSD") == 0 || | | 1065 | "NetBSD") == 0 || |
1066 | strcmp((char *)riscix_part->partitions[loop].rp_name, | | 1066 | strcmp((char *)riscix_part->partitions[loop].rp_name, |
1067 | "Empty:") == 0) { | | 1067 | "Empty:") == 0) { |
1068 | return riscix_part->partitions[loop].rp_start; | | 1068 | return riscix_part->partitions[loop].rp_start; |
1069 | break; | | 1069 | break; |
1070 | } | | 1070 | } |
1071 | } | | 1071 | } |
1072 | /* | | 1072 | /* |
1073 | * Valid filecore boot block, RISCiX partition table | | 1073 | * Valid filecore boot block, RISCiX partition table |
1074 | * but no NetBSD partition. We should leave this | | 1074 | * but no NetBSD partition. We should leave this |
1075 | * disc alone. | | 1075 | * disc alone. |
1076 | */ | | 1076 | */ |
1077 | errx(4, "cannot label: no NetBSD partition found" | | 1077 | errx(4, "cannot label: no NetBSD partition found" |
1078 | " in RISCiX partition table"); | | 1078 | " in RISCiX partition table"); |
1079 | | | 1079 | |
1080 | default: | | 1080 | default: |
1081 | /* | | 1081 | /* |
1082 | * Valid filecore boot block and no non-ADFS partition. | | 1082 | * Valid filecore boot block and no non-ADFS partition. |
1083 | * This means that the whole disc is allocated for ADFS | | 1083 | * This means that the whole disc is allocated for ADFS |
1084 | * so do not trash ! If the user really wants to put a | | 1084 | * so do not trash ! If the user really wants to put a |
1085 | * NetBSD disklabel on the disc then they should remove | | 1085 | * NetBSD disklabel on the disc then they should remove |
1086 | * the filecore boot block first with dd. | | 1086 | * the filecore boot block first with dd. |
1087 | */ | | 1087 | */ |
1088 | errx(4, "cannot label: filecore-only disk" | | 1088 | errx(4, "cannot label: filecore-only disk" |
1089 | " (no non-ADFS partition)"); | | 1089 | " (no non-ADFS partition)"); |
1090 | } | | 1090 | } |
1091 | return (0); | | 1091 | return (0); |
1092 | } | | 1092 | } |
1093 | #endif /* USE_ACORN */ | | 1093 | #endif /* USE_ACORN */ |
1094 | | | 1094 | |
1095 | /* | | 1095 | /* |
1096 | * Fetch disklabel for disk to 'lab'. | | 1096 | * Fetch disklabel for disk to 'lab'. |
1097 | * Use ioctl to get label unless -r flag is given. | | 1097 | * Use ioctl to get label unless -r flag is given. |
1098 | */ | | 1098 | */ |
1099 | static void | | 1099 | static void |
1100 | readlabel(int f) | | 1100 | readlabel(int f) |
1101 | { | | 1101 | { |
1102 | if (rflag) { | | 1102 | if (rflag) { |
1103 | /* Get label directly from disk */ | | 1103 | /* Get label directly from disk */ |
1104 | if (readlabel_direct(f) == 0) | | 1104 | if (readlabel_direct(f) == 0) |
1105 | return; | | 1105 | return; |
1106 | /* | | 1106 | /* |
1107 | * There was no label on the disk. Get the fictious one | | 1107 | * There was no label on the disk. Get the fictious one |
1108 | * as a basis for initialisation. | | 1108 | * as a basis for initialisation. |
1109 | */ | | 1109 | */ |
1110 | if (!Fflag && Iflag && (dk_ioctl(f, DIOCGDINFO, &lab) == 0 || | | 1110 | if (!Fflag && Iflag && (dk_ioctl(f, DIOCGDINFO, &lab) == 0 || |
1111 | dk_ioctl(f, DIOCGDEFLABEL, &lab) == 0)) | | 1111 | dk_ioctl(f, DIOCGDEFLABEL, &lab) == 0)) |
1112 | return; | | 1112 | return; |
1113 | } else { | | 1113 | } else { |
1114 | /* Get label from kernel. */ | | 1114 | /* Get label from kernel. */ |
1115 | if (dk_ioctl(f, DIOCGDINFO, &lab) < 0) | | 1115 | if (dk_ioctl(f, DIOCGDINFO, &lab) < 0) |
1116 | err(4, "ioctl DIOCGDINFO"); | | 1116 | err(4, "ioctl DIOCGDINFO"); |
1117 | return; | | 1117 | return; |
1118 | } | | 1118 | } |
1119 | | | 1119 | |
1120 | if (read_all == 2) | | 1120 | if (read_all == 2) |
1121 | /* We actually found one, and printed it... */ | | 1121 | /* We actually found one, and printed it... */ |
1122 | exit(0); | | 1122 | exit(0); |
1123 | errx(1, "could not read existing label"); | | 1123 | errx(1, "could not read existing label"); |
1124 | } | | 1124 | } |
1125 | | | 1125 | |
1126 | /* | | 1126 | /* |
1127 | * Reading the label from the disk is largely a case of 'hunt the label'. | | 1127 | * Reading the label from the disk is largely a case of 'hunt the label'. |
1128 | * and since different architectures default to different places there | | 1128 | * and since different architectures default to different places there |
1129 | * could even be more than one label that contradict each other! | | 1129 | * could even be more than one label that contradict each other! |
1130 | * For now we look in the expected place, then search through likely | | 1130 | * For now we look in the expected place, then search through likely |
1131 | * other locations. | | 1131 | * other locations. |
1132 | */ | | 1132 | */ |
1133 | static struct disklabel * | | 1133 | static struct disklabel * |
1134 | find_label(int f, u_int sector) | | 1134 | find_label(int f, u_int sector) |
1135 | { | | 1135 | { |
1136 | struct disklabel *disk_lp, hlp; | | 1136 | struct disklabel *disk_lp, hlp; |
1137 | int i; | | 1137 | int i; |
1138 | u_int offset; | | 1138 | u_int offset; |
1139 | const char *is_deleted; | | 1139 | const char *is_deleted; |
1140 | | | 1140 | |
1141 | bootarea_len = pread(f, bootarea, sizeof bootarea, | | 1141 | bootarea_len = pread(f, bootarea, sizeof bootarea, |
1142 | sector * (off_t)DEV_BSIZE); | | 1142 | sector * (off_t)DEV_BSIZE); |
1143 | if (bootarea_len <= 0) { | | 1143 | if (bootarea_len <= 0) { |
1144 | if (verbose) | | 1144 | if (verbose) |
1145 | warn("failed to read bootarea from sector %u", sector); | | 1145 | warn("failed to read bootarea from sector %u", sector); |
1146 | return NULL; | | 1146 | return NULL; |
1147 | } | | 1147 | } |
1148 | | | 1148 | |
1149 | if (verbose > 2) | | 1149 | if (verbose > 2) |
1150 | warnx("read sector %u len %d looking for label", | | 1150 | warnx("read sector %u len %d looking for label", |
1151 | sector, bootarea_len); | | 1151 | sector, bootarea_len); |
1152 | | | 1152 | |
1153 | /* Check expected offset first */ | | 1153 | /* Check expected offset first */ |
1154 | for (offset = LABEL_OFFSET, i = -4;; offset = i += 4) { | | 1154 | for (offset = LABEL_OFFSET, i = -4;; offset = i += 4) { |
1155 | is_deleted = ""; | | 1155 | is_deleted = ""; |
1156 | disk_lp = (void *)(bootarea + offset); | | 1156 | disk_lp = (void *)(bootarea + offset); |
1157 | if (i == LABEL_OFFSET) | | 1157 | if (i == LABEL_OFFSET) |
1158 | continue; | | 1158 | continue; |
1159 | if ((char *)(disk_lp + 1) > bootarea + bootarea_len) | | 1159 | if ((char *)(disk_lp + 1) > bootarea + bootarea_len) |
1160 | break; | | 1160 | break; |
1161 | if (disk_lp->d_magic2 != disk_lp->d_magic) | | 1161 | if (disk_lp->d_magic2 != disk_lp->d_magic) |
1162 | continue; | | 1162 | continue; |
1163 | if (read_all && (disk_lp->d_magic == DISKMAGIC_DELETED || | | 1163 | if (read_all && (disk_lp->d_magic == DISKMAGIC_DELETED || |
1164 | disk_lp->d_magic == DISKMAGIC_DELETED_REV)) { | | 1164 | disk_lp->d_magic == DISKMAGIC_DELETED_REV)) { |
1165 | disk_lp->d_magic ^= ~0u; | | 1165 | disk_lp->d_magic ^= ~0u; |
1166 | disk_lp->d_magic2 ^= ~0u; | | 1166 | disk_lp->d_magic2 ^= ~0u; |
1167 | is_deleted = "deleted "; | | 1167 | is_deleted = "deleted "; |
1168 | } | | 1168 | } |
1169 | if (target32toh(disk_lp->d_magic) != DISKMAGIC) { | | 1169 | if (target32toh(disk_lp->d_magic) != DISKMAGIC) { |
1170 | /* XXX: Do something about byte-swapped labels ? */ | | 1170 | /* XXX: Do something about byte-swapped labels ? */ |
1171 | if (target32toh(disk_lp->d_magic) == DISKMAGIC_REV && | | 1171 | if (target32toh(disk_lp->d_magic) == DISKMAGIC_REV && |
1172 | target32toh(disk_lp->d_magic2) == DISKMAGIC_REV) | | 1172 | target32toh(disk_lp->d_magic2) == DISKMAGIC_REV) |
1173 | warnx("ignoring %sbyteswapped label" | | 1173 | warnx("ignoring %sbyteswapped label" |
1174 | " at offset %u from sector %u", | | 1174 | " at offset %u from sector %u", |
1175 | is_deleted, offset, sector); | | 1175 | is_deleted, offset, sector); |
1176 | continue; | | 1176 | continue; |
1177 | } | | 1177 | } |
1178 | if (target16toh(disk_lp->d_npartitions) > maxpartitions || | | 1178 | if (target16toh(disk_lp->d_npartitions) > maxpartitions || |
1179 | dkcksum_target(disk_lp) != 0) { | | 1179 | dkcksum_target(disk_lp) != 0) { |
1180 | if (verbose > 0) | | 1180 | if (verbose > 0) |
1181 | warnx("corrupt label found at offset %u in " | | 1181 | warnx("corrupt label found at offset %u in " |
1182 | "sector %u", offset, sector); | | 1182 | "sector %u", offset, sector); |
1183 | continue; | | 1183 | continue; |
1184 | } | | 1184 | } |
1185 | if (verbose > 1) | | 1185 | if (verbose > 1) |
1186 | warnx("%slabel found at offset %u from sector %u", | | 1186 | warnx("%slabel found at offset %u from sector %u", |
1187 | is_deleted, offset, sector); | | 1187 | is_deleted, offset, sector); |
1188 | if (!read_all) | | 1188 | if (!read_all) |
1189 | return disk_lp; | | 1189 | return disk_lp; |
1190 | | | 1190 | |
1191 | /* To print all the labels we have to do it here */ | | 1191 | /* To print all the labels we have to do it here */ |
1192 | /* XXX: maybe we should compare them? */ | | 1192 | /* XXX: maybe we should compare them? */ |
1193 | targettohlabel(&hlp, disk_lp); | | 1193 | targettohlabel(&hlp, disk_lp); |
1194 | printf("# %ssector %u offset %u bytes\n", | | 1194 | printf("# %ssector %u offset %u bytes\n", |
1195 | is_deleted, sector, offset); | | 1195 | is_deleted, sector, offset); |
1196 | if (tflag) | | 1196 | if (tflag) |
1197 | makedisktab(stdout, &hlp); | | 1197 | makedisktab(stdout, &hlp); |
1198 | else { | | 1198 | else { |
1199 | showinfo(stdout, &hlp, specname); | | 1199 | showinfo(stdout, &hlp, specname); |
1200 | showpartitions(stdout, &hlp, Cflag); | | 1200 | showpartitions(stdout, &hlp, Cflag); |
1201 | } | | 1201 | } |
1202 | checklabel(&hlp); | | 1202 | checklabel(&hlp); |
1203 | htotargetlabel(disk_lp, &hlp); | | 1203 | htotargetlabel(disk_lp, &hlp); |
1204 | /* Remember we've found a label */ | | 1204 | /* Remember we've found a label */ |
1205 | read_all = 2; | | 1205 | read_all = 2; |
1206 | } | | 1206 | } |
1207 | return NULL; | | 1207 | return NULL; |
1208 | } | | 1208 | } |
1209 | | | 1209 | |
1210 | static void | | 1210 | static void |
1211 | write_bootarea(int f, u_int sector) | | 1211 | write_bootarea(int f, u_int sector) |
1212 | { | | 1212 | { |
1213 | int wlen; | | 1213 | int wlen; |
1214 | | | 1214 | |
1215 | if (bootarea_len <= 0) | | 1215 | if (bootarea_len <= 0) |
1216 | errx(1, "attempting to write after failed read"); | | 1216 | errx(1, "attempting to write after failed read"); |
1217 | | | 1217 | |
1218 | #ifdef ALPHA_BOOTBLOCK_CKSUM | | 1218 | #ifdef ALPHA_BOOTBLOCK_CKSUM |
1219 | /* | | 1219 | /* |
1220 | * The Alpha requires that the boot block be checksummed. | | 1220 | * The Alpha requires that the boot block be checksummed. |
1221 | * <sys/bootblock.h> provides a macro to do it. | | 1221 | * <sys/bootblock.h> provides a macro to do it. |
1222 | */ | | 1222 | */ |
1223 | if (sector == 0) { | | 1223 | if (sector == 0) { |
1224 | struct alpha_boot_block *bb; | | 1224 | struct alpha_boot_block *bb; |
1225 | | | 1225 | |
1226 | bb = (struct alpha_boot_block *)(void *)bootarea; | | 1226 | bb = (struct alpha_boot_block *)(void *)bootarea; |
1227 | bb->bb_cksum = 0; | | 1227 | bb->bb_cksum = 0; |
1228 | ALPHA_BOOT_BLOCK_CKSUM(bb, &bb->bb_cksum); | | 1228 | ALPHA_BOOT_BLOCK_CKSUM(bb, &bb->bb_cksum); |
1229 | } | | 1229 | } |
1230 | #endif /* ALPHA_BOOTBLOCK_CKSUM */ | | 1230 | #endif /* ALPHA_BOOTBLOCK_CKSUM */ |
1231 | | | 1231 | |
1232 | wlen = pwrite(f, bootarea, bootarea_len, sector * (off_t)DEV_BSIZE); | | 1232 | wlen = pwrite(f, bootarea, bootarea_len, sector * (off_t)DEV_BSIZE); |
1233 | if (wlen == bootarea_len) | | 1233 | if (wlen == bootarea_len) |
1234 | return; | | 1234 | return; |
1235 | if (wlen == -1) | | 1235 | if (wlen == -1) |
1236 | err(1, "disklabel write (sector %u) size %d failed", | | 1236 | err(1, "disklabel write (sector %u) size %d failed", |
1237 | sector, bootarea_len); | | 1237 | sector, bootarea_len); |
1238 | errx(1, "disklabel write (sector %u) size %d truncated to %d", | | 1238 | errx(1, "disklabel write (sector %u) size %d truncated to %d", |
1239 | sector, bootarea_len, wlen); | | 1239 | sector, bootarea_len, wlen); |
1240 | } | | 1240 | } |
1241 | | | 1241 | |
1242 | static int | | 1242 | static int |
1243 | update_label(int f, u_int label_sector, u_int label_offset) | | 1243 | update_label(int f, u_int label_sector, u_int label_offset) |
1244 | { | | 1244 | { |
1245 | struct disklabel *disk_lp; | | 1245 | struct disklabel *disk_lp; |
1246 | | | 1246 | |
1247 | disk_lp = find_label(f, label_sector); | | 1247 | disk_lp = find_label(f, label_sector); |
1248 | | | 1248 | |
1249 | if (disk_lp && Dflag) { | | 1249 | if (disk_lp && Dflag) { |
1250 | /* Invalidate the existing label */ | | 1250 | /* Invalidate the existing label */ |
1251 | disk_lp->d_magic ^= ~0u; | | 1251 | disk_lp->d_magic ^= ~0u; |
1252 | disk_lp->d_magic2 ^= ~0u; | | 1252 | disk_lp->d_magic2 ^= ~0u; |
1253 | if (Dflag == 2) | | 1253 | if (Dflag == 2) |
1254 | write_bootarea(f, label_sector); | | 1254 | write_bootarea(f, label_sector); |
1255 | /* Force label to default location */ | | 1255 | /* Force label to default location */ |
1256 | disk_lp = NULL; | | 1256 | disk_lp = NULL; |
1257 | } | | 1257 | } |
1258 | | | 1258 | |
1259 | if (Dflag == 2) | | 1259 | if (Dflag == 2) |
1260 | /* We are just deleting the label */ | | 1260 | /* We are just deleting the label */ |
1261 | return 0; | | 1261 | return 0; |
1262 | | | 1262 | |
1263 | if (disk_lp == NULL) { | | 1263 | if (disk_lp == NULL) { |
1264 | if (label_offset == ~0u) | | 1264 | if (label_offset == ~0u) |
1265 | return 0; | | 1265 | return 0; |
1266 | /* Nothing on the disk - we need to add it */ | | 1266 | /* Nothing on the disk - we need to add it */ |
1267 | disk_lp = (void *)(bootarea + label_offset); | | 1267 | disk_lp = (void *)(bootarea + label_offset); |
1268 | if ((char *)(disk_lp + 1) > bootarea + bootarea_len) | | 1268 | if ((char *)(disk_lp + 1) > bootarea + bootarea_len) |
1269 | errx(1, "no space in bootarea (sector %u) " | | 1269 | errx(1, "no space in bootarea (sector %u) " |
1270 | "to create label", label_sector); | | 1270 | "to create label", label_sector); |
1271 | } | | 1271 | } |
1272 | | | 1272 | |
1273 | htotargetlabel(disk_lp, &lab); | | 1273 | htotargetlabel(disk_lp, &lab); |
1274 | write_bootarea(f, label_sector); | | 1274 | write_bootarea(f, label_sector); |
1275 | return 1; | | 1275 | return 1; |
1276 | } | | 1276 | } |
1277 | | | 1277 | |
1278 | static void | | 1278 | static void |
1279 | writelabel_direct(int f) | | 1279 | writelabel_direct(int f) |
1280 | { | | 1280 | { |
1281 | u_int label_sector; | | 1281 | u_int label_sector; |
1282 | int written = 0; | | 1282 | int written = 0; |
1283 | int rval; | | 1283 | int rval; |
1284 | | | 1284 | |
1285 | label_sector = get_filecore_partition(f); | | 1285 | label_sector = get_filecore_partition(f); |
1286 | if (label_sector != 0) | | 1286 | if (label_sector != 0) |
1287 | /* The offset needs to be that from the acorn ports... */ | | 1287 | /* The offset needs to be that from the acorn ports... */ |
1288 | written = update_label(f, label_sector, DEV_BSIZE); | | 1288 | written = update_label(f, label_sector, DEV_BSIZE); |
1289 | | | 1289 | |
1290 | rval = process_mbr(f, writelabel_mbr); | | 1290 | rval = process_mbr(f, writelabel_mbr); |
1291 | | | 1291 | |
1292 | if (rval == 2 || written) | | 1292 | if (rval == 2 || written) |
1293 | /* Don't add a label to sector 0, but update one if there */ | | 1293 | /* Don't add a label to sector 0, but update one if there */ |
1294 | update_label(f, 0, ~0u); | | 1294 | update_label(f, 0, ~0u); |
1295 | else | | 1295 | else |
1296 | update_label(f, 0, LABEL_OFFSET); | | 1296 | update_label(f, 0, LABEL_OFFSET); |
1297 | } | | 1297 | } |
1298 | | | 1298 | |
1299 | static int | | 1299 | static int |
1300 | readlabel_direct(int f) | | 1300 | readlabel_direct(int f) |
1301 | { | | 1301 | { |
1302 | struct disklabel *disk_lp; | | 1302 | struct disklabel *disk_lp; |
1303 | u_int filecore_partition_offset; | | 1303 | u_int filecore_partition_offset; |
1304 | | | 1304 | |
1305 | filecore_partition_offset = get_filecore_partition(f); | | 1305 | filecore_partition_offset = get_filecore_partition(f); |
1306 | if (filecore_partition_offset != 0) { | | 1306 | if (filecore_partition_offset != 0) { |
1307 | disk_lp = find_label(f, filecore_partition_offset); | | 1307 | disk_lp = find_label(f, filecore_partition_offset); |
1308 | if (disk_lp != NULL) { | | 1308 | if (disk_lp != NULL) { |
1309 | targettohlabel(&lab, disk_lp); | | 1309 | targettohlabel(&lab, disk_lp); |
1310 | return 0; | | 1310 | return 0; |
1311 | } | | 1311 | } |
1312 | } | | 1312 | } |
1313 | | | 1313 | |
1314 | if (mflag && process_mbr(f, readlabel_mbr) == 0) | | 1314 | if (mflag && process_mbr(f, readlabel_mbr) == 0) |
1315 | return 0; | | 1315 | return 0; |
1316 | | | 1316 | |
1317 | disk_lp = find_label(f, 0); | | 1317 | disk_lp = find_label(f, 0); |
1318 | if (disk_lp != NULL) { | | 1318 | if (disk_lp != NULL) { |
1319 | targettohlabel(&lab, disk_lp); | | 1319 | targettohlabel(&lab, disk_lp); |
1320 | return 0; | | 1320 | return 0; |
1321 | } | | 1321 | } |
1322 | | | 1322 | |
1323 | if (!mflag && process_mbr(f, readlabel_mbr) == 0) | | 1323 | if (!mflag && process_mbr(f, readlabel_mbr) == 0) |
1324 | return 0; | | 1324 | return 0; |
1325 | | | 1325 | |
1326 | return 1; | | 1326 | return 1; |
1327 | } | | 1327 | } |
1328 | | | 1328 | |
1329 | static void | | 1329 | static void |
1330 | makedisktab(FILE *f, struct disklabel *lp) | | 1330 | makedisktab(FILE *f, struct disklabel *lp) |
1331 | { | | 1331 | { |
1332 | int i; | | 1332 | int i; |
1333 | const char *did; | | 1333 | const char *did; |
1334 | struct partition *pp; | | 1334 | struct partition *pp; |
1335 | | | 1335 | |
1336 | did = "\\\n\t:"; | | 1336 | did = "\\\n\t:"; |
1337 | (void) fprintf(f, "%.*s|Automatically generated label:\\\n\t:dt=", | | 1337 | (void) fprintf(f, "%.*s|Automatically generated label:\\\n\t:dt=", |
1338 | (int) sizeof(lp->d_typename), lp->d_typename); | | 1338 | (int) sizeof(lp->d_typename), lp->d_typename); |
1339 | if ((unsigned) lp->d_type < DKMAXTYPES) | | 1339 | if ((unsigned) lp->d_type < DKMAXTYPES) |
1340 | (void) fprintf(f, "%s:", dktypenames[lp->d_type]); | | 1340 | (void) fprintf(f, "%s:", dktypenames[lp->d_type]); |
1341 | else | | 1341 | else |
1342 | (void) fprintf(f, "unknown%" PRIu16 ":", lp->d_type); | | 1342 | (void) fprintf(f, "unknown%" PRIu16 ":", lp->d_type); |
1343 | | | 1343 | |
1344 | (void) fprintf(f, "se#%" PRIu32 ":", lp->d_secsize); | | 1344 | (void) fprintf(f, "se#%" PRIu32 ":", lp->d_secsize); |
1345 | (void) fprintf(f, "ns#%" PRIu32 ":", lp->d_nsectors); | | 1345 | (void) fprintf(f, "ns#%" PRIu32 ":", lp->d_nsectors); |
1346 | (void) fprintf(f, "nt#%" PRIu32 ":", lp->d_ntracks); | | 1346 | (void) fprintf(f, "nt#%" PRIu32 ":", lp->d_ntracks); |
1347 | (void) fprintf(f, "sc#%" PRIu32 ":", lp->d_secpercyl); | | 1347 | (void) fprintf(f, "sc#%" PRIu32 ":", lp->d_secpercyl); |
1348 | (void) fprintf(f, "nc#%" PRIu32 ":", lp->d_ncylinders); | | 1348 | (void) fprintf(f, "nc#%" PRIu32 ":", lp->d_ncylinders); |
1349 | | | 1349 | |
1350 | if ((lp->d_secpercyl * lp->d_ncylinders) != lp->d_secperunit) { | | 1350 | if ((lp->d_secpercyl * lp->d_ncylinders) != lp->d_secperunit) { |
1351 | (void) fprintf(f, "%ssu#%" PRIu32 ":", did, lp->d_secperunit); | | 1351 | (void) fprintf(f, "%ssu#%" PRIu32 ":", did, lp->d_secperunit); |
1352 | did = ""; | | 1352 | did = ""; |
1353 | } | | 1353 | } |
1354 | if (lp->d_rpm != 3600) { | | 1354 | if (lp->d_rpm != 3600) { |
1355 | (void) fprintf(f, "%srm#%" PRIu16 ":", did, lp->d_rpm); | | 1355 | (void) fprintf(f, "%srm#%" PRIu16 ":", did, lp->d_rpm); |
1356 | did = ""; | | 1356 | did = ""; |
1357 | } | | 1357 | } |
1358 | if (lp->d_interleave != 1) { | | 1358 | if (lp->d_interleave != 1) { |
1359 | (void) fprintf(f, "%sil#%" PRIu16 ":", did, lp->d_interleave); | | 1359 | (void) fprintf(f, "%sil#%" PRIu16 ":", did, lp->d_interleave); |
1360 | did = ""; | | 1360 | did = ""; |
1361 | } | | 1361 | } |
1362 | if (lp->d_trackskew != 0) { | | 1362 | if (lp->d_trackskew != 0) { |
1363 | (void) fprintf(f, "%ssk#%" PRIu16 ":", did, lp->d_trackskew); | | 1363 | (void) fprintf(f, "%ssk#%" PRIu16 ":", did, lp->d_trackskew); |
1364 | did = ""; | | 1364 | did = ""; |
1365 | } | | 1365 | } |
1366 | if (lp->d_cylskew != 0) { | | 1366 | if (lp->d_cylskew != 0) { |
1367 | (void) fprintf(f, "%scs#%" PRIu16 ":", did, lp->d_cylskew); | | 1367 | (void) fprintf(f, "%scs#%" PRIu16 ":", did, lp->d_cylskew); |
1368 | did = ""; | | 1368 | did = ""; |
1369 | } | | 1369 | } |
1370 | if (lp->d_headswitch != 0) { | | 1370 | if (lp->d_headswitch != 0) { |
1371 | (void) fprintf(f, "%shs#%" PRIu16 ":", did, lp->d_headswitch); | | 1371 | (void) fprintf(f, "%shs#%" PRIu16 ":", did, lp->d_headswitch); |
1372 | did = ""; | | 1372 | did = ""; |
1373 | } | | 1373 | } |
1374 | if (lp->d_trkseek != 0) { | | 1374 | if (lp->d_trkseek != 0) { |
1375 | (void) fprintf(f, "%sts#%" PRIu32 ":", did, lp->d_trkseek); | | 1375 | (void) fprintf(f, "%sts#%" PRIu32 ":", did, lp->d_trkseek); |
1376 | did = ""; | | 1376 | did = ""; |
1377 | } | | 1377 | } |
1378 | #ifdef notyet | | 1378 | #ifdef notyet |
1379 | (void) fprintf(f, "drivedata: "); | | 1379 | (void) fprintf(f, "drivedata: "); |
1380 | for (i = NDDATA - 1; i >= 0; i--) | | 1380 | for (i = NDDATA - 1; i >= 0; i--) |
1381 | if (lp->d_drivedata[i]) | | 1381 | if (lp->d_drivedata[i]) |
1382 | break; | | 1382 | break; |
1383 | if (i < 0) | | 1383 | if (i < 0) |
1384 | i = 0; | | 1384 | i = 0; |
1385 | for (j = 0; j <= i; j++) | | 1385 | for (j = 0; j <= i; j++) |
1386 | (void) fprintf(f, "%" PRIu32 " ", lp->d_drivedata[j]); | | 1386 | (void) fprintf(f, "%" PRIu32 " ", lp->d_drivedata[j]); |
1387 | #endif /* notyet */ | | 1387 | #endif /* notyet */ |
1388 | pp = lp->d_partitions; | | 1388 | pp = lp->d_partitions; |
1389 | for (i = 0; i < lp->d_npartitions; i++, pp++) { | | 1389 | for (i = 0; i < lp->d_npartitions; i++, pp++) { |
1390 | if (pp->p_size) { | | 1390 | if (pp->p_size) { |
1391 | char c = 'a' + i; | | 1391 | char c = 'a' + i; |
1392 | (void) fprintf(f, "\\\n\t:"); | | 1392 | (void) fprintf(f, "\\\n\t:"); |
1393 | (void) fprintf(f, "p%c#%" PRIu32 ":", c, pp->p_size); | | 1393 | (void) fprintf(f, "p%c#%" PRIu32 ":", c, pp->p_size); |
1394 | (void) fprintf(f, "o%c#%" PRIu32 ":", c, pp->p_offset); | | 1394 | (void) fprintf(f, "o%c#%" PRIu32 ":", c, pp->p_offset); |
1395 | if (pp->p_fstype != FS_UNUSED) { | | 1395 | if (pp->p_fstype != FS_UNUSED) { |
1396 | if ((unsigned) pp->p_fstype < FSMAXTYPES) | | 1396 | if ((unsigned) pp->p_fstype < FSMAXTYPES) |
1397 | (void) fprintf(f, "t%c=%s:", c, | | 1397 | (void) fprintf(f, "t%c=%s:", c, |
1398 | fstypenames[pp->p_fstype]); | | 1398 | fstypenames[pp->p_fstype]); |
1399 | else | | 1399 | else |
1400 | (void) fprintf(f, | | 1400 | (void) fprintf(f, |
1401 | "t%c=unknown%" PRIu8 ":", | | 1401 | "t%c=unknown%" PRIu8 ":", |
1402 | c, pp->p_fstype); | | 1402 | c, pp->p_fstype); |
1403 | } | | 1403 | } |
1404 | switch (pp->p_fstype) { | | 1404 | switch (pp->p_fstype) { |
1405 | | | 1405 | |
1406 | case FS_UNUSED: | | 1406 | case FS_UNUSED: |
1407 | break; | | 1407 | break; |
1408 | | | 1408 | |
1409 | case FS_BSDFFS: | | 1409 | case FS_BSDFFS: |
1410 | case FS_BSDLFS: | | 1410 | case FS_BSDLFS: |
1411 | case FS_EX2FS: | | 1411 | case FS_EX2FS: |
1412 | case FS_ADOS: | | 1412 | case FS_ADOS: |
1413 | case FS_APPLEUFS: | | 1413 | case FS_APPLEUFS: |
1414 | (void) fprintf(f, "b%c#%" PRIu64 ":", c, | | 1414 | (void) fprintf(f, "b%c#%" PRIu64 ":", c, |
1415 | (uint64_t)pp->p_fsize * pp->p_frag); | | 1415 | (uint64_t)pp->p_fsize * pp->p_frag); |
1416 | (void) fprintf(f, "f%c#%" PRIu32 ":", c, | | 1416 | (void) fprintf(f, "f%c#%" PRIu32 ":", c, |
1417 | pp->p_fsize); | | 1417 | pp->p_fsize); |
1418 | break; | | 1418 | break; |
1419 | default: | | 1419 | default: |
1420 | break; | | 1420 | break; |
1421 | } | | 1421 | } |
1422 | } | | 1422 | } |
1423 | } | | 1423 | } |
1424 | (void) fprintf(f, "\n"); | | 1424 | (void) fprintf(f, "\n"); |
1425 | (void) fflush(f); | | 1425 | (void) fflush(f); |
1426 | } | | 1426 | } |
1427 | | | 1427 | |
1428 | static int | | 1428 | static int |
1429 | edit(int f) | | 1429 | edit(int f) |
1430 | { | | 1430 | { |
1431 | const char *tmpdir; | | 1431 | const char *tmpdir; |
1432 | char tmpfil[MAXPATHLEN]; | | 1432 | char tmpfil[MAXPATHLEN]; |
1433 | int first, ch, fd; | | 1433 | int first, ch, fd; |
1434 | int get_ok; | | 1434 | int get_ok; |
1435 | FILE *fp; | | 1435 | FILE *fp; |
1436 | | | 1436 | |
1437 | if ((tmpdir = getenv("TMPDIR")) == NULL) | | 1437 | if ((tmpdir = getenv("TMPDIR")) == NULL) |
1438 | tmpdir = _PATH_TMP; | | 1438 | tmpdir = _PATH_TMP; |
1439 | (void)snprintf(tmpfil, sizeof(tmpfil), "%s/%s", tmpdir, TMPFILE); | | 1439 | (void)snprintf(tmpfil, sizeof(tmpfil), "%s/%s", tmpdir, TMPFILE); |
1440 | if ((fd = mkstemp(tmpfil)) == -1 || (fp = fdopen(fd, "w")) == NULL) { | | 1440 | if ((fd = mkstemp(tmpfil)) == -1 || (fp = fdopen(fd, "w")) == NULL) { |
1441 | warn("%s", tmpfil); | | 1441 | warn("%s", tmpfil); |
1442 | return (1); | | 1442 | return (1); |
1443 | } | | 1443 | } |
1444 | (void)fchmod(fd, 0600); | | 1444 | (void)fchmod(fd, 0600); |
1445 | showinfo(fp, &lab, specname); | | 1445 | showinfo(fp, &lab, specname); |
1446 | showpartitions(fp, &lab, Cflag); | | 1446 | showpartitions(fp, &lab, Cflag); |
1447 | (void) fclose(fp); | | 1447 | (void) fclose(fp); |
1448 | for (;;) { | | 1448 | for (;;) { |
1449 | if (!editit(tmpfil)) | | 1449 | if (!editit(tmpfil)) |
1450 | break; | | 1450 | break; |
1451 | fp = fopen(tmpfil, "r"); | | 1451 | fp = fopen(tmpfil, "r"); |
1452 | if (fp == NULL) { | | 1452 | if (fp == NULL) { |
1453 | warn("%s", tmpfil); | | 1453 | warn("%s", tmpfil); |
1454 | break; | | 1454 | break; |
1455 | } | | 1455 | } |
1456 | (void) memset(&lab, 0, sizeof(lab)); | | 1456 | (void) memset(&lab, 0, sizeof(lab)); |
1457 | get_ok = getasciilabel(fp, &lab); | | 1457 | get_ok = getasciilabel(fp, &lab); |
1458 | fclose(fp); | | 1458 | fclose(fp); |
1459 | if (get_ok && write_label(f) == 0) { | | 1459 | if (get_ok && write_label(f) == 0) { |
1460 | (void) unlink(tmpfil); | | 1460 | (void) unlink(tmpfil); |
1461 | return (0); | | 1461 | return (0); |
1462 | } | | 1462 | } |
1463 | (void) printf("re-edit the label? [y]: "); | | 1463 | (void) printf("re-edit the label? [y]: "); |
1464 | (void) fflush(stdout); | | 1464 | (void) fflush(stdout); |
1465 | first = ch = getchar(); | | 1465 | first = ch = getchar(); |
1466 | while (ch != '\n' && ch != EOF) | | 1466 | while (ch != '\n' && ch != EOF) |
1467 | ch = getchar(); | | 1467 | ch = getchar(); |
1468 | if (first == 'n' || first == 'N') | | 1468 | if (first == 'n' || first == 'N') |
1469 | break; | | 1469 | break; |
1470 | } | | 1470 | } |
1471 | (void)unlink(tmpfil); | | 1471 | (void)unlink(tmpfil); |
1472 | return (1); | | 1472 | return (1); |
1473 | } | | 1473 | } |
1474 | | | 1474 | |
1475 | static int | | 1475 | static int |
1476 | editit(const char *tmpfil) | | 1476 | editit(const char *tmpfil) |
1477 | { | | 1477 | { |
1478 | int pid, xpid; | | 1478 | int pid, xpid; |
1479 | int status; | | 1479 | int status; |
1480 | sigset_t nsigset, osigset; | | 1480 | sigset_t nsigset, osigset; |
1481 | | | 1481 | |
1482 | sigemptyset(&nsigset); | | 1482 | sigemptyset(&nsigset); |
1483 | sigaddset(&nsigset, SIGINT); | | 1483 | sigaddset(&nsigset, SIGINT); |
1484 | sigaddset(&nsigset, SIGQUIT); | | 1484 | sigaddset(&nsigset, SIGQUIT); |
1485 | sigaddset(&nsigset, SIGHUP); | | 1485 | sigaddset(&nsigset, SIGHUP); |
1486 | sigprocmask(SIG_BLOCK, &nsigset, &osigset); | | 1486 | sigprocmask(SIG_BLOCK, &nsigset, &osigset); |
1487 | while ((pid = fork()) < 0) { | | 1487 | while ((pid = fork()) < 0) { |
1488 | if (errno != EAGAIN) { | | 1488 | if (errno != EAGAIN) { |
1489 | sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); | | 1489 | sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); |
1490 | warn("fork"); | | 1490 | warn("fork"); |
1491 | return (0); | | 1491 | return (0); |
1492 | } | | 1492 | } |
1493 | sleep(1); | | 1493 | sleep(1); |
1494 | } | | 1494 | } |
1495 | if (pid == 0) { | | 1495 | if (pid == 0) { |
1496 | const char *ed; | | 1496 | const char *ed; |
1497 | char *buf; | | 1497 | char *buf; |
1498 | int retval; | | 1498 | int retval; |
1499 | | | 1499 | |
1500 | sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); | | 1500 | sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); |
1501 | setgid(getgid()); | | 1501 | setgid(getgid()); |
1502 | setuid(getuid()); | | 1502 | setuid(getuid()); |
1503 | if ((ed = getenv("EDITOR")) == (char *)0) | | 1503 | if ((ed = getenv("EDITOR")) == (char *)0) |
1504 | ed = DEFEDITOR; | | 1504 | ed = DEFEDITOR; |
1505 | /* | | 1505 | /* |
1506 | * Jump through a few extra hoops in case someone's editor | | 1506 | * Jump through a few extra hoops in case someone's editor |
1507 | * is "editor arg1 arg2". | | 1507 | * is "editor arg1 arg2". |
1508 | */ | | 1508 | */ |
1509 | asprintf(&buf, "%s %s", ed, tmpfil); | | 1509 | asprintf(&buf, "%s %s", ed, tmpfil); |
1510 | if (!buf) | | 1510 | if (!buf) |
1511 | err(1, "malloc"); | | 1511 | err(1, "malloc"); |
1512 | retval = execlp(_PATH_BSHELL, _PATH_BSHELL, "-c", buf, NULL); | | 1512 | retval = execlp(_PATH_BSHELL, _PATH_BSHELL, "-c", buf, NULL); |
1513 | if (retval == -1) | | 1513 | if (retval == -1) |
1514 | perror(ed); | | 1514 | perror(ed); |
1515 | exit(retval); | | 1515 | exit(retval); |
1516 | } | | 1516 | } |
1517 | while ((xpid = wait(&status)) >= 0) | | 1517 | while ((xpid = wait(&status)) >= 0) |
1518 | if (xpid == pid) | | 1518 | if (xpid == pid) |
1519 | break; | | 1519 | break; |
1520 | sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); | | 1520 | sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); |
1521 | return (!status); | | 1521 | return (!status); |
1522 | } | | 1522 | } |
1523 | | | 1523 | |
1524 | static char * | | 1524 | static char * |
1525 | skip(char *cp) | | 1525 | skip(char *cp) |
1526 | { | | 1526 | { |
1527 | | | 1527 | |
1528 | cp += strspn(cp, " \t"); | | 1528 | cp += strspn(cp, " \t"); |
1529 | if (*cp == '\0') | | 1529 | if (*cp == '\0') |
1530 | return (NULL); | | 1530 | return (NULL); |
1531 | return (cp); | | 1531 | return (cp); |
1532 | } | | 1532 | } |
1533 | | | 1533 | |
1534 | static char * | | 1534 | static char * |
1535 | word(char *cp) | | 1535 | word(char *cp) |
1536 | { | | 1536 | { |
1537 | | | 1537 | |
1538 | if (cp == NULL || *cp == '\0') | | 1538 | if (cp == NULL || *cp == '\0') |
1539 | return (NULL); | | 1539 | return (NULL); |
1540 | | | 1540 | |
1541 | cp += strcspn(cp, " \t"); | | 1541 | cp += strcspn(cp, " \t"); |
1542 | if (*cp == '\0') | | 1542 | if (*cp == '\0') |
1543 | return (NULL); | | 1543 | return (NULL); |
1544 | *cp++ = '\0'; | | 1544 | *cp++ = '\0'; |
1545 | cp += strspn(cp, " \t"); | | 1545 | cp += strspn(cp, " \t"); |
1546 | if (*cp == '\0') | | 1546 | if (*cp == '\0') |
1547 | return (NULL); | | 1547 | return (NULL); |
1548 | return (cp); | | 1548 | return (cp); |
1549 | } | | 1549 | } |
1550 | | | 1550 | |
1551 | #define _CHECKLINE \ | | 1551 | #define _CHECKLINE \ |
1552 | if (tp == NULL || *tp == '\0') { \ | | 1552 | if (tp == NULL || *tp == '\0') { \ |
1553 | warnx("line %d: too few fields", lineno); \ | | 1553 | warnx("line %d: too few fields", lineno); \ |
1554 | errors++; \ | | 1554 | errors++; \ |
1555 | break; \ | | 1555 | break; \ |
1556 | } | | 1556 | } |
1557 | | | 1557 | |
1558 | #define __CHECKLINE \ | | 1558 | #define __CHECKLINE \ |
1559 | if (*tp == NULL || **tp == '\0') { \ | | 1559 | if (*tp == NULL || **tp == '\0') { \ |
1560 | warnx("line %d: too few fields", lineno); \ | | 1560 | warnx("line %d: too few fields", lineno); \ |
1561 | *tp = _error_; \ | | 1561 | *tp = _error_; \ |
1562 | return 0; \ | | 1562 | return 0; \ |
1563 | } | | 1563 | } |
1564 | | | 1564 | |
1565 | static char _error_[] = ""; | | 1565 | static char _error_[] = ""; |
1566 | #define NXTNUM(n) if ((n = nxtnum(&tp, lineno),0) + tp != _error_) \ | | 1566 | #define NXTNUM(n) if ((n = nxtnum(&tp, lineno),0) + tp != _error_) \ |
1567 | ; else goto error | | 1567 | ; else goto error |
1568 | #define NXTXNUM(n) if ((n = nxtxnum(&tp, lp, lineno),0) + tp != _error_) \ | | 1568 | #define NXTXNUM(n) if ((n = nxtxnum(&tp, lp, lineno),0) + tp != _error_) \ |
1569 | ; else goto error | | 1569 | ; else goto error |
1570 | | | 1570 | |
1571 | static unsigned long | | 1571 | static unsigned long |
1572 | nxtnum(char **tp, int lineno) | | 1572 | nxtnum(char **tp, int lineno) |
1573 | { | | 1573 | { |
1574 | char *cp; | | 1574 | char *cp; |
1575 | unsigned long v; | | 1575 | unsigned long v; |