📄 fdisksgilabel.c
字号:
/* * * fdisksgilabel.c * * Copyright (C) Andreas Neuper, Sep 1998. * This file may be modified and redistributed under * the terms of the GNU Public License. * * 1999-03-20 Arnaldo Carvalho de Melo <acme@conectiva.com.br> * Internationalization * * 2003-03-20 Phillip Kesling <pkesling@sgi.com> * Some fixes */#include <stdio.h> /* stderr */#include <stdlib.h> /* exit */#include <string.h> /* strstr */#include <unistd.h> /* write */#include <sys/ioctl.h> /* ioctl */#include <sys/stat.h> /* stat */#include <assert.h> /* assert */#include <endian.h>#include "nls.h"#include <linux/major.h> /* FLOPPY_MAJOR */#include "common.h"#include "fdisk.h"#include "fdisksgilabel.h"static int other_endian = 0;static int debug = 0;static short volumes=1;/* * only dealing with free blocks here */typedef struct { unsigned int first; unsigned int last; } freeblocks;static freeblocks freelist[17]; /* 16 partitions can produce 17 vacant slots */static voidsetfreelist(int i, unsigned int f, unsigned int l) { freelist[i].first = f; freelist[i].last = l;}static voidadd2freelist(unsigned int f, unsigned int l) { int i = 0; for ( ; i < 17 ; i++) if (freelist[i].last == 0) break; setfreelist(i, f, l);}static voidclearfreelist(void) { int i; for (i = 0; i < 17 ; i++) setfreelist(i, 0, 0);}static unsigned intisinfreelist(unsigned int b) { int i; for (i = 0; i < 17 ; i++) if (freelist[i].first <= b && freelist[i].last >= b) return freelist[i].last; return 0;} /* return last vacant block of this stride (never 0). */ /* the '>=' is not quite correct, but simplifies the code *//* * end of free blocks section */struct systypes sgi_sys_types[] = { {SGI_VOLHDR, N_("SGI volhdr")}, {0x01, N_("SGI trkrepl")}, {0x02, N_("SGI secrepl")}, {SGI_SWAP, N_("SGI raw")}, {0x04, N_("SGI bsd")}, {0x05, N_("SGI sysv")}, {ENTIRE_DISK, N_("SGI volume")}, {SGI_EFS, N_("SGI efs")}, {0x08, N_("SGI lvol")}, {0x09, N_("SGI rlvol")}, {SGI_XFS, N_("SGI xfs")}, {SGI_XFSLOG, N_("SGI xfslog")}, {SGI_XLV, N_("SGI xlv")}, {SGI_XVM, N_("SGI xvm")}, {LINUX_SWAP, N_("Linux swap")}, {LINUX_NATIVE, N_("Linux native")}, {LINUX_LVM, N_("Linux LVM")}, {LINUX_RAID, N_("Linux RAID")}, {0, NULL }};static inline unsigned short__swap16(unsigned short x) { return (((__u16)(x) & 0xFF) << 8) | (((__u16)(x) & 0xFF00) >> 8);}static inline __u32__swap32(__u32 x) { return (((x & 0xFF) << 24) | ((x & 0xFF00) << 8) | ((x & 0xFF0000) >> 8) | ((x & 0xFF000000) >> 24));}static intsgi_get_nsect(void) { return SSWAP16(sgilabel->devparam.nsect);}static intsgi_get_ntrks(void) { return SSWAP16(sgilabel->devparam.ntrks);}#if 0static intsgi_get_head_vol0(void) { return SSWAP16(sgilabel->devparam.head_vol0);}static intsgi_get_bytes(void) { return SSWAP16(sgilabel->devparam.bytes);}static intsgi_get_pcylcount(void) { return SSWAP16(sgilabel->devparam.pcylcount);}#endifvoidsgi_nolabel() { sgilabel->magic = 0; sgi_label = 0; partitions = 4;}static unsigned inttwo_s_complement_32bit_sum(unsigned int *base, int size /* in bytes */) { int i = 0; unsigned int sum = 0; size /= sizeof(unsigned int); for (i = 0; i < size; i++) sum -= SSWAP32(base[i]); return sum;}intcheck_sgi_label() { if (sizeof(sgilabel) > 512) { fprintf(stderr, _("According to MIPS Computer Systems, Inc the " "Label must not contain more than 512 bytes\n")); exit(1); } if (sgilabel->magic != SGI_LABEL_MAGIC && sgilabel->magic != SGI_LABEL_MAGIC_SWAPPED) { sgi_label = 0; other_endian = 0; return 0; } other_endian = (sgilabel->magic == SGI_LABEL_MAGIC_SWAPPED); /* * test for correct checksum */ if (two_s_complement_32bit_sum((unsigned int*)sgilabel, sizeof(*sgilabel))) { fprintf(stderr, _("Detected sgi disklabel with wrong checksum.\n")); } update_units(); sgi_label = 1; partitions= 16; volumes = 15; return 1;}voidsgi_list_table(int xtra) { int i, w; int kpi = 0; /* kernel partition ID */ char *type; w = strlen(disk_device); if (xtra) { printf(_("\nDisk %s (SGI disk label): %d heads, %d sectors\n" "%d cylinders, %d physical cylinders\n" "%d extra sects/cyl, interleave %d:1\n" "%s\n" "Units = %s of %d * 512 bytes\n\n"), disk_device, heads, sectors, cylinders, SSWAP16(sgiparam.pcylcount), SSWAP16(sgiparam.sparecyl), SSWAP16(sgiparam.ilfact), (char *)sgilabel, str_units(PLURAL), units_per_sector); } else { printf(_("\nDisk %s (SGI disk label): " "%d heads, %d sectors, %d cylinders\n" "Units = %s of %d * 512 bytes\n\n"), disk_device, heads, sectors, cylinders, str_units(PLURAL), units_per_sector); } printf(_("----- partitions -----\n" "Pt# %*s Info Start End Sectors Id System\n"), w + 1, _("Device")); for (i = 0 ; i < partitions; i++) { if (sgi_get_num_sectors(i) || debug) { __u32 start = sgi_get_start_sector(i); __u32 len = sgi_get_num_sectors(i); kpi++; /* only count nonempty partitions */ printf( "%2d: %s %4s %9ld %9ld %9ld %2x %s\n",/* fdisk part number */ i+1,/* device */ partname(disk_device, kpi, w+2),/* flags */ (sgi_get_swappartition() == i) ? "swap" :/* flags */ (sgi_get_bootpartition() == i) ? "boot" : " ", /* start */ (long) scround(start),/* end */ (long) scround(start+len)-1,/* no odd flag on end */ (long) len, /* type id */ sgi_get_sysid(i),/* type name */ (type = partition_type(sgi_get_sysid(i))) ? type : _("Unknown")); } } printf(_("----- Bootinfo -----\nBootfile: %s\n" "----- Directory Entries -----\n"), sgilabel->boot_file); for (i = 0 ; i < volumes; i++) { if (sgilabel->directory[i].vol_file_size) { __u32 start = SSWAP32(sgilabel->directory[i].vol_file_start); __u32 len = SSWAP32(sgilabel->directory[i].vol_file_size); char *name = sgilabel->directory[i].vol_file_name; printf(_("%2d: %-10s sector%5u size%8u\n"), i, name, (unsigned int) start, (unsigned int) len); } }}unsigned intsgi_get_start_sector(int i) { return SSWAP32(sgilabel->partitions[i].start_sector);}unsigned intsgi_get_num_sectors(int i) { return SSWAP32(sgilabel->partitions[i].num_sectors);}intsgi_get_sysid(int i){ return SSWAP32(sgilabel->partitions[i].id);}intsgi_get_bootpartition(void){ return SSWAP16(sgilabel->boot_part);}intsgi_get_swappartition(void){ return SSWAP16(sgilabel->swap_part);}voidsgi_set_bootpartition(int i){ sgilabel->boot_part = SSWAP16(((short)i));}static unsigned intsgi_get_lastblock(void) { return heads * sectors * cylinders;}voidsgi_set_swappartition(int i) { sgilabel->swap_part = SSWAP16(((short)i));}static intsgi_check_bootfile(const char* aFile) { if (strlen(aFile) < 3) /* "/a\n" is minimum */ { printf(_("\nInvalid Bootfile!\n" "\tThe bootfile must be an absolute non-zero pathname,\n" "\te.g. \"/unix\" or \"/unix.save\".\n")); return 0; } else { if (strlen(aFile) > 16) { printf(_("\n\tName of Bootfile too long: " "16 bytes maximum.\n")); return 0; } else { if (aFile[0] != '/') { printf(_("\n\tBootfile must have a " "fully qualified pathname.\n")); return 0; } } } if (strncmp(aFile, sgilabel->boot_file, 16)) { printf(_("\n\tBe aware, that the bootfile is not checked for existence.\n\t" "SGI's default is \"/unix\" and for backup \"/unix.save\".\n")); /* filename is correct and did change */ return 1; } return 0; /* filename did not change */}const char *sgi_get_bootfile(void) { return sgilabel->boot_file;}voidsgi_set_bootfile(const char* aFile) { int i = 0; if (sgi_check_bootfile(aFile)) { while (i < 16) { if ((aFile[i] != '\n') /* in principle caught again by next line */ && (strlen(aFile) > i)) sgilabel->boot_file[i] = aFile[i]; else sgilabel->boot_file[i] = 0; i++; } printf(_("\n\tBootfile is changed to \"%s\".\n"), sgilabel->boot_file); }}voidcreate_sgiinfo(void) { /* I keep SGI's habit to write the sgilabel to the second block */ sgilabel->directory[0].vol_file_start = SSWAP32(2); sgilabel->directory[0].vol_file_size = SSWAP32(sizeof(sgiinfo)); strncpy(sgilabel->directory[0].vol_file_name, "sgilabel", 8);}sgiinfo *fill_sgiinfo(void);voidsgi_write_table(void) { sgilabel->csum = 0; sgilabel->csum = SSWAP32(two_s_complement_32bit_sum( (unsigned int*)sgilabel, sizeof(*sgilabel))); assert(two_s_complement_32bit_sum( (unsigned int*)sgilabel, sizeof(*sgilabel)) == 0); if (lseek(fd, 0, SEEK_SET) < 0) fatal(unable_to_seek); if (write(fd, sgilabel, SECTOR_SIZE) != SECTOR_SIZE) fatal(unable_to_write); if (! strncmp(sgilabel->directory[0].vol_file_name, "sgilabel", 8)) { /* * keep this habit of first writing the "sgilabel". * I never tested whether it works without (AN 981002). */ sgiinfo *info = fill_sgiinfo(); int infostartblock = SSWAP32(sgilabel->directory[0].vol_file_start); if (ext2_llseek(fd, (long long)infostartblock* SECTOR_SIZE, SEEK_SET) < 0) fatal(unable_to_seek); if (write(fd, info, SECTOR_SIZE) != SECTOR_SIZE) fatal(unable_to_write); free(info); }}static intcompare_start(int *x, int *y) { /* * sort according to start sectors * and prefers largest partition: * entry zero is entire disk entry */ unsigned int i = *x; unsigned int j = *y; unsigned int a = sgi_get_start_sector(i); unsigned int b = sgi_get_start_sector(j); unsigned int c = sgi_get_num_sectors(i); unsigned int d = sgi_get_num_sectors(j); if (a == b) return (d > c) ? 1 : (d == c) ? 0 : -1; return (a > b) ? 1 : -1;}static intsgi_gaps(void) { /* * returned value is: * = 0 : disk is properly filled to the rim * < 0 : there is an overlap * > 0 : there is still some vacant space */ return verify_sgi(0);}intverify_sgi(int verbose){ int Index[16]; /* list of valid partitions */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -