| @@ -1,1693 +1,1693 @@ | | | @@ -1,1693 +1,1693 @@ |
1 | /* $NetBSD: disks.c,v 1.15 2018/06/03 13:16:30 martin Exp $ */ | | 1 | /* $NetBSD: disks.c,v 1.16 2018/06/03 13:18:06 martin Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright 1997 Piermont Information Systems Inc. | | 4 | * Copyright 1997 Piermont Information Systems Inc. |
5 | * All rights reserved. | | 5 | * All rights reserved. |
6 | * | | 6 | * |
7 | * Written by Philip A. Nelson for Piermont Information Systems Inc. | | 7 | * Written by Philip A. Nelson for Piermont Information Systems Inc. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
15 | * notice, this list of conditions and the following disclaimer in the | | 15 | * notice, this list of conditions and the following disclaimer in the |
16 | * documentation and/or other materials provided with the distribution. | | 16 | * documentation and/or other materials provided with the distribution. |
17 | * 3. The name of Piermont Information Systems Inc. may not be used to endorse | | 17 | * 3. The name of Piermont Information Systems Inc. may not be used to endorse |
18 | * or promote products derived from this software without specific prior | | 18 | * or promote products derived from this software without specific prior |
19 | * written permission. | | 19 | * written permission. |
20 | * | | 20 | * |
21 | * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' | | 21 | * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' |
22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | | 22 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | | 23 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
24 | * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE | | 24 | * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE |
25 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | | 25 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | | 26 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | | 27 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | | 28 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | | 29 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF | | 30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
31 | * THE POSSIBILITY OF SUCH DAMAGE. | | 31 | * THE POSSIBILITY OF SUCH DAMAGE. |
32 | * | | 32 | * |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | /* disks.c -- routines to deal with finding disks and labeling disks. */ | | 35 | /* disks.c -- routines to deal with finding disks and labeling disks. */ |
36 | | | 36 | |
37 | | | 37 | |
38 | #include <errno.h> | | 38 | #include <errno.h> |
39 | #include <stdio.h> | | 39 | #include <stdio.h> |
40 | #include <stdlib.h> | | 40 | #include <stdlib.h> |
41 | #include <unistd.h> | | 41 | #include <unistd.h> |
42 | #include <fcntl.h> | | 42 | #include <fcntl.h> |
43 | #include <util.h> | | 43 | #include <util.h> |
44 | #include <uuid.h> | | 44 | #include <uuid.h> |
45 | | | 45 | |
46 | #include <sys/param.h> | | 46 | #include <sys/param.h> |
47 | #include <sys/sysctl.h> | | 47 | #include <sys/sysctl.h> |
48 | #include <sys/swap.h> | | 48 | #include <sys/swap.h> |
49 | #include <ufs/ufs/dinode.h> | | 49 | #include <ufs/ufs/dinode.h> |
50 | #include <ufs/ffs/fs.h> | | 50 | #include <ufs/ffs/fs.h> |
51 | #define FSTYPENAMES | | 51 | #define FSTYPENAMES |
52 | #include <sys/disklabel.h> | | 52 | #include <sys/disklabel.h> |
53 | #include <sys/disklabel_gpt.h> | | 53 | #include <sys/disklabel_gpt.h> |
54 | | | 54 | |
55 | #include <dev/scsipi/scsipi_all.h> | | 55 | #include <dev/scsipi/scsipi_all.h> |
56 | #include <sys/scsiio.h> | | 56 | #include <sys/scsiio.h> |
57 | | | 57 | |
58 | #include <dev/ata/atareg.h> | | 58 | #include <dev/ata/atareg.h> |
59 | #include <sys/ataio.h> | | 59 | #include <sys/ataio.h> |
60 | | | 60 | |
61 | #include "defs.h" | | 61 | #include "defs.h" |
62 | #include "md.h" | | 62 | #include "md.h" |
63 | #include "msg_defs.h" | | 63 | #include "msg_defs.h" |
64 | #include "menu_defs.h" | | 64 | #include "menu_defs.h" |
65 | #include "txtwalk.h" | | 65 | #include "txtwalk.h" |
66 | | | 66 | |
67 | /* Disk descriptions */ | | 67 | /* Disk descriptions */ |
68 | struct disk_desc { | | 68 | struct disk_desc { |
69 | char dd_name[SSTRSIZE]; | | 69 | char dd_name[SSTRSIZE]; |
70 | char dd_descr[70]; | | 70 | char dd_descr[70]; |
71 | bool dd_no_mbr, dd_no_part; | | 71 | bool dd_no_mbr, dd_no_part; |
72 | uint dd_cyl; | | 72 | uint dd_cyl; |
73 | uint dd_head; | | 73 | uint dd_head; |
74 | uint dd_sec; | | 74 | uint dd_sec; |
75 | uint dd_secsize; | | 75 | uint dd_secsize; |
76 | uint dd_totsec; | | 76 | uint dd_totsec; |
77 | }; | | 77 | }; |
78 | | | 78 | |
79 | /* gpt(8) use different filesystem names. | | 79 | /* gpt(8) use different filesystem names. |
80 | So, we cant use ./common/lib/libutil/getfstypename.c */ | | 80 | So, we cant use ./common/lib/libutil/getfstypename.c */ |
81 | struct gptfs_t { | | 81 | struct gptfs_t { |
82 | const char *name; | | 82 | const char *name; |
83 | int id; | | 83 | int id; |
84 | uuid_t uuid; | | 84 | uuid_t uuid; |
85 | }; | | 85 | }; |
86 | static const struct gptfs_t gpt_filesystems[] = { | | 86 | static const struct gptfs_t gpt_filesystems[] = { |
87 | { "swap", FS_SWAP, GPT_ENT_TYPE_NETBSD_SWAP, }, | | 87 | { "swap", FS_SWAP, GPT_ENT_TYPE_NETBSD_SWAP, }, |
88 | { "ffs", FS_BSDFFS, GPT_ENT_TYPE_NETBSD_FFS, }, | | 88 | { "ffs", FS_BSDFFS, GPT_ENT_TYPE_NETBSD_FFS, }, |
89 | { "lfs", FS_BSDLFS, GPT_ENT_TYPE_NETBSD_LFS, }, | | 89 | { "lfs", FS_BSDLFS, GPT_ENT_TYPE_NETBSD_LFS, }, |
90 | { "linux", FS_EX2FS, GPT_ENT_TYPE_LINUX_DATA, }, | | 90 | { "linux", FS_EX2FS, GPT_ENT_TYPE_LINUX_DATA, }, |
91 | { "windows,", FS_MSDOS, GPT_ENT_TYPE_MS_BASIC_DATA, }, | | 91 | { "windows,", FS_MSDOS, GPT_ENT_TYPE_MS_BASIC_DATA, }, |
92 | { "hfs", FS_HFS, GPT_ENT_TYPE_APPLE_HFS, }, | | 92 | { "hfs", FS_HFS, GPT_ENT_TYPE_APPLE_HFS, }, |
93 | { "ufs", FS_OTHER, GPT_ENT_TYPE_APPLE_UFS, }, | | 93 | { "ufs", FS_OTHER, GPT_ENT_TYPE_APPLE_UFS, }, |
94 | { "ccd", FS_CCD, GPT_ENT_TYPE_NETBSD_CCD, }, | | 94 | { "ccd", FS_CCD, GPT_ENT_TYPE_NETBSD_CCD, }, |
95 | { "raid", FS_RAID, GPT_ENT_TYPE_NETBSD_RAIDFRAME, }, | | 95 | { "raid", FS_RAID, GPT_ENT_TYPE_NETBSD_RAIDFRAME, }, |
96 | { "cgd", FS_CGD, GPT_ENT_TYPE_NETBSD_CGD, }, | | 96 | { "cgd", FS_CGD, GPT_ENT_TYPE_NETBSD_CGD, }, |
97 | { "efi", FS_OTHER, GPT_ENT_TYPE_EFI, }, | | 97 | { "efi", FS_OTHER, GPT_ENT_TYPE_EFI, }, |
98 | { "bios", FS_OTHER, GPT_ENT_TYPE_BIOS, }, | | 98 | { "bios", FS_OTHER, GPT_ENT_TYPE_BIOS, }, |
99 | { NULL, -1, GPT_ENT_TYPE_UNUSED, }, | | 99 | { NULL, -1, GPT_ENT_TYPE_UNUSED, }, |
100 | }; | | 100 | }; |
101 | | | 101 | |
102 | /* Local prototypes */ | | 102 | /* Local prototypes */ |
103 | static int foundffs(struct data *, size_t); | | 103 | static int foundffs(struct data *, size_t); |
104 | #ifdef USE_SYSVBFS | | 104 | #ifdef USE_SYSVBFS |
105 | static int foundsysvbfs(struct data *, size_t); | | 105 | static int foundsysvbfs(struct data *, size_t); |
106 | #endif | | 106 | #endif |
107 | static int fsck_preen(const char *, int, const char *, bool silent); | | 107 | static int fsck_preen(const char *, int, const char *, bool silent); |
108 | static void fixsb(const char *, const char *, char); | | 108 | static void fixsb(const char *, const char *, char); |
109 | static bool is_gpt(const char *); | | 109 | static bool is_gpt(const char *); |
110 | static int incoregpt(pm_devs_t *, partinfo *); | | 110 | static int incoregpt(pm_devs_t *, partinfo *); |
111 | | | 111 | |
112 | #ifndef DISK_NAMES | | 112 | #ifndef DISK_NAMES |
113 | #define DISK_NAMES "wd", "sd", "ld", "raid" | | 113 | #define DISK_NAMES "wd", "sd", "ld", "raid" |
114 | #endif | | 114 | #endif |
115 | | | 115 | |
116 | static const char *disk_names[] = { DISK_NAMES, | | 116 | static const char *disk_names[] = { DISK_NAMES, |
117 | "vnd", "cgd", "dk:no_part", NULL }; | | 117 | "vnd", "cgd", "dk:no_part", NULL }; |
118 | | | 118 | |
119 | static bool tmpfs_on_var_shm(void); | | 119 | static bool tmpfs_on_var_shm(void); |
120 | | | 120 | |
121 | const char * | | 121 | const char * |
122 | getfslabelname(uint8_t f) | | 122 | getfslabelname(uint8_t f) |
123 | { | | 123 | { |
124 | if (f >= __arraycount(fstypenames) || fstypenames[f] == NULL) | | 124 | if (f >= __arraycount(fstypenames) || fstypenames[f] == NULL) |
125 | return "invalid"; | | 125 | return "invalid"; |
126 | return fstypenames[f]; | | 126 | return fstypenames[f]; |
127 | } | | 127 | } |
128 | | | 128 | |
129 | /* | | 129 | /* |
130 | * Decide wether we want to mount a tmpfs on /var/shm: we do this always | | 130 | * Decide wether we want to mount a tmpfs on /var/shm: we do this always |
131 | * when the machine has more than 16 MB of user memory. On smaller machines, | | 131 | * when the machine has more than 16 MB of user memory. On smaller machines, |
132 | * shm_open() and friends will not perform well anyway. | | 132 | * shm_open() and friends will not perform well anyway. |
133 | */ | | 133 | */ |
134 | static bool | | 134 | static bool |
135 | tmpfs_on_var_shm() | | 135 | tmpfs_on_var_shm() |
136 | { | | 136 | { |
137 | uint64_t ram; | | 137 | uint64_t ram; |
138 | size_t len; | | 138 | size_t len; |
139 | | | 139 | |
140 | len = sizeof(ram); | | 140 | len = sizeof(ram); |
141 | if (sysctlbyname("hw.usermem64", &ram, &len, NULL, 0)) | | 141 | if (sysctlbyname("hw.usermem64", &ram, &len, NULL, 0)) |
142 | return false; | | 142 | return false; |
143 | | | 143 | |
144 | return ram > 16UL*1024UL*1024UL; | | 144 | return ram > 16UL*1024UL*1024UL; |
145 | } | | 145 | } |
146 | | | 146 | |
147 | /* from src/sbin/atactl/atactl.c | | 147 | /* from src/sbin/atactl/atactl.c |
148 | * extract_string: copy a block of bytes out of ataparams and make | | 148 | * extract_string: copy a block of bytes out of ataparams and make |
149 | * a proper string out of it, truncating trailing spaces and preserving | | 149 | * a proper string out of it, truncating trailing spaces and preserving |
150 | * strict typing. And also, not doing unaligned accesses. | | 150 | * strict typing. And also, not doing unaligned accesses. |
151 | */ | | 151 | */ |
152 | static void | | 152 | static void |
153 | ata_extract_string(char *buf, size_t bufmax, | | 153 | ata_extract_string(char *buf, size_t bufmax, |
154 | uint8_t *bytes, unsigned numbytes, | | 154 | uint8_t *bytes, unsigned numbytes, |
155 | int needswap) | | 155 | int needswap) |
156 | { | | 156 | { |
157 | unsigned i; | | 157 | unsigned i; |
158 | size_t j; | | 158 | size_t j; |
159 | unsigned char ch1, ch2; | | 159 | unsigned char ch1, ch2; |
160 | | | 160 | |
161 | for (i = 0, j = 0; i < numbytes; i += 2) { | | 161 | for (i = 0, j = 0; i < numbytes; i += 2) { |
162 | ch1 = bytes[i]; | | 162 | ch1 = bytes[i]; |
163 | ch2 = bytes[i+1]; | | 163 | ch2 = bytes[i+1]; |
164 | if (needswap && j < bufmax-1) { | | 164 | if (needswap && j < bufmax-1) { |
165 | buf[j++] = ch2; | | 165 | buf[j++] = ch2; |
166 | } | | 166 | } |
167 | if (j < bufmax-1) { | | 167 | if (j < bufmax-1) { |
168 | buf[j++] = ch1; | | 168 | buf[j++] = ch1; |
169 | } | | 169 | } |
170 | if (!needswap && j < bufmax-1) { | | 170 | if (!needswap && j < bufmax-1) { |
171 | buf[j++] = ch2; | | 171 | buf[j++] = ch2; |
172 | } | | 172 | } |
173 | } | | 173 | } |
174 | while (j > 0 && buf[j-1] == ' ') { | | 174 | while (j > 0 && buf[j-1] == ' ') { |
175 | j--; | | 175 | j--; |
176 | } | | 176 | } |
177 | buf[j] = '\0'; | | 177 | buf[j] = '\0'; |
178 | } | | 178 | } |
179 | | | 179 | |
180 | /* | | 180 | /* |
181 | * from src/sbin/scsictl/scsi_subr.c | | 181 | * from src/sbin/scsictl/scsi_subr.c |
182 | */ | | 182 | */ |
183 | #define STRVIS_ISWHITE(x) ((x) == ' ' || (x) == '\0' || (x) == (u_char)'\377') | | 183 | #define STRVIS_ISWHITE(x) ((x) == ' ' || (x) == '\0' || (x) == (u_char)'\377') |
184 | | | 184 | |
185 | static void | | 185 | static void |
186 | scsi_strvis(char *sdst, size_t dlen, const char *ssrc, size_t slen) | | 186 | scsi_strvis(char *sdst, size_t dlen, const char *ssrc, size_t slen) |
187 | { | | 187 | { |
188 | u_char *dst = (u_char *)sdst; | | 188 | u_char *dst = (u_char *)sdst; |
189 | const u_char *src = (const u_char *)ssrc; | | 189 | const u_char *src = (const u_char *)ssrc; |
190 | | | 190 | |
191 | /* Trim leading and trailing blanks and NULs. */ | | 191 | /* Trim leading and trailing blanks and NULs. */ |
192 | while (slen > 0 && STRVIS_ISWHITE(src[0])) | | 192 | while (slen > 0 && STRVIS_ISWHITE(src[0])) |
193 | ++src, --slen; | | 193 | ++src, --slen; |
194 | while (slen > 0 && STRVIS_ISWHITE(src[slen - 1])) | | 194 | while (slen > 0 && STRVIS_ISWHITE(src[slen - 1])) |
195 | --slen; | | 195 | --slen; |
196 | | | 196 | |
197 | while (slen > 0) { | | 197 | while (slen > 0) { |
198 | if (*src < 0x20 || *src >= 0x80) { | | 198 | if (*src < 0x20 || *src >= 0x80) { |
199 | /* non-printable characters */ | | 199 | /* non-printable characters */ |
200 | dlen -= 4; | | 200 | dlen -= 4; |
201 | if (dlen < 1) | | 201 | if (dlen < 1) |
202 | break; | | 202 | break; |
203 | *dst++ = '\\'; | | 203 | *dst++ = '\\'; |
204 | *dst++ = ((*src & 0300) >> 6) + '0'; | | 204 | *dst++ = ((*src & 0300) >> 6) + '0'; |
205 | *dst++ = ((*src & 0070) >> 3) + '0'; | | 205 | *dst++ = ((*src & 0070) >> 3) + '0'; |
206 | *dst++ = ((*src & 0007) >> 0) + '0'; | | 206 | *dst++ = ((*src & 0007) >> 0) + '0'; |
207 | } else if (*src == '\\') { | | 207 | } else if (*src == '\\') { |
208 | /* quote characters */ | | 208 | /* quote characters */ |
209 | dlen -= 2; | | 209 | dlen -= 2; |
210 | if (dlen < 1) | | 210 | if (dlen < 1) |
211 | break; | | 211 | break; |
212 | *dst++ = '\\'; | | 212 | *dst++ = '\\'; |
213 | *dst++ = '\\'; | | 213 | *dst++ = '\\'; |
214 | } else { | | 214 | } else { |
215 | /* normal characters */ | | 215 | /* normal characters */ |
216 | if (--dlen < 1) | | 216 | if (--dlen < 1) |
217 | break; | | 217 | break; |
218 | *dst++ = *src; | | 218 | *dst++ = *src; |
219 | } | | 219 | } |
220 | ++src, --slen; | | 220 | ++src, --slen; |
221 | } | | 221 | } |
222 | | | 222 | |
223 | *dst++ = 0; | | 223 | *dst++ = 0; |
224 | } | | 224 | } |
225 | | | 225 | |
226 | | | 226 | |
227 | static int | | 227 | static int |
228 | get_descr_scsi(struct disk_desc *dd, int fd) | | 228 | get_descr_scsi(struct disk_desc *dd, int fd) |
229 | { | | 229 | { |
230 | struct scsipi_inquiry_data inqbuf; | | 230 | struct scsipi_inquiry_data inqbuf; |
231 | struct scsipi_inquiry cmd; | | 231 | struct scsipi_inquiry cmd; |
232 | scsireq_t req; | | 232 | scsireq_t req; |
233 | /* x4 in case every character is escaped, +1 for NUL. */ | | 233 | /* x4 in case every character is escaped, +1 for NUL. */ |
234 | char vendor[(sizeof(inqbuf.vendor) * 4) + 1], | | 234 | char vendor[(sizeof(inqbuf.vendor) * 4) + 1], |
235 | product[(sizeof(inqbuf.product) * 4) + 1], | | 235 | product[(sizeof(inqbuf.product) * 4) + 1], |
236 | revision[(sizeof(inqbuf.revision) * 4) + 1]; | | 236 | revision[(sizeof(inqbuf.revision) * 4) + 1]; |
237 | char size[5]; | | 237 | char size[5]; |
238 | int error; | | 238 | int error; |
239 | | | 239 | |
240 | memset(&inqbuf, 0, sizeof(inqbuf)); | | 240 | memset(&inqbuf, 0, sizeof(inqbuf)); |
241 | memset(&cmd, 0, sizeof(cmd)); | | 241 | memset(&cmd, 0, sizeof(cmd)); |
242 | memset(&req, 0, sizeof(req)); | | 242 | memset(&req, 0, sizeof(req)); |
243 | | | 243 | |
244 | cmd.opcode = INQUIRY; | | 244 | cmd.opcode = INQUIRY; |
245 | cmd.length = sizeof(inqbuf); | | 245 | cmd.length = sizeof(inqbuf); |
246 | memcpy(req.cmd, &cmd, sizeof(cmd)); | | 246 | memcpy(req.cmd, &cmd, sizeof(cmd)); |
247 | req.cmdlen = sizeof(cmd); | | 247 | req.cmdlen = sizeof(cmd); |
248 | req.databuf = &inqbuf; | | 248 | req.databuf = &inqbuf; |
249 | req.datalen = sizeof(inqbuf); | | 249 | req.datalen = sizeof(inqbuf); |
250 | req.timeout = 10000; | | 250 | req.timeout = 10000; |
251 | req.flags = SCCMD_READ; | | 251 | req.flags = SCCMD_READ; |
252 | req.senselen = SENSEBUFLEN; | | 252 | req.senselen = SENSEBUFLEN; |
253 | | | 253 | |
254 | error = ioctl(fd, SCIOCCOMMAND, &req); | | 254 | error = ioctl(fd, SCIOCCOMMAND, &req); |
255 | if (error == -1 || req.retsts != SCCMD_OK) | | 255 | if (error == -1 || req.retsts != SCCMD_OK) |
256 | return 0; | | 256 | return 0; |
257 | | | 257 | |
258 | scsi_strvis(vendor, sizeof(vendor), inqbuf.vendor, | | 258 | scsi_strvis(vendor, sizeof(vendor), inqbuf.vendor, |
259 | sizeof(inqbuf.vendor)); | | 259 | sizeof(inqbuf.vendor)); |
260 | scsi_strvis(product, sizeof(product), inqbuf.product, | | 260 | scsi_strvis(product, sizeof(product), inqbuf.product, |
261 | sizeof(inqbuf.product)); | | 261 | sizeof(inqbuf.product)); |
262 | scsi_strvis(revision, sizeof(revision), inqbuf.revision, | | 262 | scsi_strvis(revision, sizeof(revision), inqbuf.revision, |
263 | sizeof(inqbuf.revision)); | | 263 | sizeof(inqbuf.revision)); |
264 | | | 264 | |
265 | humanize_number(size, sizeof(size), | | 265 | humanize_number(size, sizeof(size), |
266 | (uint64_t)dd->dd_secsize * (uint64_t)dd->dd_totsec, | | 266 | (uint64_t)dd->dd_secsize * (uint64_t)dd->dd_totsec, |
267 | "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); | | 267 | "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); |
268 | | | 268 | |
269 | snprintf(dd->dd_descr, sizeof(dd->dd_descr), | | 269 | snprintf(dd->dd_descr, sizeof(dd->dd_descr), |
270 | "%s (%s, %s %s)", | | 270 | "%s (%s, %s %s)", |
271 | dd->dd_name, size, vendor, product); | | 271 | dd->dd_name, size, vendor, product); |
272 | | | 272 | |
273 | return 1; | | 273 | return 1; |
274 | } | | 274 | } |
275 | | | 275 | |
276 | static int | | 276 | static int |
277 | get_descr_ata(struct disk_desc *dd, int fd) | | 277 | get_descr_ata(struct disk_desc *dd, int fd) |
278 | { | | 278 | { |
279 | struct atareq req; | | 279 | struct atareq req; |
280 | static union { | | 280 | static union { |
281 | unsigned char inbuf[DEV_BSIZE]; | | 281 | unsigned char inbuf[DEV_BSIZE]; |
282 | struct ataparams inqbuf; | | 282 | struct ataparams inqbuf; |
283 | } inbuf; | | 283 | } inbuf; |
284 | struct ataparams *inqbuf = &inbuf.inqbuf; | | 284 | struct ataparams *inqbuf = &inbuf.inqbuf; |
285 | char model[sizeof(inqbuf->atap_model)+1]; | | 285 | char model[sizeof(inqbuf->atap_model)+1]; |
286 | char size[5]; | | 286 | char size[5]; |
287 | int error, needswap = 0; | | 287 | int error, needswap = 0; |
288 | | | 288 | |
289 | memset(&inbuf, 0, sizeof(inbuf)); | | 289 | memset(&inbuf, 0, sizeof(inbuf)); |
290 | memset(&req, 0, sizeof(req)); | | 290 | memset(&req, 0, sizeof(req)); |
291 | | | 291 | |
292 | req.flags = ATACMD_READ; | | 292 | req.flags = ATACMD_READ; |
293 | req.command = WDCC_IDENTIFY; | | 293 | req.command = WDCC_IDENTIFY; |
294 | req.databuf = (void *)&inbuf; | | 294 | req.databuf = (void *)&inbuf; |
295 | req.datalen = sizeof(inbuf); | | 295 | req.datalen = sizeof(inbuf); |
296 | req.timeout = 1000; | | 296 | req.timeout = 1000; |
297 | | | 297 | |
298 | error = ioctl(fd, ATAIOCCOMMAND, &req); | | 298 | error = ioctl(fd, ATAIOCCOMMAND, &req); |
299 | if (error == -1 || req.retsts != ATACMD_OK) | | 299 | if (error == -1 || req.retsts != ATACMD_OK) |
300 | return 0; | | 300 | return 0; |
301 | | | 301 | |
302 | #if BYTE_ORDER == LITTLE_ENDIAN | | 302 | #if BYTE_ORDER == LITTLE_ENDIAN |
303 | /* | | 303 | /* |
304 | * On little endian machines, we need to shuffle the string | | 304 | * On little endian machines, we need to shuffle the string |
305 | * byte order. However, we don't have to do this for NEC or | | 305 | * byte order. However, we don't have to do this for NEC or |
306 | * Mitsumi ATAPI devices | | 306 | * Mitsumi ATAPI devices |
307 | */ | | 307 | */ |
308 | | | 308 | |
309 | if (!(inqbuf->atap_config != WDC_CFG_CFA_MAGIC && | | 309 | if (!(inqbuf->atap_config != WDC_CFG_CFA_MAGIC && |
310 | (inqbuf->atap_config & WDC_CFG_ATAPI) && | | 310 | (inqbuf->atap_config & WDC_CFG_ATAPI) && |
311 | ((inqbuf->atap_model[0] == 'N' && | | 311 | ((inqbuf->atap_model[0] == 'N' && |
312 | inqbuf->atap_model[1] == 'E') || | | 312 | inqbuf->atap_model[1] == 'E') || |
313 | (inqbuf->atap_model[0] == 'F' && | | 313 | (inqbuf->atap_model[0] == 'F' && |
314 | inqbuf->atap_model[1] == 'X')))) { | | 314 | inqbuf->atap_model[1] == 'X')))) { |
315 | needswap = 1; | | 315 | needswap = 1; |
316 | } | | 316 | } |
317 | #endif | | 317 | #endif |
318 | | | 318 | |
319 | ata_extract_string(model, sizeof(model), | | 319 | ata_extract_string(model, sizeof(model), |
320 | inqbuf->atap_model, sizeof(inqbuf->atap_model), needswap); | | 320 | inqbuf->atap_model, sizeof(inqbuf->atap_model), needswap); |
321 | humanize_number(size, sizeof(size), | | 321 | humanize_number(size, sizeof(size), |
322 | (uint64_t)dd->dd_secsize * (uint64_t)dd->dd_totsec, | | 322 | (uint64_t)dd->dd_secsize * (uint64_t)dd->dd_totsec, |
323 | "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); | | 323 | "", HN_AUTOSCALE, HN_B | HN_NOSPACE | HN_DECIMAL); |
324 | | | 324 | |
325 | snprintf(dd->dd_descr, sizeof(dd->dd_descr), "%s (%s, %s)", | | 325 | snprintf(dd->dd_descr, sizeof(dd->dd_descr), "%s (%s, %s)", |
326 | dd->dd_name, size, model); | | 326 | dd->dd_name, size, model); |
327 | | | 327 | |
328 | return 1; | | 328 | return 1; |
329 | } | | 329 | } |
330 | | | 330 | |
331 | static void | | 331 | static void |
332 | get_descr(struct disk_desc *dd) | | 332 | get_descr(struct disk_desc *dd) |
333 | { | | 333 | { |
334 | char diskpath[MAXPATHLEN]; | | 334 | char diskpath[MAXPATHLEN]; |
335 | int fd = -1; | | 335 | int fd = -1; |
336 | | | 336 | |
337 | fd = opendisk(dd->dd_name, O_RDONLY, diskpath, sizeof(diskpath), 0); | | 337 | fd = opendisk(dd->dd_name, O_RDONLY, diskpath, sizeof(diskpath), 0); |
338 | if (fd < 0) | | 338 | if (fd < 0) |
339 | goto done; | | 339 | goto done; |
340 | | | 340 | |
341 | dd->dd_descr[0] = '\0'; | | 341 | dd->dd_descr[0] = '\0'; |
342 | | | 342 | |
343 | /* try ATA */ | | 343 | /* try ATA */ |
344 | if (get_descr_ata(dd, fd)) | | 344 | if (get_descr_ata(dd, fd)) |
345 | goto done; | | 345 | goto done; |
346 | /* try SCSI */ | | 346 | /* try SCSI */ |
347 | if (get_descr_scsi(dd, fd)) | | 347 | if (get_descr_scsi(dd, fd)) |
348 | goto done; | | 348 | goto done; |
349 | /* XXX: get description from raid, cgd, vnd... */ | | 349 | /* XXX: get description from raid, cgd, vnd... */ |
350 | | | 350 | |
351 | done: | | 351 | done: |
352 | if (fd >= 0) | | 352 | if (fd >= 0) |
353 | close(fd); | | 353 | close(fd); |
354 | if (strlen(dd->dd_descr) == 0) | | 354 | if (strlen(dd->dd_descr) == 0) |
355 | strcpy(dd->dd_descr, dd->dd_name); | | 355 | strcpy(dd->dd_descr, dd->dd_name); |
356 | } | | 356 | } |
357 | | | 357 | |
358 | /* disknames - contains device names without partition letters | | 358 | /* disknames - contains device names without partition letters |
359 | * cdrom_devices - contains devices including partition letters | | 359 | * cdrom_devices - contains devices including partition letters |
360 | * returns the first entry in hw.disknames matching a cdrom_device, or | | 360 | * returns the first entry in hw.disknames matching a cdrom_device, or |
361 | * first entry on error or no match | | 361 | * first entry on error or no match |
362 | */ | | 362 | */ |
363 | const char * | | 363 | const char * |
364 | get_default_cdrom(void) | | 364 | get_default_cdrom(void) |
365 | { | | 365 | { |
366 | static const char *cdrom_devices[] = { CD_NAMES, 0}; | | 366 | static const char *cdrom_devices[] = { CD_NAMES, 0}; |
367 | static const char mib_name[] = "hw.disknames"; | | 367 | static const char mib_name[] = "hw.disknames"; |
368 | size_t len; | | 368 | size_t len; |
369 | char *disknames; | | 369 | char *disknames; |
370 | char *last; | | 370 | char *last; |
371 | char *name; | | 371 | char *name; |
372 | const char **arg; | | 372 | const char **arg; |
373 | const char *cd_dev; | | 373 | const char *cd_dev; |
374 | | | 374 | |
375 | /* On error just use first entry in cdrom_devices */ | | 375 | /* On error just use first entry in cdrom_devices */ |
376 | if (sysctlbyname(mib_name, NULL, &len, NULL, 0) == -1) | | 376 | if (sysctlbyname(mib_name, NULL, &len, NULL, 0) == -1) |
377 | return cdrom_devices[0]; | | 377 | return cdrom_devices[0]; |
378 | if ((disknames = malloc(len + 2)) == 0) /* skip on malloc fail */ | | 378 | if ((disknames = malloc(len + 2)) == 0) /* skip on malloc fail */ |
379 | return cdrom_devices[0]; | | 379 | return cdrom_devices[0]; |
380 | | | 380 | |
381 | (void)sysctlbyname(mib_name, disknames, &len, NULL, 0); | | 381 | (void)sysctlbyname(mib_name, disknames, &len, NULL, 0); |
382 | for ((name = strtok_r(disknames, " ", &last)); name; | | 382 | for ((name = strtok_r(disknames, " ", &last)); name; |
383 | (name = strtok_r(NULL, " ", &last))) { | | 383 | (name = strtok_r(NULL, " ", &last))) { |
384 | for (arg = cdrom_devices; *arg; ++arg) { | | 384 | for (arg = cdrom_devices; *arg; ++arg) { |
385 | cd_dev = *arg; | | 385 | cd_dev = *arg; |
386 | /* skip unit and partition */ | | 386 | /* skip unit and partition */ |
387 | if (strncmp(cd_dev, name, strlen(cd_dev) - 2) != 0) | | 387 | if (strncmp(cd_dev, name, strlen(cd_dev) - 2) != 0) |
388 | continue; | | 388 | continue; |
389 | if (name != disknames) | | 389 | if (name != disknames) |
390 | strcpy(disknames, name); | | 390 | strcpy(disknames, name); |
391 | strcat(disknames, "a"); | | 391 | strcat(disknames, "a"); |
392 | /* XXX: leaks, but so what? */ | | 392 | /* XXX: leaks, but so what? */ |
393 | return disknames; | | 393 | return disknames; |
394 | } | | 394 | } |
395 | } | | 395 | } |
396 | free(disknames); | | 396 | free(disknames); |
397 | return cdrom_devices[0]; | | 397 | return cdrom_devices[0]; |
398 | } | | 398 | } |
399 | | | 399 | |
400 | static void | | 400 | static void |
401 | get_wedge_descr(struct disk_desc *dd) | | 401 | get_wedge_descr(struct disk_desc *dd) |
402 | { | | 402 | { |
403 | struct dkwedge_info dkw; | | 403 | struct dkwedge_info dkw; |
404 | char buf[MAXPATHLEN]; | | 404 | char buf[MAXPATHLEN]; |
405 | int fd; | | 405 | int fd; |
406 | | | 406 | |
407 | fd = opendisk(dd->dd_name, O_RDONLY, buf, sizeof(buf), 0); | | 407 | fd = opendisk(dd->dd_name, O_RDONLY, buf, sizeof(buf), 0); |
408 | if (fd == -1) | | 408 | if (fd == -1) |
409 | return; | | 409 | return; |
410 | | | 410 | |
411 | if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == 0) { | | 411 | if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == 0) { |
412 | fprintf(stderr, "device %s\n", dd->dd_name); | | 412 | fprintf(stderr, "device %s\n", dd->dd_name); |
413 | sprintf(dd->dd_descr, "%s (%s@%s)", | | 413 | sprintf(dd->dd_descr, "%s (%s@%s)", |
414 | dkw.dkw_wname, dkw.dkw_devname, dkw.dkw_parent); | | 414 | dkw.dkw_wname, dkw.dkw_devname, dkw.dkw_parent); |
415 | } | | 415 | } |
416 | close(fd); | | 416 | close(fd); |
417 | } | | 417 | } |
418 | | | 418 | |
419 | static bool | | 419 | static bool |
420 | get_name_and_parent(const char *dev, char *name, char *parent) | | 420 | get_name_and_parent(const char *dev, char *name, char *parent) |
421 | { | | 421 | { |
422 | struct dkwedge_info dkw; | | 422 | struct dkwedge_info dkw; |
423 | char buf[MAXPATHLEN]; | | 423 | char buf[MAXPATHLEN]; |
424 | int fd; | | 424 | int fd; |
425 | bool res = false; | | 425 | bool res = false; |
426 | | | 426 | |
427 | fd = opendisk(dev, O_RDONLY, buf, sizeof(buf), 0); | | 427 | fd = opendisk(dev, O_RDONLY, buf, sizeof(buf), 0); |
428 | if (fd == -1) | | 428 | if (fd == -1) |
429 | return false; | | 429 | return false; |
430 | | | 430 | |
431 | if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == 0) { | | 431 | if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == 0) { |
432 | strcpy(name, (const char *)dkw.dkw_wname); | | 432 | strcpy(name, (const char *)dkw.dkw_wname); |
433 | strcpy(parent, dkw.dkw_parent); | | 433 | strcpy(parent, dkw.dkw_parent); |
434 | res = true; | | 434 | res = true; |
435 | } | | 435 | } |
436 | close(fd); | | 436 | close(fd); |
437 | return res; | | 437 | return res; |
438 | } | | 438 | } |
439 | | | 439 | |
440 | static bool | | 440 | static bool |
441 | find_swap_part_on(const char *dev, char *swap_name) | | 441 | find_swap_part_on(const char *dev, char *swap_name) |
442 | { | | 442 | { |
443 | struct dkwedge_info *dkw; | | 443 | struct dkwedge_info *dkw; |
444 | struct dkwedge_list dkwl; | | 444 | struct dkwedge_list dkwl; |
445 | char buf[MAXPATHLEN]; | | 445 | char buf[MAXPATHLEN]; |
446 | size_t bufsize; | | 446 | size_t bufsize; |
447 | int fd; | | 447 | int fd; |
448 | u_int i; | | 448 | u_int i; |
449 | bool res = false; | | 449 | bool res = false; |
450 | | | 450 | |
451 | dkw = NULL; | | 451 | dkw = NULL; |
452 | dkwl.dkwl_buf = dkw; | | 452 | dkwl.dkwl_buf = dkw; |
453 | dkwl.dkwl_bufsize = 0; | | 453 | dkwl.dkwl_bufsize = 0; |
454 | | | 454 | |
455 | fd = opendisk(dev, O_RDONLY, buf, sizeof(buf), 0); | | 455 | fd = opendisk(dev, O_RDONLY, buf, sizeof(buf), 0); |
456 | if (fd == -1) | | 456 | if (fd == -1) |
457 | return false; | | 457 | return false; |
458 | | | 458 | |
459 | for (;;) { | | 459 | for (;;) { |
460 | if (ioctl(fd, DIOCLWEDGES, &dkwl) == -1) { | | 460 | if (ioctl(fd, DIOCLWEDGES, &dkwl) == -1) { |
461 | dkwl.dkwl_ncopied = 0; | | 461 | dkwl.dkwl_ncopied = 0; |
462 | break; | | 462 | break; |
463 | } | | 463 | } |
464 | if (dkwl.dkwl_nwedges == dkwl.dkwl_ncopied) | | 464 | if (dkwl.dkwl_nwedges == dkwl.dkwl_ncopied) |
465 | break; | | 465 | break; |
466 | bufsize = dkwl.dkwl_nwedges * sizeof(*dkw); | | 466 | bufsize = dkwl.dkwl_nwedges * sizeof(*dkw); |
467 | if (dkwl.dkwl_bufsize < bufsize) { | | 467 | if (dkwl.dkwl_bufsize < bufsize) { |
468 | dkw = realloc(dkwl.dkwl_buf, bufsize); | | 468 | dkw = realloc(dkwl.dkwl_buf, bufsize); |
469 | if (dkw == NULL) | | 469 | if (dkw == NULL) |
470 | break; | | 470 | break; |
471 | dkwl.dkwl_buf = dkw; | | 471 | dkwl.dkwl_buf = dkw; |
472 | dkwl.dkwl_bufsize = bufsize; | | 472 | dkwl.dkwl_bufsize = bufsize; |
473 | } | | 473 | } |
474 | } | | 474 | } |
475 | | | 475 | |
476 | for (i = 0; i < dkwl.dkwl_nwedges; i++) { | | 476 | for (i = 0; i < dkwl.dkwl_nwedges; i++) { |
477 | res = strcmp(dkw[i].dkw_ptype, DKW_PTYPE_SWAP) == 0; | | 477 | res = strcmp(dkw[i].dkw_ptype, DKW_PTYPE_SWAP) == 0; |
478 | if (res) { | | 478 | if (res) { |
479 | strcpy(swap_name, (const char*)dkw[i].dkw_wname); | | 479 | strcpy(swap_name, (const char*)dkw[i].dkw_wname); |
480 | break; | | 480 | break; |
481 | } | | 481 | } |
482 | } | | 482 | } |
483 | | | 483 | |
484 | close(fd); | | 484 | close(fd); |
485 | | | 485 | |
486 | return res; | | 486 | return res; |
487 | } | | 487 | } |
488 | | | 488 | |
489 | static bool | | 489 | static bool |
490 | is_ffs_wedge(const char *dev) | | 490 | is_ffs_wedge(const char *dev) |
491 | { | | 491 | { |
492 | struct dkwedge_info dkw; | | 492 | struct dkwedge_info dkw; |
493 | char buf[MAXPATHLEN]; | | 493 | char buf[MAXPATHLEN]; |
494 | int fd; | | 494 | int fd; |
495 | bool res; | | 495 | bool res; |
496 | | | 496 | |
497 | fd = opendisk(dev, O_RDONLY, buf, sizeof(buf), 0); | | 497 | fd = opendisk(dev, O_RDONLY, buf, sizeof(buf), 0); |
498 | if (fd == -1) | | 498 | if (fd == -1) |
499 | return false; | | 499 | return false; |
500 | | | 500 | |
501 | if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == -1) | | 501 | if (ioctl(fd, DIOCGWEDGEINFO, &dkw) == -1) |
502 | return false; | | 502 | return false; |
503 | | | 503 | |
504 | res = strcmp(dkw.dkw_ptype, DKW_PTYPE_FFS) == 0; | | 504 | res = strcmp(dkw.dkw_ptype, DKW_PTYPE_FFS) == 0; |
505 | close(fd); | | 505 | close(fd); |
506 | | | 506 | |
507 | return res; | | 507 | return res; |
508 | } | | 508 | } |
509 | | | 509 | |
510 | static int | | 510 | static int |
511 | get_disks(struct disk_desc *dd, bool with_non_partitionable) | | 511 | get_disks(struct disk_desc *dd, bool with_non_partitionable) |
512 | { | | 512 | { |
513 | const char **xd; | | 513 | const char **xd; |
514 | char *cp; | | 514 | char *cp; |
515 | struct disklabel l; | | 515 | struct disklabel l; |
516 | int i; | | 516 | int i; |
517 | int numdisks; | | 517 | int numdisks; |
518 | | | 518 | |
519 | /* initialize */ | | 519 | /* initialize */ |
520 | numdisks = 0; | | 520 | numdisks = 0; |
521 | | | 521 | |
522 | for (xd = disk_names; *xd != NULL; xd++) { | | 522 | for (xd = disk_names; *xd != NULL; xd++) { |
523 | for (i = 0; i < MAX_DISKS; i++) { | | 523 | for (i = 0; i < MAX_DISKS; i++) { |
524 | strlcpy(dd->dd_name, *xd, sizeof dd->dd_name - 2); | | 524 | strlcpy(dd->dd_name, *xd, sizeof dd->dd_name - 2); |
525 | cp = strchr(dd->dd_name, ':'); | | 525 | cp = strchr(dd->dd_name, ':'); |
526 | if (cp != NULL) { | | 526 | if (cp != NULL) { |
527 | dd->dd_no_mbr = !strcmp(cp, ":no_mbr"); | | 527 | dd->dd_no_mbr = !strcmp(cp, ":no_mbr"); |
528 | dd->dd_no_part = !strcmp(cp, ":no_part"); | | 528 | dd->dd_no_part = !strcmp(cp, ":no_part"); |
529 | } else { | | 529 | } else { |
530 | dd->dd_no_mbr = false; | | 530 | dd->dd_no_mbr = false; |
531 | dd->dd_no_part = false; | | 531 | dd->dd_no_part = false; |
532 | cp = strchr(dd->dd_name, 0); | | 532 | cp = strchr(dd->dd_name, 0); |
533 | } | | 533 | } |
534 | if (dd->dd_no_part && !with_non_partitionable) | | 534 | if (dd->dd_no_part && !with_non_partitionable) |
535 | continue; | | 535 | continue; |
536 | | | 536 | |
537 | snprintf(cp, 2 + 1, "%d", i); | | 537 | snprintf(cp, 2 + 1, "%d", i); |
538 | if (!get_geom(dd->dd_name, &l)) { | | 538 | if (!get_geom(dd->dd_name, &l)) { |
539 | if (errno == ENOENT) | | 539 | if (errno == ENOENT) |
540 | break; | | 540 | break; |
541 | if (errno != ENOTTY || !dd->dd_no_part) | | 541 | if (errno != ENOTTY || !dd->dd_no_part) |
542 | /* | | 542 | /* |
543 | * Allow plain partitions, | | 543 | * Allow plain partitions, |
544 | * like already existing wedges | | 544 | * like already existing wedges |
545 | * (like dk0) if marked as | | 545 | * (like dk0) if marked as |
546 | * non-partitioning device. | | 546 | * non-partitioning device. |
547 | * For all other cases, continue | | 547 | * For all other cases, continue |
548 | * with the next disk. | | 548 | * with the next disk. |
549 | */ | | 549 | */ |
550 | continue; | | 550 | continue; |
551 | if (!is_ffs_wedge(dd->dd_name)) | | 551 | if (!is_ffs_wedge(dd->dd_name)) |
552 | continue; | | 552 | continue; |
553 | } | | 553 | } |
554 | | | 554 | |
555 | /* | | 555 | /* |
556 | * Exclude a disk mounted as root partition, | | 556 | * Exclude a disk mounted as root partition, |
557 | * in case of install-image on a USB memstick. | | 557 | * in case of install-image on a USB memstick. |
558 | */ | | 558 | */ |
559 | if (is_active_rootpart(dd->dd_name, 0)) | | 559 | if (is_active_rootpart(dd->dd_name, 0)) |
560 | continue; | | 560 | continue; |
561 | | | 561 | |
562 | if (!dd->dd_no_part) { | | 562 | if (!dd->dd_no_part) { |
563 | dd->dd_cyl = l.d_ncylinders; | | 563 | dd->dd_cyl = l.d_ncylinders; |
564 | dd->dd_head = l.d_ntracks; | | 564 | dd->dd_head = l.d_ntracks; |
565 | dd->dd_sec = l.d_nsectors; | | 565 | dd->dd_sec = l.d_nsectors; |
566 | dd->dd_secsize = l.d_secsize; | | 566 | dd->dd_secsize = l.d_secsize; |
567 | dd->dd_totsec = l.d_secperunit; | | 567 | dd->dd_totsec = l.d_secperunit; |
568 | } | | 568 | } |
569 | if (dd->dd_no_part) | | 569 | if (dd->dd_no_part) |
570 | get_wedge_descr(dd); | | 570 | get_wedge_descr(dd); |
571 | else | | 571 | else |
572 | get_descr(dd); | | 572 | get_descr(dd); |
573 | dd++; | | 573 | dd++; |
574 | numdisks++; | | 574 | numdisks++; |
575 | if (numdisks >= MAX_DISKS) | | 575 | if (numdisks >= MAX_DISKS) |
576 | return numdisks; | | 576 | return numdisks; |
577 | } | | 577 | } |
578 | } | | 578 | } |
579 | return numdisks; | | 579 | return numdisks; |
580 | } | | 580 | } |
581 | | | 581 | |
582 | int | | 582 | int |
583 | find_disks(const char *doingwhat) | | 583 | find_disks(const char *doingwhat) |
584 | { | | 584 | { |
585 | struct disk_desc disks[MAX_DISKS]; | | 585 | struct disk_desc disks[MAX_DISKS]; |
586 | menu_ent dsk_menu[nelem(disks) + 1]; // + 1 for extended partitioning entry | | 586 | menu_ent dsk_menu[nelem(disks) + 1]; // + 1 for extended partitioning entry |
587 | struct disk_desc *disk; | | 587 | struct disk_desc *disk; |
588 | int i = 0, skipped = 0; | | 588 | int i = 0, skipped = 0; |
589 | int already_found, numdisks, selected_disk = -1; | | 589 | int already_found, numdisks, selected_disk = -1; |
590 | int menu_no; | | 590 | int menu_no; |
591 | pm_devs_t *pm_i, *pm_last = NULL; | | 591 | pm_devs_t *pm_i, *pm_last = NULL; |
592 | | | 592 | |
593 | /* Find disks. */ | | 593 | /* Find disks. */ |
594 | numdisks = get_disks(disks, partman_go <= 0); | | 594 | numdisks = get_disks(disks, partman_go <= 0); |
595 | | | 595 | |
596 | /* need a redraw here, kernel messages hose everything */ | | 596 | /* need a redraw here, kernel messages hose everything */ |
597 | touchwin(stdscr); | | 597 | touchwin(stdscr); |
598 | refresh(); | | 598 | refresh(); |
599 | /* Kill typeahead, it won't be what the user had in mind */ | | 599 | /* Kill typeahead, it won't be what the user had in mind */ |
600 | fpurge(stdin); | | 600 | fpurge(stdin); |
601 | | | 601 | |
602 | /* | | 602 | /* |
603 | * partman_go: <0 - we want to see menu with extended partitioning | | 603 | * partman_go: <0 - we want to see menu with extended partitioning |
604 | * ==0 - we want to see simple select disk menu | | 604 | * ==0 - we want to see simple select disk menu |
605 | * >0 - we do not want to see any menus, just detect | | 605 | * >0 - we do not want to see any menus, just detect |
606 | * all disks | | 606 | * all disks |
607 | */ | | 607 | */ |
608 | if (partman_go <= 0) { | | 608 | if (partman_go <= 0) { |
609 | if (numdisks == 0) { | | 609 | if (numdisks == 0) { |
610 | /* No disks found! */ | | 610 | /* No disks found! */ |
611 | msg_display(MSG_nodisk); | | 611 | msg_display(MSG_nodisk); |
612 | process_menu(MENU_ok, NULL); | | 612 | process_menu(MENU_ok, NULL); |
613 | /*endwin();*/ | | 613 | /*endwin();*/ |
614 | return -1; | | 614 | return -1; |
615 | } else { | | 615 | } else { |
616 | /* One or more disks found! */ | | 616 | /* One or more disks found! */ |
617 | for (i = 0; i < numdisks; i++) { | | 617 | for (i = 0; i < numdisks; i++) { |
618 | dsk_menu[i].opt_name = | | 618 | dsk_menu[i].opt_name = |
619 | disks[i].dd_descr; | | 619 | disks[i].dd_descr; |
620 | dsk_menu[i].opt_menu = OPT_NOMENU; | | 620 | dsk_menu[i].opt_menu = OPT_NOMENU; |
621 | dsk_menu[i].opt_flags = OPT_EXIT; | | 621 | dsk_menu[i].opt_flags = OPT_EXIT; |
622 | dsk_menu[i].opt_action = set_menu_select; | | 622 | dsk_menu[i].opt_action = set_menu_select; |
623 | } | | 623 | } |
624 | if (partman_go < 0) { | | 624 | if (partman_go < 0) { |
625 | dsk_menu[i].opt_name = MSG_partman; | | 625 | dsk_menu[i].opt_name = MSG_partman; |
626 | dsk_menu[i].opt_menu = OPT_NOMENU; | | 626 | dsk_menu[i].opt_menu = OPT_NOMENU; |
627 | dsk_menu[i].opt_flags = OPT_EXIT; | | 627 | dsk_menu[i].opt_flags = OPT_EXIT; |
628 | dsk_menu[i].opt_action = set_menu_select; | | 628 | dsk_menu[i].opt_action = set_menu_select; |
629 | } | | 629 | } |
630 | menu_no = new_menu(MSG_Available_disks, | | 630 | menu_no = new_menu(MSG_Available_disks, |
631 | dsk_menu, numdisks | | 631 | dsk_menu, numdisks |
632 | + ((partman_go<0)?1:0), -1, | | 632 | + ((partman_go<0)?1:0), -1, |
633 | 4, 0, 0, MC_SCROLL, | | 633 | 4, 0, 0, MC_SCROLL, |
634 | NULL, NULL, NULL, NULL, NULL); | | 634 | NULL, NULL, NULL, NULL, NULL); |
635 | if (menu_no == -1) | | 635 | if (menu_no == -1) |
636 | return -1; | | 636 | return -1; |
637 | msg_display(MSG_ask_disk, doingwhat); | | 637 | msg_display(MSG_ask_disk, doingwhat); |
638 | process_menu(menu_no, &selected_disk); | | 638 | process_menu(menu_no, &selected_disk); |
639 | free_menu(menu_no); | | 639 | free_menu(menu_no); |
640 | } | | 640 | } |
641 | if (partman_go < 0 && selected_disk == numdisks) { | | 641 | if (partman_go < 0 && selected_disk == numdisks) { |
642 | partman_go = 1; | | 642 | partman_go = 1; |
643 | return -2; | | 643 | return -2; |
644 | } else | | 644 | } else |
645 | partman_go = 0; | | 645 | partman_go = 0; |
646 | if (selected_disk < 0 || selected_disk >= numdisks) | | 646 | if (selected_disk < 0 || selected_disk >= numdisks) |
647 | return -1; | | 647 | return -1; |
648 | } | | 648 | } |
649 | | | 649 | |
650 | /* Fill pm struct with device(s) info */ | | 650 | /* Fill pm struct with device(s) info */ |
651 | for (i = 0; i < numdisks; i++) { | | 651 | for (i = 0; i < numdisks; i++) { |
652 | if (! partman_go) | | 652 | if (! partman_go) |
653 | disk = disks + selected_disk; | | 653 | disk = disks + selected_disk; |
654 | else { | | 654 | else { |
655 | disk = disks + i; | | 655 | disk = disks + i; |
656 | already_found = 0; | | 656 | already_found = 0; |
657 | SLIST_FOREACH(pm_i, &pm_head, l) { | | 657 | SLIST_FOREACH(pm_i, &pm_head, l) { |
658 | pm_last = pm_i; | | 658 | pm_last = pm_i; |
659 | if (!already_found && | | 659 | if (!already_found && |
660 | strcmp(pm_i->diskdev, disk->dd_name) == 0) { | | 660 | strcmp(pm_i->diskdev, disk->dd_name) == 0) { |
661 | pm_i->found = 1; | | 661 | pm_i->found = 1; |
662 | break; | | 662 | break; |
663 | } | | 663 | } |
664 | } | | 664 | } |
665 | if (pm_i != NULL && pm_i->found) | | 665 | if (pm_i != NULL && pm_i->found) |
666 | /* We already added this device, skipping */ | | 666 | /* We already added this device, skipping */ |
667 | continue; | | 667 | continue; |
668 | } | | 668 | } |
669 | pm = pm_new; | | 669 | pm = pm_new; |
670 | pm->found = 1; | | 670 | pm->found = 1; |
671 | pm->bootable = 0; | | 671 | pm->bootable = 0; |
672 | pm->pi.menu_no = -1; | | 672 | pm->pi.menu_no = -1; |
673 | pm->disktype = "unknown"; | | 673 | pm->disktype = "unknown"; |
674 | pm->doessf = ""; | | 674 | pm->doessf = ""; |
675 | strlcpy(pm->diskdev, disk->dd_name, sizeof pm->diskdev); | | 675 | strlcpy(pm->diskdev, disk->dd_name, sizeof pm->diskdev); |
676 | strlcpy(pm->diskdev_descr, disk->dd_descr, sizeof pm->diskdev_descr); | | 676 | strlcpy(pm->diskdev_descr, disk->dd_descr, sizeof pm->diskdev_descr); |
677 | /* Use as a default disk if the user has the sets on a local disk */ | | 677 | /* Use as a default disk if the user has the sets on a local disk */ |
678 | strlcpy(localfs_dev, disk->dd_name, sizeof localfs_dev); | | 678 | strlcpy(localfs_dev, disk->dd_name, sizeof localfs_dev); |
679 | | | 679 | |
680 | pm->gpt = is_gpt(pm->diskdev); | | 680 | pm->gpt = is_gpt(pm->diskdev); |
681 | pm->no_mbr = disk->dd_no_mbr || pm->gpt; | | 681 | pm->no_mbr = disk->dd_no_mbr || pm->gpt; |
682 | pm->no_part = disk->dd_no_part; | | 682 | pm->no_part = disk->dd_no_part; |
683 | if (!pm->no_part) { | | 683 | if (!pm->no_part) { |
684 | pm->sectorsize = disk->dd_secsize; | | 684 | pm->sectorsize = disk->dd_secsize; |
685 | pm->dlcyl = disk->dd_cyl; | | 685 | pm->dlcyl = disk->dd_cyl; |
686 | pm->dlhead = disk->dd_head; | | 686 | pm->dlhead = disk->dd_head; |
687 | pm->dlsec = disk->dd_sec; | | 687 | pm->dlsec = disk->dd_sec; |
688 | pm->dlsize = disk->dd_totsec; | | 688 | pm->dlsize = disk->dd_totsec; |
689 | if (pm->dlsize == 0) | | 689 | if (pm->dlsize == 0) |
690 | pm->dlsize = disk->dd_cyl * disk->dd_head * disk->dd_sec; | | 690 | pm->dlsize = disk->dd_cyl * disk->dd_head * disk->dd_sec; |
691 | if (pm->dlsize > UINT32_MAX && ! partman_go) { | | 691 | if (pm->dlsize > UINT32_MAX && ! partman_go) { |
692 | if (logfp) | | 692 | if (logfp) |
693 | fprintf(logfp, "Cannot process disk %s: too big size (%d)\n", | | 693 | fprintf(logfp, "Cannot process disk %s: too big size (%d)\n", |
694 | pm->diskdev, (int)pm->dlsize); | | 694 | pm->diskdev, (int)pm->dlsize); |
695 | msg_display(MSG_toobigdisklabel); | | 695 | msg_display(MSG_toobigdisklabel); |
696 | process_menu(MENU_ok, NULL); | | 696 | process_menu(MENU_ok, NULL); |
697 | return -1; | | 697 | return -1; |
698 | } | | 698 | } |
699 | } else { | | 699 | } else { |
700 | pm->sectorsize = 0; | | 700 | pm->sectorsize = 0; |
701 | pm->dlcyl = 0; | | 701 | pm->dlcyl = 0; |
702 | pm->dlhead = 0; | | 702 | pm->dlhead = 0; |
703 | pm->dlsec = 0; | | 703 | pm->dlsec = 0; |
704 | pm->dlsize = 0; | | 704 | pm->dlsize = 0; |
705 | pm->rootpart = -1; | | 705 | pm->rootpart = -1; |
706 | pm->no_mbr = 1; | | 706 | pm->no_mbr = 1; |
707 | memset(&pm->bsdlabel, 0, sizeof(pm->bsdlabel)); | | 707 | memset(&pm->bsdlabel, 0, sizeof(pm->bsdlabel)); |
708 | } | | 708 | } |
709 | pm->dlcylsize = pm->dlhead * pm->dlsec; | | 709 | pm->dlcylsize = pm->dlhead * pm->dlsec; |
710 | | | 710 | |
711 | label_read(); | | 711 | label_read(); |
712 | if (partman_go) { | | 712 | if (partman_go) { |
713 | pm_getrefdev(pm_new); | | 713 | pm_getrefdev(pm_new); |
714 | if (SLIST_EMPTY(&pm_head) || pm_last == NULL) | | 714 | if (SLIST_EMPTY(&pm_head) || pm_last == NULL) |
715 | SLIST_INSERT_HEAD(&pm_head, pm_new, l); | | 715 | SLIST_INSERT_HEAD(&pm_head, pm_new, l); |
716 | else | | 716 | else |
717 | SLIST_INSERT_AFTER(pm_last, pm_new, l); | | 717 | SLIST_INSERT_AFTER(pm_last, pm_new, l); |
718 | pm_new = malloc(sizeof (pm_devs_t)); | | 718 | pm_new = malloc(sizeof (pm_devs_t)); |
719 | memset(pm_new, 0, sizeof *pm_new); | | 719 | memset(pm_new, 0, sizeof *pm_new); |
720 | } else | | 720 | } else |
721 | /* We is not in partman and do not want to process all devices, exit */ | | 721 | /* We is not in partman and do not want to process all devices, exit */ |
722 | break; | | 722 | break; |
723 | } | | 723 | } |
724 | | | 724 | |
725 | return numdisks-skipped; | | 725 | return numdisks-skipped; |
726 | } | | 726 | } |
727 | | | 727 | |
728 | | | 728 | |
729 | void | | 729 | void |
730 | label_read(void) | | 730 | label_read(void) |
731 | { | | 731 | { |
732 | | | 732 | |
733 | if (pm->no_part) | | 733 | if (pm->no_part) |
734 | return; | | 734 | return; |
735 | | | 735 | |
736 | check_available_binaries(); | | 736 | check_available_binaries(); |
737 | | | 737 | |
738 | /* Get existing/default label */ | | 738 | /* Get existing/default label */ |
739 | memset(&pm->oldlabel, 0, sizeof pm->oldlabel); | | 739 | memset(&pm->oldlabel, 0, sizeof pm->oldlabel); |
740 | if (!have_gpt || !pm->gpt) | | 740 | if (!have_gpt || !pm->gpt) |
741 | incorelabel(pm->diskdev, pm->oldlabel); | | 741 | incorelabel(pm->diskdev, pm->oldlabel); |
742 | else | | 742 | else |
743 | incoregpt(pm, pm->oldlabel); | | 743 | incoregpt(pm, pm->oldlabel); |
744 | /* Set 'target' label to current label in case we don't change it */ | | 744 | /* Set 'target' label to current label in case we don't change it */ |
745 | memcpy(&pm->bsdlabel, &pm->oldlabel, sizeof pm->bsdlabel); | | 745 | memcpy(&pm->bsdlabel, &pm->oldlabel, sizeof pm->bsdlabel); |
746 | #ifndef NO_DISKLABEL | | 746 | #ifndef NO_DISKLABEL |
747 | if (! pm->gpt) | | 747 | if (! pm->gpt) |
748 | savenewlabel(pm->oldlabel, getmaxpartitions()); | | 748 | savenewlabel(pm->oldlabel, getmaxpartitions()); |
749 | #endif | | 749 | #endif |
750 | } | | 750 | } |
751 | | | 751 | |
752 | void | | 752 | void |
753 | fmt_fspart(menudesc *m, int ptn, void *arg) | | 753 | fmt_fspart(menudesc *m, int ptn, void *arg) |
754 | { | | 754 | { |
755 | unsigned int poffset, psize, pend; | | 755 | unsigned int poffset, psize, pend; |
756 | const char *desc; | | 756 | const char *desc; |
757 | static const char *Yes; | | 757 | static const char *Yes; |
758 | partinfo *p = pm->bsdlabel + ptn; | | 758 | partinfo *p = pm->bsdlabel + ptn; |
759 | | | 759 | |
760 | if (Yes == NULL) | | 760 | if (Yes == NULL) |
761 | Yes = msg_string(MSG_Yes); | | 761 | Yes = msg_string(MSG_Yes); |
762 | | | 762 | |
763 | poffset = p->pi_offset / sizemult; | | 763 | poffset = p->pi_offset / sizemult; |
764 | psize = p->pi_size / sizemult; | | 764 | psize = p->pi_size / sizemult; |
765 | if (psize == 0) | | 765 | if (psize == 0) |
766 | pend = 0; | | 766 | pend = 0; |
767 | else | | 767 | else |
768 | pend = (p->pi_offset + p->pi_size) / sizemult - 1; | | 768 | pend = (p->pi_offset + p->pi_size) / sizemult - 1; |
769 | | | 769 | |
770 | if (p->pi_fstype == FS_BSDFFS) | | 770 | if (p->pi_fstype == FS_BSDFFS) |
771 | if (p->pi_flags & PIF_FFSv2) | | 771 | if (p->pi_flags & PIF_FFSv2) |
772 | desc = "FFSv2"; | | 772 | desc = "FFSv2"; |
773 | else | | 773 | else |
774 | desc = "FFSv1"; | | 774 | desc = "FFSv1"; |
775 | else | | 775 | else |
776 | desc = getfslabelname(p->pi_fstype); | | 776 | desc = getfslabelname(p->pi_fstype); |
777 | | | 777 | |
778 | #ifdef PART_BOOT | | 778 | #ifdef PART_BOOT |
779 | if (ptn == PART_BOOT) | | 779 | if (ptn == PART_BOOT) |
780 | desc = msg_string(MSG_Boot_partition_cant_change); | | 780 | desc = msg_string(MSG_Boot_partition_cant_change); |
781 | #endif | | 781 | #endif |
782 | if (ptn == getrawpartition()) | | 782 | if (ptn == getrawpartition()) |
783 | desc = msg_string(MSG_Whole_disk_cant_change); | | 783 | desc = msg_string(MSG_Whole_disk_cant_change); |
784 | else { | | 784 | else { |
785 | if (ptn == PART_C) | | 785 | if (ptn == PART_C) |
786 | desc = msg_string(MSG_NetBSD_partition_cant_change); | | 786 | desc = msg_string(MSG_NetBSD_partition_cant_change); |
787 | } | | 787 | } |
788 | | | 788 | |
789 | wprintw(m->mw, msg_string(MSG_fspart_row), | | 789 | wprintw(m->mw, msg_string(MSG_fspart_row), |
790 | poffset, pend, psize, desc, | | 790 | poffset, pend, psize, desc, |
791 | p->pi_flags & PIF_NEWFS ? Yes : "", | | 791 | p->pi_flags & PIF_NEWFS ? Yes : "", |
792 | p->pi_flags & PIF_MOUNT ? Yes : "", | | 792 | p->pi_flags & PIF_MOUNT ? Yes : "", |
793 | p->pi_mount); | | 793 | p->pi_mount); |
794 | } | | 794 | } |
795 | | | 795 | |
796 | /* | | 796 | /* |
797 | * Label a disk using an MD-specific string DISKLABEL_CMD for | | 797 | * Label a disk using an MD-specific string DISKLABEL_CMD for |
798 | * to invoke disklabel. | | 798 | * to invoke disklabel. |
799 | * if MD code does not define DISKLABEL_CMD, this is a no-op. | | 799 | * if MD code does not define DISKLABEL_CMD, this is a no-op. |
800 | * | | 800 | * |
801 | * i386 port uses "/sbin/disklabel -w -r", just like i386 | | 801 | * i386 port uses "/sbin/disklabel -w -r", just like i386 |
802 | * miniroot scripts, though this may leave a bogus incore label. | | 802 | * miniroot scripts, though this may leave a bogus incore label. |
803 | * | | 803 | * |
804 | * Sun ports should use DISKLABEL_CMD "/sbin/disklabel -w" | | 804 | * Sun ports should use DISKLABEL_CMD "/sbin/disklabel -w" |
805 | * to get incore to ondisk inode translation for the Sun proms. | | 805 | * to get incore to ondisk inode translation for the Sun proms. |
806 | */ | | 806 | */ |
807 | int | | 807 | int |
808 | write_disklabel (void) | | 808 | write_disklabel (void) |
809 | { | | 809 | { |
810 | int rv = 0; | | 810 | int rv = 0; |
811 | | | 811 | |
812 | if (pm && pm->no_part) | | 812 | if (pm && pm->no_part) |
813 | return 0; | | 813 | return 0; |
814 | | | 814 | |
815 | #ifdef DISKLABEL_CMD | | 815 | #ifdef DISKLABEL_CMD |
816 | /* disklabel the disk */ | | 816 | /* disklabel the disk */ |
817 | rv = run_program(RUN_DISPLAY, "%s -f /tmp/disktab %s '%s'", | | 817 | rv = run_program(RUN_DISPLAY, "%s -f /tmp/disktab %s '%s'", |
818 | DISKLABEL_CMD, pm->diskdev, pm->bsddiskname); | | 818 | DISKLABEL_CMD, pm->diskdev, pm->bsddiskname); |
819 | if (rv == 0) | | 819 | if (rv == 0) |
820 | update_wedges(pm->diskdev); | | 820 | update_wedges(pm->diskdev); |
821 | #endif | | 821 | #endif |
822 | return rv; | | 822 | return rv; |
823 | } | | 823 | } |
824 | | | 824 | |
825 | | | 825 | |
826 | static int | | 826 | static int |
827 | ptn_sort(const void *a, const void *b) | | 827 | ptn_sort(const void *a, const void *b) |
828 | { | | 828 | { |
829 | return strcmp(pm->bsdlabel[*(const int *)a].pi_mount, | | 829 | return strcmp(pm->bsdlabel[*(const int *)a].pi_mount, |
830 | pm->bsdlabel[*(const int *)b].pi_mount); | | 830 | pm->bsdlabel[*(const int *)b].pi_mount); |
831 | } | | 831 | } |
832 | | | 832 | |
833 | int | | 833 | int |
834 | make_filesystems(void) | | 834 | make_filesystems(void) |
835 | { | | 835 | { |
836 | unsigned int i; | | 836 | unsigned int i; |
837 | int ptn; | | 837 | int ptn; |
838 | int ptn_order[nelem(pm->bsdlabel)]; | | 838 | int ptn_order[nelem(pm->bsdlabel)]; |
839 | int error = 0; | | 839 | int error = 0; |
840 | unsigned int maxpart = getmaxpartitions(); | | 840 | unsigned int maxpart = getmaxpartitions(); |
841 | char *newfs = NULL, *dev = NULL, *devdev = NULL; | | 841 | char *newfs = NULL, *dev = NULL, *devdev = NULL; |
842 | partinfo *lbl; | | 842 | partinfo *lbl; |
843 | | | 843 | |
844 | if (pm->no_part) { | | 844 | if (pm->no_part) { |
845 | /* check if this target device already has a ffs */ | | 845 | /* check if this target device already has a ffs */ |
846 | error = fsck_preen(pm->diskdev, -1, "ffs", true); | | 846 | error = fsck_preen(pm->diskdev, -1, "ffs", true); |
847 | if (error) { | | 847 | if (error) { |
848 | if (!ask_noyes(MSG_No_filesystem_newfs)) | | 848 | if (!ask_noyes(MSG_No_filesystem_newfs)) |
849 | return EINVAL; | | 849 | return EINVAL; |
850 | error = run_program(RUN_DISPLAY | RUN_PROGRESS, | | 850 | error = run_program(RUN_DISPLAY | RUN_PROGRESS, |
851 | "/sbin/newfs -V2 -O2 /dev/r%s", pm->diskdev); | | 851 | "/sbin/newfs -V2 -O2 /dev/r%s", pm->diskdev); |
852 | } | | 852 | } |
853 | | | 853 | |
854 | md_pre_mount(); | | 854 | md_pre_mount(); |
855 | | | 855 | |
856 | make_target_dir("/"); | | 856 | make_target_dir("/"); |
857 | asprintf(&devdev, "/dev/%s", pm->diskdev); | | 857 | asprintf(&devdev, "/dev/%s", pm->diskdev); |
858 | if (devdev == NULL) | | 858 | if (devdev == NULL) |
859 | return (ENOMEM); | | 859 | return (ENOMEM); |
860 | error = target_mount_do("-o async", devdev, "/"); | | 860 | error = target_mount_do("-o async", devdev, "/"); |
861 | if (error) { | | 861 | if (error) { |
862 | msg_display(MSG_mountfail, devdev, ' ', | | 862 | msg_display(MSG_mountfail, devdev, ' ', |
863 | "/"); | | 863 | "/"); |
864 | process_menu(MENU_ok, NULL); | | 864 | process_menu(MENU_ok, NULL); |
865 | } | | 865 | } |
866 | free(devdev); | | 866 | free(devdev); |
867 | return error; | | 867 | return error; |
868 | } | | 868 | } |
869 | | | 869 | |
870 | if (maxpart > nelem(pm->bsdlabel)) | | 870 | if (maxpart > nelem(pm->bsdlabel)) |
871 | maxpart = nelem(pm->bsdlabel); | | 871 | maxpart = nelem(pm->bsdlabel); |
872 | | | 872 | |
873 | /* Making new file systems and mounting them */ | | 873 | /* Making new file systems and mounting them */ |
874 | | | 874 | |
875 | /* sort to ensure /usr/local is mounted after /usr (etc) */ | | 875 | /* sort to ensure /usr/local is mounted after /usr (etc) */ |
876 | for (i = 0; i < maxpart; i++) | | 876 | for (i = 0; i < maxpart; i++) |
877 | ptn_order[i] = i; | | 877 | ptn_order[i] = i; |
878 | qsort(ptn_order, maxpart, sizeof ptn_order[0], ptn_sort); | | 878 | qsort(ptn_order, maxpart, sizeof ptn_order[0], ptn_sort); |
879 | | | 879 | |
880 | for (i = 0; i < maxpart; i++) { | | 880 | for (i = 0; i < maxpart; i++) { |
881 | /* | | 881 | /* |
882 | * newfs and mount. For now, process only BSD filesystems. | | 882 | * newfs and mount. For now, process only BSD filesystems. |
883 | * but if this is the mounted-on root, has no mount | | 883 | * but if this is the mounted-on root, has no mount |
884 | * point defined, or is marked preserve, don't touch it! | | 884 | * point defined, or is marked preserve, don't touch it! |
885 | */ | | 885 | */ |
886 | ptn = ptn_order[i]; | | 886 | ptn = ptn_order[i]; |
887 | lbl = pm->bsdlabel + ptn; | | 887 | lbl = pm->bsdlabel + ptn; |
888 | | | 888 | |
889 | if (is_active_rootpart(pm->diskdev, ptn)) | | 889 | if (is_active_rootpart(pm->diskdev, ptn)) |
890 | continue; | | 890 | continue; |
891 | | | 891 | |
892 | if (*lbl->pi_mount == 0) | | 892 | if (*lbl->pi_mount == 0) |
893 | /* No mount point */ | | 893 | /* No mount point */ |
894 | continue; | | 894 | continue; |
895 | | | 895 | |
896 | if (pm->isspecial) { | | 896 | if (pm->isspecial) { |
897 | asprintf(&dev, "%s", pm->diskdev); | | 897 | asprintf(&dev, "%s", pm->diskdev); |
898 | ptn = 0 - 'a'; | | 898 | ptn = 0 - 'a'; |
899 | } else { | | 899 | } else { |
900 | asprintf(&dev, "%s%c", pm->diskdev, 'a' + ptn); | | 900 | asprintf(&dev, "%s%c", pm->diskdev, 'a' + ptn); |
901 | } | | 901 | } |
902 | if (dev == NULL) | | 902 | if (dev == NULL) |
903 | return (ENOMEM); | | 903 | return (ENOMEM); |
904 | asprintf(&devdev, "/dev/%s", dev); | | 904 | asprintf(&devdev, "/dev/%s", dev); |
905 | if (devdev == NULL) | | 905 | if (devdev == NULL) |
906 | return (ENOMEM); | | 906 | return (ENOMEM); |
907 | | | 907 | |
908 | newfs = NULL; | | 908 | newfs = NULL; |
909 | lbl->mnt_opts = NULL; | | 909 | lbl->mnt_opts = NULL; |
910 | lbl->fsname = NULL; | | 910 | lbl->fsname = NULL; |
911 | switch (lbl->pi_fstype) { | | 911 | switch (lbl->pi_fstype) { |
912 | case FS_APPLEUFS: | | 912 | case FS_APPLEUFS: |
913 | asprintf(&newfs, "/sbin/newfs %s%.0d", | | 913 | asprintf(&newfs, "/sbin/newfs %s%.0d", |
914 | lbl->pi_isize != 0 ? "-i" : "", lbl->pi_isize); | | 914 | lbl->pi_isize != 0 ? "-i" : "", lbl->pi_isize); |
915 | lbl->mnt_opts = "-tffs -o async"; | | 915 | lbl->mnt_opts = "-tffs -o async"; |
916 | lbl->fsname = "ffs"; | | 916 | lbl->fsname = "ffs"; |
917 | break; | | 917 | break; |
918 | case FS_BSDFFS: | | 918 | case FS_BSDFFS: |
919 | asprintf(&newfs, | | 919 | asprintf(&newfs, |
920 | "/sbin/newfs -V2 -O %d -b %d -f %d%s%.0d", | | 920 | "/sbin/newfs -V2 -O %d -b %d -f %d%s%.0d", |
921 | lbl->pi_flags & PIF_FFSv2 ? 2 : 1, | | 921 | lbl->pi_flags & PIF_FFSv2 ? 2 : 1, |
922 | lbl->pi_fsize * lbl->pi_frag, lbl->pi_fsize, | | 922 | lbl->pi_fsize * lbl->pi_frag, lbl->pi_fsize, |
923 | lbl->pi_isize != 0 ? " -i " : "", lbl->pi_isize); | | 923 | lbl->pi_isize != 0 ? " -i " : "", lbl->pi_isize); |
924 | if (lbl->pi_flags & PIF_LOG) | | 924 | if (lbl->pi_flags & PIF_LOG) |
925 | lbl->mnt_opts = "-tffs -o log"; | | 925 | lbl->mnt_opts = "-tffs -o log"; |
926 | else | | 926 | else |
927 | lbl->mnt_opts = "-tffs -o async"; | | 927 | lbl->mnt_opts = "-tffs -o async"; |
928 | lbl->fsname = "ffs"; | | 928 | lbl->fsname = "ffs"; |
929 | break; | | 929 | break; |
930 | case FS_BSDLFS: | | 930 | case FS_BSDLFS: |
931 | asprintf(&newfs, "/sbin/newfs_lfs -b %d", | | 931 | asprintf(&newfs, "/sbin/newfs_lfs -b %d", |
932 | lbl->pi_fsize * lbl->pi_frag); | | 932 | lbl->pi_fsize * lbl->pi_frag); |
933 | lbl->mnt_opts = "-tlfs"; | | 933 | lbl->mnt_opts = "-tlfs"; |
934 | lbl->fsname = "lfs"; | | 934 | lbl->fsname = "lfs"; |
935 | break; | | 935 | break; |
936 | case FS_MSDOS: | | 936 | case FS_MSDOS: |
937 | #ifdef USE_NEWFS_MSDOS | | 937 | #ifdef USE_NEWFS_MSDOS |
938 | asprintf(&newfs, "/sbin/newfs_msdos"); | | 938 | asprintf(&newfs, "/sbin/newfs_msdos"); |
939 | #endif | | 939 | #endif |
940 | lbl->mnt_opts = "-tmsdos"; | | 940 | lbl->mnt_opts = "-tmsdos"; |
941 | lbl->fsname = "msdos"; | | 941 | lbl->fsname = "msdos"; |
942 | break; | | 942 | break; |
943 | #ifdef USE_SYSVBFS | | 943 | #ifdef USE_SYSVBFS |
944 | case FS_SYSVBFS: | | 944 | case FS_SYSVBFS: |
945 | asprintf(&newfs, "/sbin/newfs_sysvbfs"); | | 945 | asprintf(&newfs, "/sbin/newfs_sysvbfs"); |
946 | lbl->mnt_opts = "-tsysvbfs"; | | 946 | lbl->mnt_opts = "-tsysvbfs"; |
947 | lbl->fsname = "sysvbfs"; | | 947 | lbl->fsname = "sysvbfs"; |
948 | break; | | 948 | break; |
949 | #endif | | 949 | #endif |
950 | #ifdef USE_EXT2FS | | 950 | #ifdef USE_EXT2FS |
951 | case FS_EX2FS: | | 951 | case FS_EX2FS: |
952 | asprintf(&newfs, "/sbin/newfs_ext2fs"); | | 952 | asprintf(&newfs, "/sbin/newfs_ext2fs"); |
953 | lbl->mnt_opts = "-text2fs"; | | 953 | lbl->mnt_opts = "-text2fs"; |
954 | lbl->fsname = "ext2fs"; | | 954 | lbl->fsname = "ext2fs"; |
955 | break; | | 955 | break; |
956 | #endif | | 956 | #endif |
957 | } | | 957 | } |
958 | if (lbl->pi_flags & PIF_NEWFS && newfs != NULL) { | | 958 | if (lbl->pi_flags & PIF_NEWFS && newfs != NULL) { |
959 | #ifdef USE_NEWFS_MSDOS | | 959 | #ifdef USE_NEWFS_MSDOS |
960 | if (lbl->pi_fstype == FS_MSDOS) { | | 960 | if (lbl->pi_fstype == FS_MSDOS) { |
961 | /* newfs only if mount fails */ | | 961 | /* newfs only if mount fails */ |
962 | if (run_program(RUN_SILENT | RUN_ERROR_OK, | | 962 | if (run_program(RUN_SILENT | RUN_ERROR_OK, |
963 | "mount -rt msdos /dev/%s /mnt2", dev) != 0) | | 963 | "mount -rt msdos /dev/%s /mnt2", dev) != 0) |
964 | error = run_program( | | 964 | error = run_program( |
965 | RUN_DISPLAY | RUN_PROGRESS, | | 965 | RUN_DISPLAY | RUN_PROGRESS, |
966 | "%s /dev/r%s", | | 966 | "%s /dev/r%s", |
967 | newfs, dev); | | 967 | newfs, dev); |
968 | else { | | 968 | else { |
969 | run_program(RUN_SILENT | RUN_ERROR_OK, | | 969 | run_program(RUN_SILENT | RUN_ERROR_OK, |
970 | "umount /mnt2"); | | 970 | "umount /mnt2"); |
971 | error = 0; | | 971 | error = 0; |
972 | } | | 972 | } |
973 | } else | | 973 | } else |
974 | #endif | | 974 | #endif |
975 | error = run_program(RUN_DISPLAY | RUN_PROGRESS, | | 975 | error = run_program(RUN_DISPLAY | RUN_PROGRESS, |
976 | "%s /dev/r%s", newfs, dev); | | 976 | "%s /dev/r%s", newfs, dev); |
977 | } else { | | 977 | } else { |
978 | /* We'd better check it isn't dirty */ | | 978 | /* We'd better check it isn't dirty */ |
979 | error = fsck_preen(pm->diskdev, ptn, lbl->fsname, false); | | 979 | error = fsck_preen(pm->diskdev, ptn, lbl->fsname, false); |
980 | } | | 980 | } |
981 | free(newfs); | | 981 | free(newfs); |
982 | if (error != 0) { | | 982 | if (error != 0) { |
983 | free(devdev); | | 983 | free(devdev); |
984 | free(dev); | | 984 | free(dev); |
985 | return error; | | 985 | return error; |
986 | } | | 986 | } |
987 | | | 987 | |
988 | lbl->pi_flags ^= PIF_NEWFS; | | 988 | lbl->pi_flags ^= PIF_NEWFS; |
989 | md_pre_mount(); | | 989 | md_pre_mount(); |
990 | | | 990 | |
991 | if (partman_go == 0 && lbl->pi_flags & PIF_MOUNT && | | 991 | if (partman_go == 0 && lbl->pi_flags & PIF_MOUNT && |
992 | lbl->mnt_opts != NULL) { | | 992 | lbl->mnt_opts != NULL) { |
993 | make_target_dir(lbl->pi_mount); | | 993 | make_target_dir(lbl->pi_mount); |
994 | error = target_mount_do(lbl->mnt_opts, devdev, lbl->pi_mount); | | 994 | error = target_mount_do(lbl->mnt_opts, devdev, lbl->pi_mount); |
995 | if (error) { | | 995 | if (error) { |
996 | msg_display(MSG_mountfail, dev, ' ', lbl->pi_mount); | | 996 | msg_display(MSG_mountfail, dev, ' ', lbl->pi_mount); |
997 | process_menu(MENU_ok, NULL); | | 997 | process_menu(MENU_ok, NULL); |
998 | free(devdev); | | 998 | free(devdev); |
999 | free(dev); | | 999 | free(dev); |
1000 | return error; | | 1000 | return error; |
1001 | } | | 1001 | } |
1002 | } | | 1002 | } |
1003 | free(devdev); | | 1003 | free(devdev); |
1004 | free(dev); | | 1004 | free(dev); |
1005 | } | | 1005 | } |
1006 | return 0; | | 1006 | return 0; |
1007 | } | | 1007 | } |
1008 | | | 1008 | |
1009 | int | | 1009 | int |
1010 | make_fstab(void) | | 1010 | make_fstab(void) |
1011 | { | | 1011 | { |
1012 | FILE *f; | | 1012 | FILE *f; |
1013 | int i, swap_dev = -1; | | 1013 | int i, swap_dev = -1; |
1014 | const char *dump_dev; | | 1014 | const char *dump_dev; |
1015 | char *dev = NULL; | | 1015 | char *dev = NULL; |
1016 | pm_devs_t *pm_i; | | 1016 | pm_devs_t *pm_i; |
1017 | #ifndef HAVE_TMPFS | | 1017 | #ifndef HAVE_TMPFS |
1018 | pm_devs_t *pm_with_swap = NULL; | | 1018 | pm_devs_t *pm_with_swap = NULL; |
1019 | #endif | | 1019 | #endif |
1020 | | | 1020 | |
1021 | /* Create the fstab. */ | | 1021 | /* Create the fstab. */ |
1022 | make_target_dir("/etc"); | | 1022 | make_target_dir("/etc"); |
1023 | f = target_fopen("/etc/fstab", "w"); | | 1023 | f = target_fopen("/etc/fstab", "w"); |
1024 | scripting_fprintf(NULL, "cat <<EOF >%s/etc/fstab\n", target_prefix()); | | 1024 | scripting_fprintf(NULL, "cat <<EOF >%s/etc/fstab\n", target_prefix()); |
1025 | | | 1025 | |
1026 | if (logfp) | | 1026 | if (logfp) |
1027 | (void)fprintf(logfp, | | 1027 | (void)fprintf(logfp, |
1028 | "Making %s/etc/fstab (%s).\n", target_prefix(), pm->diskdev); | | 1028 | "Making %s/etc/fstab (%s).\n", target_prefix(), pm->diskdev); |
1029 | | | 1029 | |
1030 | if (f == NULL) { | | 1030 | if (f == NULL) { |
1031 | msg_display(MSG_createfstab); | | 1031 | msg_display(MSG_createfstab); |
1032 | if (logfp) | | 1032 | if (logfp) |
1033 | (void)fprintf(logfp, "Failed to make /etc/fstab!\n"); | | 1033 | (void)fprintf(logfp, "Failed to make /etc/fstab!\n"); |
1034 | process_menu(MENU_ok, NULL); | | 1034 | process_menu(MENU_ok, NULL); |
1035 | #ifndef DEBUG | | 1035 | #ifndef DEBUG |
1036 | return 1; | | 1036 | return 1; |
1037 | #else | | 1037 | #else |
1038 | f = stdout; | | 1038 | f = stdout; |
1039 | #endif | | 1039 | #endif |
1040 | } | | 1040 | } |
1041 | | | 1041 | |
1042 | scripting_fprintf(f, "# NetBSD %s/etc/fstab\n# See /usr/share/examples/" | | 1042 | scripting_fprintf(f, "# NetBSD /etc/fstab\n# See /usr/share/examples/" |
1043 | "fstab/ for more examples.\n", target_prefix()); | | 1043 | "fstab/ for more examples.\n"); |
1044 | | | 1044 | |
1045 | if (pm->no_part) { | | 1045 | if (pm->no_part) { |
1046 | /* single dk? target */ | | 1046 | /* single dk? target */ |
1047 | char buf[200], parent[200], swap[200], *prompt; | | 1047 | char buf[200], parent[200], swap[200], *prompt; |
1048 | int res; | | 1048 | int res; |
1049 | | | 1049 | |
1050 | if (!get_name_and_parent(pm->diskdev, buf, parent)) | | 1050 | if (!get_name_and_parent(pm->diskdev, buf, parent)) |
1051 | goto done_with_disks; | | 1051 | goto done_with_disks; |
1052 | scripting_fprintf(f, "NAME=%s\t/\tffs\trw\t\t1 1\n", | | 1052 | scripting_fprintf(f, "NAME=%s\t/\tffs\trw\t\t1 1\n", |
1053 | buf); | | 1053 | buf); |
1054 | if (!find_swap_part_on(parent, swap)) | | 1054 | if (!find_swap_part_on(parent, swap)) |
1055 | goto done_with_disks; | | 1055 | goto done_with_disks; |
1056 | asprintf(&prompt, msg_string(MSG_Auto_add_swap_part), | | 1056 | asprintf(&prompt, msg_string(MSG_Auto_add_swap_part), |
1057 | swap, parent); | | 1057 | swap, parent); |
1058 | res = ask_yesno(prompt); | | 1058 | res = ask_yesno(prompt); |
1059 | free(prompt); | | 1059 | free(prompt); |
1060 | if (res) | | 1060 | if (res) |
1061 | scripting_fprintf(f, "NAME=%s\tnone" | | 1061 | scripting_fprintf(f, "NAME=%s\tnone" |
1062 | "\tswap\tsw,dp\t\t0 0\n", swap); | | 1062 | "\tswap\tsw,dp\t\t0 0\n", swap); |
1063 | goto done_with_disks; | | 1063 | goto done_with_disks; |
1064 | } | | 1064 | } |
1065 | | | 1065 | |
1066 | if (! partman_go) { | | 1066 | if (! partman_go) { |
1067 | /* We want to process only one disk... */ | | 1067 | /* We want to process only one disk... */ |
1068 | pm_i = pm; | | 1068 | pm_i = pm; |
1069 | goto onlyonediskinfstab; | | 1069 | goto onlyonediskinfstab; |
1070 | } | | 1070 | } |
1071 | SLIST_FOREACH(pm_i, &pm_head, l) { | | 1071 | SLIST_FOREACH(pm_i, &pm_head, l) { |
1072 | onlyonediskinfstab: | | 1072 | onlyonediskinfstab: |
1073 | for (i = 0; i < getmaxpartitions(); i++) { | | 1073 | for (i = 0; i < getmaxpartitions(); i++) { |
1074 | const char *s = ""; | | 1074 | const char *s = ""; |
1075 | const char *mp = pm_i->bsdlabel[i].pi_mount; | | 1075 | const char *mp = pm_i->bsdlabel[i].pi_mount; |
1076 | const char *fstype = "ffs"; | | 1076 | const char *fstype = "ffs"; |
1077 | int fsck_pass = 0, dump_freq = 0; | | 1077 | int fsck_pass = 0, dump_freq = 0; |
1078 | | | 1078 | |
1079 | if (dev != NULL) | | 1079 | if (dev != NULL) |
1080 | free(dev); | | 1080 | free(dev); |
1081 | if (pm_i->isspecial) | | 1081 | if (pm_i->isspecial) |
1082 | asprintf(&dev, "%s", pm_i->diskdev); | | 1082 | asprintf(&dev, "%s", pm_i->diskdev); |
1083 | else | | 1083 | else |
1084 | asprintf(&dev, "%s%c", pm_i->diskdev, 'a' + i); | | 1084 | asprintf(&dev, "%s%c", pm_i->diskdev, 'a' + i); |
1085 | if (dev == NULL) | | 1085 | if (dev == NULL) |
1086 | return (ENOMEM); | | 1086 | return (ENOMEM); |
1087 | | | 1087 | |
1088 | if (!*mp) { | | 1088 | if (!*mp) { |
1089 | /* | | 1089 | /* |
1090 | * No mount point specified, comment out line and | | 1090 | * No mount point specified, comment out line and |
1091 | * use /mnt as a placeholder for the mount point. | | 1091 | * use /mnt as a placeholder for the mount point. |
1092 | */ | | 1092 | */ |
1093 | s = "# "; | | 1093 | s = "# "; |
1094 | mp = "/mnt"; | | 1094 | mp = "/mnt"; |
1095 | } | | 1095 | } |
1096 | | | 1096 | |
1097 | switch (pm_i->bsdlabel[i].pi_fstype) { | | 1097 | switch (pm_i->bsdlabel[i].pi_fstype) { |
1098 | case FS_UNUSED: | | 1098 | case FS_UNUSED: |
1099 | continue; | | 1099 | continue; |
1100 | case FS_BSDLFS: | | 1100 | case FS_BSDLFS: |
1101 | /* If there is no LFS, just comment it out. */ | | 1101 | /* If there is no LFS, just comment it out. */ |
1102 | if (!check_lfs_progs()) | | 1102 | if (!check_lfs_progs()) |
1103 | s = "# "; | | 1103 | s = "# "; |
1104 | fstype = "lfs"; | | 1104 | fstype = "lfs"; |
1105 | /* FALLTHROUGH */ | | 1105 | /* FALLTHROUGH */ |
1106 | case FS_BSDFFS: | | 1106 | case FS_BSDFFS: |
1107 | fsck_pass = (strcmp(mp, "/") == 0) ? 1 : 2; | | 1107 | fsck_pass = (strcmp(mp, "/") == 0) ? 1 : 2; |
1108 | dump_freq = 1; | | 1108 | dump_freq = 1; |
1109 | break; | | 1109 | break; |
1110 | case FS_MSDOS: | | 1110 | case FS_MSDOS: |
1111 | fstype = "msdos"; | | 1111 | fstype = "msdos"; |
1112 | break; | | 1112 | break; |
1113 | case FS_SWAP: | | 1113 | case FS_SWAP: |
1114 | if (pm_i->isspecial) | | 1114 | if (pm_i->isspecial) |
1115 | continue; | | 1115 | continue; |
1116 | if (swap_dev == -1) { | | 1116 | if (swap_dev == -1) { |
1117 | swap_dev = i; | | 1117 | swap_dev = i; |
1118 | dump_dev = ",dp"; | | 1118 | dump_dev = ",dp"; |
1119 | #ifndef HAVE_TMPFS | | 1119 | #ifndef HAVE_TMPFS |
1120 | pm_with_swap = pm_i; | | 1120 | pm_with_swap = pm_i; |
1121 | #endif | | 1121 | #endif |
1122 | } else { | | 1122 | } else { |
1123 | dump_dev = ""; | | 1123 | dump_dev = ""; |
1124 | } | | 1124 | } |
1125 | scripting_fprintf(f, "/dev/%s\t\tnone\tswap\tsw%s\t\t 0 0\n", | | 1125 | scripting_fprintf(f, "/dev/%s\t\tnone\tswap\tsw%s\t\t 0 0\n", |
1126 | dev, dump_dev); | | 1126 | dev, dump_dev); |
1127 | continue; | | 1127 | continue; |
1128 | #ifdef USE_SYSVBFS | | 1128 | #ifdef USE_SYSVBFS |
1129 | case FS_SYSVBFS: | | 1129 | case FS_SYSVBFS: |
1130 | fstype = "sysvbfs"; | | 1130 | fstype = "sysvbfs"; |
1131 | make_target_dir("/stand"); | | 1131 | make_target_dir("/stand"); |
1132 | break; | | 1132 | break; |
1133 | #endif | | 1133 | #endif |
1134 | default: | | 1134 | default: |
1135 | fstype = "???"; | | 1135 | fstype = "???"; |
1136 | s = "# "; | | 1136 | s = "# "; |
1137 | break; | | 1137 | break; |
1138 | } | | 1138 | } |
1139 | /* The code that remounts root rw doesn't check the partition */ | | 1139 | /* The code that remounts root rw doesn't check the partition */ |
1140 | if (strcmp(mp, "/") == 0 && !(pm_i->bsdlabel[i].pi_flags & PIF_MOUNT)) | | 1140 | if (strcmp(mp, "/") == 0 && !(pm_i->bsdlabel[i].pi_flags & PIF_MOUNT)) |
1141 | s = "# "; | | 1141 | s = "# "; |
1142 | | | 1142 | |
1143 | scripting_fprintf(f, | | 1143 | scripting_fprintf(f, |
1144 | "%s/dev/%s\t\t%s\t%s\trw%s%s%s%s%s%s%s%s\t\t %d %d\n", | | 1144 | "%s/dev/%s\t\t%s\t%s\trw%s%s%s%s%s%s%s%s\t\t %d %d\n", |
1145 | s, dev, mp, fstype, | | 1145 | s, dev, mp, fstype, |
1146 | pm_i->bsdlabel[i].pi_flags & PIF_LOG ? ",log" : "", | | 1146 | pm_i->bsdlabel[i].pi_flags & PIF_LOG ? ",log" : "", |
1147 | pm_i->bsdlabel[i].pi_flags & PIF_MOUNT ? "" : ",noauto", | | 1147 | pm_i->bsdlabel[i].pi_flags & PIF_MOUNT ? "" : ",noauto", |
1148 | pm_i->bsdlabel[i].pi_flags & PIF_ASYNC ? ",async" : "", | | 1148 | pm_i->bsdlabel[i].pi_flags & PIF_ASYNC ? ",async" : "", |
1149 | pm_i->bsdlabel[i].pi_flags & PIF_NOATIME ? ",noatime" : "", | | 1149 | pm_i->bsdlabel[i].pi_flags & PIF_NOATIME ? ",noatime" : "", |
1150 | pm_i->bsdlabel[i].pi_flags & PIF_NODEV ? ",nodev" : "", | | 1150 | pm_i->bsdlabel[i].pi_flags & PIF_NODEV ? ",nodev" : "", |
1151 | pm_i->bsdlabel[i].pi_flags & PIF_NODEVMTIME ? ",nodevmtime" : "", | | 1151 | pm_i->bsdlabel[i].pi_flags & PIF_NODEVMTIME ? ",nodevmtime" : "", |
1152 | pm_i->bsdlabel[i].pi_flags & PIF_NOEXEC ? ",noexec" : "", | | 1152 | pm_i->bsdlabel[i].pi_flags & PIF_NOEXEC ? ",noexec" : "", |
1153 | pm_i->bsdlabel[i].pi_flags & PIF_NOSUID ? ",nosuid" : "", | | 1153 | pm_i->bsdlabel[i].pi_flags & PIF_NOSUID ? ",nosuid" : "", |
1154 | dump_freq, fsck_pass); | | 1154 | dump_freq, fsck_pass); |
1155 | if (pm_i->isspecial) | | 1155 | if (pm_i->isspecial) |
1156 | /* Special device (such as dk*) have only one partition */ | | 1156 | /* Special device (such as dk*) have only one partition */ |
1157 | break; | | 1157 | break; |
1158 | } | | 1158 | } |
1159 | /* Simple install, only one disk */ | | 1159 | /* Simple install, only one disk */ |
1160 | if (!partman_go) | | 1160 | if (!partman_go) |
1161 | break; | | 1161 | break; |
1162 | } | | 1162 | } |
1163 | done_with_disks: | | 1163 | done_with_disks: |
1164 | if (tmp_ramdisk_size != 0) { | | 1164 | if (tmp_ramdisk_size != 0) { |
1165 | #ifdef HAVE_TMPFS | | 1165 | #ifdef HAVE_TMPFS |
1166 | scripting_fprintf(f, "tmpfs\t\t/tmp\ttmpfs\trw,-m=1777,-s=%" | | 1166 | scripting_fprintf(f, "tmpfs\t\t/tmp\ttmpfs\trw,-m=1777,-s=%" |
1167 | PRIi64 "\n", | | 1167 | PRIi64 "\n", |
1168 | tmp_ramdisk_size * 512); | | 1168 | tmp_ramdisk_size * 512); |
1169 | #else | | 1169 | #else |
1170 | if (swap_dev != -1 && pm_with_swap != NULL) | | 1170 | if (swap_dev != -1 && pm_with_swap != NULL) |
1171 | scripting_fprintf(f, "/dev/%s%c\t\t/tmp\tmfs\trw,-s=%" | | 1171 | scripting_fprintf(f, "/dev/%s%c\t\t/tmp\tmfs\trw,-s=%" |
1172 | PRIi64 "\n", | | 1172 | PRIi64 "\n", |
1173 | pm_with_swap->diskdev, 'a' + swap_dev, tmp_ramdisk_size); | | 1173 | pm_with_swap->diskdev, 'a' + swap_dev, tmp_ramdisk_size); |
1174 | else | | 1174 | else |
1175 | scripting_fprintf(f, "swap\t\t/tmp\tmfs\trw,-s=%" | | 1175 | scripting_fprintf(f, "swap\t\t/tmp\tmfs\trw,-s=%" |
1176 | PRIi64 "\n", | | 1176 | PRIi64 "\n", |
1177 | tmp_ramdisk_size); | | 1177 | tmp_ramdisk_size); |
1178 | #endif | | 1178 | #endif |
1179 | } | | 1179 | } |
1180 | | | 1180 | |
1181 | /* Add /kern, /proc and /dev/pts to fstab and make mountpoint. */ | | 1181 | /* Add /kern, /proc and /dev/pts to fstab and make mountpoint. */ |
1182 | scripting_fprintf(f, "kernfs\t\t/kern\tkernfs\trw\n"); | | 1182 | scripting_fprintf(f, "kernfs\t\t/kern\tkernfs\trw\n"); |
1183 | scripting_fprintf(f, "ptyfs\t\t/dev/pts\tptyfs\trw\n"); | | 1183 | scripting_fprintf(f, "ptyfs\t\t/dev/pts\tptyfs\trw\n"); |
1184 | scripting_fprintf(f, "procfs\t\t/proc\tprocfs\trw\n"); | | 1184 | scripting_fprintf(f, "procfs\t\t/proc\tprocfs\trw\n"); |
1185 | scripting_fprintf(f, "/dev/%s\t\t/cdrom\tcd9660\tro,noauto\n", | | 1185 | scripting_fprintf(f, "/dev/%s\t\t/cdrom\tcd9660\tro,noauto\n", |
1186 | get_default_cdrom()); | | 1186 | get_default_cdrom()); |
1187 | scripting_fprintf(f, "%stmpfs\t\t/var/shm\ttmpfs\trw,-m1777,-sram%%25\n", | | 1187 | scripting_fprintf(f, "%stmpfs\t\t/var/shm\ttmpfs\trw,-m1777,-sram%%25\n", |
1188 | tmpfs_on_var_shm() ? "" : "#"); | | 1188 | tmpfs_on_var_shm() ? "" : "#"); |
1189 | make_target_dir("/kern"); | | 1189 | make_target_dir("/kern"); |
1190 | make_target_dir("/proc"); | | 1190 | make_target_dir("/proc"); |
1191 | make_target_dir("/dev/pts"); | | 1191 | make_target_dir("/dev/pts"); |
1192 | make_target_dir("/cdrom"); | | 1192 | make_target_dir("/cdrom"); |
1193 | make_target_dir("/var/shm"); | | 1193 | make_target_dir("/var/shm"); |
1194 | | | 1194 | |
1195 | scripting_fprintf(NULL, "EOF\n"); | | 1195 | scripting_fprintf(NULL, "EOF\n"); |
1196 | | | 1196 | |
1197 | if (dev != NULL) | | 1197 | if (dev != NULL) |
1198 | free(dev); | | 1198 | free(dev); |
1199 | fclose(f); | | 1199 | fclose(f); |
1200 | fflush(NULL); | | 1200 | fflush(NULL); |
1201 | return 0; | | 1201 | return 0; |
1202 | } | | 1202 | } |
1203 | | | 1203 | |
1204 | | | 1204 | |
1205 | | | 1205 | |
1206 | static int | | 1206 | static int |
1207 | /*ARGSUSED*/ | | 1207 | /*ARGSUSED*/ |
1208 | foundffs(struct data *list, size_t num) | | 1208 | foundffs(struct data *list, size_t num) |
1209 | { | | 1209 | { |
1210 | int error; | | 1210 | int error; |
1211 | | | 1211 | |
1212 | if (num < 2 || strcmp(list[1].u.s_val, "/") == 0 || | | 1212 | if (num < 2 || strcmp(list[1].u.s_val, "/") == 0 || |
1213 | strstr(list[2].u.s_val, "noauto") != NULL) | | 1213 | strstr(list[2].u.s_val, "noauto") != NULL) |
1214 | return 0; | | 1214 | return 0; |
1215 | | | 1215 | |
1216 | error = fsck_preen(list[0].u.s_val, ' '-'a', "ffs", false); | | 1216 | error = fsck_preen(list[0].u.s_val, ' '-'a', "ffs", false); |
1217 | if (error != 0) | | 1217 | if (error != 0) |
1218 | return error; | | 1218 | return error; |
1219 | | | 1219 | |
1220 | error = target_mount("", list[0].u.s_val, ' '-'a', list[1].u.s_val); | | 1220 | error = target_mount("", list[0].u.s_val, ' '-'a', list[1].u.s_val); |
1221 | if (error != 0) { | | 1221 | if (error != 0) { |
1222 | msg_display(MSG_mount_failed, list[0].u.s_val); | | 1222 | msg_display(MSG_mount_failed, list[0].u.s_val); |
1223 | if (!ask_noyes(NULL)) | | 1223 | if (!ask_noyes(NULL)) |
1224 | return error; | | 1224 | return error; |
1225 | } | | 1225 | } |
1226 | return 0; | | 1226 | return 0; |
1227 | } | | 1227 | } |
1228 | | | 1228 | |
1229 | #ifdef USE_SYSVBFS | | 1229 | #ifdef USE_SYSVBFS |
1230 | static int | | 1230 | static int |
1231 | /*ARGSUSED*/ | | 1231 | /*ARGSUSED*/ |
1232 | foundsysvbfs(struct data *list, size_t num) | | 1232 | foundsysvbfs(struct data *list, size_t num) |
1233 | { | | 1233 | { |
1234 | int error; | | 1234 | int error; |
1235 | | | 1235 | |
1236 | if (num < 2 || strcmp(list[1].u.s_val, "/") == 0 || | | 1236 | if (num < 2 || strcmp(list[1].u.s_val, "/") == 0 || |
1237 | strstr(list[2].u.s_val, "noauto") != NULL) | | 1237 | strstr(list[2].u.s_val, "noauto") != NULL) |
1238 | return 0; | | 1238 | return 0; |
1239 | | | 1239 | |
1240 | error = target_mount("", list[0].u.s_val, ' '-'a', list[1].u.s_val); | | 1240 | error = target_mount("", list[0].u.s_val, ' '-'a', list[1].u.s_val); |
1241 | if (error != 0) | | 1241 | if (error != 0) |
1242 | return error; | | 1242 | return error; |
1243 | return 0; | | 1243 | return 0; |
1244 | } | | 1244 | } |
1245 | #endif | | 1245 | #endif |
1246 | | | 1246 | |
1247 | /* | | 1247 | /* |
1248 | * Do an fsck. On failure, inform the user by showing a warning | | 1248 | * Do an fsck. On failure, inform the user by showing a warning |
1249 | * message and doing menu_ok() before proceeding. | | 1249 | * message and doing menu_ok() before proceeding. |
1250 | * Returns 0 on success, or nonzero return code from fsck() on failure. | | 1250 | * Returns 0 on success, or nonzero return code from fsck() on failure. |
1251 | */ | | 1251 | */ |
1252 | static int | | 1252 | static int |
1253 | fsck_preen(const char *disk, int ptn, const char *fsname, bool silent) | | 1253 | fsck_preen(const char *disk, int ptn, const char *fsname, bool silent) |
1254 | { | | 1254 | { |
1255 | char *prog; | | 1255 | char *prog; |
1256 | int error; | | 1256 | int error; |
1257 | | | 1257 | |
1258 | ptn = (ptn < 0)? 0 : 'a' + ptn; | | 1258 | ptn = (ptn < 0)? 0 : 'a' + ptn; |
1259 | if (fsname == NULL) | | 1259 | if (fsname == NULL) |
1260 | return 0; | | 1260 | return 0; |
1261 | /* first, check if fsck program exists, if not, assume ok */ | | 1261 | /* first, check if fsck program exists, if not, assume ok */ |
1262 | asprintf(&prog, "/sbin/fsck_%s", fsname); | | 1262 | asprintf(&prog, "/sbin/fsck_%s", fsname); |
1263 | if (prog == NULL) | | 1263 | if (prog == NULL) |
1264 | return 0; | | 1264 | return 0; |
1265 | if (access(prog, X_OK) != 0) { | | 1265 | if (access(prog, X_OK) != 0) { |
1266 | free(prog); | | 1266 | free(prog); |
1267 | return 0; | | 1267 | return 0; |
1268 | } | | 1268 | } |
1269 | if (!strcmp(fsname,"ffs")) | | 1269 | if (!strcmp(fsname,"ffs")) |
1270 | fixsb(prog, disk, ptn); | | 1270 | fixsb(prog, disk, ptn); |
1271 | error = run_program(silent? RUN_SILENT|RUN_ERROR_OK : 0, "%s -p -q /dev/r%s%c", prog, disk, ptn); | | 1271 | error = run_program(silent? RUN_SILENT|RUN_ERROR_OK : 0, "%s -p -q /dev/r%s%c", prog, disk, ptn); |
1272 | free(prog); | | 1272 | free(prog); |
1273 | if (error != 0 && !silent) { | | 1273 | if (error != 0 && !silent) { |
1274 | msg_display(MSG_badfs, disk, ptn, error); | | 1274 | msg_display(MSG_badfs, disk, ptn, error); |
1275 | if (ask_noyes(NULL)) | | 1275 | if (ask_noyes(NULL)) |
1276 | error = 0; | | 1276 | error = 0; |
1277 | /* XXX at this point maybe we should run a full fsck? */ | | 1277 | /* XXX at this point maybe we should run a full fsck? */ |
1278 | } | | 1278 | } |
1279 | return error; | | 1279 | return error; |
1280 | } | | 1280 | } |
1281 | | | 1281 | |
1282 | /* This performs the same function as the etc/rc.d/fixsb script | | 1282 | /* This performs the same function as the etc/rc.d/fixsb script |
1283 | * which attempts to correct problems with ffs1 filesystems | | 1283 | * which attempts to correct problems with ffs1 filesystems |
1284 | * which may have been introduced by booting a netbsd-current kernel | | 1284 | * which may have been introduced by booting a netbsd-current kernel |
1285 | * from between April of 2003 and January 2004. For more information | | 1285 | * from between April of 2003 and January 2004. For more information |
1286 | * This script was developed as a response to NetBSD pr install/25138 | | 1286 | * This script was developed as a response to NetBSD pr install/25138 |
1287 | * Additional prs regarding the original issue include: | | 1287 | * Additional prs regarding the original issue include: |
1288 | * bin/17910 kern/21283 kern/21404 port-macppc/23925 port-macppc/23926 | | 1288 | * bin/17910 kern/21283 kern/21404 port-macppc/23925 port-macppc/23926 |
1289 | */ | | 1289 | */ |
1290 | static void | | 1290 | static void |
1291 | fixsb(const char *prog, const char *disk, char ptn) | | 1291 | fixsb(const char *prog, const char *disk, char ptn) |
1292 | { | | 1292 | { |
1293 | int fd; | | 1293 | int fd; |
1294 | int rval; | | 1294 | int rval; |
1295 | union { | | 1295 | union { |
1296 | struct fs fs; | | 1296 | struct fs fs; |
1297 | char buf[SBLOCKSIZE]; | | 1297 | char buf[SBLOCKSIZE]; |
1298 | } sblk; | | 1298 | } sblk; |
1299 | struct fs *fs = &sblk.fs; | | 1299 | struct fs *fs = &sblk.fs; |
1300 | | | 1300 | |
1301 | snprintf(sblk.buf, sizeof(sblk.buf), "/dev/r%s%c", | | 1301 | snprintf(sblk.buf, sizeof(sblk.buf), "/dev/r%s%c", |
1302 | disk, ptn == ' ' ? 0 : ptn); | | 1302 | disk, ptn == ' ' ? 0 : ptn); |
1303 | fd = open(sblk.buf, O_RDONLY); | | 1303 | fd = open(sblk.buf, O_RDONLY); |
1304 | if (fd == -1) | | 1304 | if (fd == -1) |
1305 | return; | | 1305 | return; |
1306 | | | 1306 | |
1307 | /* Read ffsv1 main superblock */ | | 1307 | /* Read ffsv1 main superblock */ |
1308 | rval = pread(fd, sblk.buf, sizeof sblk.buf, SBLOCK_UFS1); | | 1308 | rval = pread(fd, sblk.buf, sizeof sblk.buf, SBLOCK_UFS1); |
1309 | close(fd); | | 1309 | close(fd); |
1310 | if (rval != sizeof sblk.buf) | | 1310 | if (rval != sizeof sblk.buf) |
1311 | return; | | 1311 | return; |
1312 | | | 1312 | |
1313 | if (fs->fs_magic != FS_UFS1_MAGIC && | | 1313 | if (fs->fs_magic != FS_UFS1_MAGIC && |
1314 | fs->fs_magic != FS_UFS1_MAGIC_SWAPPED) | | 1314 | fs->fs_magic != FS_UFS1_MAGIC_SWAPPED) |
1315 | /* Not FFSv1 */ | | 1315 | /* Not FFSv1 */ |
1316 | return; | | 1316 | return; |
1317 | if (fs->fs_old_flags & FS_FLAGS_UPDATED) | | 1317 | if (fs->fs_old_flags & FS_FLAGS_UPDATED) |
1318 | /* properly updated fslevel 4 */ | | 1318 | /* properly updated fslevel 4 */ |
1319 | return; | | 1319 | return; |
1320 | if (fs->fs_bsize != fs->fs_maxbsize) | | 1320 | if (fs->fs_bsize != fs->fs_maxbsize) |
1321 | /* not messed up */ | | 1321 | /* not messed up */ |
1322 | return; | | 1322 | return; |
1323 | | | 1323 | |
1324 | /* | | 1324 | /* |
1325 | * OK we have a munged fs, first 'upgrade' to fslevel 4, | | 1325 | * OK we have a munged fs, first 'upgrade' to fslevel 4, |
1326 | * We specify -b16 in order to stop fsck bleating that the | | 1326 | * We specify -b16 in order to stop fsck bleating that the |
1327 | * sb doesn't match the first alternate. | | 1327 | * sb doesn't match the first alternate. |
1328 | */ | | 1328 | */ |
1329 | run_program(RUN_DISPLAY | RUN_PROGRESS, | | 1329 | run_program(RUN_DISPLAY | RUN_PROGRESS, |
1330 | "%s -p -b 16 -c 4 /dev/r%s%c", prog, disk, ptn); | | 1330 | "%s -p -b 16 -c 4 /dev/r%s%c", prog, disk, ptn); |
1331 | /* Then downgrade to fslevel 3 */ | | 1331 | /* Then downgrade to fslevel 3 */ |
1332 | run_program(RUN_DISPLAY | RUN_PROGRESS, | | 1332 | run_program(RUN_DISPLAY | RUN_PROGRESS, |
1333 | "%s -p -c 3 /dev/r%s%c", prog, disk, ptn); | | 1333 | "%s -p -c 3 /dev/r%s%c", prog, disk, ptn); |
1334 | } | | 1334 | } |
1335 | | | 1335 | |
1336 | /* | | 1336 | /* |
1337 | * fsck and mount the root partition. | | 1337 | * fsck and mount the root partition. |
1338 | */ | | 1338 | */ |
1339 | static int | | 1339 | static int |
1340 | mount_root(void) | | 1340 | mount_root(void) |
1341 | { | | 1341 | { |
1342 | int error; | | 1342 | int error; |
1343 | int ptn = (pm->isspecial)? 0 - 'a' : pm->rootpart; | | 1343 | int ptn = (pm->isspecial)? 0 - 'a' : pm->rootpart; |
1344 | | | 1344 | |
1345 | error = fsck_preen(pm->diskdev, ptn, "ffs", false); | | 1345 | error = fsck_preen(pm->diskdev, ptn, "ffs", false); |
1346 | if (error != 0) | | 1346 | if (error != 0) |
1347 | return error; | | 1347 | return error; |
1348 | | | 1348 | |
1349 | md_pre_mount(); | | 1349 | md_pre_mount(); |
1350 | | | 1350 | |
1351 | /* Mount /dev/<diskdev>a on target's "". | | 1351 | /* Mount /dev/<diskdev>a on target's "". |
1352 | * If we pass "" as mount-on, Prefixing will DTRT. | | 1352 | * If we pass "" as mount-on, Prefixing will DTRT. |
1353 | * for now, use no options. | | 1353 | * for now, use no options. |
1354 | * XXX consider -o remount in case target root is | | 1354 | * XXX consider -o remount in case target root is |
1355 | * current root, still readonly from single-user? | | 1355 | * current root, still readonly from single-user? |
1356 | */ | | 1356 | */ |
1357 | return target_mount("", pm->diskdev, ptn, ""); | | 1357 | return target_mount("", pm->diskdev, ptn, ""); |
1358 | } | | 1358 | } |
1359 | | | 1359 | |
1360 | /* Get information on the file systems mounted from the root filesystem. | | 1360 | /* Get information on the file systems mounted from the root filesystem. |
1361 | * Offer to convert them into 4.4BSD inodes if they are not 4.4BSD | | 1361 | * Offer to convert them into 4.4BSD inodes if they are not 4.4BSD |
1362 | * inodes. Fsck them. Mount them. | | 1362 | * inodes. Fsck them. Mount them. |
1363 | */ | | 1363 | */ |
1364 | | | 1364 | |
1365 | int | | 1365 | int |
1366 | mount_disks(void) | | 1366 | mount_disks(void) |
1367 | { | | 1367 | { |
1368 | char *fstab; | | 1368 | char *fstab; |
1369 | int fstabsize; | | 1369 | int fstabsize; |
1370 | int error; | | 1370 | int error; |
1371 | | | 1371 | |
1372 | static struct lookfor fstabbuf[] = { | | 1372 | static struct lookfor fstabbuf[] = { |
1373 | {"/dev/", "/dev/%s %s ffs %s", "c", NULL, 0, 0, foundffs}, | | 1373 | {"/dev/", "/dev/%s %s ffs %s", "c", NULL, 0, 0, foundffs}, |
1374 | {"/dev/", "/dev/%s %s ufs %s", "c", NULL, 0, 0, foundffs}, | | 1374 | {"/dev/", "/dev/%s %s ufs %s", "c", NULL, 0, 0, foundffs}, |
1375 | #ifdef USE_SYSVBFS | | 1375 | #ifdef USE_SYSVBFS |
1376 | {"/dev/", "/dev/%s %s sysvbfs %s", "c", NULL, 0, 0, | | 1376 | {"/dev/", "/dev/%s %s sysvbfs %s", "c", NULL, 0, 0, |
1377 | foundsysvbfs}, | | 1377 | foundsysvbfs}, |
1378 | #endif | | 1378 | #endif |
1379 | }; | | 1379 | }; |
1380 | static size_t numfstabbuf = sizeof(fstabbuf) / sizeof(struct lookfor); | | 1380 | static size_t numfstabbuf = sizeof(fstabbuf) / sizeof(struct lookfor); |
1381 | | | 1381 | |
1382 | /* First the root device. */ | | 1382 | /* First the root device. */ |
1383 | if (target_already_root()) | | 1383 | if (target_already_root()) |
1384 | /* avoid needing to call target_already_root() again */ | | 1384 | /* avoid needing to call target_already_root() again */ |
1385 | targetroot_mnt[0] = 0; | | 1385 | targetroot_mnt[0] = 0; |
1386 | else { | | 1386 | else { |
1387 | error = mount_root(); | | 1387 | error = mount_root(); |
1388 | if (error != 0 && error != EBUSY) | | 1388 | if (error != 0 && error != EBUSY) |
1389 | return -1; | | 1389 | return -1; |
1390 | } | | 1390 | } |
1391 | | | 1391 | |
1392 | /* Check the target /etc/fstab exists before trying to parse it. */ | | 1392 | /* Check the target /etc/fstab exists before trying to parse it. */ |
1393 | if (target_dir_exists_p("/etc") == 0 || | | 1393 | if (target_dir_exists_p("/etc") == 0 || |
1394 | target_file_exists_p("/etc/fstab") == 0) { | | 1394 | target_file_exists_p("/etc/fstab") == 0) { |
1395 | msg_display(MSG_noetcfstab, pm->diskdev); | | 1395 | msg_display(MSG_noetcfstab, pm->diskdev); |
1396 | process_menu(MENU_ok, NULL); | | 1396 | process_menu(MENU_ok, NULL); |
1397 | return -1; | | 1397 | return -1; |
1398 | } | | 1398 | } |
1399 | | | 1399 | |
1400 | | | 1400 | |
1401 | /* Get fstab entries from the target-root /etc/fstab. */ | | 1401 | /* Get fstab entries from the target-root /etc/fstab. */ |
1402 | fstabsize = target_collect_file(T_FILE, &fstab, "/etc/fstab"); | | 1402 | fstabsize = target_collect_file(T_FILE, &fstab, "/etc/fstab"); |
1403 | if (fstabsize < 0) { | | 1403 | if (fstabsize < 0) { |
1404 | /* error ! */ | | 1404 | /* error ! */ |
1405 | msg_display(MSG_badetcfstab, pm->diskdev); | | 1405 | msg_display(MSG_badetcfstab, pm->diskdev); |
1406 | process_menu(MENU_ok, NULL); | | 1406 | process_menu(MENU_ok, NULL); |
1407 | return -2; | | 1407 | return -2; |
1408 | } | | 1408 | } |
1409 | error = walk(fstab, (size_t)fstabsize, fstabbuf, numfstabbuf); | | 1409 | error = walk(fstab, (size_t)fstabsize, fstabbuf, numfstabbuf); |
1410 | free(fstab); | | 1410 | free(fstab); |
1411 | | | 1411 | |
1412 | return error; | | 1412 | return error; |
1413 | } | | 1413 | } |
1414 | | | 1414 | |
1415 | int | | 1415 | int |
1416 | set_swap_if_low_ram(const char *disk, partinfo *pp) | | 1416 | set_swap_if_low_ram(const char *disk, partinfo *pp) |
1417 | { | | 1417 | { |
1418 | if (get_ramsize() <= 32) | | 1418 | if (get_ramsize() <= 32) |
1419 | return set_swap(disk, pp); | | 1419 | return set_swap(disk, pp); |
1420 | return 0; | | 1420 | return 0; |
1421 | } | | 1421 | } |
1422 | | | 1422 | |
1423 | int | | 1423 | int |
1424 | set_swap(const char *disk, partinfo *pp) | | 1424 | set_swap(const char *disk, partinfo *pp) |
1425 | { | | 1425 | { |
1426 | int i; | | 1426 | int i; |
1427 | char *cp; | | 1427 | char *cp; |
1428 | int rval; | | 1428 | int rval; |
1429 | | | 1429 | |
1430 | if (pp == NULL) | | 1430 | if (pp == NULL) |
1431 | pp = pm->oldlabel; | | 1431 | pp = pm->oldlabel; |
1432 | | | 1432 | |
1433 | for (i = 0; i < MAXPARTITIONS; i++) { | | 1433 | for (i = 0; i < MAXPARTITIONS; i++) { |
1434 | if (pp[i].pi_fstype != FS_SWAP) | | 1434 | if (pp[i].pi_fstype != FS_SWAP) |
1435 | continue; | | 1435 | continue; |
1436 | asprintf(&cp, "/dev/%s%c", disk, 'a' + i); | | 1436 | asprintf(&cp, "/dev/%s%c", disk, 'a' + i); |
1437 | rval = swapctl(SWAP_ON, cp, 0); | | 1437 | rval = swapctl(SWAP_ON, cp, 0); |
1438 | free(cp); | | 1438 | free(cp); |
1439 | if (rval != 0) | | 1439 | if (rval != 0) |
1440 | return -1; | | 1440 | return -1; |
1441 | } | | 1441 | } |
1442 | | | 1442 | |
1443 | return 0; | | 1443 | return 0; |
1444 | } | | 1444 | } |
1445 | | | 1445 | |
1446 | int | | 1446 | int |
1447 | check_swap(const char *disk, int remove_swap) | | 1447 | check_swap(const char *disk, int remove_swap) |
1448 | { | | 1448 | { |
1449 | struct swapent *swap; | | 1449 | struct swapent *swap; |
1450 | char *cp; | | 1450 | char *cp; |
1451 | int nswap; | | 1451 | int nswap; |
1452 | int l; | | 1452 | int l; |
1453 | int rval = 0; | | 1453 | int rval = 0; |
1454 | | | 1454 | |
1455 | nswap = swapctl(SWAP_NSWAP, 0, 0); | | 1455 | nswap = swapctl(SWAP_NSWAP, 0, 0); |
1456 | if (nswap <= 0) | | 1456 | if (nswap <= 0) |
1457 | return 0; | | 1457 | return 0; |
1458 | | | 1458 | |
1459 | swap = malloc(nswap * sizeof *swap); | | 1459 | swap = malloc(nswap * sizeof *swap); |
1460 | if (swap == NULL) | | 1460 | if (swap == NULL) |
1461 | return -1; | | 1461 | return -1; |
1462 | | | 1462 | |
1463 | nswap = swapctl(SWAP_STATS, swap, nswap); | | 1463 | nswap = swapctl(SWAP_STATS, swap, nswap); |
1464 | if (nswap < 0) | | 1464 | if (nswap < 0) |
1465 | goto bad_swap; | | 1465 | goto bad_swap; |
1466 | | | 1466 | |
1467 | l = strlen(disk); | | 1467 | l = strlen(disk); |
1468 | while (--nswap >= 0) { | | 1468 | while (--nswap >= 0) { |
1469 | /* Should we check the se_dev or se_path? */ | | 1469 | /* Should we check the se_dev or se_path? */ |
1470 | cp = swap[nswap].se_path; | | 1470 | cp = swap[nswap].se_path; |
1471 | if (memcmp(cp, "/dev/", 5) != 0) | | 1471 | if (memcmp(cp, "/dev/", 5) != 0) |
1472 | continue; | | 1472 | continue; |
1473 | if (memcmp(cp + 5, disk, l) != 0) | | 1473 | if (memcmp(cp + 5, disk, l) != 0) |
1474 | continue; | | 1474 | continue; |
1475 | if (!isalpha(*(unsigned char *)(cp + 5 + l))) | | 1475 | if (!isalpha(*(unsigned char *)(cp + 5 + l))) |
1476 | continue; | | 1476 | continue; |
1477 | if (cp[5 + l + 1] != 0) | | 1477 | if (cp[5 + l + 1] != 0) |
1478 | continue; | | 1478 | continue; |
1479 | /* ok path looks like it is for this device */ | | 1479 | /* ok path looks like it is for this device */ |
1480 | if (!remove_swap) { | | 1480 | if (!remove_swap) { |
1481 | /* count active swap areas */ | | 1481 | /* count active swap areas */ |
1482 | rval++; | | 1482 | rval++; |
1483 | continue; | | 1483 | continue; |
1484 | } | | 1484 | } |
1485 | if (swapctl(SWAP_OFF, cp, 0) == -1) | | 1485 | if (swapctl(SWAP_OFF, cp, 0) == -1) |
1486 | rval = -1; | | 1486 | rval = -1; |
1487 | } | | 1487 | } |
1488 | | | 1488 | |
1489 | done: | | 1489 | done: |
1490 | free(swap); | | 1490 | free(swap); |
1491 | return rval; | | 1491 | return rval; |
1492 | | | 1492 | |
1493 | bad_swap: | | 1493 | bad_swap: |
1494 | rval = -1; | | 1494 | rval = -1; |
1495 | goto done; | | 1495 | goto done; |
1496 | } | | 1496 | } |
1497 | | | 1497 | |
1498 | #ifdef HAVE_BOOTXX_xFS | | 1498 | #ifdef HAVE_BOOTXX_xFS |
1499 | char * | | 1499 | char * |
1500 | bootxx_name(void) | | 1500 | bootxx_name(void) |
1501 | { | | 1501 | { |
1502 | int fstype; | | 1502 | int fstype; |
1503 | const char *bootxxname; | | 1503 | const char *bootxxname; |
1504 | char *bootxx; | | 1504 | char *bootxx; |
1505 | | | 1505 | |
1506 | /* check we have boot code for the root partition type */ | | 1506 | /* check we have boot code for the root partition type */ |
1507 | fstype = pm->bsdlabel[pm->rootpart].pi_fstype; | | 1507 | fstype = pm->bsdlabel[pm->rootpart].pi_fstype; |
1508 | switch (fstype) { | | 1508 | switch (fstype) { |
1509 | #if defined(BOOTXX_FFSV1) || defined(BOOTXX_FFSV2) | | 1509 | #if defined(BOOTXX_FFSV1) || defined(BOOTXX_FFSV2) |
1510 | case FS_BSDFFS: | | 1510 | case FS_BSDFFS: |
1511 | if (pm->bsdlabel[pm->rootpart].pi_flags & PIF_FFSv2) { | | 1511 | if (pm->bsdlabel[pm->rootpart].pi_flags & PIF_FFSv2) { |
1512 | #ifdef BOOTXX_FFSV2 | | 1512 | #ifdef BOOTXX_FFSV2 |
1513 | bootxxname = BOOTXX_FFSV2; | | 1513 | bootxxname = BOOTXX_FFSV2; |
1514 | #else | | 1514 | #else |
1515 | bootxxname = NULL; | | 1515 | bootxxname = NULL; |
1516 | #endif | | 1516 | #endif |
1517 | } else { | | 1517 | } else { |
1518 | #ifdef BOOTXX_FFSV1 | | 1518 | #ifdef BOOTXX_FFSV1 |
1519 | bootxxname = BOOTXX_FFSV1; | | 1519 | bootxxname = BOOTXX_FFSV1; |
1520 | #else | | 1520 | #else |
1521 | bootxxname = NULL; | | 1521 | bootxxname = NULL; |
1522 | #endif | | 1522 | #endif |
1523 | } | | 1523 | } |
1524 | break; | | 1524 | break; |
1525 | #endif | | 1525 | #endif |
1526 | #ifdef BOOTXX_LFSV2 | | 1526 | #ifdef BOOTXX_LFSV2 |
1527 | case FS_BSDLFS: | | 1527 | case FS_BSDLFS: |
1528 | bootxxname = BOOTXX_LFSV2; | | 1528 | bootxxname = BOOTXX_LFSV2; |
1529 | break; | | 1529 | break; |
1530 | #endif | | 1530 | #endif |
1531 | default: | | 1531 | default: |
1532 | bootxxname = NULL; | | 1532 | bootxxname = NULL; |
1533 | break; | | 1533 | break; |
1534 | } | | 1534 | } |
1535 | | | 1535 | |
1536 | if (bootxxname == NULL) | | 1536 | if (bootxxname == NULL) |
1537 | return NULL; | | 1537 | return NULL; |
1538 | | | 1538 | |
1539 | asprintf(&bootxx, "%s/%s", BOOTXXDIR, bootxxname); | | 1539 | asprintf(&bootxx, "%s/%s", BOOTXXDIR, bootxxname); |
1540 | return bootxx; | | 1540 | return bootxx; |
1541 | } | | 1541 | } |
1542 | #endif | | 1542 | #endif |
1543 | | | 1543 | |
1544 | static int | | 1544 | static int |
1545 | get_fsid_by_gptuuid(const char *str) | | 1545 | get_fsid_by_gptuuid(const char *str) |
1546 | { | | 1546 | { |
1547 | int i; | | 1547 | int i; |
1548 | uuid_t uuid; | | 1548 | uuid_t uuid; |
1549 | uint32_t status; | | 1549 | uint32_t status; |
1550 | | | 1550 | |
1551 | uuid_from_string(str, &uuid, &status); | | 1551 | uuid_from_string(str, &uuid, &status); |
1552 | if (status == uuid_s_ok) { | | 1552 | if (status == uuid_s_ok) { |
1553 | for (i = 0; gpt_filesystems[i].id > 0; i++) | | 1553 | for (i = 0; gpt_filesystems[i].id > 0; i++) |
1554 | if (uuid_equal(&uuid, &(gpt_filesystems[i].uuid), NULL)) | | 1554 | if (uuid_equal(&uuid, &(gpt_filesystems[i].uuid), NULL)) |
1555 | return gpt_filesystems[i].id; | | 1555 | return gpt_filesystems[i].id; |
1556 | } | | 1556 | } |
1557 | return FS_OTHER; | | 1557 | return FS_OTHER; |
1558 | } | | 1558 | } |
1559 | | | 1559 | |
1560 | const char * | | 1560 | const char * |
1561 | get_gptfs_by_id(int filesystem) | | 1561 | get_gptfs_by_id(int filesystem) |
1562 | { | | 1562 | { |
1563 | int i; | | 1563 | int i; |
1564 | for (i = 0; gpt_filesystems[i].id > 0; i++) | | 1564 | for (i = 0; gpt_filesystems[i].id > 0; i++) |
1565 | if (filesystem == gpt_filesystems[i].id) | | 1565 | if (filesystem == gpt_filesystems[i].id) |
1566 | return gpt_filesystems[i].name; | | 1566 | return gpt_filesystems[i].name; |
1567 | return NULL; | | 1567 | return NULL; |
1568 | } | | 1568 | } |
1569 | | | 1569 | |
1570 | /* from dkctl.c */ | | 1570 | /* from dkctl.c */ |
1571 | static int | | 1571 | static int |
1572 | get_dkwedges_sort(const void *a, const void *b) | | 1572 | get_dkwedges_sort(const void *a, const void *b) |
1573 | { | | 1573 | { |
1574 | const struct dkwedge_info *dkwa = a, *dkwb = b; | | 1574 | const struct dkwedge_info *dkwa = a, *dkwb = b; |
1575 | const daddr_t oa = dkwa->dkw_offset, ob = dkwb->dkw_offset; | | 1575 | const daddr_t oa = dkwa->dkw_offset, ob = dkwb->dkw_offset; |
1576 | return (oa < ob) ? -1 : (oa > ob) ? 1 : 0; | | 1576 | return (oa < ob) ? -1 : (oa > ob) ? 1 : 0; |
1577 | } | | 1577 | } |
1578 | | | 1578 | |
1579 | int | | 1579 | int |
1580 | get_dkwedges(struct dkwedge_info **dkw, const char *diskdev) | | 1580 | get_dkwedges(struct dkwedge_info **dkw, const char *diskdev) |
1581 | { | | 1581 | { |
1582 | int fd; | | 1582 | int fd; |
1583 | char buf[STRSIZE]; | | 1583 | char buf[STRSIZE]; |
1584 | size_t bufsize; | | 1584 | size_t bufsize; |
1585 | struct dkwedge_list dkwl; | | 1585 | struct dkwedge_list dkwl; |
1586 | | | 1586 | |
1587 | *dkw = NULL; | | 1587 | *dkw = NULL; |
1588 | dkwl.dkwl_buf = *dkw; | | 1588 | dkwl.dkwl_buf = *dkw; |
1589 | dkwl.dkwl_bufsize = 0; | | 1589 | dkwl.dkwl_bufsize = 0; |
1590 | fd = opendisk(diskdev, O_RDONLY, buf, STRSIZE, 0); | | 1590 | fd = opendisk(diskdev, O_RDONLY, buf, STRSIZE, 0); |
1591 | if (fd < 0) | | 1591 | if (fd < 0) |
1592 | return -1; | | 1592 | return -1; |
1593 | | | 1593 | |
1594 | for (;;) { | | 1594 | for (;;) { |
1595 | if (ioctl(fd, DIOCLWEDGES, &dkwl) == -1) | | 1595 | if (ioctl(fd, DIOCLWEDGES, &dkwl) == -1) |
1596 | return -2; | | 1596 | return -2; |
1597 | if (dkwl.dkwl_nwedges == dkwl.dkwl_ncopied) | | 1597 | if (dkwl.dkwl_nwedges == dkwl.dkwl_ncopied) |
1598 | break; | | 1598 | break; |
1599 | bufsize = dkwl.dkwl_nwedges * sizeof(**dkw); | | 1599 | bufsize = dkwl.dkwl_nwedges * sizeof(**dkw); |
1600 | if (dkwl.dkwl_bufsize < bufsize) { | | 1600 | if (dkwl.dkwl_bufsize < bufsize) { |
1601 | *dkw = realloc(dkwl.dkwl_buf, bufsize); | | 1601 | *dkw = realloc(dkwl.dkwl_buf, bufsize); |
1602 | if (*dkw == NULL) | | 1602 | if (*dkw == NULL) |
1603 | return -3; | | 1603 | return -3; |
1604 | dkwl.dkwl_buf = *dkw; | | 1604 | dkwl.dkwl_buf = *dkw; |
1605 | dkwl.dkwl_bufsize = bufsize; | | 1605 | dkwl.dkwl_bufsize = bufsize; |
1606 | } | | 1606 | } |
1607 | } | | 1607 | } |
1608 | | | 1608 | |
1609 | if (dkwl.dkwl_nwedges > 0 && *dkw != NULL) | | 1609 | if (dkwl.dkwl_nwedges > 0 && *dkw != NULL) |
1610 | qsort(*dkw, dkwl.dkwl_nwedges, sizeof(**dkw), get_dkwedges_sort); | | 1610 | qsort(*dkw, dkwl.dkwl_nwedges, sizeof(**dkw), get_dkwedges_sort); |
1611 | | | 1611 | |
1612 | close(fd); | | 1612 | close(fd); |
1613 | return dkwl.dkwl_nwedges; | | 1613 | return dkwl.dkwl_nwedges; |
1614 | } | | 1614 | } |
1615 | | | 1615 | |
1616 | /* XXX: rewrite */ | | 1616 | /* XXX: rewrite */ |
1617 | static int | | 1617 | static int |
1618 | incoregpt(pm_devs_t *pm_cur, partinfo *lp) | | 1618 | incoregpt(pm_devs_t *pm_cur, partinfo *lp) |
1619 | { | | 1619 | { |
1620 | int i, num; | | 1620 | int i, num; |
1621 | unsigned int p_num; | | 1621 | unsigned int p_num; |
1622 | uint64_t p_start, p_size; | | 1622 | uint64_t p_start, p_size; |
1623 | char *textbuf, *t, *tt, p_type[STRSIZE]; | | 1623 | char *textbuf, *t, *tt, p_type[STRSIZE]; |
1624 | struct dkwedge_info *dkw; | | 1624 | struct dkwedge_info *dkw; |
1625 | | | 1625 | |
1626 | num = get_dkwedges(&dkw, pm_cur->diskdev); | | 1626 | num = get_dkwedges(&dkw, pm_cur->diskdev); |
1627 | if (dkw != NULL) { | | 1627 | if (dkw != NULL) { |
1628 | for (i = 0; i < num && i < MAX_WEDGES; i++) | | 1628 | for (i = 0; i < num && i < MAX_WEDGES; i++) |
1629 | run_program(RUN_SILENT, "dkctl %s delwedge %s", | | 1629 | run_program(RUN_SILENT, "dkctl %s delwedge %s", |
1630 | pm_cur->diskdev, dkw[i].dkw_devname); | | 1630 | pm_cur->diskdev, dkw[i].dkw_devname); |
1631 | free (dkw); | | 1631 | free (dkw); |
1632 | } | | 1632 | } |
1633 | | | 1633 | |
1634 | if (collect(T_OUTPUT, &textbuf, "gpt show -u %s 2>/dev/null", pm_cur->diskdev) < 1) | | 1634 | if (collect(T_OUTPUT, &textbuf, "gpt show -u %s 2>/dev/null", pm_cur->diskdev) < 1) |
1635 | return -1; | | 1635 | return -1; |
1636 | | | 1636 | |
1637 | (void)strtok(textbuf, "\n"); /* ignore first line */ | | 1637 | (void)strtok(textbuf, "\n"); /* ignore first line */ |
1638 | while ((t = strtok(NULL, "\n")) != NULL) { | | 1638 | while ((t = strtok(NULL, "\n")) != NULL) { |
1639 | i = 0; p_start = 0; p_size = 0; p_num = 0; strcpy(p_type, ""); /* init */ | | 1639 | i = 0; p_start = 0; p_size = 0; p_num = 0; strcpy(p_type, ""); /* init */ |
1640 | while ((tt = strsep(&t, " \t")) != NULL) { | | 1640 | while ((tt = strsep(&t, " \t")) != NULL) { |
1641 | if (strlen(tt) == 0) | | 1641 | if (strlen(tt) == 0) |
1642 | continue; | | 1642 | continue; |
1643 | if (i == 0) | | 1643 | if (i == 0) |
1644 | p_start = strtouq(tt, NULL, 10); | | 1644 | p_start = strtouq(tt, NULL, 10); |
1645 | if (i == 1) | | 1645 | if (i == 1) |
1646 | p_size = strtouq(tt, NULL, 10); | | 1646 | p_size = strtouq(tt, NULL, 10); |
1647 | if (i == 2) | | 1647 | if (i == 2) |
1648 | p_num = strtouq(tt, NULL, 10); | | 1648 | p_num = strtouq(tt, NULL, 10); |
1649 | if (i > 2 || (i == 2 && p_num == 0)) | | 1649 | if (i > 2 || (i == 2 && p_num == 0)) |
1650 | if ( | | 1650 | if ( |
1651 | strcmp(tt, "GPT") && | | 1651 | strcmp(tt, "GPT") && |
1652 | strcmp(tt, "part") && | | 1652 | strcmp(tt, "part") && |
1653 | strcmp(tt, "-") | | 1653 | strcmp(tt, "-") |
1654 | ) | | 1654 | ) |
1655 | strlcat(p_type, tt, STRSIZE); | | 1655 | strlcat(p_type, tt, STRSIZE); |
1656 | i++; | | 1656 | i++; |
1657 | } | | 1657 | } |
1658 | if (p_start == 0 || p_size == 0) | | 1658 | if (p_start == 0 || p_size == 0) |
1659 | continue; | | 1659 | continue; |
1660 | else if (! strcmp(p_type, "Pritable")) | | 1660 | else if (! strcmp(p_type, "Pritable")) |
1661 | pm_cur->ptstart = p_start + p_size; | | 1661 | pm_cur->ptstart = p_start + p_size; |
1662 | else if (! strcmp(p_type, "Sectable")) | | 1662 | else if (! strcmp(p_type, "Sectable")) |
1663 | pm_cur->ptsize = p_start - pm_cur->ptstart - 1; | | 1663 | pm_cur->ptsize = p_start - pm_cur->ptstart - 1; |
1664 | else if (p_num == 0 && strlen(p_type) > 0) | | 1664 | else if (p_num == 0 && strlen(p_type) > 0) |
1665 | /* Utilitary entry (PMBR, etc) */ | | 1665 | /* Utilitary entry (PMBR, etc) */ |
1666 | continue; | | 1666 | continue; |
1667 | else if (p_num == 0) { | | 1667 | else if (p_num == 0) { |
1668 | /* Free space */ | | 1668 | /* Free space */ |
1669 | continue; | | 1669 | continue; |
1670 | } else { | | 1670 | } else { |
1671 | /* Usual partition */ | | 1671 | /* Usual partition */ |
1672 | lp[p_num].pi_size = p_size; | | 1672 | lp[p_num].pi_size = p_size; |
1673 | lp[p_num].pi_offset = p_start; | | 1673 | lp[p_num].pi_offset = p_start; |
1674 | lp[p_num].pi_fstype = get_fsid_by_gptuuid(p_type); | | 1674 | lp[p_num].pi_fstype = get_fsid_by_gptuuid(p_type); |
1675 | } | | 1675 | } |
1676 | } | | 1676 | } |
1677 | free(textbuf); | | 1677 | free(textbuf); |
1678 | | | 1678 | |
1679 | return 0; | | 1679 | return 0; |
1680 | } | | 1680 | } |
1681 | | | 1681 | |
1682 | static bool | | 1682 | static bool |
1683 | is_gpt(const char *dev) | | 1683 | is_gpt(const char *dev) |
1684 | { | | 1684 | { |
1685 | | | 1685 | |
1686 | check_available_binaries(); | | 1686 | check_available_binaries(); |
1687 | | | 1687 | |
1688 | if (!have_gpt) | | 1688 | if (!have_gpt) |
1689 | return false; | | 1689 | return false; |
1690 | | | 1690 | |
1691 | return run_program(RUN_SILENT | RUN_ERROR_OK, | | 1691 | return run_program(RUN_SILENT | RUN_ERROR_OK, |
1692 | "gpt -qr header %s", dev) == 0; | | 1692 | "gpt -qr header %s", dev) == 0; |
1693 | } | | 1693 | } |