|
1 /* |
|
2 * CDDL HEADER START |
|
3 * |
|
4 * The contents of this file are subject to the terms of the |
|
5 * Common Development and Distribution License, Version 1.0 only |
|
6 * (the "License"). You may not use this file except in compliance |
|
7 * with the License. |
|
8 * |
|
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE |
|
10 * or http://www.opensolaris.org/os/licensing. |
|
11 * See the License for the specific language governing permissions |
|
12 * and limitations under the License. |
|
13 * |
|
14 * When distributing Covered Code, include this CDDL HEADER in each |
|
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. |
|
16 * If applicable, add the following below this CDDL HEADER, with the |
|
17 * fields enclosed by brackets "[]" replaced with your own identifying |
|
18 * information: Portions Copyright [yyyy] [name of copyright owner] |
|
19 * |
|
20 * CDDL HEADER END |
|
21 */ |
|
22 /* |
|
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. |
|
24 * Use is subject to license terms. |
|
25 */ |
|
26 |
|
27 |
|
28 #pragma ident "%Z%%M% %I% %E% SMI" |
|
29 |
|
30 /* |
|
31 * This file contains miscellaneous device validation routines. |
|
32 */ |
|
33 |
|
34 #include "global.h" |
|
35 #include <sys/mnttab.h> |
|
36 #include <sys/mntent.h> |
|
37 #include <sys/autoconf.h> |
|
38 |
|
39 #include <signal.h> |
|
40 #include <malloc.h> |
|
41 #include <unistd.h> |
|
42 #include <string.h> |
|
43 #include <errno.h> |
|
44 #include <fcntl.h> |
|
45 #include <sys/ioctl.h> |
|
46 #include <sys/fcntl.h> |
|
47 #include <sys/stat.h> |
|
48 #include <sys/swap.h> |
|
49 #include <sys/sysmacros.h> |
|
50 #include <ctype.h> |
|
51 #include <libdiskmgt.h> |
|
52 #include <libnvpair.h> |
|
53 #include "misc.h" |
|
54 #include "checkdev.h" |
|
55 |
|
56 /* Function prototypes */ |
|
57 #ifdef __STDC__ |
|
58 |
|
59 static struct swaptable *getswapentries(void); |
|
60 static void freeswapentries(struct swaptable *); |
|
61 static int getpartition(char *pathname); |
|
62 static int checkpartitions(int bm_mounted); |
|
63 |
|
64 #else /* __STDC__ */ |
|
65 |
|
66 static struct swaptable *getswapentries(); |
|
67 static void freeswapentries(); |
|
68 static int getpartition(); |
|
69 static int checkpartitions(); |
|
70 |
|
71 #endif /* __STDC__ */ |
|
72 |
|
73 extern char *getfullname(); |
|
74 |
|
75 static struct swaptable * |
|
76 getswapentries(void) |
|
77 { |
|
78 register struct swaptable *st; |
|
79 register struct swapent *swapent; |
|
80 int i, num; |
|
81 char fullpathname[MAXPATHLEN]; |
|
82 |
|
83 /* |
|
84 * get the number of swap entries |
|
85 */ |
|
86 if ((num = swapctl(SC_GETNSWP, (void *)NULL)) == -1) { |
|
87 err_print("swapctl error "); |
|
88 fullabort(); |
|
89 } |
|
90 if (num == 0) |
|
91 return (NULL); |
|
92 if ((st = (swaptbl_t *)malloc(num * sizeof (swapent_t) + sizeof (int))) |
|
93 == NULL) { |
|
94 err_print("getswapentries: malloc failed.\n"); |
|
95 fullabort(); |
|
96 } |
|
97 swapent = st->swt_ent; |
|
98 for (i = 0; i < num; i++, swapent++) { |
|
99 if ((swapent->ste_path = malloc(MAXPATHLEN)) == NULL) { |
|
100 err_print("getswapentries: malloc failed.\n"); |
|
101 fullabort(); |
|
102 } |
|
103 } |
|
104 st->swt_n = num; |
|
105 if ((num = swapctl(SC_LIST, (void *)st)) == -1) { |
|
106 err_print("swapctl error "); |
|
107 fullabort(); |
|
108 } |
|
109 swapent = st->swt_ent; |
|
110 for (i = 0; i < num; i++, swapent++) { |
|
111 if (*swapent->ste_path != '/') { |
|
112 (void) snprintf(fullpathname, sizeof (fullpathname), |
|
113 "/dev/%s", swapent->ste_path); |
|
114 (void) strcpy(swapent->ste_path, fullpathname); |
|
115 } |
|
116 } |
|
117 return (st); |
|
118 } |
|
119 |
|
120 static void |
|
121 freeswapentries(st) |
|
122 struct swaptable *st; |
|
123 { |
|
124 register struct swapent *swapent; |
|
125 int i; |
|
126 |
|
127 swapent = st->swt_ent; |
|
128 for (i = 0; i < st->swt_n; i++, swapent++) |
|
129 free(swapent->ste_path); |
|
130 free(st); |
|
131 |
|
132 } |
|
133 |
|
134 /* |
|
135 * function getpartition: |
|
136 */ |
|
137 static int |
|
138 getpartition(pathname) |
|
139 char *pathname; |
|
140 { |
|
141 int mfd; |
|
142 struct dk_cinfo dkinfo; |
|
143 struct stat stbuf; |
|
144 char raw_device[MAXPATHLEN]; |
|
145 int found = -1; |
|
146 |
|
147 /* |
|
148 * Map the block device name to the raw device name. |
|
149 * If it doesn't appear to be a device name, skip it. |
|
150 */ |
|
151 if (match_substr(pathname, "/dev/") == 0) |
|
152 return (found); |
|
153 (void) strcpy(raw_device, "/dev/r"); |
|
154 (void) strcat(raw_device, pathname + strlen("/dev/")); |
|
155 /* |
|
156 * Determine if this appears to be a disk device. |
|
157 * First attempt to open the device. If if fails, skip it. |
|
158 */ |
|
159 if ((mfd = open(raw_device, O_RDWR | O_NDELAY)) < 0) { |
|
160 return (found); |
|
161 } |
|
162 /* |
|
163 * Must be a character device |
|
164 */ |
|
165 if (fstat(mfd, &stbuf) == -1 || !S_ISCHR(stbuf.st_mode)) { |
|
166 (void) close(mfd); |
|
167 return (found); |
|
168 } |
|
169 /* |
|
170 * Attempt to read the configuration info on the disk. |
|
171 */ |
|
172 if (ioctl(mfd, DKIOCINFO, &dkinfo) < 0) { |
|
173 (void) close(mfd); |
|
174 return (found); |
|
175 } |
|
176 /* |
|
177 * Finished with the opened device |
|
178 */ |
|
179 (void) close(mfd); |
|
180 |
|
181 /* |
|
182 * If it's not the disk we're interested in, it doesn't apply. |
|
183 */ |
|
184 if (cur_disk->disk_dkinfo.dki_ctype != dkinfo.dki_ctype || |
|
185 cur_disk->disk_dkinfo.dki_cnum != dkinfo.dki_cnum || |
|
186 cur_disk->disk_dkinfo.dki_unit != dkinfo.dki_unit || |
|
187 strcmp(cur_disk->disk_dkinfo.dki_dname, |
|
188 dkinfo.dki_dname) != 0) { |
|
189 return (found); |
|
190 } |
|
191 |
|
192 /* |
|
193 * Extract the partition that is mounted. |
|
194 */ |
|
195 return (PARTITION(stbuf.st_rdev)); |
|
196 } |
|
197 |
|
198 /* |
|
199 * This Routine checks to see if there are partitions used for swapping overlaps |
|
200 * a given portion of a disk. If the start parameter is < 0, it means |
|
201 * that the entire disk should be checked |
|
202 */ |
|
203 int |
|
204 checkswap(start, end) |
|
205 diskaddr_t start, end; |
|
206 { |
|
207 struct swaptable *st; |
|
208 struct swapent *swapent; |
|
209 int i; |
|
210 int found = 0; |
|
211 struct dk_map32 *map; |
|
212 int part; |
|
213 |
|
214 /* |
|
215 * If we are only checking part of the disk, the disk must |
|
216 * have a partition map to check against. If it doesn't, |
|
217 * we hope for the best. |
|
218 */ |
|
219 if (cur_parts == NULL) |
|
220 return (0); |
|
221 |
|
222 /* |
|
223 * check for swap entries |
|
224 */ |
|
225 st = getswapentries(); |
|
226 /* |
|
227 * if there are no swap entries return. |
|
228 */ |
|
229 if (st == (struct swaptable *)NULL) |
|
230 return (0); |
|
231 swapent = st->swt_ent; |
|
232 for (i = 0; i < st->swt_n; i++, swapent++) { |
|
233 if ((part = getpartition(swapent->ste_path)) != -1) { |
|
234 if (start == UINT_MAX64) { |
|
235 found = -1; |
|
236 break; |
|
237 } |
|
238 map = &cur_parts->pinfo_map[part]; |
|
239 if ((start >= (int)(map->dkl_cylno * spc() + |
|
240 map->dkl_nblk)) || (end < (int)(map->dkl_cylno |
|
241 * spc()))) { |
|
242 continue; |
|
243 } |
|
244 found = -1; |
|
245 break; |
|
246 }; |
|
247 } |
|
248 freeswapentries(st); |
|
249 /* |
|
250 * If we found trouble and we're running from a command file, |
|
251 * quit before doing something we really regret. |
|
252 */ |
|
253 |
|
254 if (found && option_f) { |
|
255 err_print( |
|
256 "Operation on disks being used for swapping must be interactive.\n"); |
|
257 cmdabort(SIGINT); |
|
258 } |
|
259 |
|
260 return (found); |
|
261 |
|
262 |
|
263 } |
|
264 /* |
|
265 * Determines if there are partitions that are a part of an SVM, VxVM, zpool |
|
266 * volume or a live upgrade device, overlapping a given portion of a disk. |
|
267 * Mounts and swap devices are checked in legacy format code. |
|
268 */ |
|
269 int |
|
270 checkdevinuse(char *cur_disk_path, diskaddr_t start, diskaddr_t end, int print, |
|
271 int check_label) |
|
272 { |
|
273 |
|
274 int error; |
|
275 int found = 0; |
|
276 int check = 0; |
|
277 int i; |
|
278 int bm_inuse = 0; |
|
279 int part = 0; |
|
280 uint64_t slice_start, slice_size; |
|
281 dm_descriptor_t *slices = NULL; |
|
282 nvlist_t *attrs = NULL; |
|
283 char *usage; |
|
284 char *name; |
|
285 |
|
286 /* |
|
287 * For format, we get basic 'in use' details from libdiskmgt. After |
|
288 * that we must do the appropriate checking to see if the 'in use' |
|
289 * details require a bit of additional work. |
|
290 */ |
|
291 |
|
292 dm_get_slices(cur_disk_path, &slices, &error); |
|
293 if (error) { |
|
294 err_print("Error occurred with device in use checking: %s\n", |
|
295 strerror(error)); |
|
296 return (found); |
|
297 } |
|
298 if (slices == NULL) |
|
299 return (found); |
|
300 |
|
301 for (i = 0; slices[i] != NULL; i++) { |
|
302 /* |
|
303 * If we are checking the whole disk |
|
304 * then any and all in use data is |
|
305 * relevant. |
|
306 */ |
|
307 if (start == UINT_MAX64) { |
|
308 name = dm_get_name(slices[i], &error); |
|
309 if (error != 0 || !name) { |
|
310 err_print("Error occurred with device " |
|
311 "in use checking: %s\n", |
|
312 strerror(error)); |
|
313 continue; |
|
314 } |
|
315 if (dm_inuse(name, &usage, DM_WHO_FORMAT, &error) || |
|
316 error) { |
|
317 if (error != 0) { |
|
318 dm_free_name(name); |
|
319 name = NULL; |
|
320 err_print("Error occurred with device " |
|
321 "in use checking: %s\n", |
|
322 strerror(error)); |
|
323 continue; |
|
324 } |
|
325 dm_free_name(name); |
|
326 name = NULL; |
|
327 /* |
|
328 * If this is a dump device, then it is |
|
329 * a failure. You cannot format a slice |
|
330 * that is a dedicated dump device. |
|
331 */ |
|
332 |
|
333 if (strstr(usage, DM_USE_DUMP)) { |
|
334 if (print) { |
|
335 err_print(usage); |
|
336 free(usage); |
|
337 } |
|
338 dm_free_descriptors(slices); |
|
339 return (1); |
|
340 } |
|
341 /* |
|
342 * We really found a device that is in use. |
|
343 * Set 'found' for the return value, and set |
|
344 * 'check' to indicate below that we must |
|
345 * get the partition number to set bm_inuse |
|
346 * in the event we are trying to label this |
|
347 * device. check_label is set when we are |
|
348 * checking modifications for in use slices |
|
349 * on the device. |
|
350 */ |
|
351 found ++; |
|
352 check = 1; |
|
353 if (print) { |
|
354 err_print(usage); |
|
355 free(usage); |
|
356 } |
|
357 } |
|
358 } else { |
|
359 /* |
|
360 * Before getting the in use data, verify that the |
|
361 * current slice is within the range we are checking. |
|
362 */ |
|
363 attrs = dm_get_attributes(slices[i], &error); |
|
364 if (error) { |
|
365 err_print("Error occurred with device in use " |
|
366 "checking: %s\n", strerror(error)); |
|
367 continue; |
|
368 } |
|
369 if (attrs == NULL) { |
|
370 continue; |
|
371 } |
|
372 |
|
373 (void) nvlist_lookup_uint64(attrs, DM_START, |
|
374 &slice_start); |
|
375 (void) nvlist_lookup_uint64(attrs, DM_SIZE, |
|
376 &slice_size); |
|
377 if (start >= (slice_start + slice_size) || |
|
378 (end < slice_start)) { |
|
379 nvlist_free(attrs); |
|
380 attrs = NULL; |
|
381 continue; |
|
382 } |
|
383 name = dm_get_name(slices[i], &error); |
|
384 if (error != 0 || !name) { |
|
385 err_print("Error occurred with device " |
|
386 "in use checking: %s\n", |
|
387 strerror(error)); |
|
388 nvlist_free(attrs); |
|
389 attrs = NULL; |
|
390 continue; |
|
391 } |
|
392 if (dm_inuse(name, &usage, |
|
393 DM_WHO_FORMAT, &error) || error) { |
|
394 if (error != 0) { |
|
395 dm_free_name(name); |
|
396 name = NULL; |
|
397 err_print("Error occurred with device " |
|
398 "in use checking: %s\n", |
|
399 strerror(error)); |
|
400 nvlist_free(attrs); |
|
401 attrs = NULL; |
|
402 continue; |
|
403 } |
|
404 dm_free_name(name); |
|
405 name = NULL; |
|
406 /* |
|
407 * If this is a dump device, then it is |
|
408 * a failure. You cannot format a slice |
|
409 * that is a dedicated dump device. |
|
410 */ |
|
411 if (strstr(usage, DM_USE_DUMP)) { |
|
412 if (print) { |
|
413 err_print(usage); |
|
414 free(usage); |
|
415 } |
|
416 dm_free_descriptors(slices); |
|
417 nvlist_free(attrs); |
|
418 return (1); |
|
419 } |
|
420 /* |
|
421 * We really found a device that is in use. |
|
422 * Set 'found' for the return value, and set |
|
423 * 'check' to indicate below that we must |
|
424 * get the partition number to set bm_inuse |
|
425 * in the event we are trying to label this |
|
426 * device. check_label is set when we are |
|
427 * checking modifications for in use slices |
|
428 * on the device. |
|
429 */ |
|
430 found ++; |
|
431 check = 1; |
|
432 if (print) { |
|
433 err_print(usage); |
|
434 free(usage); |
|
435 } |
|
436 } |
|
437 } |
|
438 /* |
|
439 * If check is set it means we found a slice(the current slice) |
|
440 * on this device in use in some way. We potentially want |
|
441 * to check this slice when labeling is |
|
442 * requested. We set bm_inuse with this partition value |
|
443 * for use later if check_label was set when called. |
|
444 */ |
|
445 if (check) { |
|
446 name = dm_get_name(slices[i], &error); |
|
447 if (error != 0 || !name) { |
|
448 err_print("Error occurred with device " |
|
449 "in use checking: %s\n", |
|
450 strerror(error)); |
|
451 nvlist_free(attrs); |
|
452 attrs = NULL; |
|
453 continue; |
|
454 } |
|
455 part = getpartition(name); |
|
456 dm_free_name(name); |
|
457 name = NULL; |
|
458 if (part != -1) { |
|
459 bm_inuse |= 1 << part; |
|
460 } |
|
461 check = 0; |
|
462 } |
|
463 /* |
|
464 * If we have attributes then we have successfully |
|
465 * found the slice we were looking for and we also |
|
466 * know this means we are not searching the whole |
|
467 * disk so break out of the loop |
|
468 * now. |
|
469 */ |
|
470 if (attrs) { |
|
471 nvlist_free(attrs); |
|
472 break; |
|
473 } |
|
474 } |
|
475 |
|
476 if (slices) { |
|
477 dm_free_descriptors(slices); |
|
478 } |
|
479 |
|
480 /* |
|
481 * The user is trying to label the disk. We have to do special |
|
482 * checking here to ensure they are not trying to modify a slice |
|
483 * that is in use in an incompatible way. |
|
484 */ |
|
485 if (check_label && bm_inuse) { |
|
486 /* |
|
487 * !0 indicates that we found a |
|
488 * problem. In this case, we have overloaded |
|
489 * the use of checkpartitions to work for |
|
490 * in use devices. bm_inuse is representative |
|
491 * of the slice that is in use, not that |
|
492 * is mounted as is in the case of the normal |
|
493 * use of checkpartitions. |
|
494 * |
|
495 * The call to checkpartitions will return !0 if |
|
496 * we are trying to shrink a device that we have found |
|
497 * to be in use above. |
|
498 */ |
|
499 return (checkpartitions(bm_inuse)); |
|
500 } |
|
501 |
|
502 return (found); |
|
503 } |
|
504 /* |
|
505 * This routine checks to see if there are mounted partitions overlapping |
|
506 * a given portion of a disk. If the start parameter is < 0, it means |
|
507 * that the entire disk should be checked. |
|
508 */ |
|
509 int |
|
510 checkmount(start, end) |
|
511 diskaddr_t start, end; |
|
512 { |
|
513 FILE *fp; |
|
514 int found = 0; |
|
515 struct dk_map32 *map; |
|
516 int part; |
|
517 struct mnttab mnt_record; |
|
518 struct mnttab *mp = &mnt_record; |
|
519 |
|
520 /* |
|
521 * If we are only checking part of the disk, the disk must |
|
522 * have a partition map to check against. If it doesn't, |
|
523 * we hope for the best. |
|
524 */ |
|
525 if (cur_parts == NULL) |
|
526 return (0); |
|
527 |
|
528 /* |
|
529 * Lock out interrupts because of the mntent protocol. |
|
530 */ |
|
531 enter_critical(); |
|
532 /* |
|
533 * Open the mount table. |
|
534 */ |
|
535 fp = fopen(MNTTAB, "r"); |
|
536 if (fp == NULL) { |
|
537 err_print("Unable to open mount table.\n"); |
|
538 fullabort(); |
|
539 } |
|
540 /* |
|
541 * Loop through the mount table until we run out of entries. |
|
542 */ |
|
543 while ((getmntent(fp, mp)) != -1) { |
|
544 |
|
545 if ((part = getpartition(mp->mnt_special)) == -1) |
|
546 continue; |
|
547 |
|
548 /* |
|
549 * It's a mount on the disk we're checking. If we are |
|
550 * checking whole disk, then we found trouble. We can |
|
551 * quit searching. |
|
552 */ |
|
553 if (start == UINT_MAX64) { |
|
554 found = -1; |
|
555 break; |
|
556 } |
|
557 |
|
558 /* |
|
559 * If the partition overlaps the zone we're checking, |
|
560 * then we found trouble. We can quit searching. |
|
561 */ |
|
562 map = &cur_parts->pinfo_map[part]; |
|
563 if ((start >= (int)(map->dkl_cylno * spc() + map->dkl_nblk)) || |
|
564 (end < (int)(map->dkl_cylno * spc()))) { |
|
565 continue; |
|
566 } |
|
567 found = -1; |
|
568 break; |
|
569 } |
|
570 /* |
|
571 * Close down the mount table. |
|
572 */ |
|
573 (void) fclose(fp); |
|
574 exit_critical(); |
|
575 |
|
576 /* |
|
577 * If we found trouble and we're running from a command file, |
|
578 * quit before doing something we really regret. |
|
579 */ |
|
580 |
|
581 if (found && option_f) { |
|
582 err_print("Operation on mounted disks must be interactive.\n"); |
|
583 cmdabort(SIGINT); |
|
584 } |
|
585 /* |
|
586 * Return the result. |
|
587 */ |
|
588 return (found); |
|
589 } |
|
590 |
|
591 int |
|
592 check_label_with_swap() |
|
593 { |
|
594 int i; |
|
595 struct swaptable *st; |
|
596 struct swapent *swapent; |
|
597 int part; |
|
598 int bm_swap = 0; |
|
599 |
|
600 /* |
|
601 * If we are only checking part of the disk, the disk must |
|
602 * have a partition map to check against. If it doesn't, |
|
603 * we hope for the best. |
|
604 */ |
|
605 if (cur_parts == NULL) |
|
606 return (0); /* Will be checked later */ |
|
607 |
|
608 /* |
|
609 * Check for swap entries |
|
610 */ |
|
611 st = getswapentries(); |
|
612 /* |
|
613 * if there are no swap entries return. |
|
614 */ |
|
615 if (st == (struct swaptable *)NULL) |
|
616 return (0); |
|
617 swapent = st->swt_ent; |
|
618 for (i = 0; i < st->swt_n; i++, swapent++) |
|
619 if ((part = getpartition(swapent->ste_path)) != -1) |
|
620 bm_swap |= (1 << part); |
|
621 freeswapentries(st); |
|
622 |
|
623 return (checkpartitions(bm_swap)); |
|
624 } |
|
625 |
|
626 /* |
|
627 * Check the new label with the existing label on the disk, |
|
628 * to make sure that any mounted partitions are not being |
|
629 * affected by writing the new label. |
|
630 */ |
|
631 int |
|
632 check_label_with_mount() |
|
633 { |
|
634 FILE *fp; |
|
635 int part; |
|
636 struct mnttab mnt_record; |
|
637 struct mnttab *mp = &mnt_record; |
|
638 int bm_mounted = 0; |
|
639 |
|
640 |
|
641 /* |
|
642 * If we are only checking part of the disk, the disk must |
|
643 * have a partition map to check against. If it doesn't, |
|
644 * we hope for the best. |
|
645 */ |
|
646 if (cur_parts == NULL) |
|
647 return (0); /* Will be checked later */ |
|
648 |
|
649 /* |
|
650 * Lock out interrupts because of the mntent protocol. |
|
651 */ |
|
652 enter_critical(); |
|
653 /* |
|
654 * Open the mount table. |
|
655 */ |
|
656 fp = fopen(MNTTAB, "r"); |
|
657 if (fp == NULL) { |
|
658 err_print("Unable to open mount table.\n"); |
|
659 fullabort(); |
|
660 } |
|
661 /* |
|
662 * Loop through the mount table until we run out of entries. |
|
663 */ |
|
664 while ((getmntent(fp, mp)) != -1) { |
|
665 if ((part = getpartition(mp->mnt_special)) != -1) |
|
666 bm_mounted |= (1 << part); |
|
667 } |
|
668 /* |
|
669 * Close down the mount table. |
|
670 */ |
|
671 (void) fclose(fp); |
|
672 exit_critical(); |
|
673 |
|
674 return (checkpartitions(bm_mounted)); |
|
675 |
|
676 } |
|
677 |
|
678 /* |
|
679 * This Routine checks if any partitions specified |
|
680 * are affected by writing the new label |
|
681 */ |
|
682 static int |
|
683 checkpartitions(int bm_mounted) |
|
684 { |
|
685 struct dk_map32 *n; |
|
686 struct dk_map *o; |
|
687 struct dk_allmap old_map; |
|
688 int i, found = 0; |
|
689 |
|
690 /* |
|
691 * Now we need to check that the current partition list and the |
|
692 * previous partition list (which there must be if we actually |
|
693 * have partitions mounted) overlap in any way on the mounted |
|
694 * partitions |
|
695 */ |
|
696 |
|
697 /* |
|
698 * Get the "real" (on-disk) version of the partition table |
|
699 */ |
|
700 if (ioctl(cur_file, DKIOCGAPART, &old_map) == -1) { |
|
701 err_print("Unable to get current partition map.\n"); |
|
702 return (-1); |
|
703 } |
|
704 for (i = 0; i < NDKMAP; i++) { |
|
705 if (bm_mounted & (1 << i)) { |
|
706 /* |
|
707 * This partition is mounted |
|
708 */ |
|
709 o = &old_map.dka_map[i]; |
|
710 n = &cur_parts->pinfo_map[i]; |
|
711 #ifdef DEBUG |
|
712 fmt_print( |
|
713 "checkpartitions :checking partition '%c' \n", i + PARTITION_BASE); |
|
714 #endif |
|
715 /* |
|
716 * If partition is identical, we're fine. |
|
717 * If the partition grows, we're also fine, because |
|
718 * the routines in partition.c check for overflow. |
|
719 * It will (ultimately) be up to the routines in |
|
720 * partition.c to warn about creation of overlapping |
|
721 * partitions |
|
722 */ |
|
723 if (o->dkl_cylno == n->dkl_cylno && |
|
724 o->dkl_nblk <= n->dkl_nblk) { |
|
725 #ifdef DEBUG |
|
726 if (o->dkl_nblk < n->dkl_nblk) { |
|
727 fmt_print( |
|
728 "- new partition larger by %d blocks", n->dkl_nblk-o->dkl_nblk); |
|
729 } |
|
730 fmt_print("\n"); |
|
731 #endif |
|
732 continue; |
|
733 } |
|
734 #ifdef DEBUG |
|
735 fmt_print("- changes; old (%d,%d)->new (%d,%d)\n", |
|
736 o->dkl_cylno, o->dkl_nblk, n->dkl_cylno, |
|
737 n->dkl_nblk); |
|
738 #endif |
|
739 found = -1; |
|
740 } |
|
741 if (found) |
|
742 break; |
|
743 } |
|
744 |
|
745 /* |
|
746 * If we found trouble and we're running from a command file, |
|
747 * quit before doing something we really regret. |
|
748 */ |
|
749 |
|
750 if (found && option_f) { |
|
751 err_print("Operation on mounted disks or \ |
|
752 disks currently being used for swapping must be interactive.\n"); |
|
753 cmdabort(SIGINT); |
|
754 } |
|
755 /* |
|
756 * Return the result. |
|
757 */ |
|
758 return (found); |
|
759 } |