diff -u -r fdisk.old/Makefile fdisk/Makefile --- fdisk.old/Makefile Tue Apr 27 14:11:03 1999 +++ fdisk/Makefile Fri Jun 25 12:26:55 1999 @@ -21,7 +21,7 @@ ifeq "$(CPU)" "m68k" # It seems the m68k people do not want *fdisk else -SBIN:=$(SBIN) fdisk +SBIN:=$(SBIN) fdisk sunfdisk MAN8:=$(MAN8) fdisk.8 ifneq "$(CPU)" "sparc" SBIN:=$(SBIN) $(CFDISK) sfdisk @@ -30,6 +30,8 @@ endif all: $(SBIN) $(NOTMADE) + +sunfdisk: sunfdisk.o llseek.o fdisksunlabel.o cfdisk.o: cfdisk.c ifeq "$(HAVE_SLANG)" "yes" diff -u -r fdisk.old/fdisksunlabel.c fdisk/fdisksunlabel.c --- fdisk.old/fdisksunlabel.c Sat May 1 13:39:23 1999 +++ fdisk/fdisksunlabel.c Fri Jun 25 12:25:03 1999 @@ -16,17 +16,24 @@ #include /* write */ #include /* ioctl */ #include /* stat */ +#if defined (sun) && defined (__svr4__) +#include +#endif #include "nls.h" +#if !(defined (sun) && defined (__svr4__)) #include +#endif #include "../defines.h" /* for HAVE_scsi_h */ #ifdef HAVE_scsi_h #define u_char unsigned char #include /* SCSI_IOCTL_GET_IDLUN */ #undef u_char #endif +#if !(defined (sun) && defined (__svr4__)) #include /* FLOPPY_MAJOR */ #include /* HDIO_GETGEO */ +#endif #include "common.h" #include "fdisk.h" @@ -72,15 +79,19 @@ if (fstat (fd, &bootstat) < 0) { scsi_disk = 0; floppy = 0; +#if defined (IDE0_MAJOR) && defined (IDE1_MAJOR) } else if (S_ISBLK(bootstat.st_mode) && ((bootstat.st_rdev >> 8) == IDE0_MAJOR || (bootstat.st_rdev >> 8) == IDE1_MAJOR)) { scsi_disk = 0; floppy = 0; +#endif +#ifdef FLOPPY_MAJOR } else if (S_ISBLK(bootstat.st_mode) && (bootstat.st_rdev >> 8) == FLOPPY_MAJOR) { scsi_disk = 0; floppy = 1; +#endif } else { scsi_disk = 1; floppy = 0; @@ -160,6 +171,7 @@ {"","SUN1.3G",6,1965,2,3500,17,80,5400}, {"","SUN2.1G",0,2733,2,3500,19,80,5400}, {"IOMEGA","Jaz",0,1019,2,1021,64,32,5394}, +{"CD-ROM", "74min", 0, 2048, 0, 2048, 1, 640, 860}, }; struct sun_predefined_drives * @@ -232,11 +244,19 @@ void create_sunlabel(void) { +#if defined (HDIO_REQ) || defined (HDIO_GETGEO) struct hd_geometry geometry; +#elif defined (DKIOCGGEOM) + struct dk_geom dkgeom; +#endif unsigned int ndiv; int i; unsigned char c; struct sun_predefined_drives *p = NULL; + unsigned short acylinders; + unsigned short rpm; + unsigned short ilfact; + unsigned short sparecyl; fprintf(stderr, _("Building a new sun disklabel. Changes will remain in memory only,\n" @@ -279,19 +299,41 @@ } } if (!p || floppy) { -#ifdef HDIO_REQ +#if defined (HDIO_REQ) || defined (HDIO_GETGEO) +# ifdef HDIO_REQ if (!ioctl(fd, HDIO_REQ, &geometry)) { -#else +# else if (!ioctl(fd, HDIO_GETGEO, &geometry)) { -#endif +# endif heads = geometry.heads; sectors = geometry.sectors; - cylinders = geometry.cylinders; + acylinders = 2; + cylinders = geometry.cylinders - acylinders; + rpm = 5400; + ilfact = 1; + sparecyl = 0; + } else { +#elif defined (DKIOCGGEOM) + if (!ioctl (fd, DKIOCGGEOM, &dkgeom)) { + heads = dkgeom.dkg_nhead; + sectors = dkgeom.dkg_nsect; + cylinders = dkgeom.dkg_ncyl; + acylinders = dkgeom.dkg_acyl; + rpm = dkgeom.dkg_rpm; + ilfact = dkgeom.dkg_intrlv; + sparecyl = dkgeom.dkg_apc; } else { +#endif heads = 0; sectors = 0; cylinders = 0; + acylinders = 2; + rpm = 5400; + ilfact = 1; + sparecyl = 0; +#if defined (HDIO_REQ) || defined (HDIO_GETGEO) || defined (DKIOCGGEOM) } +#endif if (floppy) { sunlabel->nacyl = 0; sunlabel->pcylcount = SSWAP16(cylinders); @@ -301,23 +343,20 @@ } else { heads = read_int(1,heads,1024,0,_("Heads")); sectors = read_int(1,sectors,1024,0,_("Sectors/track")); - if (cylinders) - cylinders = read_int(1,cylinders-2,65535,0,_("Cylinders")); - else - cylinders = read_int(1,0,65535,0,_("Cylinders")); + cylinders = read_int(1,cylinders,65535,0,_("Cylinders")); sunlabel->nacyl = - SSWAP16(read_int(0,2,65535,0, + SSWAP16(read_int(0,acylinders,65535,0, _("Alternate cylinders"))); sunlabel->pcylcount = SSWAP16(read_int(0,cylinders+SSWAP16(sunlabel->nacyl), 65535,0,_("Physical cylinders"))); sunlabel->rspeed = - SSWAP16(read_int(1,5400,100000,0, + SSWAP16(read_int(1,rpm,100000,0, _("Rotation speed (rpm)"))); sunlabel->ilfact = - SSWAP16(read_int(1,1,32,0,_("Interleave factor"))); + SSWAP16(read_int(1,ilfact,32,0,_("Interleave factor"))); sunlabel->sparecyl = - SSWAP16(read_int(0,0,sectors,0, + SSWAP16(read_int(0,sparecyl,sectors,0, _("Extra sectors per cylinder"))); } } else { @@ -498,11 +537,10 @@ else first = read_int(scround(start), scround(stop)+1, scround(stop), 0, mesg); - if (display_in_cyl_units) - first *= units_per_sector; - else - /* Starting sector has to be properly aligned */ - first = (first + heads * sectors - 1) / (heads * sectors); + if (!display_in_cyl_units) + /* Starting sector has to be properly aligned */ + first = (first + units_per_sector - 1) / units_per_sector; + first *= units_per_sector; if (n == 2 && first != 0) printf ("\ It is highly recommended that the third partition covers the whole disk\n\ diff -u -r fdisk.old/fdisksunlabel.h fdisk/fdisksunlabel.h --- fdisk.old/fdisksunlabel.h Wed Feb 24 20:20:26 1999 +++ fdisk/fdisksunlabel.h Fri Jun 25 12:29:03 1999 @@ -1,4 +1,9 @@ -#include /* for __u32 etc */ +#if defined (sun) && defined (__svr4__) + typedef unsigned int __u32; + typedef unsigned short __u16; +#else +# include /* for __u32 etc */ +#endif typedef struct { unsigned char info[128]; /* Informative text string */ diff -u -r fdisk.old/sunfdisk.c fdisk/sunfdisk.c --- fdisk.old/sunfdisk.c Fri Jun 25 12:38:20 1999 +++ fdisk/sunfdisk.c Fri Jun 25 12:20:56 1999 @@ -0,0 +1,996 @@ +/* sunfdisk.c -- Partition table manipulator for Solaris/Linux. + * + * Copyright (C) 1992 A. V. Le Blanc (LeBlanc@mcc.ac.uk) + * + * This program is free software. You can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation: either version 1 or + * (at your option) any later version. + * + * Before Linux version 0.95c, this program requires a kernel patch. + * + * This is a stripped down version of fdisk.c such that it will also + * compile on Solaris (tested with Solaris 2.6 and gcc 2.8.1). It + * is basically a wrapper around fdisksunlabel.c. The base version + * of fdisk.c used was that from util-linux-2.9r. + * -- Eric Negaard (EJN@Negaard.Net) 1999-06-25 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#if !(defined (sun) && defined (__svr4__)) +#include +#endif +#include +#include "nls.h" + +#include +#include + +#if !(defined (sun) && defined (__svr4__)) +#include /* for HDIO_GETGEO */ +#include /* for BLKRRPART, BLKGETSIZE */ +#endif + +#include "common.h" +#include "fdisk.h" + +#include "fdisksunlabel.h" + +#include "../version.h" + +#define hex_val(c) ({ \ + char _c = (c); \ + isdigit(_c) ? _c - '0' : \ + tolower(_c) + 10 - 'a'; \ + }) + +#define DEFAULT_DEVICE "/dev/dsk/c0t0d0s2" +#define ALTERNATE_DEVICE "/dev/dsk/c0t3d0s2" +#define LINE_LENGTH 80 + +/* normally O_RDWR, -l option gives O_RDONLY */ +static int type_open = O_RDWR; + +char *disk_device = DEFAULT_DEVICE, /* c0t0d0s2, unless specified */ + *line_ptr, /* interactive input */ + line_buffer[LINE_LENGTH], + changed[MAXIMUM_PARTS], /* marks changed buffers */ + buffer[MAX_SECTOR_SIZE], /* first four partitions */ + *buffers[MAXIMUM_PARTS] /* pointers to buffers */ + = {buffer, buffer, buffer, buffer}; + +int fd, /* the disk */ + listing = 0, /* no aborts for fdisk -l */ + nowarn = 0, /* no warnings for fdisk -l/-s */ + partitions = 8; /* maximum partition + 1 */ + +uint heads, + sectors, + cylinders, + sector_size = DEFAULT_SECTOR_SIZE, + sector_offset = 1, + units_per_sector = 1, + display_in_cyl_units = 1; + +int sun_label = 1; /* looking at sun disklabel */ + +jmp_buf listingbuf; + +void fatal(enum failure why) +{ + char error[LINE_LENGTH], + *message = error; + + if (listing) { + close(fd); + longjmp(listingbuf, 1); + } + + switch (why) { + case usage: message = + _("Usage: sunfdisk [-b SSZ] [-u] [DISK] Change partition table\n" + " sunfdisk -l [-b SSZ] [-u] [DISK] List partition table(s)\n" + " sunfdisk -s PARTITION Give partition size(s) in Kbytes\n" + " sunfdisk -v Give sunfdisk version\n" + "Here DISK is something like /dev/hdb or /dev/sda\n" + "and PARTITION is something like /dev/hda7\n" + "-u: give Start and End in sector (instead of cylinder) units\n" + "-b 2048: (for certain MO drives) use 2048-byte sectors\n"); + break; + case no_device: + message = _("A disk block device is needed.\n"); + break; + case no_partition: + message =_("Given name does not refer to a partition,\n" + "or maybe not even to a block device.\n"); + break; + case unable_to_open: + sprintf(error, _("Unable to open %s\n"), disk_device); + break; + case unable_to_read: + sprintf(error, _("Unable to read %s\n"), disk_device); + break; + case unable_to_seek: + sprintf(error, _("Unable to seek on %s\n"),disk_device); + break; + case unable_to_write: + sprintf(error, _("Unable to write %s\n"), disk_device); + break; + case out_of_memory: + message = _("Unable to allocate any more memory\n"); + break; + default: message = _("Fatal error\n"); + } + + fputc('\n', stderr); + fputs(message, stderr); + exit(1); +} + +void menu(void) +{ + puts(_("Command action")); + puts(_(" a toggle a read only flag")); + puts(_(" c toggle the mountable flag")); + puts(_(" d delete a partition")); + puts(_(" l list known partition types")); + puts(_(" m print this menu")); + puts(_(" n add a new partition")); + puts(_(" p print the partition table")); + puts(_(" q quit without saving changes")); + puts(_(" s create a new empty Sun disklabel")); + puts(_(" t change a partition's system id")); + puts(_(" u change display/entry units")); + puts(_(" v verify the partition table")); + puts(_(" w write table to disk and exit")); + puts(_(" x extra functionality (experts only)")); +} + +void xmenu(void) +{ + puts(_("Command action")); + puts(_(" a change number of alternate cylinders")); + puts(_(" c change number of cylinders")); + puts(_(" d print the raw data in the partition table")); + puts(_(" e change number of extra sectors per cylinder")); + puts(_(" h change number of heads")); + puts(_(" i change interleave factor")); + puts(_(" o change rotation speed (rpm)")); + puts(_(" m print this menu")); + puts(_(" p print the partition table")); + puts(_(" q quit without saving changes")); + puts(_(" r return to main menu")); + puts(_(" s change number of sectors")); + puts(_(" v verify the partition table")); + puts(_(" w write table to disk and exit")); + puts(_(" y change number of physical cylinders")); +} + +char *partition_type(unsigned char type) +{ + int i; + struct systypes *types = sun_sys_types; + + for (i=0; types[i].name; i++) + if (types[i].type == type) + return _(types[i].name); + + return NULL; +} + +void list_types(struct systypes *sys) +{ + uint last[4], done = 0, next = 0, size; + int i; + + for (i = 0; sys[i].name; i++); + size = i; + + for (i = 3; i >= 0; i--) + last[3 - i] = done += (size + i - done) / (i + 1); + i = done = 0; + + do { + printf("%c%2x %-15.15s", i ? ' ' : '\n', + sys[next].type, _(sys[next].name)); + next = last[i++] + done; + if (i > 3 || next >= last[i]) { + i = 0; + next = ++done; + } + } while (done < last[0]); + putchar('\n'); +} + +int test_c(char **m, char *mesg) +{ + int val = 0; + if (!*m) + fprintf(stderr, _("You must set")); + else { + fprintf(stderr, " %s", *m); + val = 1; + } + *m = mesg; + return val; +} + +int warn_geometry(void) +{ + char *m = NULL; + int prev = 0; + if (!heads) + prev = test_c(&m, _("heads")); + if (!sectors) + prev = test_c(&m, _("sectors")); + if (!cylinders) + prev = test_c(&m, _("cylinders")); + if (!m) + return 0; + fprintf(stderr, + _("%s%s.\nYou can do this from the extra functions menu.\n"), + prev ? _(" and ") : " ", m); + return 1; +} + +void update_units(void) +{ + int cyl_units = heads * sectors; + + if (display_in_cyl_units && cyl_units) + units_per_sector = cyl_units; + else + units_per_sector = 1; /* in sectors */ +} + +/* + * Read MBR. Returns: + * -1: no label found + * 0: found or created label + */ +int get_boot(enum action what) +{ + if (what == create_empty) + goto got_table; /* skip reading disk */ + + if ((fd = open(disk_device, type_open)) < 0) { + if ((fd = open(disk_device, O_RDONLY)) < 0) + fatal(unable_to_open); + else + printf(_("You will not be able to write the partition table.\n")); + } + + guess_device_type (fd); + + if (sector_size != read(fd, buffer, sector_size)) + fatal (unable_to_read); + + heads = cylinders = sectors = 0; + + update_units (); + + got_table: + + if (check_sun_label()) + return 0; + + switch(what) { + case fdisk: + fprintf(stderr, _("Device does not contain a valid Sun disklabel\n")); + create_sunlabel(); + return 0; + case require: + return -1; + case try_only: + return -1; + case create_empty: + break; + } + + fprintf(stderr, _("Internal error\n")); + exit(1); +} + +/* read line; return 0 or first char */ +int +read_line(void) +{ + static int got_eof = 0; + + line_ptr = line_buffer; + if (!fgets(line_buffer, LINE_LENGTH, stdin)) { + if (feof(stdin)) + got_eof++; /* user typed ^D ? */ + if (got_eof >= 3) { + fflush(stdout); + fprintf(stderr, _("\ngot EOF thrice - exiting..\n")); + exit(1); + } + return 0; + } + while (*line_ptr && !isgraph(*line_ptr)) + line_ptr++; + return *line_ptr; +} + +char +read_char(char *mesg) +{ + do { + fputs(mesg, stdout); + } while (!read_line()); + return *line_ptr; +} + +char +read_chars(char *mesg) +{ + fputs(mesg, stdout); + if (!read_line()) { + *line_ptr = '\n'; + line_ptr[1] = 0; + } + return *line_ptr; +} + +int +read_hex(struct systypes *sys) +{ + int hex; + + while (1) + { + read_char(_("Hex code (type L to list codes): ")); + if (tolower(*line_ptr) == 'l') + list_types(sys); + else if (isxdigit (*line_ptr)) + { + hex = 0; + do + hex = hex << 4 | hex_val(*line_ptr++); + while (isxdigit(*line_ptr)); + return hex; + } + } +} + +/* + * Print the message MESG, then read an integer between LOW and HIGH. + * If the user hits Enter, DFLT is returned. + * Answers like +10 are interpreted as offsets from BASE. + * + * There is no default if DFLT is not between LOW and HIGH. + */ +uint +read_int(uint low, uint dflt, uint high, uint base, char *mesg) +{ + uint i; + int default_ok = 1; + static char *ms = NULL; + static int mslen = 0; + + if (!ms || strlen(mesg)+50 > mslen) { + mslen = strlen(mesg)+100; + if (!(ms = realloc(ms,mslen))) + fatal(out_of_memory); + } + + if (dflt < low || dflt > high) + default_ok = 0; + + if (default_ok) + sprintf(ms, _("%s (%d-%d, default %d): "), mesg, low, high, dflt); + else + sprintf(ms, "%s (%d-%d): ", mesg, low, high); + + while (1) { + int use_default = default_ok; + + /* ask question and read answer */ + while (read_chars(ms) != '\n' && !isdigit(*line_ptr) + && *line_ptr != '-' && *line_ptr != '+') + continue; + + if (*line_ptr == '+' || *line_ptr == '-') { + i = atoi(line_ptr+1); + if (*line_ptr == '-') + i = -i; + while (isdigit(*++line_ptr)) + use_default = 0; + switch (*line_ptr) { + case 'c': + case 'C': + if (!display_in_cyl_units) + i *= heads * sectors; + break; + case 'k': + case 'K': + i *= 2; + i /= (sector_size / 512); + i /= units_per_sector; + break; + case 'm': + case 'M': + i *= 2048; + i /= (sector_size / 512); + i /= units_per_sector; + break; + case 'g': + case 'G': + i *= 2048 * 1024; + i /= (sector_size / 512); + i /= units_per_sector; + break; + default: + break; + } + i += base; + } else { + i = atoi(line_ptr); + while (isdigit(*line_ptr)) { + line_ptr++; + use_default = 0; + } + } + if (use_default) + printf(_("Using default value %d\n"), i = dflt); + if (i >= low && i <= high) + break; + else + printf(_("Value out of range.\n")); + } + return i; +} + +int get_partition(int warn, int max) +{ + int i = read_int(1, 0, max, 0, _("Partition number")) - 1; + + if (warn && (!sunlabel->partitions[i].num_sectors || + !sunlabel->infos[i].id) + ) fprintf(stderr, _("Warning: partition %d has empty type\n"), i+1); + return i; +} + +char *const str_units(int n) /* n==1: use singular */ +{ + if (n == 1) + return display_in_cyl_units ? _("cylinder") : _("sector"); + else + return display_in_cyl_units ? _("cylinders") : _("sectors"); +} + +void change_units(void) +{ + display_in_cyl_units = !display_in_cyl_units; + update_units(); + printf(_("Changing display/entry units to %s\n"), + str_units(PLURAL)); +} + +void delete_partition(int i) +{ + if (warn_geometry()) + return; + + changed[i] = 1; + + sun_delete_partition(i); + return; +} + +void change_sysid(void) +{ + char *temp; + int i = get_partition(0, partitions), sys, origsys; + + origsys = sys = sunlabel->infos[i].id; + + if (!sys) + printf(_("Partition %d does not exist yet!\n"), i + 1); + else while (1) { + sys = read_hex (sun_sys_types); + + if (!sys) { + printf(_("Type 0 means free space to many systems\n" + "(but not to Linux). Having partitions of\n" + "type 0 is probably unwise. You can delete\n" + "a partition using the `d' command.\n")); + /* break; */ + } + + if (sys < 256) { + if (i == 2 && sys != WHOLE_DISK) + printf(_("Consider leaving partition 3 " + "as Whole disk (5),\n" + "as SunOS/Solaris expects it and " + "even Linux likes it.\n\n")); + if (sys == origsys) + break; + + sun_change_sysid(i, sys); + + printf (_("Changed system type of partition %d " + "to %x (%s)\n"), i + 1, sys, + (temp = partition_type(sys)) ? temp : + _("Unknown")); + changed[i] = 1; + break; + } + } +} + +void list_disk_geometry(void) +{ + printf(_("\nDisk %s: %d heads, %d sectors, %d cylinders\nUnits = " + "%s of %d * %d bytes\n\n"), disk_device, heads, sectors, + cylinders, str_units(PLURAL), units_per_sector, sector_size); +} + +void list_table(int xtra) +{ + sun_list_table(xtra); + return; +} + +void verify(void) +{ + + if (warn_geometry()) + return; + + verify_sun(); + return; +} + +void new_partition(void) +{ + if (warn_geometry()) + return; + + add_sun_partition(get_partition(0, partitions), LINUX_NATIVE); + return; +} + +void write_table(void) +{ + int i, error = 0; + + changed[3] = changed[0] || changed[1] || changed[2] || changed[3]; + + if (changed[3] || changed[4] || changed[5] || + changed[6] || changed[7]) { + sun_write_table(); + } else { + printf(_("The partition table has not been altered!\n\n")); + exit (0); + } + + printf(_("The partition table has been altered!\n\n")); + +#ifdef BLKRRPART + printf(_("Calling ioctl() to re-read partition table.\n")); + sync(); + sleep(2); + + if ((i = ioctl(fd, BLKRRPART)) != 0) { + error = errno; + } else { + /* some kernel versions (1.2.x) seem to have trouble + rereading the partition table, but if asked to do it + twice, the second time works. - biro@yggdrasil.com */ + sync(); + sleep(2); + if((i = ioctl(fd, BLKRRPART)) != 0) + error = errno; + } +#else + printf(_("The new label has been written to disk, but the kernel" + " has not\nupdated its' idea of the label.\nReboot your " + "system to ensure the partition table is updated.\n")); + i = 0; +#endif + + close(fd); + +#ifdef BLKRRPART + printf(_("Syncing disks.\n")); + sync(); + sleep(4); /* for sync() */ +#endif + + if (i < 0) + printf(_("Re-read table failed with error %d: %s.\nReboot your " + "system to ensure the partition table is updated.\n"), + error, strerror(error)); + + exit(0); +} + +#define MAX_PER_LINE 16 +void print_buffer(char buffer[]) +{ + int i, + l; + + for (i = 0, l = 0; i < sector_size; i++, l++) { + if (l == 0) + printf("0x%03X:", i); + printf(" %02X", (unsigned char) buffer[i]); + if (l == MAX_PER_LINE - 1) { + printf("\n"); + l = -1; + } + } + if (l > 0) + printf("\n"); + printf("\n"); +} + +void print_raw(void) +{ + printf(_("Device: %s\n"), disk_device); + print_buffer(buffer); +} + +void xselect(void) +{ + while(1) { + putchar('\n'); + switch (tolower(read_char(_("Expert command (m for help): ")))) { + case 'a': + sun_set_alt_cyl(); + break; + case 'c': + cylinders = read_int(1, cylinders, 65535, + 0, _("Number of cylinders")); + sun_set_ncyl(cylinders); + break; + case 'd': + print_raw(); + break; + case 'e': + sun_set_xcyl(); + break; + case 'h': + heads = read_int(1, heads, 256, 0, + _("Number of heads")); + update_units(); + break; + case 'i': + sun_set_ilfact(); + break; + case 'o': + sun_set_rspeed(); + break; + case 'p': + list_table(1); + break; + case 'q': + close(fd); + printf("\n"); + exit(0); + case 'r': + return; + case 's': + sectors = read_int(1, sectors, 63, 0, + _("Number of sectors")); + update_units(); + break; + case 'v': + verify(); + break; + case 'w': + write_table(); /* does not return */ + break; + case 'y': + sun_set_pcylcount(); + break; + default: + xmenu(); + } + } +} + +void try(char *device, int user_specified) +{ + disk_device = device; + if (!setjmp(listingbuf)) { + if ((fd = open(disk_device, type_open)) >= 0) { + if (get_boot(try_only) < 0) { + list_disk_geometry(); + close(fd); + } else { + close(fd); + list_table(0); + } + } else { + /* Ignore other errors, since we try IDE + and SCSI hard disks which may not be + installed on the system. */ + if(errno == EACCES) { + fprintf(stderr, _("Cannot open %s\n"), device); + return; + } + } + } +} + +int +dir_exists(char *dirname) +{ + struct stat statbuf; + + return (stat(dirname, &statbuf) == 0 && S_ISDIR(statbuf.st_mode)); +} + +void +dummy(int *kk) +{} + +int +main(int argc, char **argv) +{ + int i, j, s, c; + int optl = 0, opts = 0; + char *part; + int user_set_sector_size = 0; + + setlocale(LC_ALL, ""); + bindtextdomain(PACKAGE, LOCALEDIR); + textdomain(PACKAGE); + + /* + * Calls: + * sunfdisk -v + * sunfdisk -l [-b sectorsize] [-u] [device] ... + * sunfdisk -s [partition] ... + * sunfdisk [-b sectorsize] [-u] [device] + */ + while ((c = getopt(argc, argv, "b:lsuv")) != EOF) { + switch (c) { + case 'b': + /* ugly: this sector size is really per device, + so cannot be combined with multiple disks */ + sector_size = atoi(optarg); + if (sector_size != 512 && sector_size != 1024 && + sector_size != 2048) + fatal(usage); + sector_offset = 2; + user_set_sector_size = 1; + break; + case 'l': + optl = 1; + break; + case 's': + opts = 1; + break; + case 'u': + display_in_cyl_units = 0; + break; + case 'v': + printf("sunfdisk v" UTIL_LINUX_VERSION "\n"); + exit(0); + default: + fatal(usage); + } + } + +#if 0 + printf(_("This kernel finds the sector size itself - -b option ignored\n")); +#else + if (user_set_sector_size && argc-optind != 1) + printf(_("Warning: the -b (set sector size) option should" + " be used with one specified device\n")); +#endif + + if (optl) { + listing = 1; + nowarn = 1; + type_open = O_RDONLY; + if (argc > optind) { + int k; + /* avoid gcc warning: + variable `k' might be clobbered by `longjmp' */ + dummy(&k); + for(k=optind; k= partitions) + exit(1); + + s = get_num_sectors (sunlabel->partitions[i]); + + *p = ':'; + + if (opts == 1) + printf("%d\n", s/2); + else + printf("%s: %d\n", part, s/2); + } + exit(0); + } + + if (argc-optind == 1) + disk_device = argv[optind]; + else if (argc-optind != 0) + fatal(usage); + else { + if ((fd = open(DEFAULT_DEVICE, O_RDWR)) < 0) + disk_device = ALTERNATE_DEVICE; + else close(fd); + printf(_("Using %s as default device!\n"), disk_device); + } + get_boot(fdisk); + + while (1) { + putchar('\n'); + switch (tolower(read_char(_("Command (m for help): ")))) { + case 'a': + toggle_sunflags(get_partition(1, partitions), 0x01); + break; + case 'c': + toggle_sunflags(get_partition(1, partitions), 0x10); + break; + case 'd': + delete_partition( + get_partition(1, partitions)); + break; + case 'i': + menu(); + case 'l': + list_types(sun_sys_types); + break; + case 'n': + new_partition(); + break; + case 'p': + list_table(0); + break; + case 'q': + close(fd); + printf("\n"); + exit(0); + case 's': + create_sunlabel(); + break; + case 't': + change_sysid(); + break; + case 'u': + change_units(); + break; + case 'v': + verify(); + break; + case 'w': + write_table(); /* does not return */ + break; + case 'x': + xselect(); + break; + default: menu(); + } + } + return 0; +}