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