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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * This file contains functions that implement the fdisk menu commands. 28 */ 29 #include "global.h" 30 #include <errno.h> 31 #include <sys/time.h> 32 #include <sys/resource.h> 33 #include <sys/wait.h> 34 #include <signal.h> 35 #include <string.h> 36 #include <fcntl.h> 37 #include <stdlib.h> 38 #include <sys/dktp/fdisk.h> 39 #include <sys/stat.h> 40 #include <sys/dklabel.h> 41 42 #include "main.h" 43 #include "analyze.h" 44 #include "menu.h" 45 #include "menu_command.h" 46 #include "menu_defect.h" 47 #include "menu_partition.h" 48 #include "menu_fdisk.h" 49 #include "param.h" 50 #include "misc.h" 51 #include "label.h" 52 #include "startup.h" 53 #include "partition.h" 54 #include "prompts.h" 55 #include "checkdev.h" 56 #include "io.h" 57 #include "ctlr_scsi.h" 58 #include "auto_sense.h" 59 60 extern struct menu_item menu_fdisk[]; 61 62 /* 63 * Byte swapping macros for accessing struct ipart 64 * to resolve little endian on Sparc. 65 */ 66 #if defined(sparc) 67 #define les(val) ((((val)&0xFF)<<8)|(((val)>>8)&0xFF)) 68 #define lel(val) (((unsigned)(les((val)&0x0000FFFF))<<16) | \ 69 (les((unsigned)((val)&0xffff0000)>>16))) 70 71 #elif defined(i386) 72 73 #define les(val) (val) 74 #define lel(val) (val) 75 76 #else /* defined(sparc) */ 77 78 #error No Platform defined 79 80 #endif /* defined(sparc) */ 81 82 83 /* Function prototypes */ 84 #ifdef __STDC__ 85 86 #if defined(sparc) 87 88 static int getbyte(uchar_t **); 89 static int getlong(uchar_t **); 90 91 #endif /* defined(sparc) */ 92 93 static int get_solaris_part(int fd, struct ipart *ipart); 94 95 #else /* __STDC__ */ 96 97 #if defined(sparc) 98 99 static int getbyte(); 100 static int getlong(); 101 102 #endif /* defined(sparc) */ 103 104 static int get_solaris_part(); 105 106 #endif /* __STDC__ */ 107 108 /* 109 * Handling the alignment problem of struct ipart. 110 */ 111 static void 112 fill_ipart(char *bootptr, struct ipart *partp) 113 { 114 #if defined(sparc) 115 /* 116 * Sparc platform: 117 * 118 * Packing short/word for struct ipart to resolve 119 * little endian on Sparc since it is not 120 * properly aligned on Sparc. 121 */ 122 partp->bootid = getbyte((uchar_t **)&bootptr); 123 partp->beghead = getbyte((uchar_t **)&bootptr); 124 partp->begsect = getbyte((uchar_t **)&bootptr); 125 partp->begcyl = getbyte((uchar_t **)&bootptr); 126 partp->systid = getbyte((uchar_t **)&bootptr); 127 partp->endhead = getbyte((uchar_t **)&bootptr); 128 partp->endsect = getbyte((uchar_t **)&bootptr); 129 partp->endcyl = getbyte((uchar_t **)&bootptr); 130 partp->relsect = getlong((uchar_t **)&bootptr); 131 partp->numsect = getlong((uchar_t **)&bootptr); 132 #elif defined(i386) 133 /* 134 * i386 platform: 135 * 136 * The fdisk table does not begin on a 4-byte boundary within 137 * the master boot record; so, we need to recopy its contents 138 * to another data structure to avoid an alignment exception. 139 */ 140 (void) bcopy(bootptr, partp, sizeof (struct ipart)); 141 #else 142 #error No Platform defined 143 #endif /* defined(sparc) */ 144 } 145 146 /* 147 * Get a correct byte/short/word routines for Sparc platform. 148 */ 149 #if defined(sparc) 150 static int 151 getbyte(uchar_t **bp) 152 { 153 int b; 154 155 b = **bp; 156 *bp = *bp + 1; 157 return (b); 158 } 159 160 #ifdef DEADCODE 161 static int 162 getshort(uchar_t **bp) 163 { 164 int b; 165 166 b = ((**bp) << 8) | *(*bp + 1); 167 *bp += 2; 168 return (b); 169 } 170 #endif /* DEADCODE */ 171 172 static int 173 getlong(uchar_t **bp) 174 { 175 int b, bh, bl; 176 177 bh = ((**bp) << 8) | *(*bp + 1); 178 *bp += 2; 179 bl = ((**bp) << 8) | *(*bp + 1); 180 *bp += 2; 181 182 b = (bh << 16) | bl; 183 return (b); 184 } 185 #endif /* defined(sparc) */ 186 187 /* 188 * Convert cn[tn]dn to cn[tn]dns2 path 189 */ 190 static void 191 get_sname(char *name) 192 { 193 char buf[MAXPATHLEN]; 194 char *devp = "/dev/dsk"; 195 char *rdevp = "/dev/rdsk"; 196 char np[MAXNAMELEN]; 197 char *npt; 198 199 /* 200 * If it is a full path /dev/[r]dsk/cn[tn]dn, use this path 201 */ 202 (void) strcpy(np, cur_disk->disk_name); 203 if (strncmp(rdevp, cur_disk->disk_name, strlen(rdevp)) == 0 || 204 strncmp(devp, cur_disk->disk_name, strlen(devp)) == 0) { 205 /* 206 * Skip if the path is already included with sN 207 */ 208 if (strchr(np, 's') == strrchr(np, 's')) { 209 npt = strrchr(np, 'p'); 210 /* If pN is found, do not include it */ 211 if (npt != NULL) { 212 *npt = '\0'; 213 } 214 (void) snprintf(buf, sizeof (buf), "%ss2", np); 215 } else { 216 (void) snprintf(buf, sizeof (buf), "%s", np); 217 } 218 } else { 219 (void) snprintf(buf, sizeof (buf), "/dev/rdsk/%ss2", np); 220 } 221 (void) strcpy(name, buf); 222 } 223 224 /* 225 * Convert cn[tn]dnsn to cn[tn]dnp0 path 226 */ 227 static void 228 get_pname(char *name) 229 { 230 char buf[MAXPATHLEN]; 231 char *devp = "/dev/dsk"; 232 char *rdevp = "/dev/rdsk"; 233 char np[MAXNAMELEN]; 234 char *npt; 235 236 /* 237 * If it is a full path /dev/[r]dsk/cn[tn]dnsn, use this path 238 */ 239 if (cur_disk == NULL) { 240 (void) strcpy(np, x86_devname); 241 } else { 242 (void) strcpy(np, cur_disk->disk_name); 243 } 244 245 if (strncmp(rdevp, np, strlen(rdevp)) == 0 || 246 strncmp(devp, np, strlen(devp)) == 0) { 247 /* 248 * Skip if the path is already included with pN 249 */ 250 if (strchr(np, 'p') == NULL) { 251 npt = strrchr(np, 's'); 252 /* If sN is found, do not include it */ 253 if (isdigit(*++npt)) { 254 *--npt = '\0'; 255 } 256 (void) snprintf(buf, sizeof (buf), "%sp0", np); 257 } else { 258 (void) snprintf(buf, sizeof (buf), "%s", np); 259 } 260 } else { 261 (void) snprintf(buf, sizeof (buf), "/dev/rdsk/%sp0", np); 262 } 263 (void) strcpy(name, buf); 264 } 265 266 /* 267 * Open file descriptor for current disk (cur_file) 268 * with "p0" path or cur_disk->disk_path 269 */ 270 void 271 open_cur_file(int mode) 272 { 273 char *dkpath; 274 char pbuf[MAXPATHLEN]; 275 276 switch (mode) { 277 case FD_USE_P0_PATH: 278 (void) get_pname(&pbuf[0]); 279 dkpath = pbuf; 280 break; 281 case FD_USE_CUR_DISK_PATH: 282 if (cur_disk->fdisk_part.systid == SUNIXOS || 283 cur_disk->fdisk_part.systid == SUNIXOS2) { 284 (void) get_sname(&pbuf[0]); 285 dkpath = pbuf; 286 } else { 287 dkpath = cur_disk->disk_path; 288 } 289 break; 290 default: 291 err_print("Error: Invalid mode option for opening cur_file\n"); 292 fullabort(); 293 } 294 295 /* Close previous cur_file */ 296 (void) close(cur_file); 297 /* Open cur_file with the required path dkpath */ 298 if ((cur_file = open_disk(dkpath, O_RDWR | O_NDELAY)) < 0) { 299 err_print( 300 "Error: can't open selected disk '%s'.\n", dkpath); 301 fullabort(); 302 } 303 } 304 305 306 /* 307 * This routine implements the 'fdisk' command. It simply runs 308 * the fdisk command on the current disk. 309 * Use of this is restricted to interactive mode only. 310 */ 311 int 312 c_fdisk() 313 { 314 315 char buf[MAXPATHLEN]; 316 char pbuf[MAXPATHLEN]; 317 struct stat statbuf; 318 319 /* 320 * We must be in interactive mode to use the fdisk command 321 */ 322 if (option_f != (char *)NULL || isatty(0) != 1 || isatty(1) != 1) { 323 err_print("Fdisk command is for interactive use only!\n"); 324 return (-1); 325 } 326 327 /* 328 * There must be a current disk type and a current disk 329 */ 330 if (cur_dtype == NULL) { 331 err_print("Current Disk Type is not set.\n"); 332 return (-1); 333 } 334 335 /* 336 * Before running the fdisk command, get file status of 337 * /dev/rdsk/cn[tn]dnp0 path to see if this disk 338 * supports fixed disk partition table. 339 */ 340 (void) get_pname(&pbuf[0]); 341 if (stat(pbuf, (struct stat *)&statbuf) == -1 || 342 !S_ISCHR(statbuf.st_mode)) { 343 err_print( 344 "Disk does not support fixed disk partition table\n"); 345 return (0); 346 } 347 348 /* 349 * Run the fdisk program. 350 */ 351 (void) snprintf(buf, sizeof (buf), "fdisk %s\n", pbuf); 352 (void) system(buf); 353 354 /* 355 * Open cur_file with "p0" path for accessing the fdisk table 356 */ 357 (void) open_cur_file(FD_USE_P0_PATH); 358 359 /* 360 * Get solaris partition information in the fdisk partition table 361 */ 362 if (get_solaris_part(cur_file, &cur_disk->fdisk_part) == -1) { 363 err_print("No fdisk solaris partition found\n"); 364 cur_disk->fdisk_part.numsect = 0; /* No Solaris */ 365 } 366 367 /* 368 * Restore cur_file with cur_disk->disk_path 369 */ 370 (void) open_cur_file(FD_USE_CUR_DISK_PATH); 371 372 return (0); 373 } 374 375 /* 376 * Read MBR on the disk 377 * if the Solaris partition has changed, 378 * reread the vtoc 379 */ 380 #ifdef DEADCODE 381 static void 382 update_cur_parts() 383 { 384 385 int i; 386 register struct partition_info *parts; 387 388 for (i = 0; i < NDKMAP; i++) { 389 #if defined(_SUNOS_VTOC_16) 390 if (cur_parts->vtoc.v_part[i].p_tag && 391 cur_parts->vtoc.v_part[i].p_tag != V_ALTSCTR) { 392 cur_parts->vtoc.v_part[i].p_start = 0; 393 cur_parts->vtoc.v_part[i].p_size = 0; 394 395 #endif 396 cur_parts->pinfo_map[i].dkl_nblk = 0; 397 cur_parts->pinfo_map[i].dkl_cylno = 0; 398 cur_parts->vtoc.v_part[i].p_tag = 399 default_vtoc_map[i].p_tag; 400 cur_parts->vtoc.v_part[i].p_flag = 401 default_vtoc_map[i].p_flag; 402 #if defined(_SUNOS_VTOC_16) 403 } 404 #endif 405 } 406 cur_parts->pinfo_map[C_PARTITION].dkl_nblk = ncyl * spc(); 407 408 #if defined(_SUNOS_VTOC_16) 409 /* 410 * Adjust for the boot partitions 411 */ 412 cur_parts->pinfo_map[I_PARTITION].dkl_nblk = spc(); 413 cur_parts->pinfo_map[I_PARTITION].dkl_cylno = 0; 414 cur_parts->vtoc.v_part[C_PARTITION].p_start = 415 cur_parts->pinfo_map[C_PARTITION].dkl_cylno * nhead * nsect; 416 cur_parts->vtoc.v_part[C_PARTITION].p_size = 417 cur_parts->pinfo_map[C_PARTITION].dkl_nblk; 418 419 cur_parts->vtoc.v_part[I_PARTITION].p_start = 420 cur_parts->pinfo_map[I_PARTITION].dkl_cylno; 421 cur_parts->vtoc.v_part[I_PARTITION].p_size = 422 cur_parts->pinfo_map[I_PARTITION].dkl_nblk; 423 424 #endif /* defined(_SUNOS_VTOC_16) */ 425 parts = cur_dtype->dtype_plist; 426 cur_dtype->dtype_ncyl = ncyl; 427 cur_dtype->dtype_plist = cur_parts; 428 parts->pinfo_name = cur_parts->pinfo_name; 429 cur_disk->disk_parts = cur_parts; 430 cur_ctype->ctype_dlist = cur_dtype; 431 432 } 433 #endif /* DEADCODE */ 434 435 static int 436 get_solaris_part(int fd, struct ipart *ipart) 437 { 438 int i; 439 struct ipart ip; 440 int status; 441 char *mbr; 442 char *bootptr; 443 struct dk_label update_label; 444 445 (void) lseek(fd, 0, 0); 446 447 /* 448 * We may get mbr of different size, but the first 512 bytes 449 * are valid information. 450 */ 451 mbr = malloc(cur_blksz); 452 if (mbr == NULL) { 453 err_print("No memory available.\n"); 454 return (-1); 455 } 456 status = read(fd, mbr, cur_blksz); 457 458 if (status != cur_blksz) { 459 err_print("Bad read of fdisk partition. Status = %x\n", status); 460 err_print("Cannot read fdisk partition information.\n"); 461 free(mbr); 462 return (-1); 463 } 464 465 (void) memcpy(&boot_sec, mbr, sizeof (struct mboot)); 466 free(mbr); 467 468 for (i = 0; i < FD_NUMPART; i++) { 469 int ipc; 470 471 ipc = i * sizeof (struct ipart); 472 473 /* Handling the alignment problem of struct ipart */ 474 bootptr = &boot_sec.parts[ipc]; 475 (void) fill_ipart(bootptr, &ip); 476 477 /* 478 * we are interested in Solaris and EFI partition types 479 */ 480 if (ip.systid == SUNIXOS || 481 ip.systid == SUNIXOS2 || 482 ip.systid == EFI_PMBR) { 483 /* 484 * if the disk has an EFI label, nhead and nsect may 485 * be zero. This test protects us from FPE's, and 486 * format still seems to work fine 487 */ 488 if (nhead != 0 && nsect != 0) { 489 pcyl = lel(ip.numsect) / (nhead * nsect); 490 xstart = lel(ip.relsect) / (nhead * nsect); 491 ncyl = pcyl - acyl; 492 } 493 #ifdef DEBUG 494 else { 495 err_print("Critical geometry values are zero:\n" 496 "\tnhead = %d; nsect = %d\n", nhead, 497 nsect); 498 } 499 #endif /* DEBUG */ 500 501 solaris_offset = (uint_t)lel(ip.relsect); 502 break; 503 } 504 } 505 506 if (i == FD_NUMPART) { 507 err_print("Solaris fdisk partition not found\n"); 508 return (-1); 509 } 510 511 /* 512 * compare the previous and current Solaris partition 513 * but don't use bootid in determination of Solaris partition changes 514 */ 515 ipart->bootid = ip.bootid; 516 status = bcmp(&ip, ipart, sizeof (struct ipart)); 517 518 bcopy(&ip, ipart, sizeof (struct ipart)); 519 520 /* if the disk partitioning has changed - get the VTOC */ 521 if (status) { 522 struct extvtoc exvtoc; 523 struct vtoc vtoc; 524 525 status = ioctl(fd, DKIOCGEXTVTOC, &exvtoc); 526 if (status == -1) { 527 i = errno; 528 /* Try the old ioctl DKIOCGVTOC */ 529 status = ioctl(fd, DKIOCGVTOC, &vtoc); 530 if (status == -1) { 531 err_print("Bad ioctl DKIOCGEXTVTOC.\n"); 532 err_print("errno=%d %s\n", i, strerror(i)); 533 err_print("Cannot read vtoc information.\n"); 534 return (-1); 535 } 536 } 537 538 status = read_label(fd, &update_label); 539 if (status == -1) { 540 err_print("Cannot read label information.\n"); 541 return (-1); 542 } 543 544 /* copy vtoc information */ 545 cur_parts->vtoc = update_label.dkl_vtoc; 546 547 #if defined(_SUNOS_VTOC_16) 548 /* 549 * this is to update the slice table on x86 550 * we don't care about VTOC8 here 551 */ 552 for (i = 0; i < NDKMAP; i ++) { 553 cur_parts->pinfo_map[i].dkl_cylno = 554 update_label.dkl_vtoc.v_part[i].p_start / 555 ((int)(update_label.dkl_nhead * 556 update_label.dkl_nsect)); 557 cur_parts->pinfo_map[i].dkl_nblk = 558 update_label.dkl_vtoc.v_part[i].p_size; 559 } 560 #endif /* defined(_SUNOS_VTOC_16) */ 561 562 cur_dtype->dtype_ncyl = update_label.dkl_ncyl; 563 cur_dtype->dtype_pcyl = update_label.dkl_pcyl; 564 cur_dtype->dtype_acyl = update_label.dkl_acyl; 565 cur_dtype->dtype_nhead = update_label.dkl_nhead; 566 cur_dtype->dtype_nsect = update_label.dkl_nsect; 567 ncyl = cur_dtype->dtype_ncyl; 568 acyl = cur_dtype->dtype_acyl; 569 pcyl = cur_dtype->dtype_pcyl; 570 nsect = cur_dtype->dtype_nsect; 571 nhead = cur_dtype->dtype_nhead; 572 } 573 574 return (0); 575 } 576 577 578 int 579 copy_solaris_part(struct ipart *ipart) 580 { 581 582 int status, i, fd; 583 struct mboot mboot; 584 char *mbr; 585 struct ipart ip; 586 char buf[MAXPATHLEN]; 587 char *bootptr; 588 struct stat statbuf; 589 590 (void) get_pname(&buf[0]); 591 if (stat(buf, &statbuf) == -1 || 592 !S_ISCHR(statbuf.st_mode) || 593 ((cur_label == L_TYPE_EFI) && 594 (cur_disk->disk_flags & DSK_LABEL_DIRTY))) { 595 /* 596 * Make sure to reset solaris_offset to zero if it is 597 * previously set by a selected disk that 598 * supports the fdisk table. 599 */ 600 solaris_offset = 0; 601 /* 602 * Return if this disk does not support fdisk table or 603 * if it uses an EFI label but has not yet been labelled. 604 * If the EFI label has not been written then the open 605 * on the partition will fail. 606 */ 607 return (0); 608 } 609 610 if ((fd = open(buf, O_RDONLY)) < 0) { 611 err_print("Error: can't open disk '%s'.\n", buf); 612 return (-1); 613 } 614 615 /* 616 * We may get mbr of different size, but the first 512 bytes 617 * are valid information. 618 */ 619 mbr = malloc(cur_blksz); 620 if (mbr == NULL) { 621 err_print("No memory available.\n"); 622 return (-1); 623 } 624 status = read(fd, mbr, cur_blksz); 625 626 if (status != cur_blksz) { 627 err_print("Bad read of fdisk partition.\n"); 628 (void) close(fd); 629 free(mbr); 630 return (-1); 631 } 632 633 (void) memcpy(&mboot, mbr, sizeof (struct mboot)); 634 635 for (i = 0; i < FD_NUMPART; i++) { 636 int ipc; 637 638 ipc = i * sizeof (struct ipart); 639 640 /* Handling the alignment problem of struct ipart */ 641 bootptr = &mboot.parts[ipc]; 642 (void) fill_ipart(bootptr, &ip); 643 644 if (ip.systid == SUNIXOS || 645 ip.systid == SUNIXOS2 || 646 ip.systid == EFI_PMBR) { 647 solaris_offset = lel(ip.relsect); 648 bcopy(&ip, ipart, sizeof (struct ipart)); 649 650 /* 651 * if the disk has an EFI label, we typically won't 652 * have values for nhead and nsect. format seems to 653 * work without them, and we need to protect ourselves 654 * from FPE's 655 */ 656 if (nhead != 0 && nsect != 0) { 657 pcyl = lel(ip.numsect) / (nhead * nsect); 658 ncyl = pcyl - acyl; 659 } 660 #ifdef DEBUG 661 else { 662 err_print("Critical geometry values are zero:\n" 663 "\tnhead = %d; nsect = %d\n", nhead, 664 nsect); 665 } 666 #endif /* DEBUG */ 667 668 break; 669 } 670 } 671 672 (void) close(fd); 673 free(mbr); 674 return (0); 675 } 676 677 #if defined(_FIRMWARE_NEEDS_FDISK) 678 int 679 auto_solaris_part(struct dk_label *label) 680 { 681 682 int status, i, fd; 683 struct mboot mboot; 684 char *mbr; 685 struct ipart ip; 686 char *bootptr; 687 char pbuf[MAXPATHLEN]; 688 689 (void) get_pname(&pbuf[0]); 690 if ((fd = open_disk(pbuf, O_RDONLY)) < 0) { 691 err_print("Error: can't open selected disk '%s'.\n", pbuf); 692 return (-1); 693 } 694 695 /* 696 * We may get mbr of different size, but the first 512 bytes 697 * are valid information. 698 */ 699 mbr = malloc(cur_blksz); 700 if (mbr == NULL) { 701 err_print("No memory available.\n"); 702 return (-1); 703 } 704 status = read(fd, mbr, cur_blksz); 705 706 if (status != cur_blksz) { 707 err_print("Bad read of fdisk partition.\n"); 708 free(mbr); 709 return (-1); 710 } 711 712 (void) memcpy(&mboot, mbr, sizeof (struct mboot)); 713 714 for (i = 0; i < FD_NUMPART; i++) { 715 int ipc; 716 717 ipc = i * sizeof (struct ipart); 718 719 /* Handling the alignment problem of struct ipart */ 720 bootptr = &mboot.parts[ipc]; 721 (void) fill_ipart(bootptr, &ip); 722 723 /* 724 * if the disk has an EFI label, the nhead and nsect fields 725 * the label may be zero. This protects us from FPE's, and 726 * format still seems to work happily 727 */ 728 if (ip.systid == SUNIXOS || 729 ip.systid == SUNIXOS2 || 730 ip.systid == EFI_PMBR) { 731 if ((label->dkl_nhead != 0) && 732 (label->dkl_nsect != 0)) { 733 label->dkl_pcyl = lel(ip.numsect) / 734 (label->dkl_nhead * label->dkl_nsect); 735 label->dkl_ncyl = label->dkl_pcyl - 736 label->dkl_acyl; 737 } 738 #ifdef DEBUG 739 else { 740 err_print("Critical label fields aren't " 741 "non-zero:\n" 742 "\tlabel->dkl_nhead = %d; " 743 "label->dkl_nsect = " 744 "%d\n", label->dkl_nhead, 745 label->dkl_nsect); 746 } 747 #endif /* DEBUG */ 748 749 solaris_offset = lel(ip.relsect); 750 break; 751 } 752 } 753 754 (void) close(fd); 755 free(mbr); 756 return (0); 757 } 758 #endif /* defined(_FIRMWARE_NEEDS_FDISK) */ 759 760 761 int 762 good_fdisk() 763 { 764 char buf[MAXPATHLEN]; 765 struct stat statbuf; 766 767 (void) get_pname(&buf[0]); 768 if (stat(buf, &statbuf) == -1 || 769 !S_ISCHR(statbuf.st_mode) || 770 cur_label == L_TYPE_EFI) { 771 /* 772 * Return if this disk does not support fdisk table or 773 * if the disk is labeled with EFI. 774 */ 775 return (1); 776 } 777 778 if (lel(cur_disk->fdisk_part.numsect) > 0) { 779 return (1); 780 } else { 781 err_print("WARNING - "); 782 err_print("This disk may be in use by an application " 783 "that has\n\t modified the fdisk table. Ensure " 784 "that this disk is\n\t not currently in use " 785 "before proceeding to use fdisk.\n"); 786 return (0); 787 } 788 } 789