| @@ -1,2242 +1,2242 @@ | | | @@ -1,2242 +1,2242 @@ |
1 | /* $NetBSD: main.c,v 1.55 2020/09/29 02:58:52 msaitoh Exp $ */ | | 1 | /* $NetBSD: main.c,v 1.56 2021/05/29 17:41:51 christos 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.55 2020/09/29 02:58:52 msaitoh Exp $"); | | 79 | __RCSID("$NetBSD: main.c,v 1.56 2021/05/29 17:41:51 christos 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 verbose; | | 157 | static int verbose; |
158 | static int read_all; /* set if op = READ && Aflag */ | | 158 | static int read_all; /* set if op = READ && Aflag */ |
159 | | | 159 | |
160 | static int write_label(int); | | 160 | static int write_label(int); |
161 | static int readlabel_direct(int); | | 161 | static int readlabel_direct(int); |
162 | static void writelabel_direct(int); | | 162 | static void writelabel_direct(int); |
163 | static int update_label(int, u_int, u_int); | | 163 | static int update_label(int, u_int, u_int); |
164 | static struct disklabel *find_label(int, u_int); | | 164 | static struct disklabel *find_label(int, u_int); |
165 | #if !defined(NATIVELABEL_ONLY) | | 165 | #if !defined(NATIVELABEL_ONLY) |
166 | static void getmachineparams(const char *); | | 166 | static void getmachineparams(const char *); |
167 | #endif | | 167 | #endif |
168 | | | 168 | |
169 | static void makedisktab(FILE *, struct disklabel *); | | 169 | static void makedisktab(FILE *, struct disklabel *); |
170 | static void makelabel(const char *, const char *); | | 170 | static void makelabel(const char *, const char *); |
171 | static void l_perror(const char *); | | 171 | static void l_perror(const char *); |
172 | static void readlabel(int); | | 172 | static void readlabel(int); |
173 | static int edit(int); | | 173 | static int edit(int); |
174 | static int editit(const char *); | | 174 | static int editit(const char *); |
175 | static char *skip(char *); | | 175 | static char *skip(char *); |
176 | static char *word(char *); | | 176 | static char *word(char *); |
177 | static int getasciilabel(FILE *, struct disklabel *); | | 177 | static int getasciilabel(FILE *, struct disklabel *); |
178 | __dead static void usage(void); | | 178 | __dead static void usage(void); |
179 | static int qsort_strcmp(const void *, const void *); | | 179 | static int qsort_strcmp(const void *, const void *); |
180 | static int getulong(const char *, char, char **, | | 180 | static int getulong(const char *, char, char **, |
181 | unsigned long *, unsigned long); | | 181 | unsigned long *, unsigned long); |
182 | #define GETNUM32(a, v) getulong(a, '\0', NULL, v, UINT32_MAX) | | 182 | #define GETNUM32(a, v) getulong(a, '\0', NULL, v, UINT32_MAX) |
183 | #define GETNUM16(a, v) getulong(a, '\0', NULL, v, UINT16_MAX) | | 183 | #define GETNUM16(a, v) getulong(a, '\0', NULL, v, UINT16_MAX) |
184 | #define GETNUM8(a, v) getulong(a, '\0', NULL, v, UINT8_MAX) | | 184 | #define GETNUM8(a, v) getulong(a, '\0', NULL, v, UINT8_MAX) |
185 | | | 185 | |
186 | static int set_writable_fd = -1; | | 186 | static int set_writable_fd = -1; |
187 | | | 187 | |
188 | #if !defined(NATIVELABEL_ONLY) | | 188 | #if !defined(NATIVELABEL_ONLY) |
189 | static u_int labeloffset; | | 189 | static u_int labeloffset; |
190 | static u_int labelsector; | | 190 | static u_int labelsector; |
191 | static int labelusesmbr; | | 191 | static int labelusesmbr; |
192 | u_int maxpartitions; | | 192 | u_int maxpartitions; |
193 | static int byteorder; | | 193 | static int byteorder; |
194 | | | 194 | |
195 | static int biendian_p; | | 195 | static int biendian_p; |
196 | #ifndef HAVE_NBTOOL_CONFIG_H | | 196 | #ifndef HAVE_NBTOOL_CONFIG_H |
197 | static int native_p = 1; | | 197 | static int native_p = 1; |
198 | #endif | | 198 | #endif |
199 | int bswap_p; | | 199 | int bswap_p; |
200 | | | 200 | |
201 | static const struct disklabel_params { | | 201 | static const struct disklabel_params { |
202 | const char *machine; | | 202 | const char *machine; |
203 | u_char labelusesmbr : 1; | | 203 | u_char labelusesmbr : 1; |
204 | u_char labelsector : 7; | | 204 | u_char labelsector : 7; |
205 | u_char maxpartitions; | | 205 | u_char maxpartitions; |
206 | u_char raw_part; | | 206 | u_char raw_part; |
207 | u_char oldmaxpartitions; | | 207 | u_char oldmaxpartitions; |
208 | u_short labeloffset; | | 208 | u_short labeloffset; |
209 | u_short byteorder; | | 209 | u_short byteorder; |
210 | } disklabel_params[] = { | | 210 | } disklabel_params[] = { |
211 | { "mvme68k", 0, 0, 8, 2, 0, 0, BIG_ENDIAN }, /* m68k */ | | 211 | { "mvme68k", 0, 0, 8, 2, 0, 0, BIG_ENDIAN }, /* m68k */ |
212 | { "next68k", 0, 0, 8, 2, 0, 0, BIG_ENDIAN }, /* m68k */ | | 212 | { "next68k", 0, 0, 8, 2, 0, 0, BIG_ENDIAN }, /* m68k */ |
213 | | | 213 | |
214 | { "algor", 0, 0, 8, 2, 0, 64, LITTLE_ENDIAN }, /* mips */ | | 214 | { "algor", 0, 0, 8, 2, 0, 64, LITTLE_ENDIAN }, /* mips */ |
215 | { "alpha", 0, 0, 8, 2, 0, 64, LITTLE_ENDIAN }, /* alpha */ | | 215 | { "alpha", 0, 0, 8, 2, 0, 64, LITTLE_ENDIAN }, /* alpha */ |
216 | { "luna68k", 0, 0, 8, 2, 0, 64, BIG_ENDIAN }, /* m68k */ | | 216 | { "luna68k", 0, 0, 8, 2, 0, 64, BIG_ENDIAN }, /* m68k */ |
217 | { "mac68k", 0, 0, 8, 2, 0, 64, BIG_ENDIAN }, /* m68k */ | | 217 | { "mac68k", 0, 0, 8, 2, 0, 64, BIG_ENDIAN }, /* m68k */ |
218 | { "news68k", 0, 0, 8, 2, 0, 64, BIG_ENDIAN }, /* m68k */ | | 218 | { "news68k", 0, 0, 8, 2, 0, 64, BIG_ENDIAN }, /* m68k */ |
219 | { "newsmips", 0, 0, 8, 2, 0, 64, BIG_ENDIAN }, /* mips */ | | 219 | { "newsmips", 0, 0, 8, 2, 0, 64, BIG_ENDIAN }, /* mips */ |
220 | { "pmax", 0, 0, 8, 2, 0, 64, LITTLE_ENDIAN }, /* mips */ | | 220 | { "pmax", 0, 0, 8, 2, 0, 64, LITTLE_ENDIAN }, /* mips */ |
221 | { "sun2", 0, 0, 8, 2, 0, 64, BIG_ENDIAN }, /* m68k */ | | 221 | { "sun2", 0, 0, 8, 2, 0, 64, BIG_ENDIAN }, /* m68k */ |
222 | { "sun68k", 0, 0, 8, 2, 0, 64, BIG_ENDIAN }, /* m68010 */ | | 222 | { "sun68k", 0, 0, 8, 2, 0, 64, BIG_ENDIAN }, /* m68010 */ |
223 | { "x68k", 0, 0, 8, 2, 0, 64, BIG_ENDIAN }, /* m68k */ | | 223 | { "x68k", 0, 0, 8, 2, 0, 64, BIG_ENDIAN }, /* m68k */ |
224 | | | 224 | |
225 | { "vax", 0, 0, 12, 2, 8, 64, LITTLE_ENDIAN }, /* vax */ | | 225 | { "vax", 0, 0, 12, 2, 8, 64, LITTLE_ENDIAN }, /* vax */ |
226 | | | 226 | |
227 | { "amiga", 0, 0, 16, 2, 0, 64, BIG_ENDIAN }, /* m68k */ | | 227 | { "amiga", 0, 0, 16, 2, 0, 64, BIG_ENDIAN }, /* m68k */ |
228 | { "amigappc", 0, 0, 16, 2, 0, 64, BIG_ENDIAN }, /* powerpc */ | | 228 | { "amigappc", 0, 0, 16, 2, 0, 64, BIG_ENDIAN }, /* powerpc */ |
229 | { "evbmips", 0, 0, 16, 2, 0, 64, 0 }, /* mips */ | | 229 | { "evbmips", 0, 0, 16, 2, 0, 64, 0 }, /* mips */ |
230 | { "evbppc", 0, 0, 16, 2, 0, 64, BIG_ENDIAN }, /* powerpc */ | | 230 | { "evbppc", 0, 0, 16, 2, 0, 64, BIG_ENDIAN }, /* powerpc */ |
231 | | | 231 | |
232 | { "sparc", 0, 0, 8, 2, 0, 128, BIG_ENDIAN }, /* sun */ | | 232 | { "sparc", 0, 0, 8, 2, 0, 128, BIG_ENDIAN }, /* sun */ |
233 | { "sparc64", 0, 0, 8, 2, 0, 128, BIG_ENDIAN }, /* sun */ | | 233 | { "sparc64", 0, 0, 8, 2, 0, 128, BIG_ENDIAN }, /* sun */ |
234 | { "sun3", 0, 0, 8, 2, 0, 128, BIG_ENDIAN }, /* sun */ | | 234 | { "sun3", 0, 0, 8, 2, 0, 128, BIG_ENDIAN }, /* sun */ |
235 | | | 235 | |
236 | { "atari", 0, 0, 16, 2, 0, 516, BIG_ENDIAN }, /* m68k */ | | 236 | { "atari", 0, 0, 16, 2, 0, 516, BIG_ENDIAN }, /* m68k */ |
237 | | | 237 | |
238 | { "mipsco", 0, 1, 8, 2, 0, 0, BIG_ENDIAN }, /* mips */ | | 238 | { "mipsco", 0, 1, 8, 2, 0, 0, BIG_ENDIAN }, /* mips */ |
239 | { "mvmeppc", 0, 1, 8, 3, 0, 0, BIG_ENDIAN }, /* powerpc */ | | 239 | { "mvmeppc", 0, 1, 8, 3, 0, 0, BIG_ENDIAN }, /* powerpc */ |
240 | | | 240 | |
241 | { "bebox", 0, 1, 8, 3, 0, 0, BIG_ENDIAN }, /* powerpc */ | | 241 | { "bebox", 0, 1, 8, 3, 0, 0, BIG_ENDIAN }, /* powerpc */ |
242 | | | 242 | |
243 | { "emips", 0, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* mips */ | | 243 | { "emips", 0, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* mips */ |
244 | { "hppa", 0, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* hppa */ | | 244 | { "hppa", 0, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* hppa */ |
245 | { "ibmnws", 0, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* powerpc */ | | 245 | { "ibmnws", 0, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* powerpc */ |
246 | { "ofppc", 0, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* powerpc */ | | 246 | { "ofppc", 0, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* powerpc */ |
247 | { "rs6000", 0, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* powerpc */ | | 247 | { "rs6000", 0, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* powerpc */ |
248 | { "sandpoint", 0, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* powerpc */ | | 248 | { "sandpoint", 0, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* powerpc */ |
249 | { "sgimips", 0, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* mips */ | | 249 | { "sgimips", 0, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* mips */ |
250 | | | 250 | |
251 | { "sbmips", 0, 1, 16, 3, 0, 0, 0 }, /* mips */ | | 251 | { "sbmips", 0, 1, 16, 3, 0, 0, 0 }, /* mips */ |
252 | | | 252 | |
253 | { "cesfic", 0, 2, 8, 2, 0, 0, BIG_ENDIAN }, /* m68k */ | | 253 | { "cesfic", 0, 2, 8, 2, 0, 0, BIG_ENDIAN }, /* m68k */ |
254 | { "hp300", 0, 2, 8, 2, 0, 0, BIG_ENDIAN }, /* m68k */ | | 254 | { "hp300", 0, 2, 8, 2, 0, 0, BIG_ENDIAN }, /* m68k */ |
255 | | | 255 | |
256 | { "ews4800mips",0, 9, 16, 15, 0, 0, BIG_ENDIAN }, /* mips */ | | 256 | { "ews4800mips",0, 9, 16, 15, 0, 0, BIG_ENDIAN }, /* mips */ |
257 | | | 257 | |
258 | { "macppc", 1, 0, 16, 2, 0, 64, BIG_ENDIAN }, /* powerpc */ | | 258 | { "macppc", 1, 0, 16, 2, 0, 64, BIG_ENDIAN }, /* powerpc */ |
259 | { "pmon", 1, 0, 16, 2, 0, 64, 0 }, /* evbmips */ | | 259 | { "pmon", 1, 0, 16, 2, 0, 64, 0 }, /* evbmips */ |
260 | | | 260 | |
261 | { "prep", 1, 1, 8, 2, 0, 0, BIG_ENDIAN }, /* powerpc */ | | 261 | { "prep", 1, 1, 8, 2, 0, 0, BIG_ENDIAN }, /* powerpc */ |
262 | | | 262 | |
263 | { "dreamcast", 1, 1, 16, 2, 0, 0, LITTLE_ENDIAN }, /* sh3 */ | | 263 | { "dreamcast", 1, 1, 16, 2, 0, 0, LITTLE_ENDIAN }, /* sh3 */ |
264 | { "evbcf", 1, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* coldfire */ | | 264 | { "evbcf", 1, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* coldfire */ |
265 | { "evbppc-mbr", 1, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* powerpc */ | | 265 | { "evbppc-mbr", 1, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* powerpc */ |
266 | { "evbsh3", 1, 1, 16, 2, 0, 0, 0 }, /* sh3 */ | | 266 | { "evbsh3", 1, 1, 16, 2, 0, 0, 0 }, /* sh3 */ |
267 | { "hpcsh", 1, 1, 16, 2, 0, 0, LITTLE_ENDIAN }, /* sh3 */ | | 267 | { "hpcsh", 1, 1, 16, 2, 0, 0, LITTLE_ENDIAN }, /* sh3 */ |
268 | { "mmeye", 1, 1, 16, 2, 0, 0, 0 }, /* sh3 */ | | 268 | { "mmeye", 1, 1, 16, 2, 0, 0, 0 }, /* sh3 */ |
269 | { "or1k", 1, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* or1k */ | | 269 | { "or1k", 1, 1, 16, 2, 0, 0, BIG_ENDIAN }, /* or1k */ |
270 | { "riscv", 1, 1, 16, 2, 0, 0, LITTLE_ENDIAN }, /* riscv */ | | 270 | { "riscv", 1, 1, 16, 2, 0, 0, LITTLE_ENDIAN }, /* riscv */ |
271 | | | 271 | |
272 | { "acorn32", 1, 1, 16, 2, 8, 0, LITTLE_ENDIAN }, /* arm */ | | 272 | { "acorn32", 1, 1, 16, 2, 8, 0, LITTLE_ENDIAN }, /* arm */ |
273 | { "cats", 1, 1, 16, 2, 8, 0, LITTLE_ENDIAN }, /* arm */ | | 273 | { "cats", 1, 1, 16, 2, 8, 0, LITTLE_ENDIAN }, /* arm */ |
274 | { "evbarm", 1, 1, 16, 2, 8, 0, 0 }, /* arm */ | | 274 | { "evbarm", 1, 1, 16, 2, 8, 0, 0 }, /* arm */ |
275 | { "iyonix", 1, 1, 16, 2, 8, 0, LITTLE_ENDIAN }, /* arm */ | | 275 | { "iyonix", 1, 1, 16, 2, 8, 0, LITTLE_ENDIAN }, /* arm */ |
276 | { "netwinder", 1, 1, 16, 2, 8, 0, LITTLE_ENDIAN }, /* arm */ | | 276 | { "netwinder", 1, 1, 16, 2, 8, 0, LITTLE_ENDIAN }, /* arm */ |
277 | { "shark", 1, 1, 16, 2, 8, 0, LITTLE_ENDIAN }, /* arm */ | | 277 | { "shark", 1, 1, 16, 2, 8, 0, LITTLE_ENDIAN }, /* arm */ |
278 | | | 278 | |
279 | { "amd64", 1, 1, 16, 3, 0, 0, LITTLE_ENDIAN }, /* x86 */ | | 279 | { "amd64", 1, 1, 16, 3, 0, 0, LITTLE_ENDIAN }, /* x86 */ |
280 | { "arc", 1, 1, 16, 3, 0, 0, LITTLE_ENDIAN }, /* mips */ | | 280 | { "arc", 1, 1, 16, 3, 0, 0, LITTLE_ENDIAN }, /* mips */ |
281 | { "cobalt", 1, 1, 16, 3, 0, 0, LITTLE_ENDIAN }, /* mips */ | | 281 | { "cobalt", 1, 1, 16, 3, 0, 0, LITTLE_ENDIAN }, /* mips */ |
282 | { "landisk", 1, 1, 16, 3, 0, 0, LITTLE_ENDIAN }, /* sh3 */ | | 282 | { "landisk", 1, 1, 16, 3, 0, 0, LITTLE_ENDIAN }, /* sh3 */ |
283 | | | 283 | |
284 | { "epoc32", 1, 1, 16, 3, 8, 0, LITTLE_ENDIAN }, /* arm */ | | 284 | { "epoc32", 1, 1, 16, 3, 8, 0, LITTLE_ENDIAN }, /* arm */ |
285 | { "hpcarm", 1, 1, 16, 3, 8, 0, LITTLE_ENDIAN }, /* arm */ | | 285 | { "hpcarm", 1, 1, 16, 3, 8, 0, LITTLE_ENDIAN }, /* arm */ |
286 | { "hpcmips", 1, 1, 16, 3, 8, 0, LITTLE_ENDIAN }, /* mips */ | | 286 | { "hpcmips", 1, 1, 16, 3, 8, 0, LITTLE_ENDIAN }, /* mips */ |
287 | { "i386", 1, 1, 16, 3, 8, 0, LITTLE_ENDIAN }, /* x86 */ | | 287 | { "i386", 1, 1, 16, 3, 8, 0, LITTLE_ENDIAN }, /* x86 */ |
288 | { "ia64", 1, 1, 16, 3, 8, 0, LITTLE_ENDIAN }, /* x86 */ | | 288 | { "ia64", 1, 1, 16, 3, 8, 0, LITTLE_ENDIAN }, /* x86 */ |
289 | { "zaurus", 1, 1, 16, 3, 8, 0, LITTLE_ENDIAN }, /* arm */ | | 289 | { "zaurus", 1, 1, 16, 3, 8, 0, LITTLE_ENDIAN }, /* arm */ |
290 | | | 290 | |
291 | { NULL, 0, 0, 0, 0, 0, 0, 0 }, /* must be last */ | | 291 | { NULL, 0, 0, 0, 0, 0, 0, 0 }, /* must be last */ |
292 | }; | | 292 | }; |
293 | | | 293 | |
294 | #ifndef HAVE_NBTOOL_CONFIG_H | | 294 | #ifndef HAVE_NBTOOL_CONFIG_H |
295 | static struct disklabel_params native_params; | | 295 | static struct disklabel_params native_params; |
296 | #endif | | 296 | #endif |
297 | | | 297 | |
298 | static const struct arch_endian { | | 298 | static const struct arch_endian { |
299 | int byteorder; | | 299 | int byteorder; |
300 | const char *arch; | | 300 | const char *arch; |
301 | } arch_endians[] = { | | 301 | } arch_endians[] = { |
302 | { LITTLE_ENDIAN, "aarch64" }, | | 302 | { LITTLE_ENDIAN, "aarch64" }, |
303 | { LITTLE_ENDIAN, "alpha" }, | | 303 | { LITTLE_ENDIAN, "alpha" }, |
304 | { LITTLE_ENDIAN, "arm" }, | | 304 | { LITTLE_ENDIAN, "arm" }, |
305 | { LITTLE_ENDIAN, "earm" }, | | 305 | { LITTLE_ENDIAN, "earm" }, |
306 | { LITTLE_ENDIAN, "earmhf" }, | | 306 | { LITTLE_ENDIAN, "earmhf" }, |
307 | { LITTLE_ENDIAN, "earmv4" }, | | 307 | { LITTLE_ENDIAN, "earmv4" }, |
308 | { LITTLE_ENDIAN, "earmv5" }, | | 308 | { LITTLE_ENDIAN, "earmv5" }, |
309 | { LITTLE_ENDIAN, "earmv6" }, | | 309 | { LITTLE_ENDIAN, "earmv6" }, |
310 | { LITTLE_ENDIAN, "earmv6hf" }, | | 310 | { LITTLE_ENDIAN, "earmv6hf" }, |
311 | { LITTLE_ENDIAN, "earmv7" }, | | 311 | { LITTLE_ENDIAN, "earmv7" }, |
312 | { LITTLE_ENDIAN, "earmv7hf" }, | | 312 | { LITTLE_ENDIAN, "earmv7hf" }, |
313 | { LITTLE_ENDIAN, "i386" }, | | 313 | { LITTLE_ENDIAN, "i386" }, |
314 | { LITTLE_ENDIAN, "ia64" }, | | 314 | { LITTLE_ENDIAN, "ia64" }, |
315 | { LITTLE_ENDIAN, "mipsel" }, | | 315 | { LITTLE_ENDIAN, "mipsel" }, |
316 | { LITTLE_ENDIAN, "mips64el" }, | | 316 | { LITTLE_ENDIAN, "mips64el" }, |
317 | { LITTLE_ENDIAN, "riscv32" }, | | 317 | { LITTLE_ENDIAN, "riscv32" }, |
318 | { LITTLE_ENDIAN, "riscv64" }, | | 318 | { LITTLE_ENDIAN, "riscv64" }, |
319 | { LITTLE_ENDIAN, "sh3el" }, | | 319 | { LITTLE_ENDIAN, "sh3el" }, |
320 | { LITTLE_ENDIAN, "vax" }, | | 320 | { LITTLE_ENDIAN, "vax" }, |
321 | { LITTLE_ENDIAN, "x86_64" }, | | 321 | { LITTLE_ENDIAN, "x86_64" }, |
322 | | | 322 | |
323 | { BIG_ENDIAN, "aarch64eb" }, | | 323 | { BIG_ENDIAN, "aarch64eb" }, |
324 | { BIG_ENDIAN, "armeb" }, | | 324 | { BIG_ENDIAN, "armeb" }, |
325 | { BIG_ENDIAN, "coldfire" }, | | 325 | { BIG_ENDIAN, "coldfire" }, |
326 | { BIG_ENDIAN, "earmeb" }, | | 326 | { BIG_ENDIAN, "earmeb" }, |
327 | { BIG_ENDIAN, "earmhfeb" }, | | 327 | { BIG_ENDIAN, "earmhfeb" }, |
328 | { BIG_ENDIAN, "earmv4eb" }, | | 328 | { BIG_ENDIAN, "earmv4eb" }, |
329 | { BIG_ENDIAN, "earmv5eb" }, | | 329 | { BIG_ENDIAN, "earmv5eb" }, |
330 | { BIG_ENDIAN, "earmv6eb" }, | | 330 | { BIG_ENDIAN, "earmv6eb" }, |
331 | { BIG_ENDIAN, "earmv6hfeb" }, | | 331 | { BIG_ENDIAN, "earmv6hfeb" }, |
332 | { BIG_ENDIAN, "earmv7eb" }, | | 332 | { BIG_ENDIAN, "earmv7eb" }, |
333 | { BIG_ENDIAN, "earmv7hfeb" }, | | 333 | { BIG_ENDIAN, "earmv7hfeb" }, |
334 | { BIG_ENDIAN, "hppa" }, | | 334 | { BIG_ENDIAN, "hppa" }, |
335 | { BIG_ENDIAN, "m68000" }, | | 335 | { BIG_ENDIAN, "m68000" }, |
336 | { BIG_ENDIAN, "m68k" }, | | 336 | { BIG_ENDIAN, "m68k" }, |
337 | { BIG_ENDIAN, "mipseb" }, | | 337 | { BIG_ENDIAN, "mipseb" }, |
338 | { BIG_ENDIAN, "mips64eb" }, | | 338 | { BIG_ENDIAN, "mips64eb" }, |
339 | { BIG_ENDIAN, "or1k" }, | | 339 | { BIG_ENDIAN, "or1k" }, |
340 | { BIG_ENDIAN, "powerpc" }, | | 340 | { BIG_ENDIAN, "powerpc" }, |
341 | { BIG_ENDIAN, "sh3eb" }, | | 341 | { BIG_ENDIAN, "sh3eb" }, |
342 | { BIG_ENDIAN, "sparc" }, | | 342 | { BIG_ENDIAN, "sparc" }, |
343 | { BIG_ENDIAN, "sparc64" }, | | 343 | { BIG_ENDIAN, "sparc64" }, |
344 | | | 344 | |
345 | { 0, NULL }, | | 345 | { 0, NULL }, |
346 | }; | | 346 | }; |
347 | | | 347 | |
348 | /* Default location for label - only used if we don't find one to update */ | | 348 | /* Default location for label - only used if we don't find one to update */ |
349 | #define LABEL_OFFSET (dklabel_getlabelsector() * DEV_BSIZE + dklabel_getlabeloffset()) | | 349 | #define LABEL_OFFSET (dklabel_getlabelsector() * DEV_BSIZE + dklabel_getlabeloffset()) |
350 | #else | | 350 | #else |
351 | #define labeloffset LABELOFFSET | | 351 | #define labeloffset LABELOFFSET |
352 | #define labelsector LABELSECTOR | | 352 | #define labelsector LABELSECTOR |
353 | #define labelusesmbr LABELUSESMBR | | 353 | #define labelusesmbr LABELUSESMBR |
354 | #define maxpartitions MAXPARTITIONS | | 354 | #define maxpartitions MAXPARTITIONS |
355 | #define LABEL_OFFSET LABELOFFSET | | 355 | #define LABEL_OFFSET LABELOFFSET |
356 | #endif /* !NATIVELABEL_ONLY */ | | 356 | #endif /* !NATIVELABEL_ONLY */ |
357 | | | 357 | |
358 | /* | | 358 | /* |
359 | * For portability it doesn't make sense to use any other value.... | | 359 | * For portability it doesn't make sense to use any other value.... |
360 | * Except, maybe, the size of a physical sector. | | 360 | * Except, maybe, the size of a physical sector. |
361 | * This value is used if we have to write a label to the start of an mbr ptn. | | 361 | * This value is used if we have to write a label to the start of an mbr ptn. |
362 | */ | | 362 | */ |
363 | #ifndef LABELOFFSET_MBR | | 363 | #ifndef LABELOFFSET_MBR |
364 | #define LABELOFFSET_MBR 512 | | 364 | #define LABELOFFSET_MBR 512 |
365 | #endif | | 365 | #endif |
366 | | | 366 | |
367 | #if HAVE_NBTOOL_CONFIG_H | | 367 | #if HAVE_NBTOOL_CONFIG_H |
368 | static int | | 368 | static int |
369 | opendisk(const char *path, int flags, char *buf, int buflen, int cooked) | | 369 | opendisk(const char *path, int flags, char *buf, int buflen, int cooked) |
370 | { | | 370 | { |
371 | int f; | | 371 | int f; |
372 | f = open(path, flags, 0); | | 372 | f = open(path, flags, 0); |
373 | strlcpy(buf, path, buflen); | | 373 | strlcpy(buf, path, buflen); |
374 | return f; | | 374 | return f; |
375 | } | | 375 | } |
376 | #endif /* HAVE_NBTOOL_CONFIG_H */ | | 376 | #endif /* HAVE_NBTOOL_CONFIG_H */ |
377 | | | 377 | |
378 | #if !defined(NATIVELABEL_ONLY) | | 378 | #if !defined(NATIVELABEL_ONLY) |
379 | static void | | 379 | static void |
380 | setbyteorder(int new_byteorder) | | 380 | setbyteorder(int new_byteorder) |
381 | { | | 381 | { |
382 | static int set_p; | | 382 | static int set_p; |
383 | | | 383 | |
384 | if ((!biendian_p || set_p) | | 384 | if ((!biendian_p || set_p) |
385 | && byteorder != 0 | | 385 | && byteorder != 0 |
386 | && byteorder != new_byteorder) { | | 386 | && byteorder != new_byteorder) { |
387 | warnx("changing %s byteorder to %s", | | 387 | warnx("changing %s byteorder to %s", |
388 | byteorder == LITTLE_ENDIAN ? "le" : "be", | | 388 | byteorder == LITTLE_ENDIAN ? "le" : "be", |
389 | new_byteorder == LITTLE_ENDIAN ? "le" : "be"); | | 389 | new_byteorder == LITTLE_ENDIAN ? "le" : "be"); |
390 | } | | 390 | } |
391 | byteorder = new_byteorder; | | 391 | byteorder = new_byteorder; |
392 | biendian_p = 0; | | 392 | biendian_p = 0; |
393 | set_p = 1; | | 393 | set_p = 1; |
394 | } | | 394 | } |
395 | | | 395 | |
396 | static void | | 396 | static void |
397 | getmachineparams(const char *mach) | | 397 | getmachineparams(const char *mach) |
398 | { | | 398 | { |
399 | const struct disklabel_params *dp = disklabel_params; | | 399 | const struct disklabel_params *dp = disklabel_params; |
400 | for (; dp->machine != NULL; dp++) { | | 400 | for (; dp->machine != NULL; dp++) { |
401 | if (!strcmp(mach, dp->machine)) { | | 401 | if (!strcmp(mach, dp->machine)) { |
402 | labelusesmbr = dp->labelusesmbr; | | 402 | labelusesmbr = dp->labelusesmbr; |
403 | labelsector = dp->labelsector; | | 403 | labelsector = dp->labelsector; |
404 | labeloffset = dp->labeloffset; | | 404 | labeloffset = dp->labeloffset; |
405 | maxpartitions = dp->maxpartitions; | | 405 | maxpartitions = dp->maxpartitions; |
406 | biendian_p = (dp->byteorder == 0); | | 406 | biendian_p = (dp->byteorder == 0); |
407 | if (!biendian_p) | | 407 | if (!biendian_p) |
408 | setbyteorder(dp->byteorder); | | 408 | setbyteorder(dp->byteorder); |
409 | return; | | 409 | return; |
410 | } | | 410 | } |
411 | } | | 411 | } |
412 | errx(1, "%s: unknown machine type", mach); | | 412 | errx(1, "%s: unknown machine type", mach); |
413 | } | | 413 | } |
414 | | | 414 | |
415 | static void | | 415 | static void |
416 | getarchbyteorder(const char *arch) | | 416 | getarchbyteorder(const char *arch) |
417 | { | | 417 | { |
418 | const struct arch_endian *p = arch_endians; | | 418 | const struct arch_endian *p = arch_endians; |
419 | for (; p->arch != NULL; p++) { | | 419 | for (; p->arch != NULL; p++) { |
420 | if (!strcmp(arch, p->arch)) { | | 420 | if (!strcmp(arch, p->arch)) { |
421 | setbyteorder(p->byteorder); | | 421 | setbyteorder(p->byteorder); |
422 | return; | | 422 | return; |
423 | } | | 423 | } |
424 | } | | 424 | } |
425 | errx(1, "%s: unknown arch", arch); | | 425 | errx(1, "%s: unknown arch", arch); |
426 | } | | 426 | } |
427 | | | 427 | |
428 | static daddr_t | | 428 | static daddr_t |
429 | dklabel_getlabelsector(void) | | 429 | dklabel_getlabelsector(void) |
430 | { | | 430 | { |
431 | unsigned long int nval; | | 431 | unsigned long int nval; |
432 | char *end; | | 432 | char *end; |
433 | const char *val; | | 433 | const char *val; |
434 | | | 434 | |
435 | if ((val = getenv("DISKLABELSECTOR")) == NULL) | | 435 | if ((val = getenv("DISKLABELSECTOR")) == NULL) |
436 | return labelsector; | | 436 | return labelsector; |
437 | if ((nval = strtoul(val, &end, 10)) == ULONG_MAX && errno == ERANGE) | | 437 | if ((nval = strtoul(val, &end, 10)) == ULONG_MAX && errno == ERANGE) |
438 | err(EXIT_FAILURE, "DISKLABELSECTOR in environment"); | | 438 | err(EXIT_FAILURE, "DISKLABELSECTOR in environment"); |
439 | return nval; | | 439 | return nval; |
440 | } | | 440 | } |
441 | | | 441 | |
442 | static off_t | | 442 | static off_t |
443 | dklabel_getlabeloffset(void) | | 443 | dklabel_getlabeloffset(void) |
444 | { | | 444 | { |
445 | unsigned long int nval; | | 445 | unsigned long int nval; |
446 | char *end; | | 446 | char *end; |
447 | const char *val; | | 447 | const char *val; |
448 | | | 448 | |
449 | if ((val = getenv("DISKLABELOFFSET")) == NULL) | | 449 | if ((val = getenv("DISKLABELOFFSET")) == NULL) |
450 | return labeloffset; | | 450 | return labeloffset; |
451 | if ((nval = strtoul(val, &end, 10)) == ULONG_MAX && errno == ERANGE) | | 451 | if ((nval = strtoul(val, &end, 10)) == ULONG_MAX && errno == ERANGE) |
452 | err(EXIT_FAILURE, "DISKLABELOFFSET in environment"); | | 452 | err(EXIT_FAILURE, "DISKLABELOFFSET in environment"); |
453 | return nval; | | 453 | return nval; |
454 | } | | 454 | } |
455 | #endif /* !NATIVELABEL_ONLY */ | | 455 | #endif /* !NATIVELABEL_ONLY */ |
456 | | | 456 | |
457 | static void | | 457 | static void |
458 | clear_writable(void) | | 458 | clear_writable(void) |
459 | { | | 459 | { |
460 | static int zero = 0; | | 460 | static int zero = 0; |
461 | dk_ioctl(set_writable_fd, DIOCWLABEL, &zero); | | 461 | dk_ioctl(set_writable_fd, DIOCWLABEL, &zero); |
462 | } | | 462 | } |
463 | | | 463 | |
464 | int | | 464 | int |
465 | main(int argc, char *argv[]) | | 465 | main(int argc, char *argv[]) |
466 | { | | 466 | { |
467 | FILE *t; | | 467 | FILE *t; |
468 | int ch, f, error; | | 468 | int ch, f, error; |
469 | char *dkname; | | 469 | char *dkname; |
470 | #if !defined(NATIVELABEL_ONLY) | | 470 | #if !defined(NATIVELABEL_ONLY) |
471 | char *cp; | | 471 | char *cp; |
472 | #endif | | 472 | #endif |
473 | struct stat sb; | | 473 | struct stat sb; |
474 | int writable; | | 474 | int writable; |
475 | enum { | | 475 | enum { |
476 | UNSPEC, EDIT, READ, RESTORE, SETWRITABLE, SETREADONLY, | | 476 | UNSPEC, EDIT, READ, RESTORE, SETWRITABLE, SETREADONLY, |
477 | WRITE, | | 477 | WRITE, |
478 | #if !defined(NO_INTERACT) | | 478 | #if !defined(NO_INTERACT) |
479 | INTERACT, | | 479 | INTERACT, |
480 | #endif | | 480 | #endif |
481 | DELETE | | 481 | DELETE |
482 | } op = UNSPEC, old_op; | | 482 | } op = UNSPEC, old_op; |
483 | #if !defined(NATIVELABEL_ONLY) | | 483 | #if !defined(NATIVELABEL_ONLY) |
484 | unsigned long val; | | 484 | unsigned long val; |
485 | #endif | | 485 | #endif |
486 | | | 486 | |
487 | #ifndef HAVE_NBTOOL_CONFIG_H | | 487 | #ifndef HAVE_NBTOOL_CONFIG_H |
488 | #if !defined(NATIVELABEL_ONLY) | | 488 | #if !defined(NATIVELABEL_ONLY) |
489 | labeloffset = native_params.labeloffset = getlabeloffset(); | | 489 | labeloffset = native_params.labeloffset = getlabeloffset(); |
490 | labelsector = native_params.labelsector = getlabelsector(); | | 490 | labelsector = native_params.labelsector = getlabelsector(); |
491 | labelusesmbr = native_params.labelusesmbr = getlabelusesmbr(); | | 491 | labelusesmbr = native_params.labelusesmbr = getlabelusesmbr(); |
492 | maxpartitions = native_params.maxpartitions = getmaxpartitions(); | | 492 | maxpartitions = native_params.maxpartitions = getmaxpartitions(); |
493 | byteorder = native_params.byteorder = BYTE_ORDER; | | 493 | byteorder = native_params.byteorder = BYTE_ORDER; |
494 | #endif | | 494 | #endif |
495 | #endif | | 495 | #endif |
496 | | | 496 | |
497 | #if !defined(NATIVELABEL_ONLY) | | 497 | #if !defined(NATIVELABEL_ONLY) |
498 | if ((cp = getenv("MACHINE")) != NULL) { | | 498 | if ((cp = getenv("MACHINE")) != NULL) { |
499 | getmachineparams(cp); | | 499 | getmachineparams(cp); |
500 | } | | 500 | } |
501 | | | 501 | |
502 | if ((cp = getenv("MACHINE_ARCH")) != NULL) { | | 502 | if ((cp = getenv("MACHINE_ARCH")) != NULL) { |
503 | getarchbyteorder(cp); | | 503 | getarchbyteorder(cp); |
504 | } | | 504 | } |
505 | #endif | | 505 | #endif |
506 | | | 506 | |
507 | #if HAVE_NBTOOL_CONFIG_H | | 507 | #if HAVE_NBTOOL_CONFIG_H |
508 | /* We must avoid doing any ioctl requests */ | | 508 | /* We must avoid doing any ioctl requests */ |
509 | Fflag = rflag = 1; | | 509 | Fflag = rflag = 1; |
510 | #endif | | 510 | #endif |
511 | | | 511 | |
512 | error = 0; | | 512 | error = 0; |
513 | #if !defined(NATIVELABEL_ONLY) | | 513 | #if !defined(NATIVELABEL_ONLY) |
514 | while ((ch = getopt(argc, argv, "AB:CDFIL:M:NO:P:RWef:ilmnrtvw")) != -1) { | | 514 | while ((ch = getopt(argc, argv, "AB:CDFIL:M:NO:P:RWef:ilmnrtvw")) != -1) { |
515 | #else | | 515 | #else |
516 | while ((ch = getopt(argc, argv, "ACDFINRWef:ilrtvw")) != -1) { | | 516 | while ((ch = getopt(argc, argv, "ACDFINRWef:ilrtvw")) != -1) { |
517 | #endif | | 517 | #endif |
518 | old_op = op; | | 518 | old_op = op; |
519 | switch (ch) { | | 519 | switch (ch) { |
520 | case 'A': /* Action all labels */ | | 520 | case 'A': /* Action all labels */ |
521 | Aflag = 1; | | 521 | Aflag = 1; |
522 | rflag = 1; | | 522 | rflag = 1; |
523 | break; | | 523 | break; |
524 | case 'C': /* Display in CHS format */ | | 524 | case 'C': /* Display in CHS format */ |
525 | Cflag = 1; | | 525 | Cflag = 1; |
526 | break; | | 526 | break; |
527 | case 'D': /* Delete all existing labels */ | | 527 | case 'D': /* Delete all existing labels */ |
528 | Dflag = 1; | | 528 | Dflag = 1; |
529 | rflag = 1; | | 529 | rflag = 1; |
530 | break; | | 530 | break; |
531 | case 'F': /* Treat 'disk' as a regular file */ | | 531 | case 'F': /* Treat 'disk' as a regular file */ |
532 | Fflag = 1; | | 532 | Fflag = 1; |
533 | rflag = 1; /* Force direct access */ | | 533 | rflag = 1; /* Force direct access */ |
534 | break; | | 534 | break; |
535 | case 'I': /* Use default label if none found */ | | 535 | case 'I': /* Use default label if none found */ |
536 | Iflag = 1; | | 536 | Iflag = 1; |
537 | rflag = 1; /* Implies direct access */ | | 537 | rflag = 1; /* Implies direct access */ |
538 | break; | | 538 | break; |
539 | case 'R': /* Restore label from text file */ | | 539 | case 'R': /* Restore label from text file */ |
540 | op = RESTORE; | | 540 | op = RESTORE; |
541 | break; | | 541 | break; |
542 | #if !defined(NATIVELABEL_ONLY) | | 542 | #if !defined(NATIVELABEL_ONLY) |
543 | case 'B': /* byteorder */ | | 543 | case 'B': /* byteorder */ |
544 | if (!strcmp(optarg, "be")) { | | 544 | if (!strcmp(optarg, "be")) { |
545 | setbyteorder(BIG_ENDIAN); | | 545 | setbyteorder(BIG_ENDIAN); |
546 | } else if (!strcmp(optarg, "le")) { | | 546 | } else if (!strcmp(optarg, "le")) { |
547 | setbyteorder(LITTLE_ENDIAN); | | 547 | setbyteorder(LITTLE_ENDIAN); |
548 | } else { | | 548 | } else { |
549 | errx(1, "%s: not be or le", optarg); | | 549 | errx(1, "%s: not be or le", optarg); |
550 | } | | 550 | } |
551 | break; | | 551 | break; |
552 | case 'M': /* machine type */ | | 552 | case 'M': /* machine type */ |
553 | getmachineparams(optarg); | | 553 | getmachineparams(optarg); |
554 | break; | | 554 | break; |
555 | #endif | | 555 | #endif |
556 | case 'N': /* Disallow writes to label sector */ | | 556 | case 'N': /* Disallow writes to label sector */ |
557 | op = SETREADONLY; | | 557 | op = SETREADONLY; |
558 | break; | | 558 | break; |
559 | #if !defined(NATIVELABEL_ONLY) | | 559 | #if !defined(NATIVELABEL_ONLY) |
560 | case 'L': /* Label sector */ | | 560 | case 'L': /* Label sector */ |
561 | val = strtoul(optarg, NULL, 10); | | 561 | val = strtoul(optarg, NULL, 10); |
562 | if ((val == ULONG_MAX && errno == ERANGE) || val > UINT_MAX) | | 562 | if ((val == ULONG_MAX && errno == ERANGE) || val > UINT_MAX) |
563 | err(EXIT_FAILURE, "invalid label sector: %s", optarg); | | 563 | err(EXIT_FAILURE, "invalid label sector: %s", optarg); |
564 | labelsector = val; | | 564 | labelsector = val; |
565 | break; | | 565 | break; |
566 | case 'O': /* Label offset */ | | 566 | case 'O': /* Label offset */ |
567 | val = strtoul(optarg, NULL, 10); | | 567 | val = strtoul(optarg, NULL, 10); |
568 | if ((val == ULONG_MAX && errno == ERANGE) || val > UINT_MAX) | | 568 | if ((val == ULONG_MAX && errno == ERANGE) || val > UINT_MAX) |
569 | err(EXIT_FAILURE, "invalid label offset: %s", optarg); | | 569 | err(EXIT_FAILURE, "invalid label offset: %s", optarg); |
570 | labeloffset = val; | | 570 | labeloffset = val; |
571 | break; | | 571 | break; |
572 | case 'P': /* Max partitions */ | | 572 | case 'P': /* Max partitions */ |
573 | val = strtoul(optarg, NULL, 10); | | 573 | val = strtoul(optarg, NULL, 10); |
574 | if ((val == ULONG_MAX && errno == ERANGE) || val < 1 || val > UINT_MAX) | | 574 | if ((val == ULONG_MAX && errno == ERANGE) || val < 1 || val > UINT_MAX) |
575 | err(EXIT_FAILURE, "invalid max partitions: %s", optarg); | | 575 | err(EXIT_FAILURE, "invalid max partitions: %s", optarg); |
576 | maxpartitions = val; | | 576 | maxpartitions = val; |
577 | break; | | 577 | break; |
578 | #endif | | 578 | #endif |
579 | case 'W': /* Allow writes to label sector */ | | 579 | case 'W': /* Allow writes to label sector */ |
580 | op = SETWRITABLE; | | 580 | op = SETWRITABLE; |
581 | break; | | 581 | break; |
582 | case 'e': /* Edit label with $EDITOR */ | | 582 | case 'e': /* Edit label with $EDITOR */ |
583 | op = EDIT; | | 583 | op = EDIT; |
584 | break; | | 584 | break; |
585 | case 'f': /* Name of disktab file */ | | 585 | case 'f': /* Name of disktab file */ |
586 | if (setdisktab(optarg) == -1) | | 586 | if (setdisktab(optarg) == -1) |
587 | usage(); | | 587 | usage(); |
588 | break; | | 588 | break; |
589 | #if !defined(NO_INTERACT) | | 589 | #if !defined(NO_INTERACT) |
590 | case 'i': /* Edit using built-in editor */ | | 590 | case 'i': /* Edit using built-in editor */ |
591 | op = INTERACT; | | 591 | op = INTERACT; |
592 | break; | | 592 | break; |
593 | #endif /* !NO_INTERACT */ | | 593 | #endif /* !NO_INTERACT */ |
594 | case 'l': /* List all known file system types and exit */ | | 594 | case 'l': /* List all known file system types and exit */ |
595 | lflag = 1; | | 595 | lflag = 1; |
596 | break; | | 596 | break; |
597 | #if !defined(NATIVELABEL_ONLY) | | 597 | #if !defined(NATIVELABEL_ONLY) |
598 | case 'm': /* Expect disk to have an MBR */ | | 598 | case 'm': /* Expect disk to have an MBR */ |
599 | labelusesmbr = 1; | | 599 | labelusesmbr = 1; |
600 | break; | | 600 | break; |
601 | case 'n': /* Expect disk to not have an MBR */ | | 601 | case 'n': /* Expect disk to not have an MBR */ |
602 | labelusesmbr = 0; | | 602 | labelusesmbr = 0; |
603 | break; | | 603 | break; |
604 | #endif | | 604 | #endif |
605 | case 'r': /* Read/write label directly from disk */ | | 605 | case 'r': /* Read/write label directly from disk */ |
606 | rflag = 1; | | 606 | rflag = 1; |
607 | break; | | 607 | break; |
608 | case 't': /* Format output as a disktab entry */ | | 608 | case 't': /* Format output as a disktab entry */ |
609 | tflag = 1; | | 609 | tflag = 1; |
610 | break; | | 610 | break; |
611 | case 'v': /* verbose/diag output */ | | 611 | case 'v': /* verbose/diag output */ |
612 | verbose++; | | 612 | verbose++; |
613 | break; | | 613 | break; |
614 | case 'w': /* Write label based on disktab entry */ | | 614 | case 'w': /* Write label based on disktab entry */ |
615 | op = WRITE; | | 615 | op = WRITE; |
616 | break; | | 616 | break; |
617 | case '?': | | 617 | case '?': |
618 | default: | | 618 | default: |
619 | usage(); | | 619 | usage(); |
620 | } | | 620 | } |
621 | if (old_op != UNSPEC && old_op != op) | | 621 | if (old_op != UNSPEC && old_op != op) |
622 | usage(); | | 622 | usage(); |
623 | } | | 623 | } |
624 | | | 624 | |
625 | if (maxpartitions > MAXPARTITIONS) { | | 625 | if (maxpartitions > MAXPARTITIONS) { |
626 | errx(1, "too large maxpartitions > %u\n", MAXPARTITIONS); | | 626 | errx(1, "too large maxpartitions > %u\n", MAXPARTITIONS); |
627 | } | | 627 | } |
628 | | | 628 | |
629 | #if !defined(NATIVELABEL_ONLY) | | 629 | #if !defined(NATIVELABEL_ONLY) |
630 | if (maxpartitions == 0) { | | 630 | if (maxpartitions == 0) { |
631 | errx(1, "unknown label: use -M/-B and $MACHINE/$MACHINE_ARCH"); | | 631 | errx(1, "unknown label: use -M/-B and $MACHINE/$MACHINE_ARCH"); |
632 | } | | 632 | } |
633 | if (byteorder != BIG_ENDIAN && byteorder != LITTLE_ENDIAN) { | | 633 | if (byteorder != BIG_ENDIAN && byteorder != LITTLE_ENDIAN) { |
634 | errx(1, "unknown byteorder"); | | 634 | errx(1, "unknown byteorder"); |
635 | } | | 635 | } |
636 | bswap_p = (byteorder != BYTE_ORDER); | | 636 | bswap_p = (byteorder != BYTE_ORDER); |
637 | #ifdef DEBUG | | 637 | #ifdef DEBUG |
638 | printf("labelusesmbr=%d labelsector=%u labeloffset=%u maxpartitions=%u\n", | | 638 | printf("labelusesmbr=%d labelsector=%u labeloffset=%u maxpartitions=%u\n", |
639 | labelusesmbr, labelsector, labeloffset, maxpartitions); | | 639 | labelusesmbr, labelsector, labeloffset, maxpartitions); |
640 | printf("byteorder=%d bswap_p=%d\n", byteorder, bswap_p); | | 640 | printf("byteorder=%d bswap_p=%d\n", byteorder, bswap_p); |
641 | #endif | | 641 | #endif |
642 | #ifndef HAVE_NBTOOL_CONFIG_H | | 642 | #ifndef HAVE_NBTOOL_CONFIG_H |
643 | /* | | 643 | /* |
644 | * If the disklabel has the same location as the native disklabel and | | 644 | * If the disklabel has the same location as the native disklabel and |
645 | * fewer or equal partitions, we can use the native ioctls. Otherwise | | 645 | * fewer or equal partitions, we can use the native ioctls. Otherwise |
646 | * force file/raw access. | | 646 | * force file/raw access. |
647 | */ | | 647 | */ |
648 | native_p = native_params.labelusesmbr == labelusesmbr | | 648 | native_p = native_params.labelusesmbr == labelusesmbr |
649 | && native_params.labelsector == labelsector | | 649 | && native_params.labelsector == labelsector |
650 | && native_params.labeloffset == labeloffset | | 650 | && native_params.labeloffset == labeloffset |
651 | && maxpartitions <= native_params.maxpartitions | | 651 | && maxpartitions <= native_params.maxpartitions |
652 | && !bswap_p; | | 652 | && !bswap_p; |
653 | if (!native_p) | | 653 | if (!native_p) |
654 | Fflag = rflag = 1; | | 654 | Fflag = rflag = 1; |
655 | #endif | | 655 | #endif |
656 | #endif /* !NATIVELABEL_ONLY */ | | 656 | #endif /* !NATIVELABEL_ONLY */ |
657 | | | 657 | |
658 | argc -= optind; | | 658 | argc -= optind; |
659 | argv += optind; | | 659 | argv += optind; |
660 | | | 660 | |
661 | if (lflag) | | 661 | if (lflag) |
662 | exit(list_fs_types() ? EXIT_SUCCESS : EXIT_FAILURE); | | 662 | exit(list_fs_types() ? EXIT_SUCCESS : EXIT_FAILURE); |
663 | | | 663 | |
664 | if (op == UNSPEC) | | 664 | if (op == UNSPEC) |
665 | op = Dflag ? DELETE : READ; | | 665 | op = Dflag ? DELETE : READ; |
666 | | | 666 | |
667 | if (argc < 1) | | 667 | if (argc < 1) |
668 | usage(); | | 668 | usage(); |
669 | | | 669 | |
670 | if (Iflag && op != EDIT | | 670 | if (Iflag && op != EDIT |
671 | #if !defined(NO_INTERACT) | | 671 | #if !defined(NO_INTERACT) |
672 | && op != INTERACT | | 672 | && op != INTERACT |
673 | #endif | | 673 | #endif |
674 | ) | | 674 | ) |
675 | usage(); | | 675 | usage(); |
676 | | | 676 | |
677 | dkname = argv[0]; | | 677 | dkname = argv[0]; |
678 | f = opendisk(dkname, op == READ ? O_RDONLY : O_RDWR, | | 678 | f = opendisk(dkname, op == READ ? O_RDONLY : O_RDWR, |
679 | specname, sizeof specname, 0); | | 679 | specname, sizeof specname, 0); |
680 | if (f < 0) | | 680 | if (f < 0) |
681 | err(4, "%s", specname); | | 681 | err(4, "%s", specname); |
682 | | | 682 | |
683 | if (!Fflag && fstat(f, &sb) == 0 && S_ISREG(sb.st_mode)) | | 683 | if (!Fflag && fstat(f, &sb) == 0 && S_ISREG(sb.st_mode)) |
684 | Fflag = rflag = 1; | | 684 | Fflag = rflag = 1; |
685 | | | 685 | |
686 | switch (op) { | | 686 | switch (op) { |
687 | | | 687 | |
688 | case DELETE: /* Remove all existing labels */ | | 688 | case DELETE: /* Remove all existing labels */ |
689 | if (argc != 1) | | 689 | if (argc != 1) |
690 | usage(); | | 690 | usage(); |
691 | Dflag = 2; | | 691 | Dflag = 2; |
692 | writelabel_direct(f); | | 692 | writelabel_direct(f); |
693 | break; | | 693 | break; |
694 | | | 694 | |
695 | case EDIT: | | 695 | case EDIT: |
696 | if (argc != 1) | | 696 | if (argc != 1) |
697 | usage(); | | 697 | usage(); |
698 | readlabel(f); | | 698 | readlabel(f); |
699 | error = edit(f); | | 699 | error = edit(f); |
700 | break; | | 700 | break; |
701 | | | 701 | |
702 | #if !defined(NO_INTERACT) | | 702 | #if !defined(NO_INTERACT) |
703 | case INTERACT: | | 703 | case INTERACT: |
704 | if (argc != 1) | | 704 | if (argc != 1) |
705 | usage(); | | 705 | usage(); |
706 | readlabel(f); | | 706 | readlabel(f); |
707 | /* | | 707 | /* |
708 | * XXX: Fill some default values so checklabel does not fail | | 708 | * XXX: Fill some default values so checklabel does not fail |
709 | */ | | 709 | */ |
710 | if (lab.d_bbsize == 0) | | 710 | if (lab.d_bbsize == 0) |
711 | lab.d_bbsize = BBSIZE; | | 711 | lab.d_bbsize = BBSIZE; |
712 | if (lab.d_sbsize == 0) | | 712 | if (lab.d_sbsize == 0) |
713 | lab.d_sbsize = SBLOCKSIZE; | | 713 | lab.d_sbsize = SBLOCKSIZE; |
714 | interact(&lab, f); | | 714 | interact(&lab, f); |
715 | break; | | 715 | break; |
716 | #endif /* !NO_INTERACT */ | | 716 | #endif /* !NO_INTERACT */ |
717 | | | 717 | |
718 | case READ: | | 718 | case READ: |
719 | if (argc != 1) | | 719 | if (argc != 1) |
720 | usage(); | | 720 | usage(); |
721 | read_all = Aflag; | | 721 | read_all = Aflag; |
722 | readlabel(f); | | 722 | readlabel(f); |
723 | if (read_all) | | 723 | if (read_all) |
724 | /* Label got printed in the bowels of readlabel */ | | 724 | /* Label got printed in the bowels of readlabel */ |
725 | break; | | 725 | break; |
726 | if (tflag) | | 726 | if (tflag) |
727 | makedisktab(stdout, &lab); | | 727 | makedisktab(stdout, &lab); |
728 | else { | | 728 | else { |
729 | showinfo(stdout, &lab, specname); | | 729 | showinfo(stdout, &lab, specname); |
730 | showpartitions(stdout, &lab, Cflag); | | 730 | showpartitions(stdout, &lab, Cflag); |
731 | } | | 731 | } |
732 | error = checklabel(&lab); | | 732 | error = checklabel(&lab); |
733 | if (error) | | 733 | if (error) |
734 | error += 100; | | 734 | error += 100; |
735 | break; | | 735 | break; |
736 | | | 736 | |
737 | case RESTORE: | | 737 | case RESTORE: |
738 | if (argc != 2) | | 738 | if (argc != 2) |
739 | usage(); | | 739 | usage(); |
740 | if (!(t = fopen(argv[1], "r"))) | | 740 | if (!(t = fopen(argv[1], "r"))) |
741 | err(4, "%s", argv[1]); | | 741 | err(4, "%s", argv[1]); |
742 | if (getasciilabel(t, &lab)) | | 742 | if (getasciilabel(t, &lab)) |
743 | error = write_label(f); | | 743 | error = write_label(f); |
744 | else | | 744 | else |
745 | error = 1; | | 745 | error = 1; |
746 | break; | | 746 | break; |
747 | | | 747 | |
748 | case SETREADONLY: | | 748 | case SETREADONLY: |
749 | writable = 0; | | 749 | writable = 0; |
750 | goto do_diocwlabel; | | 750 | goto do_diocwlabel; |
751 | case SETWRITABLE: | | 751 | case SETWRITABLE: |
752 | writable = 1; | | 752 | writable = 1; |
753 | do_diocwlabel: | | 753 | do_diocwlabel: |
754 | if (argc != 1) | | 754 | if (argc != 1) |
755 | usage(); | | 755 | usage(); |
756 | if (dk_ioctl(f, DIOCWLABEL, &writable) < 0) | | 756 | if (dk_ioctl(f, DIOCWLABEL, &writable) < 0) |
757 | err(4, "ioctl DIOCWLABEL"); | | 757 | err(4, "ioctl DIOCWLABEL"); |
758 | break; | | 758 | break; |
759 | | | 759 | |
760 | case WRITE: /* Create label from /etc/disktab entry & write */ | | 760 | case WRITE: /* Create label from /etc/disktab entry & write */ |
761 | if (argc < 2 || argc > 3) | | 761 | if (argc < 2 || argc > 3) |
762 | usage(); | | 762 | usage(); |
763 | makelabel(argv[1], argv[2]); | | 763 | makelabel(argv[1], argv[2]); |
764 | if (checklabel(&lab) == 0) | | 764 | if (checklabel(&lab) == 0) |
765 | error = write_label(f); | | 765 | error = write_label(f); |
766 | else | | 766 | else |
767 | error = 1; | | 767 | error = 1; |
768 | break; | | 768 | break; |
769 | | | 769 | |
770 | case UNSPEC: | | 770 | case UNSPEC: |
771 | usage(); | | 771 | usage(); |
772 | | | 772 | |
773 | } | | 773 | } |
774 | exit(error); | | 774 | exit(error); |
775 | } | | 775 | } |
776 | | | 776 | |
777 | /* | | 777 | /* |
778 | * Construct a prototype disklabel from /etc/disktab. | | 778 | * Construct a prototype disklabel from /etc/disktab. |
779 | */ | | 779 | */ |
780 | static void | | 780 | static void |
781 | makelabel(const char *type, const char *name) | | 781 | makelabel(const char *type, const char *name) |
782 | { | | 782 | { |
783 | struct disklabel *dp; | | 783 | struct disklabel *dp; |
784 | | | 784 | |
785 | dp = getdiskbyname(type); | | 785 | dp = getdiskbyname(type); |
786 | if (dp == NULL) | | 786 | if (dp == NULL) |
787 | errx(1, "unknown disk type: %s", type); | | 787 | errx(1, "unknown disk type: %s", type); |
788 | lab = *dp; | | 788 | lab = *dp; |
789 | | | 789 | |
790 | /* d_packname is union d_boot[01], so zero */ | | 790 | /* d_packname is union d_boot[01], so zero */ |
791 | (void)memset(lab.d_packname, 0, sizeof(lab.d_packname)); | | 791 | (void)memset(lab.d_packname, 0, sizeof(lab.d_packname)); |
792 | if (name) | | 792 | if (name) |
793 | (void)strncpy(lab.d_packname, name, sizeof(lab.d_packname)); | | 793 | (void)strncpy(lab.d_packname, name, sizeof(lab.d_packname)); |
794 | } | | 794 | } |
795 | | | 795 | |
796 | static int | | 796 | static int |
797 | write_label(int f) | | 797 | write_label(int f) |
798 | { | | 798 | { |
799 | int writable; | | 799 | int writable; |
800 | | | 800 | |
801 | lab.d_magic = DISKMAGIC; | | 801 | lab.d_magic = DISKMAGIC; |
802 | lab.d_magic2 = DISKMAGIC; | | 802 | lab.d_magic2 = DISKMAGIC; |
803 | lab.d_checksum = 0; | | 803 | lab.d_checksum = 0; |
804 | lab.d_checksum = dkcksum(&lab); | | 804 | lab.d_checksum = dkcksum(&lab); |
805 | | | 805 | |
806 | if (rflag) { | | 806 | if (rflag) { |
807 | /* Write the label directly to the disk */ | | 807 | /* Write the label directly to the disk */ |
808 | | | 808 | |
809 | /* | | 809 | /* |
810 | * First set the kernel disk label, | | 810 | * First set the kernel disk label, |
811 | * then write a label to the raw disk. | | 811 | * then write a label to the raw disk. |
812 | * If the SDINFO ioctl fails because it is unimplemented, | | 812 | * If the SDINFO ioctl fails because it is unimplemented, |
813 | * keep going; otherwise, the kernel consistency checks | | 813 | * keep going; otherwise, the kernel consistency checks |
814 | * may prevent us from changing the current (in-core) | | 814 | * may prevent us from changing the current (in-core) |
815 | * label. | | 815 | * label. |
816 | */ | | 816 | */ |
817 | if (!Fflag && dk_ioctl(f, DIOCSDINFO, &lab) < 0 && | | 817 | if (!Fflag && dk_ioctl(f, DIOCSDINFO, &lab) < 0 && |
818 | errno != ENODEV && errno != ENOTTY) { | | 818 | errno != ENODEV && errno != ENOTTY) { |
819 | l_perror("ioctl DIOCSDINFO"); | | 819 | l_perror("ioctl DIOCSDINFO"); |
820 | return (1); | | 820 | return (1); |
821 | } | | 821 | } |
822 | /* | | 822 | /* |
823 | * write enable label sector before write (if necessary), | | 823 | * write enable label sector before write (if necessary), |
824 | * disable after writing. | | 824 | * disable after writing. |
825 | */ | | 825 | */ |
826 | writable = 1; | | 826 | writable = 1; |
827 | if (!Fflag) { | | 827 | if (!Fflag) { |
828 | if (dk_ioctl(f, DIOCWLABEL, &writable) < 0) | | 828 | if (dk_ioctl(f, DIOCWLABEL, &writable) < 0) |
829 | perror("ioctl DIOCWLABEL"); | | 829 | perror("ioctl DIOCWLABEL"); |
830 | set_writable_fd = f; | | 830 | set_writable_fd = f; |
831 | atexit(clear_writable); | | 831 | atexit(clear_writable); |
832 | } | | 832 | } |
833 | | | 833 | |
834 | writelabel_direct(f); | | 834 | writelabel_direct(f); |
835 | | | 835 | |
836 | /* | | 836 | /* |
837 | * Now issue a DIOCWDINFO. This will let the kernel convert the | | 837 | * Now issue a DIOCWDINFO. This will let the kernel convert the |
838 | * disklabel to some machdep format if needed. | | 838 | * disklabel to some machdep format if needed. |
839 | */ | | 839 | */ |
840 | /* XXX: This is stupid! */ | | 840 | /* XXX: This is stupid! */ |
841 | if (!Fflag && dk_ioctl(f, DIOCWDINFO, &lab) < 0) { | | 841 | if (!Fflag && dk_ioctl(f, DIOCWDINFO, &lab) < 0) { |
842 | l_perror("ioctl DIOCWDINFO"); | | 842 | l_perror("ioctl DIOCWDINFO"); |
843 | return (1); | | 843 | return (1); |
844 | } | | 844 | } |
845 | } else { | | 845 | } else { |
846 | /* Get the kernel to write the label */ | | 846 | /* Get the kernel to write the label */ |
847 | if (dk_ioctl(f, DIOCWDINFO, &lab) < 0) { | | 847 | if (dk_ioctl(f, DIOCWDINFO, &lab) < 0) { |
848 | l_perror("ioctl DIOCWDINFO"); | | 848 | l_perror("ioctl DIOCWDINFO"); |
849 | return (1); | | 849 | return (1); |
850 | } | | 850 | } |
851 | } | | 851 | } |
852 | | | 852 | |
853 | #ifdef VAX_ALTLABELS | | 853 | #ifdef VAX_ALTLABELS |
854 | if (lab.d_type == DKTYPE_SMD && lab.d_flags & D_BADSECT && | | 854 | if (lab.d_type == DKTYPE_SMD && lab.d_flags & D_BADSECT && |
855 | lab.d_secsize == 512) { | | 855 | lab.d_secsize == 512) { |
856 | /* Write the label to the odd sectors of the last track! */ | | 856 | /* Write the label to the odd sectors of the last track! */ |
857 | daddr_t alt; | | 857 | daddr_t alt; |
858 | int i; | | 858 | int i; |
859 | uint8_t sec0[512]; | | 859 | uint8_t sec0[512]; |
860 | | | 860 | |
861 | if (pread(f, sec0, 512, 0) < 512) { | | 861 | if (pread(f, sec0, 512, 0) < 512) { |
862 | warn("read master label to write alternates"); | | 862 | warn("read master label to write alternates"); |
863 | return 0; | | 863 | return 0; |
864 | } | | 864 | } |
865 | | | 865 | |
866 | alt = lab.d_ncylinders * lab.d_secpercyl - lab.d_nsectors; | | 866 | alt = lab.d_ncylinders * lab.d_secpercyl - lab.d_nsectors; |
867 | for (i = 1; i < 11 && (uint32_t)i < lab.d_nsectors; i += 2) { | | 867 | for (i = 1; i < 11 && (uint32_t)i < lab.d_nsectors; i += 2) { |
868 | if (pwrite(f, sec0, 512, (off_t)(alt + i) * 512) < 512) | | 868 | if (pwrite(f, sec0, 512, (off_t)(alt + i) * 512) < 512) |
869 | warn("alternate label %d write", i/2); | | 869 | warn("alternate label %d write", i/2); |
870 | } | | 870 | } |
871 | } | | 871 | } |
872 | #endif /* VAX_ALTLABELS */ | | 872 | #endif /* VAX_ALTLABELS */ |
873 | | | 873 | |
874 | return 0; | | 874 | return 0; |
875 | } | | 875 | } |
876 | | | 876 | |
877 | int | | 877 | int |
878 | writelabel(int f, struct disklabel *lp) | | 878 | writelabel(int f, struct disklabel *lp) |
879 | { | | 879 | { |
880 | if (lp != &lab) | | 880 | if (lp != &lab) |
881 | lab = *lp; | | 881 | lab = *lp; |
882 | return write_label(f); | | 882 | return write_label(f); |
883 | } | | 883 | } |
884 | | | 884 | |
885 | static void | | 885 | static void |
886 | l_perror(const char *s) | | 886 | l_perror(const char *s) |
887 | { | | 887 | { |
888 | | | 888 | |
889 | switch (errno) { | | 889 | switch (errno) { |
890 | | | 890 | |
891 | case ESRCH: | | 891 | case ESRCH: |
892 | warnx("%s: No disk label on disk;\n" | | 892 | warnx("%s: No disk label on disk;\n" |
893 | "use \"disklabel -I\" to install initial label", s); | | 893 | "use \"disklabel -I\" to install initial label", s); |
894 | break; | | 894 | break; |
895 | | | 895 | |
896 | case EINVAL: | | 896 | case EINVAL: |
897 | warnx("%s: Label magic number or checksum is wrong!\n" | | 897 | warnx("%s: Label magic number or checksum is wrong!\n" |
898 | "(disklabel or kernel is out of date?)", s); | | 898 | "(disklabel or kernel is out of date?)", s); |
899 | break; | | 899 | break; |
900 | | | 900 | |
901 | case EBUSY: | | 901 | case EBUSY: |
902 | warnx("%s: Open partition would move or shrink", s); | | 902 | warnx("%s: Open partition would move or shrink", s); |
903 | break; | | 903 | break; |
904 | | | 904 | |
905 | case EXDEV: | | 905 | case EXDEV: |
906 | warnx("%s: Labeled partition or 'a' partition must start" | | 906 | warnx("%s: Labeled partition or 'a' partition must start" |
907 | " at beginning of disk", s); | | 907 | " at beginning of disk", s); |
908 | break; | | 908 | break; |
909 | | | 909 | |
910 | default: | | 910 | default: |
911 | warn("%s", s); | | 911 | warn("%s", s); |
912 | break; | | 912 | break; |
913 | } | | 913 | } |
914 | } | | 914 | } |
915 | | | 915 | |
916 | #ifdef NO_MBR_SUPPORT | | 916 | #ifdef NO_MBR_SUPPORT |
917 | #define process_mbr(f, action) 1 | | 917 | #define process_mbr(f, action) 1 |
918 | #else | | 918 | #else |
919 | /* | | 919 | /* |
920 | * Scan DOS/MBR partition table and extended partition list for NetBSD ptns. | | 920 | * Scan DOS/MBR partition table and extended partition list for NetBSD ptns. |
921 | */ | | 921 | */ |
922 | static int | | 922 | static int |
923 | process_mbr(int f, int (*action)(int, u_int)) | | 923 | process_mbr(int f, int (*action)(int, u_int)) |
924 | { | | 924 | { |
925 | struct mbr_partition *dp; | | 925 | struct mbr_partition *dp; |
926 | struct mbr_sector mbr; | | 926 | struct mbr_sector mbr; |
927 | int rval = 1, res; | | 927 | int rval = 1, res; |
928 | int part; | | 928 | int part; |
929 | u_int ext_base, next_ext, this_ext, start; | | 929 | u_int ext_base, next_ext, this_ext, start; |
930 | | | 930 | |
931 | ext_base = 0; | | 931 | ext_base = 0; |
932 | next_ext = 0; | | 932 | next_ext = 0; |
933 | for (;;) { | | 933 | for (;;) { |
934 | this_ext = next_ext; | | 934 | this_ext = next_ext; |
935 | next_ext = 0; | | 935 | next_ext = 0; |
936 | if (verbose > 1) | | 936 | if (verbose > 1) |
937 | warnx("reading mbr sector %u", this_ext); | | 937 | warnx("reading mbr sector %u", this_ext); |
938 | if (pread(f, &mbr, sizeof mbr, this_ext * (off_t)DEV_BSIZE) | | 938 | if (pread(f, &mbr, sizeof mbr, this_ext * (off_t)DEV_BSIZE) |
939 | != sizeof(mbr)) { | | 939 | != sizeof(mbr)) { |
940 | if (verbose) | | 940 | if (verbose) |
941 | warn("Can't read master boot record %u", | | 941 | warn("Can't read master boot record %u", |
942 | this_ext); | | 942 | this_ext); |
943 | break; | | 943 | break; |
944 | } | | 944 | } |
945 | | | 945 | |
946 | /* Check if table is valid. */ | | 946 | /* Check if table is valid. */ |
947 | if (mbr.mbr_magic != htole16(MBR_MAGIC)) { | | 947 | if (mbr.mbr_magic != htole16(MBR_MAGIC)) { |
948 | if (verbose) | | 948 | if (verbose) |
949 | warnx("Invalid signature in mbr record %u", | | 949 | warnx("Invalid signature in mbr record %u", |
950 | this_ext); | | 950 | this_ext); |
951 | break; | | 951 | break; |
952 | } | | 952 | } |
953 | | | 953 | |
954 | dp = &mbr.mbr_parts[0]; | | 954 | dp = &mbr.mbr_parts[0]; |
955 | | | 955 | |
956 | /* Find NetBSD partition(s). */ | | 956 | /* Find NetBSD partition(s). */ |
957 | for (part = 0; part < MBR_PART_COUNT; dp++, part++) { | | 957 | for (part = 0; part < MBR_PART_COUNT; dp++, part++) { |
958 | start = le32toh(dp->mbrp_start); | | 958 | start = le32toh(dp->mbrp_start); |
959 | switch (dp->mbrp_type) { | | 959 | switch (dp->mbrp_type) { |
960 | #ifdef COMPAT_386BSD_MBRPART | | 960 | #ifdef COMPAT_386BSD_MBRPART |
961 | case MBR_PTYPE_386BSD: | | 961 | case MBR_PTYPE_386BSD: |
962 | if (ext_base != 0) | | 962 | if (ext_base != 0) |
963 | break; | | 963 | break; |
964 | /* FALLTHROUGH */ | | 964 | /* FALLTHROUGH */ |
965 | #endif | | 965 | #endif |
966 | case MBR_PTYPE_NETBSD: | | 966 | case MBR_PTYPE_NETBSD: |
967 | res = action(f, this_ext + start); | | 967 | res = action(f, this_ext + start); |
968 | if (res <= 0) | | 968 | if (res <= 0) |
969 | /* Found or failure */ | | 969 | /* Found or failure */ |
970 | return res; | | 970 | return res; |
971 | if (res > rval) | | 971 | if (res > rval) |
972 | /* Keep largest value */ | | 972 | /* Keep largest value */ |
973 | rval = res; | | 973 | rval = res; |
974 | break; | | 974 | break; |
975 | case MBR_PTYPE_EXT: | | 975 | case MBR_PTYPE_EXT: |
976 | case MBR_PTYPE_EXT_LBA: | | 976 | case MBR_PTYPE_EXT_LBA: |
977 | case MBR_PTYPE_EXT_LNX: | | 977 | case MBR_PTYPE_EXT_LNX: |
978 | next_ext = start; | | 978 | next_ext = start; |
979 | break; | | 979 | break; |
980 | default: | | 980 | default: |
981 | break; | | 981 | break; |
982 | } | | 982 | } |
983 | } | | 983 | } |
984 | if (next_ext == 0) | | 984 | if (next_ext == 0) |
985 | /* No more extended partitions */ | | 985 | /* No more extended partitions */ |
986 | break; | | 986 | break; |
987 | next_ext += ext_base; | | 987 | next_ext += ext_base; |
988 | if (ext_base == 0) | | 988 | if (ext_base == 0) |
989 | ext_base = next_ext; | | 989 | ext_base = next_ext; |
990 | | | 990 | |
991 | if (next_ext <= this_ext) { | | 991 | if (next_ext <= this_ext) { |
992 | if (verbose) | | 992 | if (verbose) |
993 | warnx("Invalid extended chain %x <= %x", | | 993 | warnx("Invalid extended chain %x <= %x", |
994 | next_ext, this_ext); | | 994 | next_ext, this_ext); |
995 | break; | | 995 | break; |
996 | } | | 996 | } |
997 | /* Maybe we should check against the disk size... */ | | 997 | /* Maybe we should check against the disk size... */ |
998 | } | | 998 | } |
999 | | | 999 | |
1000 | return rval; | | 1000 | return rval; |
1001 | } | | 1001 | } |
1002 | | | 1002 | |
1003 | static int | | 1003 | static int |
1004 | readlabel_mbr(int f, u_int sector) | | 1004 | readlabel_mbr(int f, u_int sector) |
1005 | { | | 1005 | { |
1006 | struct disklabel *disk_lp; | | 1006 | struct disklabel *disk_lp; |
1007 | | | 1007 | |
1008 | disk_lp = find_label(f, sector); | | 1008 | disk_lp = find_label(f, sector); |
1009 | if (disk_lp == NULL) | | 1009 | if (disk_lp == NULL) |
1010 | return 1; | | 1010 | return 1; |
1011 | targettohlabel(&lab, disk_lp); | | 1011 | targettohlabel(&lab, disk_lp); |
1012 | return 0; | | 1012 | return 0; |
1013 | } | | 1013 | } |
1014 | | | 1014 | |
1015 | static int | | 1015 | static int |
1016 | writelabel_mbr(int f, u_int sector) | | 1016 | writelabel_mbr(int f, u_int sector) |
1017 | { | | 1017 | { |
1018 | return update_label(f, sector, labelusesmbr ? LABELOFFSET_MBR : ~0U) ? 2 : 0; | | 1018 | return update_label(f, sector, labelusesmbr ? LABELOFFSET_MBR : ~0U) ? 2 : 0; |
1019 | } | | 1019 | } |
1020 | | | 1020 | |
1021 | #endif /* !NO_MBR_SUPPORT */ | | 1021 | #endif /* !NO_MBR_SUPPORT */ |
1022 | | | 1022 | |
1023 | #ifndef USE_ACORN | | 1023 | #ifndef USE_ACORN |
1024 | #define get_filecore_partition(f) 0 | | 1024 | #define get_filecore_partition(f) 0 |
1025 | #else | | 1025 | #else |
1026 | /* | | 1026 | /* |
1027 | * static int filecore_checksum(u_char *bootblock) | | 1027 | * static int filecore_checksum(u_char *bootblock) |
1028 | * | | 1028 | * |
1029 | * Calculates the filecore boot block checksum. This is used to validate | | 1029 | * Calculates the filecore boot block checksum. This is used to validate |
1030 | * a filecore boot block on the disk. If a boot block is validated then | | 1030 | * a filecore boot block on the disk. If a boot block is validated then |
1031 | * it is used to locate the partition table. If the boot block is not | | 1031 | * it is used to locate the partition table. If the boot block is not |
1032 | * validated, it is assumed that the whole disk is NetBSD. | | 1032 | * validated, it is assumed that the whole disk is NetBSD. |
1033 | * | | 1033 | * |
1034 | * The basic algorithm is: | | 1034 | * The basic algorithm is: |
1035 | * | | 1035 | * |
1036 | * for (each byte in block, excluding checksum) { | | 1036 | * for (each byte in block, excluding checksum) { |
1037 | * sum += byte; | | 1037 | * sum += byte; |
1038 | * if (sum > 255) | | 1038 | * if (sum > 255) |
1039 | * sum -= 255; | | 1039 | * sum -= 255; |
1040 | * } | | 1040 | * } |
1041 | * | | 1041 | * |
1042 | * That's equivalent to summing all of the bytes in the block | | 1042 | * That's equivalent to summing all of the bytes in the block |
1043 | * (excluding the checksum byte, of course), then calculating the | | 1043 | * (excluding the checksum byte, of course), then calculating the |
1044 | * checksum as "cksum = sum - ((sum - 1) / 255) * 255)". That | | 1044 | * checksum as "cksum = sum - ((sum - 1) / 255) * 255)". That |
1045 | * expression may or may not yield a faster checksum function, | | 1045 | * expression may or may not yield a faster checksum function, |
1046 | * but it's easier to reason about. | | 1046 | * but it's easier to reason about. |
1047 | * | | 1047 | * |
1048 | * Note that if you have a block filled with bytes of a single | | 1048 | * Note that if you have a block filled with bytes of a single |
1049 | * value "X" (regardless of that value!) and calculate the cksum | | 1049 | * value "X" (regardless of that value!) and calculate the cksum |
1050 | * of the block (excluding the checksum byte), you will _always_ | | 1050 | * of the block (excluding the checksum byte), you will _always_ |
1051 | * end up with a checksum of X. (Do the math; that can be derived | | 1051 | * end up with a checksum of X. (Do the math; that can be derived |
1052 | * from the checksum calculation function!) That means that | | 1052 | * from the checksum calculation function!) That means that |
1053 | * blocks which contain bytes which all have the same value will | | 1053 | * blocks which contain bytes which all have the same value will |
1054 | * always checksum properly. That's a _very_ unlikely occurrence | | 1054 | * always checksum properly. That's a _very_ unlikely occurrence |
1055 | * (probably impossible, actually) for a valid filecore boot block, | | 1055 | * (probably impossible, actually) for a valid filecore boot block, |
1056 | * so we treat such blocks as invalid. | | 1056 | * so we treat such blocks as invalid. |
1057 | */ | | 1057 | */ |
1058 | static int | | 1058 | static int |
1059 | filecore_checksum(u_char *bootblock) | | 1059 | filecore_checksum(u_char *bootblock) |
1060 | { | | 1060 | { |
1061 | u_char byte0, accum_diff; | | 1061 | u_char byte0, accum_diff; |
1062 | u_int sum; | | 1062 | u_int sum; |
1063 | int i; | | 1063 | int i; |
1064 | | | 1064 | |
1065 | sum = 0; | | 1065 | sum = 0; |
1066 | accum_diff = 0; | | 1066 | accum_diff = 0; |
1067 | byte0 = bootblock[0]; | | 1067 | byte0 = bootblock[0]; |
1068 | | | 1068 | |
1069 | /* | | 1069 | /* |
1070 | * Sum the contents of the block, keeping track of whether | | 1070 | * Sum the contents of the block, keeping track of whether |
1071 | * or not all bytes are the same. If 'accum_diff' ends up | | 1071 | * or not all bytes are the same. If 'accum_diff' ends up |
1072 | * being zero, all of the bytes are, in fact, the same. | | 1072 | * being zero, all of the bytes are, in fact, the same. |
1073 | */ | | 1073 | */ |
1074 | for (i = 0; i < 511; ++i) { | | 1074 | for (i = 0; i < 511; ++i) { |
1075 | sum += bootblock[i]; | | 1075 | sum += bootblock[i]; |
1076 | accum_diff |= bootblock[i] ^ byte0; | | 1076 | accum_diff |= bootblock[i] ^ byte0; |
1077 | } | | 1077 | } |
1078 | | | 1078 | |
1079 | /* | | 1079 | /* |
1080 | * Check to see if the checksum byte is the same as the | | 1080 | * Check to see if the checksum byte is the same as the |
1081 | * rest of the bytes, too. (Note that if all of the bytes | | 1081 | * rest of the bytes, too. (Note that if all of the bytes |
1082 | * are the same except the checksum, a checksum compare | | 1082 | * are the same except the checksum, a checksum compare |
1083 | * won't succeed, but that's not our problem.) | | 1083 | * won't succeed, but that's not our problem.) |
1084 | */ | | 1084 | */ |
1085 | accum_diff |= bootblock[i] ^ byte0; | | 1085 | accum_diff |= bootblock[i] ^ byte0; |
1086 | | | 1086 | |
1087 | /* All bytes in block are the same; call it invalid. */ | | 1087 | /* All bytes in block are the same; call it invalid. */ |
1088 | if (accum_diff == 0) | | 1088 | if (accum_diff == 0) |
1089 | return (-1); | | 1089 | return (-1); |
1090 | | | 1090 | |
1091 | return (sum - ((sum - 1) / 255) * 255); | | 1091 | return (sum - ((sum - 1) / 255) * 255); |
1092 | } | | 1092 | } |
1093 | | | 1093 | |
1094 | /* | | 1094 | /* |
1095 | * Check for the presence of a RiscOS filecore boot block | | 1095 | * Check for the presence of a RiscOS filecore boot block |
1096 | * indicating an ADFS file system on the disc. | | 1096 | * indicating an ADFS file system on the disc. |
1097 | * Return the offset to the NetBSD part of the disc if | | 1097 | * Return the offset to the NetBSD part of the disc if |
1098 | * this can be determined. | | 1098 | * this can be determined. |
1099 | * This routine will terminate disklabel if the disc | | 1099 | * This routine will terminate disklabel if the disc |
1100 | * is found to be ADFS only. | | 1100 | * is found to be ADFS only. |
1101 | */ | | 1101 | */ |
1102 | static u_int | | 1102 | static u_int |
1103 | get_filecore_partition(int f) | | 1103 | get_filecore_partition(int f) |
1104 | { | | 1104 | { |
1105 | struct filecore_bootblock *fcbb; | | 1105 | struct filecore_bootblock *fcbb; |
1106 | static u_char bb[DEV_BSIZE]; | | 1106 | static u_char bb[DEV_BSIZE]; |
1107 | u_int offset; | | 1107 | u_int offset; |
1108 | struct riscix_partition_table *riscix_part; | | 1108 | struct riscix_partition_table *riscix_part; |
1109 | int loop; | | 1109 | int loop; |
1110 | | | 1110 | |
1111 | if (pread(f, bb, sizeof(bb), (off_t)FILECORE_BOOT_SECTOR * DEV_BSIZE) != sizeof(bb)) | | 1111 | if (pread(f, bb, sizeof(bb), (off_t)FILECORE_BOOT_SECTOR * DEV_BSIZE) != sizeof(bb)) |
1112 | err(4, "can't read filecore boot block"); | | 1112 | err(4, "can't read filecore boot block"); |
1113 | fcbb = (struct filecore_bootblock *)bb; | | 1113 | fcbb = (struct filecore_bootblock *)bb; |
1114 | | | 1114 | |
1115 | /* Check if table is valid. */ | | 1115 | /* Check if table is valid. */ |
1116 | if (filecore_checksum(bb) != fcbb->checksum) | | 1116 | if (filecore_checksum(bb) != fcbb->checksum) |
1117 | return (0); | | 1117 | return (0); |
1118 | | | 1118 | |
1119 | /* | | 1119 | /* |
1120 | * Check for NetBSD/arm32 (RiscBSD) partition marker. | | 1120 | * Check for NetBSD/arm32 (RiscBSD) partition marker. |
1121 | * If found the NetBSD disklabel location is easy. | | 1121 | * If found the NetBSD disklabel location is easy. |
1122 | */ | | 1122 | */ |
1123 | offset = (fcbb->partition_cyl_low + (fcbb->partition_cyl_high << 8)) | | 1123 | offset = (fcbb->partition_cyl_low + (fcbb->partition_cyl_high << 8)) |
1124 | * fcbb->heads * fcbb->secspertrack; | | 1124 | * fcbb->heads * fcbb->secspertrack; |
1125 | | | 1125 | |
1126 | switch (fcbb->partition_type) { | | 1126 | switch (fcbb->partition_type) { |
1127 | | | 1127 | |
1128 | case PARTITION_FORMAT_RISCBSD: | | 1128 | case PARTITION_FORMAT_RISCBSD: |
1129 | return (offset); | | 1129 | return (offset); |
1130 | | | 1130 | |
1131 | case PARTITION_FORMAT_RISCIX: | | 1131 | case PARTITION_FORMAT_RISCIX: |
1132 | /* | | 1132 | /* |
1133 | * Read the RISCiX partition table and search for the | | 1133 | * Read the RISCiX partition table and search for the |
1134 | * first partition named "RiscBSD", "NetBSD", or "Empty:" | | 1134 | * first partition named "RiscBSD", "NetBSD", or "Empty:" |
1135 | * | | 1135 | * |
1136 | * XXX is use of 'Empty:' really desirable?! -- cgd | | 1136 | * XXX is use of 'Empty:' really desirable?! -- cgd |
1137 | */ | | 1137 | */ |
1138 | | | 1138 | |
1139 | if (pread(f, bb, sizeof(bb), (off_t)offset * DEV_BSIZE) != sizeof(bb)) | | 1139 | if (pread(f, bb, sizeof(bb), (off_t)offset * DEV_BSIZE) != sizeof(bb)) |
1140 | err(4, "can't read riscix partition table"); | | 1140 | err(4, "can't read riscix partition table"); |
1141 | riscix_part = (struct riscix_partition_table *)bb; | | 1141 | riscix_part = (struct riscix_partition_table *)bb; |
1142 | | | 1142 | |
1143 | for (loop = 0; loop < NRISCIX_PARTITIONS; ++loop) { | | 1143 | for (loop = 0; loop < NRISCIX_PARTITIONS; ++loop) { |
1144 | if (strcmp((char *)riscix_part->partitions[loop].rp_name, | | 1144 | if (strcmp((char *)riscix_part->partitions[loop].rp_name, |
1145 | "RiscBSD") == 0 || | | 1145 | "RiscBSD") == 0 || |
1146 | strcmp((char *)riscix_part->partitions[loop].rp_name, | | 1146 | strcmp((char *)riscix_part->partitions[loop].rp_name, |
1147 | "NetBSD") == 0 || | | 1147 | "NetBSD") == 0 || |
1148 | strcmp((char *)riscix_part->partitions[loop].rp_name, | | 1148 | strcmp((char *)riscix_part->partitions[loop].rp_name, |
1149 | "Empty:") == 0) { | | 1149 | "Empty:") == 0) { |
1150 | return riscix_part->partitions[loop].rp_start; | | 1150 | return riscix_part->partitions[loop].rp_start; |
1151 | break; | | 1151 | break; |
1152 | } | | 1152 | } |
1153 | } | | 1153 | } |
1154 | /* | | 1154 | /* |
1155 | * Valid filecore boot block, RISCiX partition table | | 1155 | * Valid filecore boot block, RISCiX partition table |
1156 | * but no NetBSD partition. We should leave this | | 1156 | * but no NetBSD partition. We should leave this |
1157 | * disc alone. | | 1157 | * disc alone. |
1158 | */ | | 1158 | */ |
1159 | errx(4, "cannot label: no NetBSD partition found" | | 1159 | errx(4, "cannot label: no NetBSD partition found" |
1160 | " in RISCiX partition table"); | | 1160 | " in RISCiX partition table"); |
1161 | | | 1161 | |
1162 | default: | | 1162 | default: |
1163 | /* | | 1163 | /* |
1164 | * Valid filecore boot block and no non-ADFS partition. | | 1164 | * Valid filecore boot block and no non-ADFS partition. |
1165 | * This means that the whole disc is allocated for ADFS | | 1165 | * This means that the whole disc is allocated for ADFS |
1166 | * so do not trash ! If the user really wants to put a | | 1166 | * so do not trash ! If the user really wants to put a |
1167 | * NetBSD disklabel on the disc then they should remove | | 1167 | * NetBSD disklabel on the disc then they should remove |
1168 | * the filecore boot block first with dd. | | 1168 | * the filecore boot block first with dd. |
1169 | */ | | 1169 | */ |
1170 | errx(4, "cannot label: filecore-only disk" | | 1170 | errx(4, "cannot label: filecore-only disk" |
1171 | " (no non-ADFS partition)"); | | 1171 | " (no non-ADFS partition)"); |
1172 | } | | 1172 | } |
1173 | return (0); | | 1173 | return (0); |
1174 | } | | 1174 | } |
1175 | #endif /* USE_ACORN */ | | 1175 | #endif /* USE_ACORN */ |
1176 | | | 1176 | |
1177 | /* | | 1177 | /* |
1178 | * Fetch disklabel for disk to 'lab'. | | 1178 | * Fetch disklabel for disk to 'lab'. |
1179 | * Use ioctl to get label unless -r flag is given. | | 1179 | * Use ioctl to get label unless -r flag is given. |
1180 | */ | | 1180 | */ |
1181 | static void | | 1181 | static void |
1182 | readlabel(int f) | | 1182 | readlabel(int f) |
1183 | { | | 1183 | { |
1184 | if (rflag) { | | 1184 | if (rflag) { |
1185 | /* Get label directly from disk */ | | 1185 | /* Get label directly from disk */ |
1186 | if (readlabel_direct(f) == 0) | | 1186 | if (readlabel_direct(f) == 0) |
1187 | return; | | 1187 | return; |
1188 | /* | | 1188 | /* |
1189 | * There was no label on the disk. Get the fictious one | | 1189 | * There was no label on the disk. Get the fictious one |
1190 | * as a basis for initialisation. | | 1190 | * as a basis for initialisation. |
1191 | */ | | 1191 | */ |
1192 | if (!Fflag && Iflag && (dk_ioctl(f, DIOCGDINFO, &lab) == 0 || | | 1192 | if (!Fflag && Iflag && (dk_ioctl(f, DIOCGDINFO, &lab) == 0 || |
1193 | dk_ioctl(f, DIOCGDEFLABEL, &lab) == 0)) | | 1193 | dk_ioctl(f, DIOCGDEFLABEL, &lab) == 0)) |
1194 | return; | | 1194 | return; |
1195 | } else { | | 1195 | } else { |
1196 | /* Get label from kernel. */ | | 1196 | /* Get label from kernel. */ |
1197 | if (dk_ioctl(f, DIOCGDINFO, &lab) < 0) | | 1197 | if (dk_ioctl(f, DIOCGDINFO, &lab) < 0) |
1198 | err(4, "ioctl DIOCGDINFO"); | | 1198 | err(4, "ioctl DIOCGDINFO"); |
1199 | return; | | 1199 | return; |
1200 | } | | 1200 | } |
1201 | | | 1201 | |
1202 | if (read_all == 2) | | 1202 | if (read_all == 2) |
1203 | /* We actually found one, and printed it... */ | | 1203 | /* We actually found one, and printed it... */ |
1204 | exit(0); | | 1204 | exit(0); |
1205 | errx(1, "could not read existing label"); | | 1205 | errx(1, "could not read existing label"); |
1206 | } | | 1206 | } |
1207 | | | 1207 | |
1208 | /* | | 1208 | /* |
1209 | * Reading the label from the disk is largely a case of 'hunt the label'. | | 1209 | * Reading the label from the disk is largely a case of 'hunt the label'. |
1210 | * and since different architectures default to different places there | | 1210 | * and since different architectures default to different places there |
1211 | * could even be more than one label that contradict each other! | | 1211 | * could even be more than one label that contradict each other! |
1212 | * For now we look in the expected place, then search through likely | | 1212 | * For now we look in the expected place, then search through likely |
1213 | * other locations. | | 1213 | * other locations. |
1214 | */ | | 1214 | */ |
1215 | static struct disklabel * | | 1215 | static struct disklabel * |
1216 | find_label(int f, u_int sector) | | 1216 | find_label(int f, u_int sector) |
1217 | { | | 1217 | { |
1218 | struct disklabel *disk_lp, hlp, tlp; | | 1218 | struct disklabel *disk_lp, hlp, tlp; |
1219 | int i; | | 1219 | int i; |
1220 | off_t offset; | | 1220 | off_t offset; |
1221 | const char *is_deleted; | | 1221 | const char *is_deleted; |
1222 | | | 1222 | |
1223 | bootarea_len = pread(f, bootarea, sizeof bootarea, | | 1223 | bootarea_len = pread(f, bootarea, sizeof bootarea, |
1224 | sector * (off_t)DEV_BSIZE); | | 1224 | sector * (off_t)DEV_BSIZE); |
1225 | if (bootarea_len <= 0) { | | 1225 | if (bootarea_len <= 0) { |
1226 | if (verbose) | | 1226 | if (verbose) |
1227 | warn("failed to read bootarea from sector %u", sector); | | 1227 | warn("failed to read bootarea from sector %u", sector); |
1228 | return NULL; | | 1228 | return NULL; |
1229 | } | | 1229 | } |
1230 | | | 1230 | |
1231 | if (verbose > 2) | | 1231 | if (verbose > 2) |
1232 | warnx("read sector %u len %d looking for label", | | 1232 | warnx("read sector %u len %d looking for label", |
1233 | sector, bootarea_len); | | 1233 | sector, bootarea_len); |
1234 | | | 1234 | |
1235 | /* Check expected offset first */ | | 1235 | /* Check expected offset first */ |
1236 | for (offset = LABEL_OFFSET, i = -4;; offset = i += 4) { | | 1236 | for (offset = LABEL_OFFSET, i = -4;; offset = i += 4) { |
1237 | is_deleted = ""; | | 1237 | is_deleted = ""; |
1238 | if (i == LABEL_OFFSET) | | 1238 | if (i == LABEL_OFFSET) |
1239 | continue; | | 1239 | continue; |
1240 | disk_lp = (void *)(bootarea + offset); | | 1240 | disk_lp = (void *)(bootarea + offset); |
1241 | memcpy(&tlp, disk_lp, sizeof(tlp)); | | | |
1242 | if ((char *)(disk_lp + 1) > bootarea + bootarea_len) | | 1241 | if ((char *)(disk_lp + 1) > bootarea + bootarea_len) |
1243 | break; | | 1242 | break; |
| | | 1243 | memcpy(&tlp, disk_lp, sizeof(tlp)); |
1244 | if (tlp.d_magic2 != tlp.d_magic) | | 1244 | if (tlp.d_magic2 != tlp.d_magic) |
1245 | continue; | | 1245 | continue; |
1246 | if (read_all && (tlp.d_magic == DISKMAGIC_DELETED || | | 1246 | if (read_all && (tlp.d_magic == DISKMAGIC_DELETED || |
1247 | tlp.d_magic == DISKMAGIC_DELETED_REV)) { | | 1247 | tlp.d_magic == DISKMAGIC_DELETED_REV)) { |
1248 | tlp.d_magic ^= ~0u; | | 1248 | tlp.d_magic ^= ~0u; |
1249 | tlp.d_magic2 ^= ~0u; | | 1249 | tlp.d_magic2 ^= ~0u; |
1250 | is_deleted = "deleted "; | | 1250 | is_deleted = "deleted "; |
1251 | } | | 1251 | } |
1252 | if (target32toh(tlp.d_magic) != DISKMAGIC) { | | 1252 | if (target32toh(tlp.d_magic) != DISKMAGIC) { |
1253 | /* XXX: Do something about byte-swapped labels ? */ | | 1253 | /* XXX: Do something about byte-swapped labels ? */ |
1254 | if (target32toh(tlp.d_magic) == DISKMAGIC_REV && | | 1254 | if (target32toh(tlp.d_magic) == DISKMAGIC_REV && |
1255 | target32toh(tlp.d_magic2) == DISKMAGIC_REV) | | 1255 | target32toh(tlp.d_magic2) == DISKMAGIC_REV) |
1256 | warnx("ignoring %sbyteswapped label" | | 1256 | warnx("ignoring %sbyteswapped label" |
1257 | " at offset %jd from sector %u", | | 1257 | " at offset %jd from sector %u", |
1258 | is_deleted, (intmax_t)offset, sector); | | 1258 | is_deleted, (intmax_t)offset, sector); |
1259 | continue; | | 1259 | continue; |
1260 | } | | 1260 | } |
1261 | if (target16toh(tlp.d_npartitions) > maxpartitions || | | 1261 | if (target16toh(tlp.d_npartitions) > maxpartitions || |
1262 | dkcksum_target(&tlp) != 0) { | | 1262 | dkcksum_target(&tlp) != 0) { |
1263 | if (verbose > 0) | | 1263 | if (verbose > 0) |
1264 | warnx("corrupt label found at offset %jd in " | | 1264 | warnx("corrupt label found at offset %jd in " |
1265 | "sector %u", (intmax_t)offset, sector); | | 1265 | "sector %u", (intmax_t)offset, sector); |
1266 | continue; | | 1266 | continue; |
1267 | } | | 1267 | } |
1268 | if (verbose > 1) | | 1268 | if (verbose > 1) |
1269 | warnx("%slabel found at offset %jd from sector %u", | | 1269 | warnx("%slabel found at offset %jd from sector %u", |
1270 | is_deleted, (intmax_t)offset, sector); | | 1270 | is_deleted, (intmax_t)offset, sector); |
1271 | if (!read_all) | | 1271 | if (!read_all) |
1272 | return disk_lp; | | 1272 | return disk_lp; |
1273 | | | 1273 | |
1274 | /* To print all the labels we have to do it here */ | | 1274 | /* To print all the labels we have to do it here */ |
1275 | /* XXX: maybe we should compare them? */ | | 1275 | /* XXX: maybe we should compare them? */ |
1276 | targettohlabel(&hlp, &tlp); | | 1276 | targettohlabel(&hlp, &tlp); |
1277 | printf("# %ssector %u offset %jd bytes\n", | | 1277 | printf("# %ssector %u offset %jd bytes\n", |
1278 | is_deleted, sector, (intmax_t)offset); | | 1278 | is_deleted, sector, (intmax_t)offset); |
1279 | if (tflag) | | 1279 | if (tflag) |
1280 | makedisktab(stdout, &hlp); | | 1280 | makedisktab(stdout, &hlp); |
1281 | else { | | 1281 | else { |
1282 | showinfo(stdout, &hlp, specname); | | 1282 | showinfo(stdout, &hlp, specname); |
1283 | showpartitions(stdout, &hlp, Cflag); | | 1283 | showpartitions(stdout, &hlp, Cflag); |
1284 | } | | 1284 | } |
1285 | checklabel(&hlp); | | 1285 | checklabel(&hlp); |
1286 | htotargetlabel(&tlp, &hlp); | | 1286 | htotargetlabel(&tlp, &hlp); |
1287 | memcpy(disk_lp, &tlp, sizeof(tlp)); | | 1287 | memcpy(disk_lp, &tlp, sizeof(tlp)); |
1288 | /* Remember we've found a label */ | | 1288 | /* Remember we've found a label */ |
1289 | read_all = 2; | | 1289 | read_all = 2; |
1290 | } | | 1290 | } |
1291 | return NULL; | | 1291 | return NULL; |
1292 | } | | 1292 | } |
1293 | | | 1293 | |
1294 | static void | | 1294 | static void |
1295 | write_bootarea(int f, u_int sector) | | 1295 | write_bootarea(int f, u_int sector) |
1296 | { | | 1296 | { |
1297 | int wlen; | | 1297 | int wlen; |
1298 | | | 1298 | |
1299 | if (bootarea_len <= 0) | | 1299 | if (bootarea_len <= 0) |
1300 | errx(1, "attempting to write after failed read"); | | 1300 | errx(1, "attempting to write after failed read"); |
1301 | | | 1301 | |
1302 | #ifdef ALPHA_BOOTBLOCK_CKSUM | | 1302 | #ifdef ALPHA_BOOTBLOCK_CKSUM |
1303 | /* | | 1303 | /* |
1304 | * The Alpha requires that the boot block be checksummed. | | 1304 | * The Alpha requires that the boot block be checksummed. |
1305 | * <sys/bootblock.h> provides a macro to do it. | | 1305 | * <sys/bootblock.h> provides a macro to do it. |
1306 | */ | | 1306 | */ |
1307 | if (sector == 0) { | | 1307 | if (sector == 0) { |
1308 | struct alpha_boot_block *bb; | | 1308 | struct alpha_boot_block *bb; |
1309 | | | 1309 | |
1310 | bb = (struct alpha_boot_block *)(void *)bootarea; | | 1310 | bb = (struct alpha_boot_block *)(void *)bootarea; |
1311 | bb->bb_cksum = 0; | | 1311 | bb->bb_cksum = 0; |
1312 | ALPHA_BOOT_BLOCK_CKSUM(bb, &bb->bb_cksum); | | 1312 | ALPHA_BOOT_BLOCK_CKSUM(bb, &bb->bb_cksum); |
1313 | } | | 1313 | } |
1314 | #endif /* ALPHA_BOOTBLOCK_CKSUM */ | | 1314 | #endif /* ALPHA_BOOTBLOCK_CKSUM */ |
1315 | | | 1315 | |
1316 | wlen = pwrite(f, bootarea, bootarea_len, sector * (off_t)DEV_BSIZE); | | 1316 | wlen = pwrite(f, bootarea, bootarea_len, sector * (off_t)DEV_BSIZE); |
1317 | if (wlen == bootarea_len) | | 1317 | if (wlen == bootarea_len) |
1318 | return; | | 1318 | return; |
1319 | if (wlen == -1) | | 1319 | if (wlen == -1) |
1320 | err(1, "disklabel write (sector %u) size %d failed", | | 1320 | err(1, "disklabel write (sector %u) size %d failed", |
1321 | sector, bootarea_len); | | 1321 | sector, bootarea_len); |
1322 | errx(1, "disklabel write (sector %u) size %d truncated to %d", | | 1322 | errx(1, "disklabel write (sector %u) size %d truncated to %d", |
1323 | sector, bootarea_len, wlen); | | 1323 | sector, bootarea_len, wlen); |
1324 | } | | 1324 | } |
1325 | | | 1325 | |
1326 | static int | | 1326 | static int |
1327 | update_label(int f, u_int label_sector, u_int label_offset) | | 1327 | update_label(int f, u_int label_sector, u_int label_offset) |
1328 | { | | 1328 | { |
1329 | struct disklabel *disk_lp; | | 1329 | struct disklabel *disk_lp; |
1330 | | | 1330 | |
1331 | disk_lp = find_label(f, label_sector); | | 1331 | disk_lp = find_label(f, label_sector); |
1332 | | | 1332 | |
1333 | if (disk_lp && Dflag) { | | 1333 | if (disk_lp && Dflag) { |
1334 | /* Invalidate the existing label */ | | 1334 | /* Invalidate the existing label */ |
1335 | disk_lp->d_magic ^= ~0u; | | 1335 | disk_lp->d_magic ^= ~0u; |
1336 | disk_lp->d_magic2 ^= ~0u; | | 1336 | disk_lp->d_magic2 ^= ~0u; |
1337 | if (Dflag == 2) | | 1337 | if (Dflag == 2) |
1338 | write_bootarea(f, label_sector); | | 1338 | write_bootarea(f, label_sector); |
1339 | /* Force label to default location */ | | 1339 | /* Force label to default location */ |
1340 | disk_lp = NULL; | | 1340 | disk_lp = NULL; |
1341 | } | | 1341 | } |
1342 | | | 1342 | |
1343 | if (Dflag == 2) | | 1343 | if (Dflag == 2) |
1344 | /* We are just deleting the label */ | | 1344 | /* We are just deleting the label */ |
1345 | return 0; | | 1345 | return 0; |
1346 | | | 1346 | |
1347 | if (disk_lp == NULL) { | | 1347 | if (disk_lp == NULL) { |
1348 | if (label_offset == ~0u) | | 1348 | if (label_offset == ~0u) |
1349 | return 0; | | 1349 | return 0; |
1350 | /* Nothing on the disk - we need to add it */ | | 1350 | /* Nothing on the disk - we need to add it */ |
1351 | disk_lp = (void *)(bootarea + label_offset); | | 1351 | disk_lp = (void *)(bootarea + label_offset); |
1352 | if ((char *)(disk_lp + 1) > bootarea + bootarea_len) | | 1352 | if ((char *)(disk_lp + 1) > bootarea + bootarea_len) |
1353 | errx(1, "no space in bootarea (sector %u) " | | 1353 | errx(1, "no space in bootarea (sector %u) " |
1354 | "to create label", label_sector); | | 1354 | "to create label", label_sector); |
1355 | } | | 1355 | } |
1356 | | | 1356 | |
1357 | htotargetlabel(disk_lp, &lab); | | 1357 | htotargetlabel(disk_lp, &lab); |
1358 | write_bootarea(f, label_sector); | | 1358 | write_bootarea(f, label_sector); |
1359 | return 1; | | 1359 | return 1; |
1360 | } | | 1360 | } |
1361 | | | 1361 | |
1362 | static void | | 1362 | static void |
1363 | writelabel_direct(int f) | | 1363 | writelabel_direct(int f) |
1364 | { | | 1364 | { |
1365 | u_int label_sector; | | 1365 | u_int label_sector; |
1366 | int written = 0; | | 1366 | int written = 0; |
1367 | int rval; | | 1367 | int rval; |
1368 | | | 1368 | |
1369 | label_sector = get_filecore_partition(f); | | 1369 | label_sector = get_filecore_partition(f); |
1370 | if (label_sector != 0) | | 1370 | if (label_sector != 0) |
1371 | /* The offset needs to be that from the acorn ports... */ | | 1371 | /* The offset needs to be that from the acorn ports... */ |
1372 | written = update_label(f, label_sector, DEV_BSIZE); | | 1372 | written = update_label(f, label_sector, DEV_BSIZE); |
1373 | | | 1373 | |
1374 | rval = process_mbr(f, writelabel_mbr); | | 1374 | rval = process_mbr(f, writelabel_mbr); |
1375 | | | 1375 | |
1376 | if (rval == 2 || written) | | 1376 | if (rval == 2 || written) |
1377 | /* Don't add a label to sector 0, but update one if there */ | | 1377 | /* Don't add a label to sector 0, but update one if there */ |
1378 | update_label(f, 0, ~0u); | | 1378 | update_label(f, 0, ~0u); |
1379 | else | | 1379 | else |
1380 | update_label(f, 0, LABEL_OFFSET); | | 1380 | update_label(f, 0, LABEL_OFFSET); |
1381 | } | | 1381 | } |
1382 | | | 1382 | |
1383 | static int | | 1383 | static int |
1384 | readlabel_direct(int f) | | 1384 | readlabel_direct(int f) |
1385 | { | | 1385 | { |
1386 | struct disklabel *disk_lp; | | 1386 | struct disklabel *disk_lp; |
1387 | u_int filecore_partition_offset; | | 1387 | u_int filecore_partition_offset; |
1388 | | | 1388 | |
1389 | filecore_partition_offset = get_filecore_partition(f); | | 1389 | filecore_partition_offset = get_filecore_partition(f); |
1390 | if (filecore_partition_offset != 0) { | | 1390 | if (filecore_partition_offset != 0) { |
1391 | disk_lp = find_label(f, filecore_partition_offset); | | 1391 | disk_lp = find_label(f, filecore_partition_offset); |
1392 | if (disk_lp != NULL) { | | 1392 | if (disk_lp != NULL) { |
1393 | targettohlabel(&lab, disk_lp); | | 1393 | targettohlabel(&lab, disk_lp); |
1394 | return 0; | | 1394 | return 0; |
1395 | } | | 1395 | } |
1396 | } | | 1396 | } |
1397 | | | 1397 | |
1398 | if (labelusesmbr && process_mbr(f, readlabel_mbr) == 0) | | 1398 | if (labelusesmbr && process_mbr(f, readlabel_mbr) == 0) |
1399 | return 0; | | 1399 | return 0; |
1400 | | | 1400 | |
1401 | disk_lp = find_label(f, 0); | | 1401 | disk_lp = find_label(f, 0); |
1402 | if (disk_lp != NULL) { | | 1402 | if (disk_lp != NULL) { |
1403 | targettohlabel(&lab, disk_lp); | | 1403 | targettohlabel(&lab, disk_lp); |
1404 | return 0; | | 1404 | return 0; |
1405 | } | | 1405 | } |
1406 | | | 1406 | |
1407 | if (!labelusesmbr && process_mbr(f, readlabel_mbr) == 0) | | 1407 | if (!labelusesmbr && process_mbr(f, readlabel_mbr) == 0) |
1408 | return 0; | | 1408 | return 0; |
1409 | | | 1409 | |
1410 | return 1; | | 1410 | return 1; |
1411 | } | | 1411 | } |
1412 | | | 1412 | |
1413 | static void | | 1413 | static void |
1414 | makedisktab(FILE *f, struct disklabel *lp) | | 1414 | makedisktab(FILE *f, struct disklabel *lp) |
1415 | { | | 1415 | { |
1416 | int i; | | 1416 | int i; |
1417 | const char *did; | | 1417 | const char *did; |
1418 | struct partition *pp; | | 1418 | struct partition *pp; |
1419 | | | 1419 | |
1420 | did = "\\\n\t:"; | | 1420 | did = "\\\n\t:"; |
1421 | (void) fprintf(f, "%.*s|Automatically generated label:\\\n\t:dt=", | | 1421 | (void) fprintf(f, "%.*s|Automatically generated label:\\\n\t:dt=", |
1422 | (int) sizeof(lp->d_typename), lp->d_typename); | | 1422 | (int) sizeof(lp->d_typename), lp->d_typename); |
1423 | if ((unsigned) lp->d_type < DKMAXTYPES) | | 1423 | if ((unsigned) lp->d_type < DKMAXTYPES) |
1424 | (void) fprintf(f, "%s:", dktypenames[lp->d_type]); | | 1424 | (void) fprintf(f, "%s:", dktypenames[lp->d_type]); |
1425 | else | | 1425 | else |
1426 | (void) fprintf(f, "unknown%" PRIu16 ":", lp->d_type); | | 1426 | (void) fprintf(f, "unknown%" PRIu16 ":", lp->d_type); |
1427 | | | 1427 | |
1428 | (void) fprintf(f, "se#%" PRIu32 ":", lp->d_secsize); | | 1428 | (void) fprintf(f, "se#%" PRIu32 ":", lp->d_secsize); |
1429 | (void) fprintf(f, "ns#%" PRIu32 ":", lp->d_nsectors); | | 1429 | (void) fprintf(f, "ns#%" PRIu32 ":", lp->d_nsectors); |
1430 | (void) fprintf(f, "nt#%" PRIu32 ":", lp->d_ntracks); | | 1430 | (void) fprintf(f, "nt#%" PRIu32 ":", lp->d_ntracks); |
1431 | (void) fprintf(f, "sc#%" PRIu32 ":", lp->d_secpercyl); | | 1431 | (void) fprintf(f, "sc#%" PRIu32 ":", lp->d_secpercyl); |
1432 | (void) fprintf(f, "nc#%" PRIu32 ":", lp->d_ncylinders); | | 1432 | (void) fprintf(f, "nc#%" PRIu32 ":", lp->d_ncylinders); |
1433 | | | 1433 | |
1434 | if ((lp->d_secpercyl * lp->d_ncylinders) != lp->d_secperunit) { | | 1434 | if ((lp->d_secpercyl * lp->d_ncylinders) != lp->d_secperunit) { |
1435 | (void) fprintf(f, "%ssu#%" PRIu32 ":", did, lp->d_secperunit); | | 1435 | (void) fprintf(f, "%ssu#%" PRIu32 ":", did, lp->d_secperunit); |
1436 | did = ""; | | 1436 | did = ""; |
1437 | } | | 1437 | } |
1438 | if (lp->d_rpm != 3600) { | | 1438 | if (lp->d_rpm != 3600) { |
1439 | (void) fprintf(f, "%srm#%" PRIu16 ":", did, lp->d_rpm); | | 1439 | (void) fprintf(f, "%srm#%" PRIu16 ":", did, lp->d_rpm); |
1440 | did = ""; | | 1440 | did = ""; |
1441 | } | | 1441 | } |
1442 | if (lp->d_interleave != 1) { | | 1442 | if (lp->d_interleave != 1) { |
1443 | (void) fprintf(f, "%sil#%" PRIu16 ":", did, lp->d_interleave); | | 1443 | (void) fprintf(f, "%sil#%" PRIu16 ":", did, lp->d_interleave); |
1444 | did = ""; | | 1444 | did = ""; |
1445 | } | | 1445 | } |
1446 | if (lp->d_trackskew != 0) { | | 1446 | if (lp->d_trackskew != 0) { |
1447 | (void) fprintf(f, "%ssk#%" PRIu16 ":", did, lp->d_trackskew); | | 1447 | (void) fprintf(f, "%ssk#%" PRIu16 ":", did, lp->d_trackskew); |
1448 | did = ""; | | 1448 | did = ""; |
1449 | } | | 1449 | } |
1450 | if (lp->d_cylskew != 0) { | | 1450 | if (lp->d_cylskew != 0) { |
1451 | (void) fprintf(f, "%scs#%" PRIu16 ":", did, lp->d_cylskew); | | 1451 | (void) fprintf(f, "%scs#%" PRIu16 ":", did, lp->d_cylskew); |
1452 | did = ""; | | 1452 | did = ""; |
1453 | } | | 1453 | } |
1454 | if (lp->d_headswitch != 0) { | | 1454 | if (lp->d_headswitch != 0) { |
1455 | (void) fprintf(f, "%shs#%" PRIu32 ":", did, lp->d_headswitch); | | 1455 | (void) fprintf(f, "%shs#%" PRIu32 ":", did, lp->d_headswitch); |
1456 | did = ""; | | 1456 | did = ""; |
1457 | } | | 1457 | } |
1458 | if (lp->d_trkseek != 0) { | | 1458 | if (lp->d_trkseek != 0) { |
1459 | (void) fprintf(f, "%sts#%" PRIu32 ":", did, lp->d_trkseek); | | 1459 | (void) fprintf(f, "%sts#%" PRIu32 ":", did, lp->d_trkseek); |
1460 | did = ""; | | 1460 | did = ""; |
1461 | } | | 1461 | } |
1462 | #ifdef notyet | | 1462 | #ifdef notyet |
1463 | (void) fprintf(f, "drivedata: "); | | 1463 | (void) fprintf(f, "drivedata: "); |
1464 | for (i = NDDATA - 1; i >= 0; i--) | | 1464 | for (i = NDDATA - 1; i >= 0; i--) |
1465 | if (lp->d_drivedata[i]) | | 1465 | if (lp->d_drivedata[i]) |
1466 | break; | | 1466 | break; |
1467 | if (i < 0) | | 1467 | if (i < 0) |
1468 | i = 0; | | 1468 | i = 0; |
1469 | for (j = 0; j <= i; j++) | | 1469 | for (j = 0; j <= i; j++) |
1470 | (void) fprintf(f, "%" PRIu32 " ", lp->d_drivedata[j]); | | 1470 | (void) fprintf(f, "%" PRIu32 " ", lp->d_drivedata[j]); |
1471 | #endif /* notyet */ | | 1471 | #endif /* notyet */ |
1472 | pp = lp->d_partitions; | | 1472 | pp = lp->d_partitions; |
1473 | for (i = 0; i < lp->d_npartitions; i++, pp++) { | | 1473 | for (i = 0; i < lp->d_npartitions; i++, pp++) { |
1474 | if (pp->p_size) { | | 1474 | if (pp->p_size) { |
1475 | char c = 'a' + i; | | 1475 | char c = 'a' + i; |
1476 | (void) fprintf(f, "\\\n\t:"); | | 1476 | (void) fprintf(f, "\\\n\t:"); |
1477 | (void) fprintf(f, "p%c#%" PRIu32 ":", c, pp->p_size); | | 1477 | (void) fprintf(f, "p%c#%" PRIu32 ":", c, pp->p_size); |
1478 | (void) fprintf(f, "o%c#%" PRIu32 ":", c, pp->p_offset); | | 1478 | (void) fprintf(f, "o%c#%" PRIu32 ":", c, pp->p_offset); |
1479 | if (pp->p_fstype != FS_UNUSED) { | | 1479 | if (pp->p_fstype != FS_UNUSED) { |
1480 | if ((unsigned) pp->p_fstype < FSMAXTYPES) | | 1480 | if ((unsigned) pp->p_fstype < FSMAXTYPES) |
1481 | (void) fprintf(f, "t%c=%s:", c, | | 1481 | (void) fprintf(f, "t%c=%s:", c, |
1482 | fstypenames[pp->p_fstype]); | | 1482 | fstypenames[pp->p_fstype]); |
1483 | else | | 1483 | else |
1484 | (void) fprintf(f, | | 1484 | (void) fprintf(f, |
1485 | "t%c=unknown%" PRIu8 ":", | | 1485 | "t%c=unknown%" PRIu8 ":", |
1486 | c, pp->p_fstype); | | 1486 | c, pp->p_fstype); |
1487 | } | | 1487 | } |
1488 | switch (pp->p_fstype) { | | 1488 | switch (pp->p_fstype) { |
1489 | | | 1489 | |
1490 | case FS_UNUSED: | | 1490 | case FS_UNUSED: |
1491 | break; | | 1491 | break; |
1492 | | | 1492 | |
1493 | case FS_BSDFFS: | | 1493 | case FS_BSDFFS: |
1494 | case FS_BSDLFS: | | 1494 | case FS_BSDLFS: |
1495 | case FS_EX2FS: | | 1495 | case FS_EX2FS: |
1496 | case FS_ADOS: | | 1496 | case FS_ADOS: |
1497 | case FS_APPLEUFS: | | 1497 | case FS_APPLEUFS: |
1498 | (void) fprintf(f, "b%c#%" PRIu64 ":", c, | | 1498 | (void) fprintf(f, "b%c#%" PRIu64 ":", c, |
1499 | (uint64_t)pp->p_fsize * pp->p_frag); | | 1499 | (uint64_t)pp->p_fsize * pp->p_frag); |
1500 | (void) fprintf(f, "f%c#%" PRIu32 ":", c, | | 1500 | (void) fprintf(f, "f%c#%" PRIu32 ":", c, |
1501 | pp->p_fsize); | | 1501 | pp->p_fsize); |
1502 | break; | | 1502 | break; |
1503 | default: | | 1503 | default: |
1504 | break; | | 1504 | break; |
1505 | } | | 1505 | } |
1506 | } | | 1506 | } |
1507 | } | | 1507 | } |
1508 | (void) fprintf(f, "\n"); | | 1508 | (void) fprintf(f, "\n"); |
1509 | (void) fflush(f); | | 1509 | (void) fflush(f); |
1510 | } | | 1510 | } |
1511 | | | 1511 | |
1512 | static int | | 1512 | static int |
1513 | edit(int f) | | 1513 | edit(int f) |
1514 | { | | 1514 | { |
1515 | const char *tmpdir; | | 1515 | const char *tmpdir; |
1516 | char tmpfil[MAXPATHLEN]; | | 1516 | char tmpfil[MAXPATHLEN]; |
1517 | int first, ch, fd; | | 1517 | int first, ch, fd; |
1518 | int get_ok; | | 1518 | int get_ok; |
1519 | FILE *fp; | | 1519 | FILE *fp; |
1520 | | | 1520 | |
1521 | if ((tmpdir = getenv("TMPDIR")) == NULL) | | 1521 | if ((tmpdir = getenv("TMPDIR")) == NULL) |
1522 | tmpdir = _PATH_TMP; | | 1522 | tmpdir = _PATH_TMP; |
1523 | (void)snprintf(tmpfil, sizeof(tmpfil), "%s/%s", tmpdir, TMPFILE); | | 1523 | (void)snprintf(tmpfil, sizeof(tmpfil), "%s/%s", tmpdir, TMPFILE); |
1524 | if ((fd = mkstemp(tmpfil)) == -1 || (fp = fdopen(fd, "w")) == NULL) { | | 1524 | if ((fd = mkstemp(tmpfil)) == -1 || (fp = fdopen(fd, "w")) == NULL) { |
1525 | warn("%s", tmpfil); | | 1525 | warn("%s", tmpfil); |
1526 | return (1); | | 1526 | return (1); |
1527 | } | | 1527 | } |
1528 | (void)fchmod(fd, 0600); | | 1528 | (void)fchmod(fd, 0600); |
1529 | showinfo(fp, &lab, specname); | | 1529 | showinfo(fp, &lab, specname); |
1530 | showpartitions(fp, &lab, Cflag); | | 1530 | showpartitions(fp, &lab, Cflag); |
1531 | (void) fclose(fp); | | 1531 | (void) fclose(fp); |
1532 | for (;;) { | | 1532 | for (;;) { |
1533 | if (!editit(tmpfil)) | | 1533 | if (!editit(tmpfil)) |
1534 | break; | | 1534 | break; |
1535 | fp = fopen(tmpfil, "r"); | | 1535 | fp = fopen(tmpfil, "r"); |
1536 | if (fp == NULL) { | | 1536 | if (fp == NULL) { |
1537 | warn("%s", tmpfil); | | 1537 | warn("%s", tmpfil); |
1538 | break; | | 1538 | break; |
1539 | } | | 1539 | } |
1540 | (void) memset(&lab, 0, sizeof(lab)); | | 1540 | (void) memset(&lab, 0, sizeof(lab)); |
1541 | get_ok = getasciilabel(fp, &lab); | | 1541 | get_ok = getasciilabel(fp, &lab); |
1542 | fclose(fp); | | 1542 | fclose(fp); |
1543 | if (get_ok && write_label(f) == 0) { | | 1543 | if (get_ok && write_label(f) == 0) { |
1544 | (void) unlink(tmpfil); | | 1544 | (void) unlink(tmpfil); |
1545 | return (0); | | 1545 | return (0); |
1546 | } | | 1546 | } |
1547 | (void) printf("re-edit the label? [y]: "); | | 1547 | (void) printf("re-edit the label? [y]: "); |
1548 | (void) fflush(stdout); | | 1548 | (void) fflush(stdout); |
1549 | first = ch = getchar(); | | 1549 | first = ch = getchar(); |
1550 | while (ch != '\n' && ch != EOF) | | 1550 | while (ch != '\n' && ch != EOF) |
1551 | ch = getchar(); | | 1551 | ch = getchar(); |
1552 | if (first == 'n' || first == 'N') | | 1552 | if (first == 'n' || first == 'N') |
1553 | break; | | 1553 | break; |
1554 | } | | 1554 | } |
1555 | (void)unlink(tmpfil); | | 1555 | (void)unlink(tmpfil); |
1556 | return (1); | | 1556 | return (1); |
1557 | } | | 1557 | } |
1558 | | | 1558 | |
1559 | static int | | 1559 | static int |
1560 | editit(const char *tmpfil) | | 1560 | editit(const char *tmpfil) |
1561 | { | | 1561 | { |
1562 | int pid, xpid; | | 1562 | int pid, xpid; |
1563 | int status; | | 1563 | int status; |
1564 | sigset_t nsigset, osigset; | | 1564 | sigset_t nsigset, osigset; |
1565 | | | 1565 | |
1566 | sigemptyset(&nsigset); | | 1566 | sigemptyset(&nsigset); |
1567 | sigaddset(&nsigset, SIGINT); | | 1567 | sigaddset(&nsigset, SIGINT); |
1568 | sigaddset(&nsigset, SIGQUIT); | | 1568 | sigaddset(&nsigset, SIGQUIT); |
1569 | sigaddset(&nsigset, SIGHUP); | | 1569 | sigaddset(&nsigset, SIGHUP); |
1570 | sigprocmask(SIG_BLOCK, &nsigset, &osigset); | | 1570 | sigprocmask(SIG_BLOCK, &nsigset, &osigset); |
1571 | while ((pid = fork()) < 0) { | | 1571 | while ((pid = fork()) < 0) { |
1572 | if (errno != EAGAIN) { | | 1572 | if (errno != EAGAIN) { |
1573 | sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); | | 1573 | sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); |
1574 | warn("fork"); | | 1574 | warn("fork"); |
1575 | return (0); | | 1575 | return (0); |
1576 | } | | 1576 | } |
1577 | sleep(1); | | 1577 | sleep(1); |
1578 | } | | 1578 | } |
1579 | if (pid == 0) { | | 1579 | if (pid == 0) { |
1580 | const char *ed; | | 1580 | const char *ed; |
1581 | char *buf; | | 1581 | char *buf; |
1582 | int retval; | | 1582 | int retval; |
1583 | | | 1583 | |
1584 | sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); | | 1584 | sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); |
1585 | setgid(getgid()); | | 1585 | setgid(getgid()); |
1586 | setuid(getuid()); | | 1586 | setuid(getuid()); |
1587 | if ((ed = getenv("EDITOR")) == (char *)0) | | 1587 | if ((ed = getenv("EDITOR")) == (char *)0) |
1588 | ed = DEFEDITOR; | | 1588 | ed = DEFEDITOR; |
1589 | /* | | 1589 | /* |
1590 | * Jump through a few extra hoops in case someone's editor | | 1590 | * Jump through a few extra hoops in case someone's editor |
1591 | * is "editor arg1 arg2". | | 1591 | * is "editor arg1 arg2". |
1592 | */ | | 1592 | */ |
1593 | asprintf(&buf, "%s %s", ed, tmpfil); | | 1593 | asprintf(&buf, "%s %s", ed, tmpfil); |
1594 | if (!buf) | | 1594 | if (!buf) |
1595 | err(1, "malloc"); | | 1595 | err(1, "malloc"); |
1596 | retval = execlp(_PATH_BSHELL, _PATH_BSHELL, "-c", buf, NULL); | | 1596 | retval = execlp(_PATH_BSHELL, _PATH_BSHELL, "-c", buf, NULL); |
1597 | if (retval == -1) | | 1597 | if (retval == -1) |
1598 | perror(ed); | | 1598 | perror(ed); |
1599 | exit(retval); | | 1599 | exit(retval); |
1600 | } | | 1600 | } |
1601 | while ((xpid = wait(&status)) >= 0) | | 1601 | while ((xpid = wait(&status)) >= 0) |
1602 | if (xpid == pid) | | 1602 | if (xpid == pid) |
1603 | break; | | 1603 | break; |
1604 | sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); | | 1604 | sigprocmask(SIG_SETMASK, &osigset, (sigset_t *)0); |
1605 | return (!status); | | 1605 | return (!status); |
1606 | } | | 1606 | } |
1607 | | | 1607 | |
1608 | static char * | | 1608 | static char * |
1609 | skip(char *cp) | | 1609 | skip(char *cp) |
1610 | { | | 1610 | { |
1611 | | | 1611 | |
1612 | cp += strspn(cp, " \t"); | | 1612 | cp += strspn(cp, " \t"); |
1613 | if (*cp == '\0') | | 1613 | if (*cp == '\0') |
1614 | return (NULL); | | 1614 | return (NULL); |
1615 | return (cp); | | 1615 | return (cp); |
1616 | } | | 1616 | } |
1617 | | | 1617 | |
1618 | static char * | | 1618 | static char * |
1619 | word(char *cp) | | 1619 | word(char *cp) |
1620 | { | | 1620 | { |
1621 | | | 1621 | |
1622 | if (cp == NULL || *cp == '\0') | | 1622 | if (cp == NULL || *cp == '\0') |
1623 | return (NULL); | | 1623 | return (NULL); |
1624 | | | 1624 | |
1625 | cp += strcspn(cp, " \t"); | | 1625 | cp += strcspn(cp, " \t"); |
1626 | if (*cp == '\0') | | 1626 | if (*cp == '\0') |
1627 | return (NULL); | | 1627 | return (NULL); |
1628 | *cp++ = '\0'; | | 1628 | *cp++ = '\0'; |
1629 | cp += strspn(cp, " \t"); | | 1629 | cp += strspn(cp, " \t"); |
1630 | if (*cp == '\0') | | 1630 | if (*cp == '\0') |
1631 | return (NULL); | | 1631 | return (NULL); |
1632 | return (cp); | | 1632 | return (cp); |
1633 | } | | 1633 | } |
1634 | | | 1634 | |
1635 | #define _CHECKLINE \ | | 1635 | #define _CHECKLINE \ |
1636 | if (tp == NULL || *tp == '\0') { \ | | 1636 | if (tp == NULL || *tp == '\0') { \ |
1637 | warnx("line %d: too few fields", lineno); \ | | 1637 | warnx("line %d: too few fields", lineno); \ |
1638 | errors++; \ | | 1638 | errors++; \ |
1639 | break; \ | | 1639 | break; \ |
1640 | } | | 1640 | } |
1641 | | | 1641 | |
1642 | #define __CHECKLINE \ | | 1642 | #define __CHECKLINE \ |
1643 | if (*tp == NULL || **tp == '\0') { \ | | 1643 | if (*tp == NULL || **tp == '\0') { \ |
1644 | warnx("line %d: too few fields", lineno); \ | | 1644 | warnx("line %d: too few fields", lineno); \ |
1645 | *tp = _error_; \ | | 1645 | *tp = _error_; \ |
1646 | return 0; \ | | 1646 | return 0; \ |
1647 | } | | 1647 | } |
1648 | | | 1648 | |
1649 | static char _error_[] = ""; | | 1649 | static char _error_[] = ""; |
1650 | #define NXTNUM(n) if ((n = nxtnum(&tp, lineno),0) + tp != _error_) \ | | 1650 | #define NXTNUM(n) if ((n = nxtnum(&tp, lineno),0) + tp != _error_) \ |
1651 | ; else goto error | | 1651 | ; else goto error |
1652 | #define NXTXNUM(n) if ((n = nxtxnum(&tp, lp, lineno),0) + tp != _error_) \ | | 1652 | #define NXTXNUM(n) if ((n = nxtxnum(&tp, lp, lineno),0) + tp != _error_) \ |
1653 | ; else goto error | | 1653 | ; else goto error |
1654 | | | 1654 | |
1655 | static unsigned long | | 1655 | static unsigned long |
1656 | nxtnum(char **tp, int lineno) | | 1656 | nxtnum(char **tp, int lineno) |
1657 | { | | 1657 | { |
1658 | char *cp; | | 1658 | char *cp; |
1659 | unsigned long v; | | 1659 | unsigned long v; |
1660 | | | 1660 | |
1661 | __CHECKLINE | | 1661 | __CHECKLINE |
1662 | if (getulong(*tp, '\0', &cp, &v, UINT32_MAX) != 0) { | | 1662 | if (getulong(*tp, '\0', &cp, &v, UINT32_MAX) != 0) { |
1663 | warnx("line %d: syntax error", lineno); | | 1663 | warnx("line %d: syntax error", lineno); |
1664 | *tp = _error_; | | 1664 | *tp = _error_; |
1665 | return 0; | | 1665 | return 0; |
1666 | } | | 1666 | } |
1667 | *tp = cp; | | 1667 | *tp = cp; |
1668 | return v; | | 1668 | return v; |
1669 | } | | 1669 | } |
1670 | | | 1670 | |
1671 | static unsigned long | | 1671 | static unsigned long |
1672 | nxtxnum(char **tp, struct disklabel *lp, int lineno) | | 1672 | nxtxnum(char **tp, struct disklabel *lp, int lineno) |
1673 | { | | 1673 | { |
1674 | char *cp, *ncp; | | 1674 | char *cp, *ncp; |
1675 | unsigned long n, v; | | 1675 | unsigned long n, v; |
1676 | | | 1676 | |
1677 | __CHECKLINE | | 1677 | __CHECKLINE |
1678 | cp = *tp; | | 1678 | cp = *tp; |
1679 | if (getulong(cp, '/', &ncp, &n, UINT32_MAX) != 0) | | 1679 | if (getulong(cp, '/', &ncp, &n, UINT32_MAX) != 0) |
1680 | goto bad; | | 1680 | goto bad; |
1681 | | | 1681 | |
1682 | if (*ncp == '/') { | | 1682 | if (*ncp == '/') { |
1683 | n *= lp->d_secpercyl; | | 1683 | n *= lp->d_secpercyl; |
1684 | cp = ncp + 1; | | 1684 | cp = ncp + 1; |
1685 | if (getulong(cp, '/', &ncp, &v, UINT32_MAX) != 0) | | 1685 | if (getulong(cp, '/', &ncp, &v, UINT32_MAX) != 0) |
1686 | goto bad; | | 1686 | goto bad; |
1687 | n += v * lp->d_nsectors; | | 1687 | n += v * lp->d_nsectors; |
1688 | cp = ncp + 1; | | 1688 | cp = ncp + 1; |
1689 | if (getulong(cp, '\0', &ncp, &v, UINT32_MAX) != 0) | | 1689 | if (getulong(cp, '\0', &ncp, &v, UINT32_MAX) != 0) |
1690 | goto bad; | | 1690 | goto bad; |
1691 | n += v; | | 1691 | n += v; |
1692 | } | | 1692 | } |
1693 | *tp = ncp; | | 1693 | *tp = ncp; |
1694 | return n; | | 1694 | return n; |
1695 | bad: | | 1695 | bad: |
1696 | warnx("line %d: invalid format", lineno); | | 1696 | warnx("line %d: invalid format", lineno); |
1697 | *tp = _error_; | | 1697 | *tp = _error_; |
1698 | return 0; | | 1698 | return 0; |
1699 | } | | 1699 | } |
1700 | | | 1700 | |
1701 | /* | | 1701 | /* |
1702 | * Read an ascii label in from fd f, | | 1702 | * Read an ascii label in from fd f, |
1703 | * in the same format as that put out by showinfo() and showpartitions(), | | 1703 | * in the same format as that put out by showinfo() and showpartitions(), |
1704 | * and fill in lp. | | 1704 | * and fill in lp. |
1705 | */ | | 1705 | */ |
1706 | static int | | 1706 | static int |
1707 | getasciilabel(FILE *f, struct disklabel *lp) | | 1707 | getasciilabel(FILE *f, struct disklabel *lp) |
1708 | { | | 1708 | { |
1709 | const char *const *cpp, *s; | | 1709 | const char *const *cpp, *s; |
1710 | struct partition *pp; | | 1710 | struct partition *pp; |
1711 | char *cp, *tp, line[BUFSIZ], tbuf[15]; | | 1711 | char *cp, *tp, line[BUFSIZ], tbuf[15]; |
1712 | int lineno, errors; | | 1712 | int lineno, errors; |
1713 | unsigned long v; | | 1713 | unsigned long v; |
1714 | unsigned int part; | | 1714 | unsigned int part; |
1715 | | | 1715 | |
1716 | lineno = 0; | | 1716 | lineno = 0; |
1717 | errors = 0; | | 1717 | errors = 0; |
1718 | lp->d_bbsize = BBSIZE; /* XXX */ | | 1718 | lp->d_bbsize = BBSIZE; /* XXX */ |
1719 | lp->d_sbsize = SBLOCKSIZE; /* XXX */ | | 1719 | lp->d_sbsize = SBLOCKSIZE; /* XXX */ |
1720 | while (fgets(line, sizeof(line) - 1, f)) { | | 1720 | while (fgets(line, sizeof(line) - 1, f)) { |
1721 | lineno++; | | 1721 | lineno++; |
1722 | if ((cp = strpbrk(line, "#\r\n")) != NULL) | | 1722 | if ((cp = strpbrk(line, "#\r\n")) != NULL) |
1723 | *cp = '\0'; | | 1723 | *cp = '\0'; |
1724 | cp = skip(line); | | 1724 | cp = skip(line); |
1725 | if (cp == NULL) /* blank line or comment line */ | | 1725 | if (cp == NULL) /* blank line or comment line */ |
1726 | continue; | | 1726 | continue; |
1727 | tp = strchr(cp, ':'); /* everything has a colon in it */ | | 1727 | tp = strchr(cp, ':'); /* everything has a colon in it */ |
1728 | if (tp == NULL) { | | 1728 | if (tp == NULL) { |
1729 | warnx("line %d: syntax error", lineno); | | 1729 | warnx("line %d: syntax error", lineno); |
1730 | errors++; | | 1730 | errors++; |
1731 | continue; | | 1731 | continue; |
1732 | } | | 1732 | } |
1733 | *tp++ = '\0', tp = skip(tp); | | 1733 | *tp++ = '\0', tp = skip(tp); |
1734 | if (!strcmp(cp, "type")) { | | 1734 | if (!strcmp(cp, "type")) { |
1735 | if (tp == NULL) { | | 1735 | if (tp == NULL) { |
1736 | strlcpy(tbuf, "unknown", sizeof(tbuf)); | | 1736 | strlcpy(tbuf, "unknown", sizeof(tbuf)); |
1737 | tp = tbuf; | | 1737 | tp = tbuf; |
1738 | } | | 1738 | } |
1739 | cpp = dktypenames; | | 1739 | cpp = dktypenames; |
1740 | for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) | | 1740 | for (; cpp < &dktypenames[DKMAXTYPES]; cpp++) |
1741 | if ((s = *cpp) && !strcasecmp(s, tp)) { | | 1741 | if ((s = *cpp) && !strcasecmp(s, tp)) { |
1742 | lp->d_type = cpp - dktypenames; | | 1742 | lp->d_type = cpp - dktypenames; |
1743 | goto next; | | 1743 | goto next; |
1744 | } | | 1744 | } |
1745 | if (GETNUM16(tp, &v) != 0) { | | 1745 | if (GETNUM16(tp, &v) != 0) { |
1746 | warnx("line %d: syntax error", lineno); | | 1746 | warnx("line %d: syntax error", lineno); |
1747 | errors++; | | 1747 | errors++; |
1748 | continue; | | 1748 | continue; |
1749 | } | | 1749 | } |
1750 | if (v >= DKMAXTYPES) | | 1750 | if (v >= DKMAXTYPES) |
1751 | warnx("line %d: warning, unknown disk type: %s", | | 1751 | warnx("line %d: warning, unknown disk type: %s", |
1752 | lineno, tp); | | 1752 | lineno, tp); |
1753 | lp->d_type = v; | | 1753 | lp->d_type = v; |
1754 | continue; | | 1754 | continue; |
1755 | } | | 1755 | } |
1756 | if (!strcmp(cp, "flags")) { | | 1756 | if (!strcmp(cp, "flags")) { |
1757 | for (v = 0; (cp = tp) && *cp != '\0';) { | | 1757 | for (v = 0; (cp = tp) && *cp != '\0';) { |
1758 | tp = word(cp); | | 1758 | tp = word(cp); |
1759 | if (!strcasecmp(cp, "removable")) | | 1759 | if (!strcasecmp(cp, "removable")) |
1760 | v |= D_REMOVABLE; | | 1760 | v |= D_REMOVABLE; |
1761 | else if (!strcasecmp(cp, "ecc")) | | 1761 | else if (!strcasecmp(cp, "ecc")) |
1762 | v |= D_ECC; | | 1762 | v |= D_ECC; |
1763 | else if (!strcasecmp(cp, "badsect")) | | 1763 | else if (!strcasecmp(cp, "badsect")) |
1764 | v |= D_BADSECT; | | 1764 | v |= D_BADSECT; |
1765 | else { | | 1765 | else { |
1766 | warnx("line %d: bad flag: %s", | | 1766 | warnx("line %d: bad flag: %s", |
1767 | lineno, cp); | | 1767 | lineno, cp); |
1768 | errors++; | | 1768 | errors++; |
1769 | } | | 1769 | } |
1770 | } | | 1770 | } |
1771 | lp->d_flags = v; | | 1771 | lp->d_flags = v; |
1772 | continue; | | 1772 | continue; |
1773 | } | | 1773 | } |
1774 | if (!strcmp(cp, "drivedata")) { | | 1774 | if (!strcmp(cp, "drivedata")) { |
1775 | int i; | | 1775 | int i; |
1776 | | | 1776 | |
1777 | for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { | | 1777 | for (i = 0; (cp = tp) && *cp != '\0' && i < NDDATA;) { |
1778 | if (GETNUM32(cp, &v) != 0) { | | 1778 | if (GETNUM32(cp, &v) != 0) { |
1779 | warnx("line %d: bad drive data", | | 1779 | warnx("line %d: bad drive data", |
1780 | lineno); | | 1780 | lineno); |
1781 | errors++; | | 1781 | errors++; |
1782 | } else | | 1782 | } else |
1783 | lp->d_drivedata[i] = v; | | 1783 | lp->d_drivedata[i] = v; |
1784 | i++; | | 1784 | i++; |
1785 | tp = word(cp); | | 1785 | tp = word(cp); |
1786 | } | | 1786 | } |
1787 | continue; | | 1787 | continue; |
1788 | } | | 1788 | } |
1789 | if (sscanf(cp, "%lu partitions", &v) == 1) { | | 1789 | if (sscanf(cp, "%lu partitions", &v) == 1) { |
1790 | if (v == 0 || v > maxpartitions) { | | 1790 | if (v == 0 || v > maxpartitions) { |
1791 | warnx("line %d: bad # of partitions", lineno); | | 1791 | warnx("line %d: bad # of partitions", lineno); |
1792 | lp->d_npartitions = maxpartitions; | | 1792 | lp->d_npartitions = maxpartitions; |
1793 | errors++; | | 1793 | errors++; |
1794 | } else | | 1794 | } else |
1795 | lp->d_npartitions = v; | | 1795 | lp->d_npartitions = v; |
1796 | continue; | | 1796 | continue; |
1797 | } | | 1797 | } |
1798 | if (tp == NULL) { | | 1798 | if (tp == NULL) { |
1799 | tbuf[0] = '\0'; | | 1799 | tbuf[0] = '\0'; |
1800 | tp = tbuf; | | 1800 | tp = tbuf; |
1801 | } | | 1801 | } |
1802 | if (!strcmp(cp, "disk")) { | | 1802 | if (!strcmp(cp, "disk")) { |
1803 | strncpy(lp->d_typename, tp, sizeof(lp->d_typename)); | | 1803 | strncpy(lp->d_typename, tp, sizeof(lp->d_typename)); |
1804 | continue; | | 1804 | continue; |
1805 | } | | 1805 | } |
1806 | if (!strcmp(cp, "label")) { | | 1806 | if (!strcmp(cp, "label")) { |
1807 | strncpy(lp->d_packname, tp, sizeof(lp->d_packname)); | | 1807 | strncpy(lp->d_packname, tp, sizeof(lp->d_packname)); |
1808 | continue; | | 1808 | continue; |
1809 | } | | 1809 | } |
1810 | if (!strcmp(cp, "bytes/sector")) { | | 1810 | if (!strcmp(cp, "bytes/sector")) { |
1811 | if (GETNUM32(tp, &v) != 0 || v <= 0 || (v % 512) != 0) { | | 1811 | if (GETNUM32(tp, &v) != 0 || v <= 0 || (v % 512) != 0) { |
1812 | warnx("line %d: bad %s: %s", lineno, cp, tp); | | 1812 | warnx("line %d: bad %s: %s", lineno, cp, tp); |
1813 | errors++; | | 1813 | errors++; |
1814 | } else | | 1814 | } else |
1815 | lp->d_secsize = v; | | 1815 | lp->d_secsize = v; |
1816 | continue; | | 1816 | continue; |
1817 | } | | 1817 | } |
1818 | if (!strcmp(cp, "sectors/track")) { | | 1818 | if (!strcmp(cp, "sectors/track")) { |
1819 | if (GETNUM32(tp, &v) != 0) { | | 1819 | if (GETNUM32(tp, &v) != 0) { |
1820 | warnx("line %d: bad %s: %s", lineno, cp, tp); | | 1820 | warnx("line %d: bad %s: %s", lineno, cp, tp); |
1821 | errors++; | | 1821 | errors++; |
1822 | } else | | 1822 | } else |
1823 | lp->d_nsectors = v; | | 1823 | lp->d_nsectors = v; |
1824 | continue; | | 1824 | continue; |
1825 | } | | 1825 | } |
1826 | if (!strcmp(cp, "sectors/cylinder")) { | | 1826 | if (!strcmp(cp, "sectors/cylinder")) { |
1827 | if (GETNUM32(tp, &v) != 0) { | | 1827 | if (GETNUM32(tp, &v) != 0) { |
1828 | warnx("line %d: bad %s: %s", lineno, cp, tp); | | 1828 | warnx("line %d: bad %s: %s", lineno, cp, tp); |
1829 | errors++; | | 1829 | errors++; |
1830 | } else | | 1830 | } else |
1831 | lp->d_secpercyl = v; | | 1831 | lp->d_secpercyl = v; |
1832 | continue; | | 1832 | continue; |
1833 | } | | 1833 | } |
1834 | if (!strcmp(cp, "tracks/cylinder")) { | | 1834 | if (!strcmp(cp, "tracks/cylinder")) { |
1835 | if (GETNUM32(tp, &v) != 0) { | | 1835 | if (GETNUM32(tp, &v) != 0) { |
1836 | warnx("line %d: bad %s: %s", lineno, cp, tp); | | 1836 | warnx("line %d: bad %s: %s", lineno, cp, tp); |
1837 | errors++; | | 1837 | errors++; |
1838 | } else | | 1838 | } else |
1839 | lp->d_ntracks = v; | | 1839 | lp->d_ntracks = v; |
1840 | continue; | | 1840 | continue; |
1841 | } | | 1841 | } |
1842 | if (!strcmp(cp, "cylinders")) { | | 1842 | if (!strcmp(cp, "cylinders")) { |
1843 | if (GETNUM32(tp, &v) != 0) { | | 1843 | if (GETNUM32(tp, &v) != 0) { |
1844 | warnx("line %d: bad %s: %s", lineno, cp, tp); | | 1844 | warnx("line %d: bad %s: %s", lineno, cp, tp); |
1845 | errors++; | | 1845 | errors++; |
1846 | } else | | 1846 | } else |
1847 | lp->d_ncylinders = v; | | 1847 | lp->d_ncylinders = v; |
1848 | continue; | | 1848 | continue; |
1849 | } | | 1849 | } |
1850 | if (!strcmp(cp, "total sectors") || | | 1850 | if (!strcmp(cp, "total sectors") || |
1851 | !strcmp(cp, "sectors/unit")) { | | 1851 | !strcmp(cp, "sectors/unit")) { |
1852 | if (GETNUM32(tp, &v) != 0) { | | 1852 | if (GETNUM32(tp, &v) != 0) { |
1853 | warnx("line %d: bad %s: %s", lineno, cp, tp); | | 1853 | warnx("line %d: bad %s: %s", lineno, cp, tp); |
1854 | errors++; | | 1854 | errors++; |
1855 | } else | | 1855 | } else |
1856 | lp->d_secperunit = v; | | 1856 | lp->d_secperunit = v; |
1857 | continue; | | 1857 | continue; |
1858 | } | | 1858 | } |
1859 | if (!strcmp(cp, "rpm")) { | | 1859 | if (!strcmp(cp, "rpm")) { |
1860 | if (GETNUM16(tp, &v) != 0) { | | 1860 | if (GETNUM16(tp, &v) != 0) { |
1861 | warnx("line %d: bad %s: %s", lineno, cp, tp); | | 1861 | warnx("line %d: bad %s: %s", lineno, cp, tp); |
1862 | errors++; | | 1862 | errors++; |
1863 | } else | | 1863 | } else |
1864 | lp->d_rpm = v; | | 1864 | lp->d_rpm = v; |
1865 | continue; | | 1865 | continue; |
1866 | } | | 1866 | } |
1867 | if (!strcmp(cp, "interleave")) { | | 1867 | if (!strcmp(cp, "interleave")) { |
1868 | if (GETNUM16(tp, &v) != 0) { | | 1868 | if (GETNUM16(tp, &v) != 0) { |
1869 | warnx("line %d: bad %s: %s", lineno, cp, tp); | | 1869 | warnx("line %d: bad %s: %s", lineno, cp, tp); |
1870 | errors++; | | 1870 | errors++; |
1871 | } else | | 1871 | } else |
1872 | lp->d_interleave = v; | | 1872 | lp->d_interleave = v; |
1873 | continue; | | 1873 | continue; |
1874 | } | | 1874 | } |
1875 | if (!strcmp(cp, "trackskew")) { | | 1875 | if (!strcmp(cp, "trackskew")) { |
1876 | if (GETNUM16(tp, &v) != 0) { | | 1876 | if (GETNUM16(tp, &v) != 0) { |
1877 | warnx("line %d: bad %s: %s", lineno, cp, tp); | | 1877 | warnx("line %d: bad %s: %s", lineno, cp, tp); |
1878 | errors++; | | 1878 | errors++; |
1879 | } else | | 1879 | } else |
1880 | lp->d_trackskew = v; | | 1880 | lp->d_trackskew = v; |
1881 | continue; | | 1881 | continue; |
1882 | } | | 1882 | } |
1883 | if (!strcmp(cp, "cylinderskew")) { | | 1883 | if (!strcmp(cp, "cylinderskew")) { |
1884 | if (GETNUM16(tp, &v) != 0) { | | 1884 | if (GETNUM16(tp, &v) != 0) { |
1885 | warnx("line %d: bad %s: %s", lineno, cp, tp); | | 1885 | warnx("line %d: bad %s: %s", lineno, cp, tp); |
1886 | errors++; | | 1886 | errors++; |
1887 | } else | | 1887 | } else |
1888 | lp->d_cylskew = v; | | 1888 | lp->d_cylskew = v; |
1889 | continue; | | 1889 | continue; |
1890 | } | | 1890 | } |
1891 | if (!strcmp(cp, "headswitch")) { | | 1891 | if (!strcmp(cp, "headswitch")) { |
1892 | if (GETNUM32(tp, &v) != 0) { | | 1892 | if (GETNUM32(tp, &v) != 0) { |
1893 | warnx("line %d: bad %s: %s", lineno, cp, tp); | | 1893 | warnx("line %d: bad %s: %s", lineno, cp, tp); |
1894 | errors++; | | 1894 | errors++; |
1895 | } else | | 1895 | } else |
1896 | lp->d_headswitch = v; | | 1896 | lp->d_headswitch = v; |
1897 | continue; | | 1897 | continue; |
1898 | } | | 1898 | } |
1899 | if (!strcmp(cp, "track-to-track seek")) { | | 1899 | if (!strcmp(cp, "track-to-track seek")) { |
1900 | if (GETNUM32(tp, &v) != 0) { | | 1900 | if (GETNUM32(tp, &v) != 0) { |
1901 | warnx("line %d: bad %s: %s", lineno, cp, tp); | | 1901 | warnx("line %d: bad %s: %s", lineno, cp, tp); |
1902 | errors++; | | 1902 | errors++; |
1903 | } else | | 1903 | } else |
1904 | lp->d_trkseek = v; | | 1904 | lp->d_trkseek = v; |
1905 | continue; | | 1905 | continue; |
1906 | } | | 1906 | } |
1907 | if ('a' > *cp || *cp > 'z' || cp[1] != '\0') { | | 1907 | if ('a' > *cp || *cp > 'z' || cp[1] != '\0') { |
1908 | warnx("line %d: unknown field: %s", lineno, cp); | | 1908 | warnx("line %d: unknown field: %s", lineno, cp); |
1909 | errors++; | | 1909 | errors++; |
1910 | continue; | | 1910 | continue; |
1911 | } | | 1911 | } |
1912 | | | 1912 | |
1913 | /* We have a partition entry */ | | 1913 | /* We have a partition entry */ |
1914 | part = *cp - 'a'; | | 1914 | part = *cp - 'a'; |
1915 | | | 1915 | |
1916 | if (part >= maxpartitions) { | | 1916 | if (part >= maxpartitions) { |
1917 | warnx("line %d: bad partition name: %s", lineno, cp); | | 1917 | warnx("line %d: bad partition name: %s", lineno, cp); |
1918 | errors++; | | 1918 | errors++; |
1919 | continue; | | 1919 | continue; |
1920 | } | | 1920 | } |
1921 | if (part >= __arraycount(lp->d_partitions)) { | | 1921 | if (part >= __arraycount(lp->d_partitions)) { |
1922 | warnx("line %d: partition id %s, >= %zu", lineno, | | 1922 | warnx("line %d: partition id %s, >= %zu", lineno, |
1923 | cp, __arraycount(lp->d_partitions)); | | 1923 | cp, __arraycount(lp->d_partitions)); |
1924 | errors++; | | 1924 | errors++; |
1925 | continue; | | 1925 | continue; |
1926 | } | | 1926 | } |
1927 | pp = &lp->d_partitions[part]; | | 1927 | pp = &lp->d_partitions[part]; |
1928 | | | 1928 | |
1929 | NXTXNUM(pp->p_size); | | 1929 | NXTXNUM(pp->p_size); |
1930 | NXTXNUM(pp->p_offset); | | 1930 | NXTXNUM(pp->p_offset); |
1931 | /* can't use word() here because of blanks in fstypenames[] */ | | 1931 | /* can't use word() here because of blanks in fstypenames[] */ |
1932 | tp += strspn(tp, " \t"); | | 1932 | tp += strspn(tp, " \t"); |
1933 | _CHECKLINE | | 1933 | _CHECKLINE |
1934 | cp = tp; | | 1934 | cp = tp; |
1935 | cpp = fstypenames; | | 1935 | cpp = fstypenames; |
1936 | for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) { | | 1936 | for (; cpp < &fstypenames[FSMAXTYPES]; cpp++) { |
1937 | s = *cpp; | | 1937 | s = *cpp; |
1938 | if (s == NULL || | | 1938 | if (s == NULL || |
1939 | (cp[strlen(s)] != ' ' && | | 1939 | (cp[strlen(s)] != ' ' && |
1940 | cp[strlen(s)] != '\t' && | | 1940 | cp[strlen(s)] != '\t' && |
1941 | cp[strlen(s)] != '\0')) | | 1941 | cp[strlen(s)] != '\0')) |
1942 | continue; | | 1942 | continue; |
1943 | if (!memcmp(s, cp, strlen(s))) { | | 1943 | if (!memcmp(s, cp, strlen(s))) { |
1944 | pp->p_fstype = cpp - fstypenames; | | 1944 | pp->p_fstype = cpp - fstypenames; |
1945 | tp += strlen(s); | | 1945 | tp += strlen(s); |
1946 | if (*tp == '\0') | | 1946 | if (*tp == '\0') |
1947 | tp = NULL; | | 1947 | tp = NULL; |
1948 | else { | | 1948 | else { |
1949 | tp += strspn(tp, " \t"); | | 1949 | tp += strspn(tp, " \t"); |
1950 | if (*tp == '\0') | | 1950 | if (*tp == '\0') |
1951 | tp = NULL; | | 1951 | tp = NULL; |
1952 | } | | 1952 | } |
1953 | goto gottype; | | 1953 | goto gottype; |
1954 | } | | 1954 | } |
1955 | } | | 1955 | } |
1956 | tp = word(cp); | | 1956 | tp = word(cp); |
1957 | if (isdigit(*cp & 0xff)) { | | 1957 | if (isdigit(*cp & 0xff)) { |
1958 | if (GETNUM8(cp, &v) != 0) { | | 1958 | if (GETNUM8(cp, &v) != 0) { |
1959 | warnx("line %d: syntax error", lineno); | | 1959 | warnx("line %d: syntax error", lineno); |
1960 | errors++; | | 1960 | errors++; |
1961 | } | | 1961 | } |
1962 | } else | | 1962 | } else |
1963 | v = FSMAXTYPES; | | 1963 | v = FSMAXTYPES; |
1964 | if ((unsigned)v >= FSMAXTYPES) { | | 1964 | if ((unsigned)v >= FSMAXTYPES) { |
1965 | warnx("line %d: warning, unknown file system type: %s", | | 1965 | warnx("line %d: warning, unknown file system type: %s", |
1966 | lineno, cp); | | 1966 | lineno, cp); |
1967 | warnx("tip: use -l to see all valid file system " | | 1967 | warnx("tip: use -l to see all valid file system " |
1968 | "types"); | | 1968 | "types"); |
1969 | v = FS_UNUSED; | | 1969 | v = FS_UNUSED; |
1970 | } | | 1970 | } |
1971 | pp->p_fstype = v; | | 1971 | pp->p_fstype = v; |
1972 | gottype: | | 1972 | gottype: |
1973 | switch (pp->p_fstype) { | | 1973 | switch (pp->p_fstype) { |
1974 | | | 1974 | |
1975 | case FS_UNUSED: /* XXX */ | | 1975 | case FS_UNUSED: /* XXX */ |
1976 | NXTNUM(pp->p_fsize); | | 1976 | NXTNUM(pp->p_fsize); |
1977 | if (pp->p_fsize == 0) | | 1977 | if (pp->p_fsize == 0) |
1978 | break; | | 1978 | break; |
1979 | NXTNUM(v); | | 1979 | NXTNUM(v); |
1980 | pp->p_frag = v / pp->p_fsize; | | 1980 | pp->p_frag = v / pp->p_fsize; |
1981 | break; | | 1981 | break; |
1982 | | | 1982 | |
1983 | case FS_BSDFFS: | | 1983 | case FS_BSDFFS: |
1984 | case FS_ADOS: | | 1984 | case FS_ADOS: |
1985 | case FS_APPLEUFS: | | 1985 | case FS_APPLEUFS: |
1986 | NXTNUM(pp->p_fsize); | | 1986 | NXTNUM(pp->p_fsize); |
1987 | if (pp->p_fsize == 0) | | 1987 | if (pp->p_fsize == 0) |
1988 | break; | | 1988 | break; |
1989 | NXTNUM(v); | | 1989 | NXTNUM(v); |
1990 | pp->p_frag = v / pp->p_fsize; | | 1990 | pp->p_frag = v / pp->p_fsize; |
1991 | NXTNUM(pp->p_cpg); | | 1991 | NXTNUM(pp->p_cpg); |
1992 | break; | | 1992 | break; |
1993 | case FS_BSDLFS: | | 1993 | case FS_BSDLFS: |
1994 | NXTNUM(pp->p_fsize); | | 1994 | NXTNUM(pp->p_fsize); |
1995 | if (pp->p_fsize == 0) | | 1995 | if (pp->p_fsize == 0) |
1996 | break; | | 1996 | break; |
1997 | NXTNUM(v); | | 1997 | NXTNUM(v); |
1998 | pp->p_frag = v / pp->p_fsize; | | 1998 | pp->p_frag = v / pp->p_fsize; |
1999 | NXTNUM(pp->p_sgs); | | 1999 | NXTNUM(pp->p_sgs); |
2000 | break; | | 2000 | break; |
2001 | case FS_EX2FS: | | 2001 | case FS_EX2FS: |
2002 | NXTNUM(pp->p_fsize); | | 2002 | NXTNUM(pp->p_fsize); |
2003 | if (pp->p_fsize == 0) | | 2003 | if (pp->p_fsize == 0) |
2004 | break; | | 2004 | break; |
2005 | NXTNUM(v); | | 2005 | NXTNUM(v); |
2006 | pp->p_frag = v / pp->p_fsize; | | 2006 | pp->p_frag = v / pp->p_fsize; |
2007 | break; | | 2007 | break; |
2008 | case FS_ISO9660: | | 2008 | case FS_ISO9660: |
2009 | NXTNUM(pp->p_cdsession); | | 2009 | NXTNUM(pp->p_cdsession); |
2010 | break; | | 2010 | break; |
2011 | default: | | 2011 | default: |
2012 | break; | | 2012 | break; |
2013 | } | | 2013 | } |
2014 | continue; | | 2014 | continue; |
2015 | error: | | 2015 | error: |
2016 | errors++; | | 2016 | errors++; |
2017 | next: | | 2017 | next: |
2018 | ; | | 2018 | ; |
2019 | } | | 2019 | } |
2020 | errors += checklabel(lp); | | 2020 | errors += checklabel(lp); |
2021 | return (errors == 0); | | 2021 | return (errors == 0); |
2022 | } | | 2022 | } |
2023 | | | 2023 | |
2024 | /* | | 2024 | /* |
2025 | * Check disklabel for errors and fill in | | 2025 | * Check disklabel for errors and fill in |
2026 | * derived fields according to supplied values. | | 2026 | * derived fields according to supplied values. |
2027 | */ | | 2027 | */ |
2028 | int | | 2028 | int |
2029 | checklabel(struct disklabel *lp) | | 2029 | checklabel(struct disklabel *lp) |
2030 | { | | 2030 | { |
2031 | struct partition *pp, *qp; | | 2031 | struct partition *pp, *qp; |
2032 | int i, j, errors; | | 2032 | int i, j, errors; |
2033 | char part; | | 2033 | char part; |
2034 | | | 2034 | |
2035 | errors = 0; | | 2035 | errors = 0; |
2036 | if (lp->d_secsize == 0) { | | 2036 | if (lp->d_secsize == 0) { |
2037 | warnx("sector size %" PRIu32, lp->d_secsize); | | 2037 | warnx("sector size %" PRIu32, lp->d_secsize); |
2038 | return (1); | | 2038 | return (1); |
2039 | } | | 2039 | } |
2040 | if (lp->d_nsectors == 0) { | | 2040 | if (lp->d_nsectors == 0) { |
2041 | warnx("sectors/track %" PRIu32, lp->d_nsectors); | | 2041 | warnx("sectors/track %" PRIu32, lp->d_nsectors); |
2042 | return (1); | | 2042 | return (1); |
2043 | } | | 2043 | } |
2044 | if (lp->d_ntracks == 0) { | | 2044 | if (lp->d_ntracks == 0) { |
2045 | warnx("tracks/cylinder %" PRIu32, lp->d_ntracks); | | 2045 | warnx("tracks/cylinder %" PRIu32, lp->d_ntracks); |
2046 | return (1); | | 2046 | return (1); |
2047 | } | | 2047 | } |
2048 | if (lp->d_ncylinders == 0) { | | 2048 | if (lp->d_ncylinders == 0) { |
2049 | warnx("cylinders/unit %" PRIu32, lp->d_ncylinders); | | 2049 | warnx("cylinders/unit %" PRIu32, lp->d_ncylinders); |
2050 | errors++; | | 2050 | errors++; |
2051 | } | | 2051 | } |
2052 | if (lp->d_rpm == 0) | | 2052 | if (lp->d_rpm == 0) |
2053 | warnx("warning, revolutions/minute %" PRIu16, lp->d_rpm); | | 2053 | warnx("warning, revolutions/minute %" PRIu16, lp->d_rpm); |
2054 | if (lp->d_secpercyl == 0) | | 2054 | if (lp->d_secpercyl == 0) |
2055 | lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; | | 2055 | lp->d_secpercyl = lp->d_nsectors * lp->d_ntracks; |
2056 | if (lp->d_secperunit == 0) | | 2056 | if (lp->d_secperunit == 0) |
2057 | lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; | | 2057 | lp->d_secperunit = lp->d_secpercyl * lp->d_ncylinders; |
2058 | if (lp->d_bbsize == 0) { | | 2058 | if (lp->d_bbsize == 0) { |
2059 | warnx("boot block size %" PRIu32, lp->d_bbsize); | | 2059 | warnx("boot block size %" PRIu32, lp->d_bbsize); |
2060 | errors++; | | 2060 | errors++; |
2061 | } else if (lp->d_bbsize % lp->d_secsize) | | 2061 | } else if (lp->d_bbsize % lp->d_secsize) |
2062 | warnx("warning, boot block size %% sector-size != 0"); | | 2062 | warnx("warning, boot block size %% sector-size != 0"); |
2063 | if (lp->d_sbsize == 0) { | | 2063 | if (lp->d_sbsize == 0) { |
2064 | warnx("super block size %" PRIu32, lp->d_sbsize); | | 2064 | warnx("super block size %" PRIu32, lp->d_sbsize); |
2065 | errors++; | | 2065 | errors++; |
2066 | } else if (lp->d_sbsize % lp->d_secsize) | | 2066 | } else if (lp->d_sbsize % lp->d_secsize) |
2067 | warnx("warning, super block size %% sector-size != 0"); | | 2067 | warnx("warning, super block size %% sector-size != 0"); |
2068 | if (lp->d_npartitions > maxpartitions) | | 2068 | if (lp->d_npartitions > maxpartitions) |
2069 | warnx("warning, number of partitions (%" PRIu16 ") > " | | 2069 | warnx("warning, number of partitions (%" PRIu16 ") > " |
2070 | "MAXPARTITIONS (%d)", | | 2070 | "MAXPARTITIONS (%d)", |
2071 | lp->d_npartitions, maxpartitions); | | 2071 | lp->d_npartitions, maxpartitions); |
2072 | else | | 2072 | else |
2073 | for (i = maxpartitions - 1; i >= lp->d_npartitions; i--) { | | 2073 | for (i = maxpartitions - 1; i >= lp->d_npartitions; i--) { |
2074 | part = 'a' + i; | | 2074 | part = 'a' + i; |
2075 | pp = &lp->d_partitions[i]; | | 2075 | pp = &lp->d_partitions[i]; |
2076 | if (pp->p_size || pp->p_offset) { | | 2076 | if (pp->p_size || pp->p_offset) { |
2077 | warnx("warning, partition %c increased " | | 2077 | warnx("warning, partition %c increased " |
2078 | "number of partitions from %" PRIu16 | | 2078 | "number of partitions from %" PRIu16 |
2079 | " to %d", | | 2079 | " to %d", |
2080 | part, lp->d_npartitions, i + 1); | | 2080 | part, lp->d_npartitions, i + 1); |
2081 | lp->d_npartitions = i + 1; | | 2081 | lp->d_npartitions = i + 1; |
2082 | break; | | 2082 | break; |
2083 | } | | 2083 | } |
2084 | } | | 2084 | } |
2085 | for (i = 0; i < lp->d_npartitions; i++) { | | 2085 | for (i = 0; i < lp->d_npartitions; i++) { |
2086 | part = 'a' + i; | | 2086 | part = 'a' + i; |
2087 | pp = &lp->d_partitions[i]; | | 2087 | pp = &lp->d_partitions[i]; |
2088 | if (pp->p_size == 0 && pp->p_offset != 0) | | 2088 | if (pp->p_size == 0 && pp->p_offset != 0) |
2089 | warnx("warning, partition %c: size 0, but " | | 2089 | warnx("warning, partition %c: size 0, but " |
2090 | "offset %" PRIu32, | | 2090 | "offset %" PRIu32, |
2091 | part, pp->p_offset); | | 2091 | part, pp->p_offset); |
2092 | #ifdef STRICT_CYLINDER_ALIGNMENT | | 2092 | #ifdef STRICT_CYLINDER_ALIGNMENT |
2093 | if (pp->p_offset % lp->d_secpercyl) { | | 2093 | if (pp->p_offset % lp->d_secpercyl) { |
2094 | warnx("warning, partition %c:" | | 2094 | warnx("warning, partition %c:" |
2095 | " not starting on cylinder boundary", | | 2095 | " not starting on cylinder boundary", |
2096 | part); | | 2096 | part); |
2097 | errors++; | | 2097 | errors++; |
2098 | } | | 2098 | } |
2099 | #endif /* STRICT_CYLINDER_ALIGNMENT */ | | 2099 | #endif /* STRICT_CYLINDER_ALIGNMENT */ |
2100 | if (pp->p_offset > lp->d_secperunit) { | | 2100 | if (pp->p_offset > lp->d_secperunit) { |
2101 | warnx("partition %c: offset past end of unit", part); | | 2101 | warnx("partition %c: offset past end of unit", part); |
2102 | errors++; | | 2102 | errors++; |
2103 | } | | 2103 | } |
2104 | if (pp->p_offset + pp->p_size > lp->d_secperunit) { | | 2104 | if (pp->p_offset + pp->p_size > lp->d_secperunit) { |
2105 | warnx("partition %c: partition extends" | | 2105 | warnx("partition %c: partition extends" |
2106 | " past end of unit", | | 2106 | " past end of unit", |
2107 | part); | | 2107 | part); |
2108 | errors++; | | 2108 | errors++; |
2109 | } | | 2109 | } |
2110 | if (pp->p_fstype != FS_UNUSED) | | 2110 | if (pp->p_fstype != FS_UNUSED) |
2111 | for (j = i + 1; j < lp->d_npartitions; j++) { | | 2111 | for (j = i + 1; j < lp->d_npartitions; j++) { |
2112 | qp = &lp->d_partitions[j]; | | 2112 | qp = &lp->d_partitions[j]; |
2113 | if (qp->p_fstype == FS_UNUSED) | | 2113 | if (qp->p_fstype == FS_UNUSED) |
2114 | continue; | | 2114 | continue; |
2115 | if (pp->p_offset < qp->p_offset + qp->p_size && | | 2115 | if (pp->p_offset < qp->p_offset + qp->p_size && |
2116 | qp->p_offset < pp->p_offset + pp->p_size) | | 2116 | qp->p_offset < pp->p_offset + pp->p_size) |
2117 | warnx("partitions %c and %c overlap", | | 2117 | warnx("partitions %c and %c overlap", |
2118 | part, 'a' + j); | | 2118 | part, 'a' + j); |
2119 | } | | 2119 | } |
2120 | } | | 2120 | } |
2121 | return (errors); | | 2121 | return (errors); |
2122 | } | | 2122 | } |
2123 | | | 2123 | |
2124 | static void | | 2124 | static void |
2125 | usage(void) | | 2125 | usage(void) |
2126 | { | | 2126 | { |
2127 | static const struct { | | 2127 | static const struct { |
2128 | const char *name; | | 2128 | const char *name; |
2129 | const char *expn; | | 2129 | const char *expn; |
2130 | } usages[] = { | | 2130 | } usages[] = { |
2131 | { "[-ABCFMrtv] disk", "(to read label)" }, | | 2131 | { "[-ABCFMrtv] disk", "(to read label)" }, |
2132 | { "-w [-BDFMrv] [-f disktab] disk disktype [packid]", "(to write label)" }, | | 2132 | { "-w [-BDFMrv] [-f disktab] disk disktype [packid]", "(to write label)" }, |
2133 | { "-e [-BCDFMIrv] disk", "(to edit label)" }, | | 2133 | { "-e [-BCDFMIrv] disk", "(to edit label)" }, |
2134 | #if !defined(NO_INTERACT) | | 2134 | #if !defined(NO_INTERACT) |
2135 | { "-i [-BDFMIrv] disk", "(to create a label interactively)" }, | | 2135 | { "-i [-BDFMIrv] disk", "(to create a label interactively)" }, |
2136 | #endif | | 2136 | #endif |
2137 | { "-D [-v] disk", "(to delete existing label(s))" }, | | 2137 | { "-D [-v] disk", "(to delete existing label(s))" }, |
2138 | { "-R [-BDFMrv] disk protofile", "(to restore label)" }, | | 2138 | { "-R [-BDFMrv] disk protofile", "(to restore label)" }, |
2139 | { "[-NW] disk", "(to write disable/enable label)" }, | | 2139 | { "[-NW] disk", "(to write disable/enable label)" }, |
2140 | { "-l", "(to show all known file system types)" }, | | 2140 | { "-l", "(to show all known file system types)" }, |
2141 | { NULL, NULL } | | 2141 | { NULL, NULL } |
2142 | }; | | 2142 | }; |
2143 | int i; | | 2143 | int i; |
2144 | const char *pn = getprogname(); | | 2144 | const char *pn = getprogname(); |
2145 | const char *t = "usage:"; | | 2145 | const char *t = "usage:"; |
2146 | | | 2146 | |
2147 | for (i = 0; usages[i].name != NULL; i++) { | | 2147 | for (i = 0; usages[i].name != NULL; i++) { |
2148 | (void)fprintf(stderr, "%s %s %s\n\t%s\n", | | 2148 | (void)fprintf(stderr, "%s %s %s\n\t%s\n", |
2149 | t, pn, usages[i].name, usages[i].expn); | | 2149 | t, pn, usages[i].name, usages[i].expn); |
2150 | t = "or"; | | 2150 | t = "or"; |
2151 | } | | 2151 | } |
2152 | exit(1); | | 2152 | exit(1); |
2153 | } | | 2153 | } |
2154 | | | 2154 | |
2155 | static int | | 2155 | static int |
2156 | getulong(const char *str, char sep, char **epp, unsigned long *ul, | | 2156 | getulong(const char *str, char sep, char **epp, unsigned long *ul, |
2157 | unsigned long max) | | 2157 | unsigned long max) |
2158 | { | | 2158 | { |
2159 | char *ep; | | 2159 | char *ep; |
2160 | | | 2160 | |
2161 | if (epp == NULL) | | 2161 | if (epp == NULL) |
2162 | epp = &ep; | | 2162 | epp = &ep; |
2163 | | | 2163 | |
2164 | *ul = strtoul(str, epp, 10); | | 2164 | *ul = strtoul(str, epp, 10); |
2165 | | | 2165 | |
2166 | if ((*ul == ULONG_MAX && errno == ERANGE) || *ul > max) | | 2166 | if ((*ul == ULONG_MAX && errno == ERANGE) || *ul > max) |
2167 | return ERANGE; | | 2167 | return ERANGE; |
2168 | | | 2168 | |
2169 | if (*str == '\0' || (**epp != '\0' && **epp != sep && | | 2169 | if (*str == '\0' || (**epp != '\0' && **epp != sep && |
2170 | !isspace((unsigned char)**epp))) | | 2170 | !isspace((unsigned char)**epp))) |
2171 | return EFTYPE; | | 2171 | return EFTYPE; |
2172 | | | 2172 | |
2173 | return 0; | | 2173 | return 0; |
2174 | } | | 2174 | } |
2175 | | | 2175 | |
2176 | /* | | 2176 | /* |
2177 | * This is a wrapper over the standard strcmp function to be used with | | 2177 | * This is a wrapper over the standard strcmp function to be used with |
2178 | * qsort on an array of pointers to strings. | | 2178 | * qsort on an array of pointers to strings. |
2179 | */ | | 2179 | */ |
2180 | static int | | 2180 | static int |
2181 | qsort_strcmp(const void *v1, const void *v2) | | 2181 | qsort_strcmp(const void *v1, const void *v2) |
2182 | { | | 2182 | { |
2183 | const char *const *sp1 = (const char *const *)v1; | | 2183 | const char *const *sp1 = (const char *const *)v1; |
2184 | const char *const *sp2 = (const char *const *)v2; | | 2184 | const char *const *sp2 = (const char *const *)v2; |
2185 | | | 2185 | |
2186 | return strcmp(*sp1, *sp2); | | 2186 | return strcmp(*sp1, *sp2); |
2187 | } | | 2187 | } |
2188 | | | 2188 | |
2189 | /* | | 2189 | /* |
2190 | * Prints all know file system types for a partition. | | 2190 | * Prints all know file system types for a partition. |
2191 | * Returns 1 on success, 0 on failure. | | 2191 | * Returns 1 on success, 0 on failure. |
2192 | */ | | 2192 | */ |
2193 | int | | 2193 | int |
2194 | list_fs_types(void) | | 2194 | list_fs_types(void) |
2195 | { | | 2195 | { |
2196 | int ret; | | 2196 | int ret; |
2197 | size_t nelems; | | 2197 | size_t nelems; |
2198 | | | 2198 | |
2199 | nelems = 0; | | 2199 | nelems = 0; |
2200 | { | | 2200 | { |
2201 | const char *const *namep; | | 2201 | const char *const *namep; |
2202 | | | 2202 | |
2203 | namep = fstypenames; | | 2203 | namep = fstypenames; |
2204 | while (*namep++ != NULL) | | 2204 | while (*namep++ != NULL) |
2205 | nelems++; | | 2205 | nelems++; |
2206 | } | | 2206 | } |
2207 | | | 2207 | |
2208 | ret = 1; | | 2208 | ret = 1; |
2209 | if (nelems > 0) { | | 2209 | if (nelems > 0) { |
2210 | const char **list; | | 2210 | const char **list; |
2211 | size_t i; | | 2211 | size_t i; |
2212 | | | 2212 | |
2213 | list = (const char **)malloc(sizeof(char *) * nelems); | | 2213 | list = (const char **)malloc(sizeof(char *) * nelems); |
2214 | if (list == NULL) { | | 2214 | if (list == NULL) { |
2215 | warnx("sorry, could not allocate memory for list"); | | 2215 | warnx("sorry, could not allocate memory for list"); |
2216 | ret = 0; | | 2216 | ret = 0; |
2217 | } else { | | 2217 | } else { |
2218 | for (i = 0; i < nelems; i++) | | 2218 | for (i = 0; i < nelems; i++) |
2219 | list[i] = fstypenames[i]; | | 2219 | list[i] = fstypenames[i]; |
2220 | | | 2220 | |
2221 | qsort(list, nelems, sizeof(char *), qsort_strcmp); | | 2221 | qsort(list, nelems, sizeof(char *), qsort_strcmp); |
2222 | | | 2222 | |
2223 | for (i = 0; i < nelems; i++) | | 2223 | for (i = 0; i < nelems; i++) |
2224 | (void)printf("%s\n", list[i]); | | 2224 | (void)printf("%s\n", list[i]); |
2225 | | | 2225 | |
2226 | free(list); | | 2226 | free(list); |
2227 | } | | 2227 | } |
2228 | } | | 2228 | } |
2229 | | | 2229 | |
2230 | return ret; | | 2230 | return ret; |
2231 | } | | 2231 | } |
2232 | | | 2232 | |
2233 | #ifndef HAVE_NBTOOL_CONFIG_H | | 2233 | #ifndef HAVE_NBTOOL_CONFIG_H |
2234 | int | | 2234 | int |
2235 | dk_ioctl(int f, u_long cmd, void *arg) | | 2235 | dk_ioctl(int f, u_long cmd, void *arg) |
2236 | { | | 2236 | { |
2237 | #if !defined(NATIVELABEL_ONLY) | | 2237 | #if !defined(NATIVELABEL_ONLY) |
2238 | if (!native_p) { | | 2238 | if (!native_p) { |
2239 | errno = ENOTTY; | | 2239 | errno = ENOTTY; |
2240 | return -1; | | 2240 | return -1; |
2241 | } | | 2241 | } |
2242 | #endif | | 2242 | #endif |