⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sfdisk.c

📁 Util-linux 软件包包含许多工具。其中比较重要的是加载、卸载、格式化、分区和管理硬盘驱动器
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * sfdisk version 3.0 - aeb - 950813 * * Copyright (C) 1995  Andries E. Brouwer (aeb@cwi.nl) * * 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. * * A.V. Le Blanc (LeBlanc@mcc.ac.uk) wrote Linux fdisk 1992-1994, * patched by various people (faith@cs.unc.edu, martin@cs.unc.edu, * leisner@sdsp.mc.xerox.com, esr@snark.thyrsus.com, aeb@cwi.nl) * 1993-1995, with version numbers (as far as I have seen) 0.93 - 2.0e. * This program had (head,sector,cylinder) as basic unit, and was * (therefore) broken in several ways for the use on larger disks - * for example, my last patch (from 2.0d to 2.0e) was required * to allow a partition to cross cylinder 8064, and to write an * extended partition past the 4GB mark. * * The current program is a rewrite from scratch, and I started a * version numbering at 3.0. * 	Andries Brouwer, aeb@cwi.nl, 950813 * * Well, a good user interface is still lacking. On the other hand, * many configurations cannot be handled by any other fdisk. * I changed the name to sfdisk to prevent confusion. - aeb, 970501 * * Changes: * 19990319 - Arnaldo Carvalho de Melo <acme@conectiva.com.br> - i18n * 20040428 - Jeroen Dobbelaere <jeroen.dobbelaere@acunia.com> - added PACKED * 20040824 - David A. Wheeler <dwheeler@dwheeler.com> - warnings to stderr */#define PROGNAME "sfdisk"#define VERSION "3.08"#define DATE "040824"#include <stdio.h>#include <stdlib.h>		/* atoi, free */#include <stdarg.h>		/* varargs */#include <unistd.h>		/* read, write */#include <fcntl.h>		/* O_RDWR */#include <errno.h>		/* ERANGE */#include <string.h>		/* index() */#include <ctype.h>#include <getopt.h>#include <sys/ioctl.h>#include <sys/stat.h>#include <sys/utsname.h>#include <linux/unistd.h>	/* _syscall */#include "nls.h"#include "common.h"#define SIZE(a)	(sizeof(a)/sizeof(a[0]))/* * Table of contents: *  A. About seeking *  B. About sectors *  C. About heads, sectors and cylinders *  D. About system Ids *  E. About partitions *  F. The standard input *  G. The command line *  H. Listing the current situation *  I. Writing the new situation */int exit_status = 0;int force = 0;		/* 1: do what I say, even if it is stupid ... */int quiet = 0;		/* 1: suppress all warnings *//* IA-64 gcc spec file currently does -DLinux... */#undef Linuxint Linux = 0;		/* 1: suppress warnings irrelevant for Linux */int DOS = 0;		/* 1: shift extended partitions by #sectors, not 1 */int DOS_extended = 0;	/* 1: use starting cylinder boundary of extd partn */int dump = 0;           /* 1: list in a format suitable for later input */int verify = 0;         /* 1: check that listed partition is reasonable */int no_write = 0;	/* 1: do not actually write to disk */int no_reread = 0;	/* 1: skip the BLKRRPART ioctl test at startup */int leave_last = 0;	/* 1: don't allocate the last cylinder */int opt_list = 0;char *save_sector_file = NULL;char *restore_sector_file = NULL;static voiddo_warn(char *s, ...) {    va_list p;    va_start(p, s);    fflush(stdout);    vfprintf(stderr, s, p);    fflush(stderr);    va_end(p);}static voidwarn(char *s, ...) {    va_list p;    va_start(p, s);    if (!quiet) {	fflush(stdout);	vfprintf(stderr, s, p);	fflush(stderr);    }    va_end(p);}static voiderror(char *s, ...) {    va_list p;    va_start(p, s);    fflush(stdout);    fprintf(stderr, "\n" PROGNAME ": ");    vfprintf(stderr, s, p);    fflush(stderr);    va_end(p);}static voidfatal(char *s, ...) {    va_list p;    va_start(p, s);    fflush(stdout);    fprintf(stderr, "\n" PROGNAME ": ");    vfprintf(stderr, s, p);    fflush(stderr);    va_end(p);    exit(1);}/* * GCC nonsense - needed for GCC 3.4.x with -O2 * * Maybe just test with #if (__GNUC__ >= 3) && (__GNUC_MINOR__ >= 4) ? */#ifndef __GNUC_PREREQ#define __GNUC_PREREQ(x,y)	0#endif#if __GNUC_PREREQ(3,4)#define __attribute__used __attribute__ ((used))#else#define __attribute__used#endif/* * arm needs PACKED - use it everywhere? */#if defined(__GNUC__) && defined(__arm__)# define PACKED __attribute__ ((packed))#else# define PACKED#endif/* *  A. About seeking *//* * sseek: seek to specified sector - return 0 on failure * * For >4GB disks lseek needs a > 32bit arg, and we have to use llseek. * On the other hand, a 32 bit sector number is OK until 2TB. * The routines _llseek and sseek below are the only ones that * know about the loff_t type. * * Note: we use 512-byte sectors here, irrespective of the hardware ss. */#undef use_lseek#if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (__s390x__)#define use_lseek#endif#ifndef use_lseekstatic __attribute__used_syscall5(int,  _llseek,  unsigned int,  fd, ulong, hi, ulong, lo,       loff_t *, res, unsigned int, wh);#endifstatic intsseek(char *dev, unsigned int fd, unsigned long s) {    loff_t in, out;    in = ((loff_t) s << 9);    out = 1;#ifndef use_lseek    if (_llseek (fd, in>>32, in & 0xffffffff, &out, SEEK_SET) != 0) {#else    if ((out = lseek(fd, in, SEEK_SET)) != in) {#endif	perror("llseek");	error(_("seek error on %s - cannot seek to %lu\n"), dev, s);	return 0;    }    if (in != out) {	error(_("seek error: wanted 0x%08x%08x, got 0x%08x%08x\n"),	       (unsigned int)(in>>32), (unsigned int)(in & 0xffffffff),	       (unsigned int)(out>>32), (unsigned int)(out & 0xffffffff));	return 0;    }    return 1;}/* *  B. About sectors *//* * We preserve all sectors read in a chain - some of these will * have to be modified and written back. */struct sector {    struct sector *next;    unsigned long sectornumber;    int to_be_written;    char data[512];} *sectorhead;static voidfree_sectors(void) {    struct sector *s;    while (sectorhead) {	s = sectorhead;	sectorhead = s->next;	free(s);    }}static struct sector *get_sector(char *dev, int fd, unsigned long sno) {    struct sector *s;    for(s = sectorhead; s; s = s->next)	if (s->sectornumber == sno)	    return s;    if (!sseek(dev, fd, sno))	return 0;    if (!(s = (struct sector *) malloc(sizeof(struct sector))))	fatal(_("out of memory - giving up\n"));    if (read(fd, s->data, sizeof(s->data)) != sizeof(s->data)) {	if (errno)		/* 0 in case we read past end-of-disk */	    perror("read");	error(_("read error on %s - cannot read sector %lu\n"), dev, sno);	free(s);	return 0;    }    s->next = sectorhead;    sectorhead = s;    s->sectornumber = sno;    s->to_be_written = 0;    return s;}static intmsdos_signature (struct sector *s) {    unsigned char *data = s->data;    if (data[510] == 0x55 && data[511] == 0xaa)	    return 1;    error(_("ERROR: sector %lu does not have an msdos signature\n"),	  s->sectornumber);    return 0;}static intwrite_sectors(char *dev, int fd) {    struct sector *s;    for (s = sectorhead; s; s = s->next)	if (s->to_be_written) {	    if (!sseek(dev, fd, s->sectornumber))		return 0;	    if (write(fd, s->data, sizeof(s->data)) != sizeof(s->data)) {		perror("write");		error(_("write error on %s - cannot write sector %lu\n"),		       dev, s->sectornumber);		return 0;	    }	    s->to_be_written = 0;	}    return 1;}static voidulong_to_chars(unsigned long u, char *uu) {    int i;    for(i=0; i<4; i++) {	uu[i] = (u & 0xff);	u >>= 8;    }}static unsigned longchars_to_ulong(unsigned char *uu) {    int i;    unsigned long u = 0;    for(i=3; i>=0; i--)	u = (u << 8) | uu[i];    return u;}static intsave_sectors(char *dev, int fdin) {    struct sector *s;    char ss[516];    int fdout;    fdout = open(save_sector_file, O_WRONLY | O_CREAT, 0444);    if (fdout < 0) {	perror(save_sector_file);	error(_("cannot open partition sector save file (%s)\n"),	       save_sector_file);	return 0;    }    for (s = sectorhead; s; s = s->next)	if (s->to_be_written) {	    ulong_to_chars(s->sectornumber, ss);	    if (!sseek(dev, fdin, s->sectornumber))		return 0;	    if (read(fdin, ss+4, 512) != 512) {		perror("read");		error(_("read error on %s - cannot read sector %lu\n"),		       dev, s->sectornumber);		return 0;	    }	    if (write(fdout, ss, sizeof(ss)) != sizeof(ss)) {		perror("write");		error(_("write error on %s\n"), save_sector_file);		return 0;	    }	}    return 1;}static void reread_disk_partition(char *dev, int fd);static intrestore_sectors(char *dev) {    int fdin, fdout, ct;    struct stat statbuf;    char *ss0, *ss;    unsigned long sno;    if (stat(restore_sector_file, &statbuf) < 0) {	perror(restore_sector_file);	error(_("cannot stat partition restore file (%s)\n"),	       restore_sector_file);	return 0;    }    if (statbuf.st_size % 516) {	error(_("partition restore file has wrong size - not restoring\n"));	return 0;    }    if (!(ss = (char *) malloc(statbuf.st_size))) {	error(_("out of memory?\n"));	return 0;    }    fdin = open(restore_sector_file, O_RDONLY);    if (fdin < 0) {	perror(restore_sector_file);	error(_("cannot open partition restore file (%s)\n"),	       restore_sector_file);	return 0;    }    if (read(fdin, ss, statbuf.st_size) != statbuf.st_size) {	perror("read");	error(_("error reading %s\n"), restore_sector_file);	return 0;    }    fdout = open(dev, O_WRONLY);    if (fdout < 0) {	perror(dev);	error(_("cannot open device %s for writing\n"), dev);	return 0;    }    ss0 = ss;    ct = statbuf.st_size/516;    while(ct--) {	sno = chars_to_ulong(ss);	if (!sseek(dev, fdout, sno))	  return 0;	if (write(fdout, ss+4, 512) != 512) {	    perror(dev);	    error(_("error writing sector %lu on %s\n"), sno, dev);	    return 0;	}	ss += 516;    }    free(ss0);    reread_disk_partition(dev, fdout);    return 1;}/* *  C. About heads, sectors and cylinders *//* * <linux/hdreg.h> defines HDIO_GETGEO and * struct hd_geometry { *      unsigned char heads; *      unsigned char sectors; *      unsigned short cylinders; *      unsigned long start; * }; * * For large disks g.cylinders is truncated, so we use BLKGETSIZE. *//* * We consider several geometries for a disk: * B - the BIOS geometry, gotten from the kernel via HDIO_GETGEO * F - the fdisk geometry * U - the user-specified geometry * * 0 means unspecified / unknown */struct geometry {	unsigned long long total_size;		/* in sectors */	unsigned long cylindersize;		/* in sectors */	unsigned long heads, sectors, cylinders;	unsigned long start;} B, F, U;static struct geometryget_geometry(char *dev, int fd, int silent) {    struct hd_geometry g;    unsigned long cyls;    unsigned long long sectors;    struct geometry R;    if (ioctl(fd, HDIO_GETGEO, &g)) {	g.heads = g.sectors = g.cylinders = g.start = 0;	if (!silent)	    do_warn(_("Disk %s: cannot get geometry\n"), dev);    }    R.start = g.start;    R.heads = g.heads;    R.sectors = g.sectors;    R.cylindersize = R.heads * R.sectors;    R.cylinders = 0;    R.total_size = 0;    if (disksize(fd, &sectors)) {	/* maybe an ordinary file */	struct stat s;	if (fstat(fd, &s) == 0 && S_ISREG(s.st_mode))	    R.total_size = (s.st_size >> 9);	else if (!silent)	    do_warn(_("Disk %s: cannot get size\n"), dev);    } else	    R.total_size = sectors;    if (R.cylindersize && R.total_size) {	    sectors /= R.cylindersize;	    cyls = sectors;	    if (cyls != sectors)		    cyls = ~0;	    R.cylinders = cyls;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -