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