diff options
-rw-r--r-- | LICENSE | 4 | ||||
-rw-r--r-- | README | 6 | ||||
-rw-r--r-- | applets/busybox.c | 8 | ||||
-rw-r--r-- | archival/gzip.c | 18 | ||||
-rw-r--r-- | archival/tar.c | 17 | ||||
-rw-r--r-- | busybox.c | 8 | ||||
-rw-r--r-- | busybox.def.h | 1 | ||||
-rw-r--r-- | cat.c | 2 | ||||
-rw-r--r-- | chmod_chown_chgrp.c | 168 | ||||
-rw-r--r-- | console-tools/loadfont.c | 4 | ||||
-rw-r--r-- | console-tools/loadkmap.c | 4 | ||||
-rw-r--r-- | coreutils/cat.c | 2 | ||||
-rw-r--r-- | coreutils/cp.c | 2 | ||||
-rw-r--r-- | coreutils/date.c | 2 | ||||
-rw-r--r-- | coreutils/dd.c | 2 | ||||
-rw-r--r-- | coreutils/df.c | 2 | ||||
-rw-r--r-- | coreutils/ls.c | 19 | ||||
-rw-r--r-- | coreutils/mkdir.c | 2 | ||||
-rw-r--r-- | coreutils/mknod.c | 2 | ||||
-rw-r--r-- | coreutils/printf.c | 2 | ||||
-rw-r--r-- | coreutils/touch.c | 2 | ||||
-rw-r--r-- | cp.c | 2 | ||||
-rw-r--r-- | date.c | 2 | ||||
-rw-r--r-- | dd.c | 2 | ||||
-rw-r--r-- | df.c | 2 | ||||
-rw-r--r-- | dmesg.c | 128 | ||||
-rw-r--r-- | dutmp.c | 4 | ||||
-rw-r--r-- | findutils/grep.c | 2 | ||||
-rw-r--r-- | grep.c | 2 | ||||
-rw-r--r-- | gzip.c | 18 | ||||
-rw-r--r-- | init.c | 2 | ||||
-rw-r--r-- | init/init.c | 2 | ||||
-rw-r--r-- | internal.h | 6 | ||||
-rw-r--r-- | kill.c | 8 | ||||
-rw-r--r-- | loadfont.c | 4 | ||||
-rw-r--r-- | loadkmap.c | 4 | ||||
-rw-r--r-- | ls.c | 19 | ||||
-rw-r--r-- | makedevs.c | 5 | ||||
-rw-r--r-- | math.c | 2 | ||||
-rw-r--r-- | miscutils/dutmp.c | 4 | ||||
-rw-r--r-- | miscutils/makedevs.c | 5 | ||||
-rw-r--r-- | miscutils/mt.c | 2 | ||||
-rw-r--r-- | mkdir.c | 2 | ||||
-rw-r--r-- | mknod.c | 2 | ||||
-rw-r--r-- | mkswap.c | 448 | ||||
-rw-r--r-- | mnc.c | 2 | ||||
-rw-r--r-- | more.c | 2 | ||||
-rw-r--r-- | mount.c | 2 | ||||
-rw-r--r-- | mt.c | 2 | ||||
-rw-r--r-- | printf.c | 2 | ||||
-rw-r--r-- | procps/kill.c | 8 | ||||
-rw-r--r-- | sfdisk.c | 2880 | ||||
-rw-r--r-- | tar.c | 17 | ||||
-rw-r--r-- | touch.c | 2 | ||||
-rw-r--r-- | umount.c | 2 | ||||
-rw-r--r-- | util-linux/dmesg.c | 128 | ||||
-rw-r--r-- | util-linux/mkswap.c | 448 | ||||
-rw-r--r-- | util-linux/more.c | 2 | ||||
-rw-r--r-- | util-linux/mount.c | 2 | ||||
-rw-r--r-- | util-linux/umount.c | 2 | ||||
-rw-r--r-- | zcat.c | 14 |
61 files changed, 3997 insertions, 472 deletions
@@ -22,3 +22,7 @@ Please see the top of the source files for more precise indivigual copyright and license info. This program suite may be distributed under the GNU General Public License. + + +Please send patches, suggestions, insults, and bribes to <andersee@debian.org>. + @@ -17,11 +17,15 @@ using C++ comments (//) After the build is complete a busybox.links file is generated to allow you to easily make the sym/hard links to the busybox binary. -Note the modular system is Makefile based, and purposly very +Note the modular system is Makefile based, and purposely very simplistic. It does no dependency checking. That is left for you to figure out by trial and error. Please feed patches back to: + Erik Andersen <andersee@deban.org> +and + Bruce Perens <bruce@perens.com> +and Dave Cinege <dcinege@psychosis.com> and: Enrique Zanardi <ezanardi@ull.es> diff --git a/applets/busybox.c b/applets/busybox.c index 3af9840..6bcb652 100644 --- a/applets/busybox.c +++ b/applets/busybox.c @@ -14,7 +14,7 @@ static const struct Applet applets[] = { {"block_device", block_device_main}, #endif #ifdef BB_CAT //bin - {"cat", cat_more_main}, + {"cat", cat_main}, #endif #ifdef BB_CHMOD_CHOWN_CHGRP //bin {"chmod", chmod_chown_chgrp_main}, @@ -43,7 +43,7 @@ static const struct Applet applets[] = { {"dmesg", dmesg_main}, #endif #ifdef BB_DUTMP //usr/sbin - {"dutmp", cat_more_main}, + {"dutmp", dutmp_main}, #endif #ifdef BB_FDFLUSH //bin {"fdflush", fdflush_main}, @@ -123,6 +123,10 @@ static const struct Applet applets[] = { #ifdef BB_RMDIR //bin {"rmdir", rmdir_main}, #endif +#ifdef BB_SFDISK //sbin + {"fdisk", sfdisk_main}, + {"sfdisk", sfdisk_main}, +#endif #ifdef BB_SLEEP //bin {"sleep", sleep_main}, #endif diff --git a/archival/gzip.c b/archival/gzip.c index c7fb25e..0ed20b6 100644 --- a/archival/gzip.c +++ b/archival/gzip.c @@ -11,7 +11,7 @@ #error you need zcat to have gzip support! #endif -const char gzip_usage[] = "gzip\nignores all command line arguments\ncompress stdin to stdout with -9 compression\n"; +static const char gzip_usage[] = "gzip\nignores all command line arguments\ncompress stdin to stdout with -9 compression\n"; /* gzip.h -- common declarations for all gzip modules * Copyright (C) 1992-1993 Jean-loup Gailly. @@ -380,7 +380,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */ # undef LZW #endif -/* $Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $ */ +/* $Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $ */ /* tailor.h -- target dependent definitions * Copyright (C) 1992-1993 Jean-loup Gailly. * This is free software; you can redistribute it and/or modify it under the @@ -391,7 +391,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */ * The target dependent functions should be defined in tailor.c. */ -/* $Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $ */ +/* $Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $ */ #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS @@ -767,7 +767,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */ #endif #ifdef RCSID -static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; +static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $"; #endif /* =========================================================================== @@ -976,7 +976,7 @@ void copy_block(buf, len, header) #include <stdio.h> #ifdef RCSID -static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; +static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $"; #endif /* =========================================================================== @@ -1592,7 +1592,7 @@ ulg deflate() */ #ifdef RCSID -static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; +static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $"; #endif #include <ctype.h> @@ -1925,7 +1925,7 @@ local void do_exit(int exitcode) #include <ctype.h> #ifdef RCSID -static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; +static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $"; #endif /* =========================================================================== @@ -2943,7 +2943,7 @@ local void set_file_type() */ #ifdef RCSID -static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; +static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $"; #endif #include <ctype.h> @@ -3142,7 +3142,7 @@ void display_ratio(num, den, file) */ #ifdef RCSID -static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; +static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $"; #endif #include <ctype.h> diff --git a/archival/tar.c b/archival/tar.c index f222c3c..b404ab0 100644 --- a/archival/tar.c +++ b/archival/tar.c @@ -12,10 +12,15 @@ #include "internal.h" +#include <stdio.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <time.h> -#ifdef BB_TAR -const char tar_usage[] = +static const char tar_usage[] = "Create, extract, or list files from a TAR file\n\n" "usage: tar -[cxtvOf] [tarFileName] [FILE] ...\n" "\tc=create, x=extract, t=list contents, v=verbose,\n" @@ -23,13 +28,6 @@ const char tar_usage[] = -#include <stdio.h> -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <time.h> - /* * Tar file constants. */ @@ -1151,5 +1149,4 @@ wantFileName (const char *fileName, int fileCount, char **fileTable) -#endif /* END CODE */ @@ -14,7 +14,7 @@ static const struct Applet applets[] = { {"block_device", block_device_main}, #endif #ifdef BB_CAT //bin - {"cat", cat_more_main}, + {"cat", cat_main}, #endif #ifdef BB_CHMOD_CHOWN_CHGRP //bin {"chmod", chmod_chown_chgrp_main}, @@ -43,7 +43,7 @@ static const struct Applet applets[] = { {"dmesg", dmesg_main}, #endif #ifdef BB_DUTMP //usr/sbin - {"dutmp", cat_more_main}, + {"dutmp", dutmp_main}, #endif #ifdef BB_FDFLUSH //bin {"fdflush", fdflush_main}, @@ -123,6 +123,10 @@ static const struct Applet applets[] = { #ifdef BB_RMDIR //bin {"rmdir", rmdir_main}, #endif +#ifdef BB_SFDISK //sbin + {"fdisk", sfdisk_main}, + {"sfdisk", sfdisk_main}, +#endif #ifdef BB_SLEEP //bin {"sleep", sleep_main}, #endif diff --git a/busybox.def.h b/busybox.def.h index 68d1ec0..c90297a 100644 --- a/busybox.def.h +++ b/busybox.def.h @@ -40,6 +40,7 @@ #define BB_REBOOT #define BB_RM #define BB_RMDIR +#define BB_SFDISK #define BB_SLEEP #define BB_SWAPONOFF #define BB_SYNC @@ -32,7 +32,7 @@ static void print_file( FILE *file) fflush(stdout); } -extern int cat_more_main(int argc, char **argv) +extern int cat_main(int argc, char **argv) { FILE *file; diff --git a/chmod_chown_chgrp.c b/chmod_chown_chgrp.c index cac09e7..e760500 100644 --- a/chmod_chown_chgrp.c +++ b/chmod_chown_chgrp.c @@ -144,3 +144,171 @@ int chmod_chown_chgrp_main(int argc, char **argv) exit(TRUE); } + + + + + + + + + + + +#ifdef fooo + + + + + + + + + + + + + + + +#include "internal.h" +#include <pwd.h> +#include <grp.h> +#include <string.h> +#include <stdio.h> + +int my_getid(const char *filename, const char *name, uid_t *id) +{ + FILE *stream; + uid_t rid; + char *rname, *start, *end, buf[128]; + + stream=fopen(filename,"r"); + + while (fgets (buf, 128, stream) != NULL) { + if (buf[0] == '#') + continue; + + start = buf; + end = strchr (start, ':'); + if (end == NULL) + continue; + *end = '\0'; + rname = start; + + start = end + 1; + end = strchr (start, ':'); + if (end == NULL) + continue; + + start = end + 1; + rid = (uid_t) strtol (start, &end, 10); + if (end == start) + continue; + + if (name) { + if (0 == strcmp(rname, name)) { + *id=rid; + return 0; + } + } else { + if ( *id == rid ) + return 0; + } + } + fclose(stream); + return -1; +} + +int +my_getpwuid(uid_t *uid) +{ + return my_getid("/etc/passwd", NULL, uid); +} + +int +my_getpwnam(char *name, uid_t *uid) +{ + return my_getid("/etc/passwd", name, uid); +} + +int +my_getgrgid(gid_t *gid) +{ + return my_getid("/etc/group", NULL, gid); +} + +int +my_getgrnam(char *name, gid_t *gid) +{ + return my_getid("/etc/group", name, gid); +} + +const char chown_usage[] = "chown [-R] user-name file [file ...]\n" +"\n\tThe group list is kept in the file /etc/groups.\n\n" +"\t-R:\tRecursively change the mode of all files and directories\n" +"\t\tunder the argument directory."; + +int +parse_user_name(const char * s, struct FileInfo * i) +{ + char * dot = strchr(s, '.'); + char * end = NULL; + uid_t id = 0; + + if (! dot ) + dot = strchr(s, ':'); + + if ( dot ) + *dot = '\0'; + + if ( my_getpwnam(s,&id) == -1 ) { + id = strtol(s,&end,10); + if ((*end != '\0') || ( my_getpwuid(&id) == -1 )) { + fprintf(stderr, "%s: no such user.\n", s); + return 1; + } + } + i->userID = id; + + if ( dot ) { + if ( my_getgrnam(++dot,&id) == -1 ) { + id = strtol(dot,&end,10); + if ((*end != '\0') || ( my_getgrgid(&id) == -1 )) { + fprintf(stderr, "%s: no such group.\n", dot); + return 1; + } + } + i->groupID = id; + i->changeGroupID = 1; + } + return 0; +} + +extern int +chown_main(struct FileInfo * i, int argc, char * * argv) +{ + int status; + + while ( argc >= 3 && strcmp("-R", argv[1]) == 0 ) { + i->recursive = 1; + argc--; + argv++; + } + + if ( (status = parse_user_name(argv[1], i)) != 0 ) + return status; + + argv++; + argc--; + + i->changeUserID = 1; + i->complainInPostProcess = 1; + + return monadic_main(i, argc, argv); +} + + + + +#endif diff --git a/console-tools/loadfont.c b/console-tools/loadfont.c index a10fa8a..e44525d 100644 --- a/console-tools/loadfont.c +++ b/console-tools/loadfont.c @@ -75,7 +75,7 @@ do_loadfont(int fd, char *inbuf, int unit, int fontsize) { for (i = 0; i < fontsize; i++) memcpy(buf+(32*i), inbuf+(unit*i), unit); -#if defined( PIO_FONTX ) && !defined( sparc ) +#if defined( PIO_FONTX ) && !defined( __sparc__ ) { struct consolefontdesc cfd; @@ -196,7 +196,7 @@ loadnewfont(int fd) { exit(1); } fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256); -#if !defined( PIO_FONTX ) || defined( sparc ) +#if !defined( PIO_FONTX ) || defined( __sparc__ ) if (fontsize != 256) { fprintf(stderr, "Only fontsize 256 supported\n"); exit(1); diff --git a/console-tools/loadkmap.c b/console-tools/loadkmap.c index eb5a5dd..27865d5 100644 --- a/console-tools/loadkmap.c +++ b/console-tools/loadkmap.c @@ -7,7 +7,7 @@ #include <sys/ioctl.h> -const char loadkmap_usage[] = "loadkmap\n" +static const char loadkmap_usage[] = "loadkmap\n" "\n" "\tLoad a binary keyboard translation table from standard input.\n" "\n"; @@ -48,7 +48,7 @@ loadkmap_main(int argc, char * * argv) if (flags[i]==1){ pos=0; while (pos < ibuffsz) { - if ( (readsz = read(0,ibuff+pos,ibuffsz-pos)) < 0 ) { + if ( (readsz = read(0,(char *)ibuff+pos,ibuffsz-pos)) < 0 ) { fprintf(stderr, "Error reading keymap: %s\n", strerror(errno)); return 1; diff --git a/coreutils/cat.c b/coreutils/cat.c index 38078d5..3aae6d7 100644 --- a/coreutils/cat.c +++ b/coreutils/cat.c @@ -32,7 +32,7 @@ static void print_file( FILE *file) fflush(stdout); } -extern int cat_more_main(int argc, char **argv) +extern int cat_main(int argc, char **argv) { FILE *file; diff --git a/coreutils/cp.c b/coreutils/cp.c index 11c7682..34c1292 100644 --- a/coreutils/cp.c +++ b/coreutils/cp.c @@ -25,7 +25,7 @@ #include <utime.h> #include <dirent.h> -const char cp_usage[] = "cp [OPTION]... SOURCE DEST\n" +static const char cp_usage[] = "cp [OPTION]... SOURCE DEST\n" " or: cp [OPTION]... SOURCE... DIRECTORY\n" "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n" "\n" diff --git a/coreutils/date.c b/coreutils/date.c index 70d5dd5..5119484 100644 --- a/coreutils/date.c +++ b/coreutils/date.c @@ -34,7 +34,7 @@ an RFC 822 complient date output for shell scripting mail commands */ -const char date_usage[] = "date [OPTION]... [+FORMAT]\n" +static const char date_usage[] = "date [OPTION]... [+FORMAT]\n" " or: date [OPTION] [MMDDhhmm[[CC]YY][.ss]]\n" "Display the current time in the given FORMAT, or set the system date.\n" "\nOptions:\n\t-R\t\toutput RFC-822 compliant date string\n" diff --git a/coreutils/dd.c b/coreutils/dd.c index ecf7e3a..1cf7316 100644 --- a/coreutils/dd.c +++ b/coreutils/dd.c @@ -14,7 +14,7 @@ #include <fcntl.h> #include <errno.h> -const char dd_usage[] = +static const char dd_usage[] = "Copy a file, converting and formatting according to options\n\ \n\ usage: [if=name] [of=name] [bs=n] [count=n]\n\ diff --git a/coreutils/df.c b/coreutils/df.c index a777d70..7a72bf8 100644 --- a/coreutils/df.c +++ b/coreutils/df.c @@ -5,7 +5,7 @@ #include <sys/vfs.h> #include <fstab.h> -const char df_usage[] = "df [filesystem ...]\n" +static const char df_usage[] = "df [filesystem ...]\n" "\n" "\tPrint the filesystem space used and space available.\n"; diff --git a/coreutils/ls.c b/coreutils/ls.c index 0adc35d..a8e7e04 100644 --- a/coreutils/ls.c +++ b/coreutils/ls.c @@ -132,7 +132,6 @@ int ls_main(int argc, char **argv) #else -#include "internal.h" /* * tiny-ls.c version 0.1.0: A minimalist 'ls' * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com> @@ -175,7 +174,7 @@ int ls_main(int argc, char **argv) * 1. requires lstat (BSD) - how do you do it without? */ -#define FEATURE_USERNAME /* show username/groupnames (libc6 uses NSS) */ +//#define FEATURE_USERNAME /* show username/groupnames (libc6 uses NSS) */ #define FEATURE_TIMESTAMPS /* show file timestamps */ #define FEATURE_AUTOWIDTH /* calculate terminal & column widths */ #define FEATURE_FILETYPECHAR /* enable -p and -F */ @@ -187,8 +186,8 @@ int ls_main(int argc, char **argv) /************************************************************************/ - -#if 1 /* FIXME libc 6 */ +#include "internal.h" +#if !defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) # include <linux/types.h> #else # include <sys/types.h> @@ -225,7 +224,7 @@ int ls_main(int argc, char **argv) /* The 9 mode bits to test */ -static const umode_t MBIT[] = { +static const mode_t MBIT[] = { S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH @@ -233,7 +232,7 @@ static const umode_t MBIT[] = { /* The special bits. If set, display SMODE0/1 instead of MODE0/1 */ -static const umode_t SBIT[] = { +static const mode_t SBIT[] = { 0, 0, S_ISUID, 0, 0, S_ISGID, 0, 0, S_ISVTX @@ -278,7 +277,7 @@ static unsigned char time_fmt = TIME_MOD; static void writenum(long val, short minwidth) { - char scratch[20]; + char scratch[128]; char *p = scratch + sizeof(scratch); short len = 0; @@ -324,7 +323,7 @@ static void tab(short col) } #ifdef FEATURE_FILETYPECHAR -static char append_char(umode_t mode) +static char append_char(mode_t mode) { if (!(opts & DISP_FTYPE)) return '\0'; @@ -343,14 +342,14 @@ static char append_char(umode_t mode) static void list_single(const char *name, struct stat *info) { - char scratch[20]; + char scratch[PATH_MAX]; short len = strlen(name); #ifdef FEATURE_FILETYPECHAR char append = append_char(info->st_mode); #endif if (display_fmt == FMT_LONG) { - umode_t mode = info->st_mode; + mode_t mode = info->st_mode; int i; scratch[0] = TYPECHAR(mode); diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c index b42899a..cf65f27 100644 --- a/coreutils/mkdir.c +++ b/coreutils/mkdir.c @@ -24,7 +24,7 @@ #include <errno.h> #include <sys/param.h> -const char mkdir_usage[] = "Usage: mkdir [OPTION] DIRECTORY...\n" +static const char mkdir_usage[] = "Usage: mkdir [OPTION] DIRECTORY...\n" "Create the DIRECTORY(ies), if they do not already exist\n\n" "-m\tset permission mode (as in chmod), not rwxrwxrwx - umask\n" "-p\tno error if existing, make parent directories as needed\n"; diff --git a/coreutils/mknod.c b/coreutils/mknod.c index 95d7de3..ea2331f 100644 --- a/coreutils/mknod.c +++ b/coreutils/mknod.c @@ -6,7 +6,7 @@ #include <fcntl.h> #include <unistd.h> -const char mknod_usage[] = "mknod file b|c|u|p major minor\n" +static const char mknod_usage[] = "mknod file b|c|u|p major minor\n" "\tMake special files.\n" "\n" "\tb:\tMake a block (buffered) device.\n" diff --git a/coreutils/printf.c b/coreutils/printf.c index 4d44659..02d0811 100644 --- a/coreutils/printf.c +++ b/coreutils/printf.c @@ -136,7 +136,7 @@ static void verify __P ((char *s, char *end)); /* The value to return to the calling program. */ static int exit_status; -const char printf_usage[] = "printf format [argument...]\n"; +static const char printf_usage[] = "printf format [argument...]\n"; int printf_main(int argc, char** argv) diff --git a/coreutils/touch.c b/coreutils/touch.c index c36ffca..d882a63 100644 --- a/coreutils/touch.c +++ b/coreutils/touch.c @@ -28,7 +28,7 @@ #include <errno.h> -const char touch_usage[] = "touch [-c] file [file ...]\n\n" +static const char touch_usage[] = "touch [-c] file [file ...]\n\n" "\tUpdate the last-modified date on the given file[s].\n"; @@ -25,7 +25,7 @@ #include <utime.h> #include <dirent.h> -const char cp_usage[] = "cp [OPTION]... SOURCE DEST\n" +static const char cp_usage[] = "cp [OPTION]... SOURCE DEST\n" " or: cp [OPTION]... SOURCE... DIRECTORY\n" "Copy SOURCE to DEST, or multiple SOURCE(s) to DIRECTORY.\n" "\n" @@ -34,7 +34,7 @@ an RFC 822 complient date output for shell scripting mail commands */ -const char date_usage[] = "date [OPTION]... [+FORMAT]\n" +static const char date_usage[] = "date [OPTION]... [+FORMAT]\n" " or: date [OPTION] [MMDDhhmm[[CC]YY][.ss]]\n" "Display the current time in the given FORMAT, or set the system date.\n" "\nOptions:\n\t-R\t\toutput RFC-822 compliant date string\n" @@ -14,7 +14,7 @@ #include <fcntl.h> #include <errno.h> -const char dd_usage[] = +static const char dd_usage[] = "Copy a file, converting and formatting according to options\n\ \n\ usage: [if=name] [of=name] [bs=n] [count=n]\n\ @@ -5,7 +5,7 @@ #include <sys/vfs.h> #include <fstab.h> -const char df_usage[] = "df [filesystem ...]\n" +static const char df_usage[] = "df [filesystem ...]\n" "\n" "\tPrint the filesystem space used and space available.\n"; @@ -1,45 +1,49 @@ -#include "internal.h" -#include <stdlib.h> -#include <unistd.h> -#include <time.h> - /* dmesg.c -- Print out the contents of the kernel ring buffer * Created: Sat Oct 9 16:19:47 1993 * Revised: Thu Oct 28 21:52:17 1993 by faith@cs.unc.edu * Copyright 1993 Theodore Ts'o (tytso@athena.mit.edu) * This program comes with ABSOLUTELY NO WARRANTY. * Modifications by Rick Sladkey (jrs@world.std.com) - * from util-linux; adapted for busybox + * Larger buffersize 3 June 1998 by Nicolai Langfeldt, based on a patch + * by Peeter Joot. This was also suggested by John Hudson. + * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org> + * - added Native Language Support + * + * from util-linux -- adapted for busybox by + * Erik Andersen <andersee@debian.org>. I ripped out Native Language + * Support, replaced getopt, added some gotos for redundant stuff. */ +#include "internal.h" #include <linux/unistd.h> #include <stdio.h> +#include <getopt.h> +#include <stdlib.h> -#define __NR_klog __NR_syslog - -#if defined(__GLIBC__) -#include <sys/klog.h> -#define klog klogctl -#else -static inline _syscall3 (int, klog, int, type, char *, b, int, len) -#endif /* __GLIBC__ */ +#if __GNU_LIBRARY__ < 5 +#ifndef __alpha__ +# define __NR_klogctl __NR_syslog + static inline _syscall3(int, klogctl, int, type, char *, b, int, len); +#else /* __alpha__ */ +#define klogctl syslog +#endif +#else +# include <sys/klog.h> +#endif -static const char dmesg_usage[] = "dmesg [-c] [-n level]\n"; +static const char dmesg_usage[] = "dmesg [-c] [-n level] [-s bufsize]\n"; -int dmesg_main (int argc, char **argv) +int dmesg_main( int argc, char** argv ) { - - char buf[4096]; - int i; - int n; - int level = 0; - int lastc; - int cmd = 3; - - argc--; - argv++; + char *buf; + int bufsize=8196; + int i; + int n; + int level = 0; + int lastc; + int cmd = 3; /* Parse any options */ while (argc && **argv == '-') { @@ -56,43 +60,57 @@ int dmesg_main (int argc, char **argv) --argc; ++argv; break; + case 's': + if (--argc == 0) + goto end; + bufsize = atoi (*(++argv)); + --argc; + ++argv; + break; default: goto end; } } + + if (argc > 1) { + goto end; + } - if (cmd == 8) { - n = klog (cmd, NULL, level); - if (n < 0) { - perror ("klog"); - exit (FALSE); - } - exit (TRUE); - } + if (cmd == 8) { + n = klogctl( cmd, NULL, level ); + if (n < 0) { + goto klogctl_error; + } + exit( TRUE ); + } - n = klog (cmd, buf, sizeof (buf)); - if (n < 0) { - perror ("klog"); - exit (FALSE); - } + if (bufsize < 4096) bufsize = 4096; + buf = (char*)malloc(bufsize); + n = klogctl( cmd, buf, bufsize ); + if (n < 0) { + goto klogctl_error; + } - lastc = '\n'; - for (i = 0; i < n; i++) { - if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') { + lastc = '\n'; + for (i = 0; i < n; i++) { + if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') { + i++; + while (buf[i] >= '0' && buf[i] <= '9') i++; - while (buf[i] >= '0' && buf[i] <= '9') - i++; - if (buf[i] == '>') - i++; - } - lastc = buf[i]; - putchar (lastc); - } - if (lastc != '\n') - putchar ('\n'); - exit (TRUE); - - end: + if (buf[i] == '>') + i++; + } + lastc = buf[i]; + putchar( lastc ); + } + if (lastc != '\n') + putchar( '\n' ); + exit( TRUE); +end: usage( dmesg_usage); exit (FALSE); +klogctl_error: + perror( "klogctl" ); + exit( FALSE ); + } @@ -14,12 +14,12 @@ #include <stdio.h> #include <utmp.h> -const char dutmp_usage[] = "dutmp\n" +static const char dutmp_usage[] = "dutmp\n" "\n" "\tDump file or stdin utmp file format to stdout, pipe delimited.\n" "\tdutmp /var/run/utmp\n"; -extern int dutmp_fn (int argc, char **argv) +static int dutmp_main (int argc, char **argv) { FILE *f = stdin; diff --git a/findutils/grep.c b/findutils/grep.c index de1c820..108c879 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -29,7 +29,7 @@ #include <ctype.h> -const char grep_usage[] = +static const char grep_usage[] = "grep [-ihn]... PATTERN [FILE]...\n" "Search for PATTERN in each FILE or standard input.\n\n" "\t-h\tsuppress the prefixing filename on output\n" @@ -29,7 +29,7 @@ #include <ctype.h> -const char grep_usage[] = +static const char grep_usage[] = "grep [-ihn]... PATTERN [FILE]...\n" "Search for PATTERN in each FILE or standard input.\n\n" "\t-h\tsuppress the prefixing filename on output\n" @@ -11,7 +11,7 @@ #error you need zcat to have gzip support! #endif -const char gzip_usage[] = "gzip\nignores all command line arguments\ncompress stdin to stdout with -9 compression\n"; +static const char gzip_usage[] = "gzip\nignores all command line arguments\ncompress stdin to stdout with -9 compression\n"; /* gzip.h -- common declarations for all gzip modules * Copyright (C) 1992-1993 Jean-loup Gailly. @@ -380,7 +380,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */ # undef LZW #endif -/* $Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $ */ +/* $Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $ */ /* tailor.h -- target dependent definitions * Copyright (C) 1992-1993 Jean-loup Gailly. * This is free software; you can redistribute it and/or modify it under the @@ -391,7 +391,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */ * The target dependent functions should be defined in tailor.c. */ -/* $Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $ */ +/* $Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $ */ #if defined(__MSDOS__) && !defined(MSDOS) # define MSDOS @@ -767,7 +767,7 @@ extern int block_mode; /* block compress mode -C compatible with 2.0 */ #endif #ifdef RCSID -static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; +static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $"; #endif /* =========================================================================== @@ -976,7 +976,7 @@ void copy_block(buf, len, header) #include <stdio.h> #ifdef RCSID -static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; +static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $"; #endif /* =========================================================================== @@ -1592,7 +1592,7 @@ ulg deflate() */ #ifdef RCSID -static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; +static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $"; #endif #include <ctype.h> @@ -1925,7 +1925,7 @@ local void do_exit(int exitcode) #include <ctype.h> #ifdef RCSID -static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; +static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $"; #endif /* =========================================================================== @@ -2943,7 +2943,7 @@ local void set_file_type() */ #ifdef RCSID -static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; +static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $"; #endif #include <ctype.h> @@ -3142,7 +3142,7 @@ void display_ratio(num, den, file) */ #ifdef RCSID -static char rcsid[] = "$Id: gzip.c,v 1.3 1999/10/16 15:48:40 andersen Exp $"; +static char rcsid[] = "$Id: gzip.c,v 1.4 1999/10/19 20:03:34 andersen Exp $"; #endif #include <ctype.h> @@ -300,7 +300,7 @@ configure_terminals( int serial_cons, int single_user_mode ) } if (!first_terminal) first_terminal = console; -#if #cpu (sparc) +#if defined (__sparc__) if (serial_cons > 0 && !strncmp(term_ptr,"TERM=linux",10)) term_ptr = "TERM=vt100"; #endif diff --git a/init/init.c b/init/init.c index ca194dd..6c44cce 100644 --- a/init/init.c +++ b/init/init.c @@ -300,7 +300,7 @@ configure_terminals( int serial_cons, int single_user_mode ) } if (!first_terminal) first_terminal = console; -#if #cpu (sparc) +#if defined (__sparc__) if (serial_cons > 0 && !strncmp(term_ptr,"TERM=linux",10)) term_ptr = "TERM=vt100"; #endif @@ -56,7 +56,7 @@ struct Applet { extern int busybox_main(int argc, char** argv); extern int block_device_main(int argc, char** argv); -extern int cat_more_main(int argc, char** argv); +extern int cat_main(int argc, char** argv); extern int more_main(int argc, char** argv); extern int cp_main(int argc, char** argv); extern int chmod_chown_chgrp_main(int argc, char** argv); @@ -66,6 +66,7 @@ extern int date_main(int argc, char** argv); extern int dd_main(int argc, char** argv); extern int df_main(int argc, char** argv); extern int dmesg_main(int argc, char** argv); +extern int dutmp_main(int argc, char** argv); extern int false_main(int argc, char** argv); extern int fdisk_main(int argc, char** argv); extern int fdflush_main(int argc, char **argv); @@ -96,11 +97,12 @@ extern int rmdir_main(int argc, char **argv); extern int rm_main(int argc, char** argv); extern int scan_partitions_main(int argc, char** argv); extern int sh_main(int argc, char** argv); +extern int sfdisk_main(int argc, char** argv); extern int sleep_main(int argc, char** argv); extern int swap_on_off_main(int argc, char** argv); +extern int sync_main(int argc, char** argv); extern int tar_main(int argc, char** argv); extern int touch_main(int argc, char** argv); -extern int sync_main(int argc, char** argv); extern int tput_main(int argc, char** argv); extern int true_main(int argc, char** argv); extern int tryopen_main(int argc, char** argv); @@ -21,20 +21,20 @@ const struct signal_name signames[] = { #ifndef __alpha__ {"IOT", SIGIOT}, #endif -#if defined(sparc) || defined(__alpha__) +#if defined(__sparc__) || defined(__alpha__) {"EMT", SIGEMT}, #else {"BUS", SIGBUS}, #endif {"FPE", SIGFPE}, {"KILL", SIGKILL}, -#if defined(sparc) || defined(__alpha__) +#if defined(__sparc__) || defined(__alpha__) {"BUS", SIGBUS}, #else {"USR1", SIGUSR1}, #endif {"SEGV", SIGSEGV}, -#if defined(sparc) || defined(__alpha__) +#if defined(__sparc__) || defined(__alpha__) {"SYS", SIGSYS}, #else {"USR2", SIGUSR2}, @@ -42,7 +42,7 @@ const struct signal_name signames[] = { {"PIPE", SIGPIPE}, {"ALRM", SIGALRM}, {"TERM", SIGTERM}, -#if defined(sparc) || defined(__alpha__) +#if defined(__sparc__) || defined(__alpha__) {"URG", SIGURG}, {"STOP", SIGSTOP}, {"TSTP", SIGTSTP}, @@ -75,7 +75,7 @@ do_loadfont(int fd, char *inbuf, int unit, int fontsize) { for (i = 0; i < fontsize; i++) memcpy(buf+(32*i), inbuf+(unit*i), unit); -#if defined( PIO_FONTX ) && !defined( sparc ) +#if defined( PIO_FONTX ) && !defined( __sparc__ ) { struct consolefontdesc cfd; @@ -196,7 +196,7 @@ loadnewfont(int fd) { exit(1); } fontsize = ((psfhdr.mode & PSF_MODE512) ? 512 : 256); -#if !defined( PIO_FONTX ) || defined( sparc ) +#if !defined( PIO_FONTX ) || defined( __sparc__ ) if (fontsize != 256) { fprintf(stderr, "Only fontsize 256 supported\n"); exit(1); @@ -7,7 +7,7 @@ #include <sys/ioctl.h> -const char loadkmap_usage[] = "loadkmap\n" +static const char loadkmap_usage[] = "loadkmap\n" "\n" "\tLoad a binary keyboard translation table from standard input.\n" "\n"; @@ -48,7 +48,7 @@ loadkmap_main(int argc, char * * argv) if (flags[i]==1){ pos=0; while (pos < ibuffsz) { - if ( (readsz = read(0,ibuff+pos,ibuffsz-pos)) < 0 ) { + if ( (readsz = read(0,(char *)ibuff+pos,ibuffsz-pos)) < 0 ) { fprintf(stderr, "Error reading keymap: %s\n", strerror(errno)); return 1; @@ -132,7 +132,6 @@ int ls_main(int argc, char **argv) #else -#include "internal.h" /* * tiny-ls.c version 0.1.0: A minimalist 'ls' * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com> @@ -175,7 +174,7 @@ int ls_main(int argc, char **argv) * 1. requires lstat (BSD) - how do you do it without? */ -#define FEATURE_USERNAME /* show username/groupnames (libc6 uses NSS) */ +//#define FEATURE_USERNAME /* show username/groupnames (libc6 uses NSS) */ #define FEATURE_TIMESTAMPS /* show file timestamps */ #define FEATURE_AUTOWIDTH /* calculate terminal & column widths */ #define FEATURE_FILETYPECHAR /* enable -p and -F */ @@ -187,8 +186,8 @@ int ls_main(int argc, char **argv) /************************************************************************/ - -#if 1 /* FIXME libc 6 */ +#include "internal.h" +#if !defined(__GLIBC__) && (__GLIBC__ >= 2) && (__GLIBC_MINOR__ >= 1) # include <linux/types.h> #else # include <sys/types.h> @@ -225,7 +224,7 @@ int ls_main(int argc, char **argv) /* The 9 mode bits to test */ -static const umode_t MBIT[] = { +static const mode_t MBIT[] = { S_IRUSR, S_IWUSR, S_IXUSR, S_IRGRP, S_IWGRP, S_IXGRP, S_IROTH, S_IWOTH, S_IXOTH @@ -233,7 +232,7 @@ static const umode_t MBIT[] = { /* The special bits. If set, display SMODE0/1 instead of MODE0/1 */ -static const umode_t SBIT[] = { +static const mode_t SBIT[] = { 0, 0, S_ISUID, 0, 0, S_ISGID, 0, 0, S_ISVTX @@ -278,7 +277,7 @@ static unsigned char time_fmt = TIME_MOD; static void writenum(long val, short minwidth) { - char scratch[20]; + char scratch[128]; char *p = scratch + sizeof(scratch); short len = 0; @@ -324,7 +323,7 @@ static void tab(short col) } #ifdef FEATURE_FILETYPECHAR -static char append_char(umode_t mode) +static char append_char(mode_t mode) { if (!(opts & DISP_FTYPE)) return '\0'; @@ -343,14 +342,14 @@ static char append_char(umode_t mode) static void list_single(const char *name, struct stat *info) { - char scratch[20]; + char scratch[PATH_MAX]; short len = strlen(name); #ifdef FEATURE_FILETYPECHAR char append = append_char(info->st_mode); #endif if (display_fmt == FMT_LONG) { - umode_t mode = info->st_mode; + mode_t mode = info->st_mode; int i; scratch[0] = TYPECHAR(mode); @@ -15,7 +15,7 @@ #include <sys/types.h> #include <sys/stat.h> -const char makedevs_usage[] = +static const char makedevs_usage[] = "makedevs 0.01 -- Create an entire range of device files\n\n" "\tmakedevs /dev/ttyS c 4 64 0 63 (ttyS0-ttyS63)\n" "\tmakedevs /dev/hda b 3 0 0 8 s (hda,hda1-hda8)\n"; @@ -45,8 +45,7 @@ char buf[255]; case 'f': mode = S_IFIFO; break; default: - fprintf(stderr, "Usage: %s\n", makedevs_usage); - return 2; + usage( makedevs_usage); } mode |= 0660; @@ -6,7 +6,7 @@ /* Tiny RPN calculator, because "expr" didn't give me bitwise operations. */ -const char math_usage[] = "math expression ..."; +static const char math_usage[] = "math expression ..."; static double stack[100]; static unsigned int pointer; diff --git a/miscutils/dutmp.c b/miscutils/dutmp.c index 7dd5b91..c5307b6 100644 --- a/miscutils/dutmp.c +++ b/miscutils/dutmp.c @@ -14,12 +14,12 @@ #include <stdio.h> #include <utmp.h> -const char dutmp_usage[] = "dutmp\n" +static const char dutmp_usage[] = "dutmp\n" "\n" "\tDump file or stdin utmp file format to stdout, pipe delimited.\n" "\tdutmp /var/run/utmp\n"; -extern int dutmp_fn (int argc, char **argv) +static int dutmp_main (int argc, char **argv) { FILE *f = stdin; diff --git a/miscutils/makedevs.c b/miscutils/makedevs.c index 00f0066..f7fbeb2 100644 --- a/miscutils/makedevs.c +++ b/miscutils/makedevs.c @@ -15,7 +15,7 @@ #include <sys/types.h> #include <sys/stat.h> -const char makedevs_usage[] = +static const char makedevs_usage[] = "makedevs 0.01 -- Create an entire range of device files\n\n" "\tmakedevs /dev/ttyS c 4 64 0 63 (ttyS0-ttyS63)\n" "\tmakedevs /dev/hda b 3 0 0 8 s (hda,hda1-hda8)\n"; @@ -45,8 +45,7 @@ char buf[255]; case 'f': mode = S_IFIFO; break; default: - fprintf(stderr, "Usage: %s\n", makedevs_usage); - return 2; + usage( makedevs_usage); } mode |= 0660; diff --git a/miscutils/mt.c b/miscutils/mt.c index a61ad5a..7168ef7 100644 --- a/miscutils/mt.c +++ b/miscutils/mt.c @@ -3,7 +3,7 @@ #include <sys/mtio.h> #include <sys/fcntl.h> -const char mt_usage[] = "mt [-f device] opcode value\n"; +static const char mt_usage[] = "mt [-f device] opcode value\n"; struct mt_opcodes { char * name; @@ -24,7 +24,7 @@ #include <errno.h> #include <sys/param.h> -const char mkdir_usage[] = "Usage: mkdir [OPTION] DIRECTORY...\n" +static const char mkdir_usage[] = "Usage: mkdir [OPTION] DIRECTORY...\n" "Create the DIRECTORY(ies), if they do not already exist\n\n" "-m\tset permission mode (as in chmod), not rwxrwxrwx - umask\n" "-p\tno error if existing, make parent directories as needed\n"; @@ -6,7 +6,7 @@ #include <fcntl.h> #include <unistd.h> -const char mknod_usage[] = "mknod file b|c|u|p major minor\n" +static const char mknod_usage[] = "mknod file b|c|u|p major minor\n" "\tMake special files.\n" "\n" "\tb:\tMake a block (buffered) device.\n" @@ -1,4 +1,3 @@ -#include "internal.h" /* * mkswap.c - set up a linux swap device * @@ -9,51 +8,170 @@ /* * 20.12.91 - time began. Got VM working yesterday by doing this by hand. * - * Usage: mkswap [-c] device [size-in-blocks] + * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks] * - * -c for readablility checking (use it unless you are SURE!) + * -c for readability checking. (Use it unless you are SURE!) + * -vN for swap areas version N. (Only N=0,1 known today.) + * -f for forcing swap creation even if it would smash partition table. * - * The device may be a block device or a image of one, but this isn't + * The device may be a block device or an image of one, but this isn't * enforced (but it's not much fun on a character device :-). * * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995. + * + * Version 1 swap area code (for kernel 2.1.117), aeb, 981010. + * + * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb. + * V1_MAX_PAGES fixes, jj, 990325. + * + * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org> + * - added Native Language Support + * + * from util-linux -- adapted for busybox by + * Erik Andersen <andersee@debian.org>. I ripped out Native Language + * Support, made some stuff smaller, and fitted for life in busybox. + * */ +#include "internal.h" #include <stdio.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <stdlib.h> +#include <sys/ioctl.h> /* for _IO */ +#include <sys/utsname.h> #include <sys/stat.h> -#include <sys/ioctl.h> +#include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */ + /* we also get PAGE_SIZE via getpagesize() */ -#include <asm/page.h> -#include <linux/fs.h> -#ifndef __linux__ -# define volatile -#endif +static const char mkswap_usage[] = "mkswap [-c] [-v0|-v1] device [block-count]\n" +"Prepare a disk partition to be used as a swap partition.\n\n" +"\t-c\tCheck for read-ability.\n" +"\t-v0\tMake version 0 swap [max 128 Megs].\n" +"\t-v1\tMake version 1 swap [big!] (default for kernels > 2.1.117).\n" +"\tblock-count\tNumber of block to use (default is entire partition).\n"; -#define TEST_BUFFER_PAGES 8 -const char mkswap_usage[] = "mkswap [-c] partition [block-count]\n" -"\n" -"\tPrepare a disk partition to be used as a swap partition.\n" -"\tThe default block count is the size of the entire partition.\n" -"\n" -"\t-c:\tCheck for read-ability.\n" -"\tblock-count\tUse only this many blocks.\n"; +#ifndef _IO +/* pre-1.3.45 */ +#define BLKGETSIZE 0x1260 +#else +/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */ +#define BLKGETSIZE _IO(0x12,96) +#endif -static const char * program_name = "mkswap"; -static const char * device_name = NULL; +static char * program_name = "mkswap"; +static char * device_name = NULL; static int DEV = -1; static long PAGES = 0; -static int do_check = 0; +static int check = 0; static int badpages = 0; +static int version = -1; + +#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) + +static int +linux_version_code(void) { + struct utsname my_utsname; + int p, q, r; + + if (uname(&my_utsname) == 0) { + p = atoi(strtok(my_utsname.release, ".")); + q = atoi(strtok(NULL, ".")); + r = atoi(strtok(NULL, ".")); + return MAKE_VERSION(p,q,r); + } + return 0; +} + +/* + * The definition of the union swap_header uses the constant PAGE_SIZE. + * Unfortunately, on some architectures this depends on the hardware model, + * and can only be found at run time -- we use getpagesize(). + */ + +static int pagesize; +static int *signature_page; + +struct swap_header_v1 { + char bootbits[1024]; /* Space for disklabel etc. */ + unsigned int version; + unsigned int last_page; + unsigned int nr_badpages; + unsigned int padding[125]; + unsigned int badpages[1]; +} *p; + +static void +init_signature_page() { + pagesize = getpagesize(); + +#ifdef PAGE_SIZE + if (pagesize != PAGE_SIZE) + fprintf(stderr, "Assuming pages of size %d\n", pagesize); +#endif + signature_page = (int *) malloc(pagesize); + memset(signature_page,0,pagesize); + p = (struct swap_header_v1 *) signature_page; +} +static void +write_signature(char *sig) { + char *sp = (char *) signature_page; -static long bit_test_and_set (unsigned int *addr, unsigned int nr) + strncpy(sp+pagesize-10, sig, 10); +} + +#define V0_MAX_PAGES (8 * (pagesize - 10)) +/* Before 2.2.0pre9 */ +#define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1) +/* Since 2.2.0pre9: + error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL)) + with variations on + #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8)) + #define SWP_OFFSET(entry) ((entry) >> 8) + on the various architectures. Below the result - yuk. + + Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2 + i386 2^12 o<<8 e>>8 1<<24 1<<19 + mips 2^12 o<<15 e>>15 1<<17 1<<19 + alpha 2^13 o<<40 e>>40 1<<24 1<<18 + m68k 2^12 o<<12 e>>12 1<<20 1<<19 + sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18} + sparc64 2^13 o<<13 e>>13 1<<51 1<<18 + ppc 2^12 o<<8 e>>8 1<<24 1<<19 + armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16} + armv 2^12 o<<9 e>>9 1<<23 1<<19 + + assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere. + + The bad part is that we need to know this since the kernel will + refuse a swap space if it is too large. +*/ +/* patch from jj - why does this differ from the above? */ +#if defined(__alpha__) +#define V1_MAX_PAGES ((1 << 24) - 1) +#elif defined(__mips__) +#define V1_MAX_PAGES ((1 << 17) - 1) +#elif defined(__sparc_v9__) +#define V1_MAX_PAGES ((3 << 29) - 1) +#elif defined(__sparc__) +#define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1)) +#else +#define V1_MAX_PAGES V1_OLD_MAX_PAGES +#endif +/* man page now says: +The maximum useful size of a swap area now depends on the architecture. +It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips, +128GB on alpha and 3TB on sparc64. +*/ + +#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int)) + +static void bit_set (unsigned int *addr, unsigned int nr) { unsigned int r, m; @@ -61,7 +179,6 @@ static long bit_test_and_set (unsigned int *addr, unsigned int nr) r = *addr; m = 1 << (nr & (8 * sizeof(int) - 1)); *addr = r | m; - return (r & m) != 0; } static int bit_test_and_clear (unsigned int *addr, unsigned int nr) @@ -75,47 +192,59 @@ static int bit_test_and_clear (unsigned int *addr, unsigned int nr) return (r & m) != 0; } -/* - * Volatile to let gcc know that this doesn't return. When trying - * to compile this under minix, volatile gives a warning, as - * exit() isn't defined as volatile under minix. - */ -volatile void fatal_error(const char * fmt_string) -{ - fprintf(stderr,fmt_string,program_name,device_name); - exit(FALSE); + +void +die(const char *str) { + fprintf(stderr, "%s: %s\n", program_name, str); + exit( FALSE); } -#define die(str) fatal_error("%s: " str "\n") +void +page_ok(int page) { + if (version==0) + bit_set(signature_page, page); +} -static void check_blocks(int * signature_page) -{ +void +page_bad(int page) { + if (version == 0) + bit_test_and_clear(signature_page, page); + else { + if (badpages == MAX_BADPAGES) + die("too many bad pages"); + p->badpages[badpages] = page; + } + badpages++; +} + +void +check_blocks(void) { unsigned int current_page; int do_seek = 1; - char buffer[PAGE_SIZE]; + char *buffer; + buffer = malloc(pagesize); + if (!buffer) + die("Out of memory"); current_page = 0; while (current_page < PAGES) { - if (!do_check) { - bit_test_and_set(signature_page,current_page++); + if (!check) { + page_ok(current_page++); continue; - } else { - printf("\r%d", current_page); } - if (do_seek && lseek(DEV,current_page*PAGE_SIZE,SEEK_SET) != - current_page*PAGE_SIZE) + if (do_seek && lseek(DEV,current_page*pagesize,SEEK_SET) != + current_page*pagesize) die("seek failed in check_blocks"); - if ( (do_seek = (PAGE_SIZE != read(DEV, buffer, PAGE_SIZE))) ) { - bit_test_and_clear(signature_page,current_page++); - badpages++; + if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) { + page_bad(current_page++); continue; } - bit_test_and_set(signature_page,current_page++); + page_ok(current_page++); } - if (do_check) - printf("\n"); - if (badpages) - printf("%d bad page%s\n",badpages,(badpages>1)?"s":""); + if (badpages == 1) + printf("one bad page\n"); + else if (badpages > 1) + printf("%d bad pages\n", badpages); } static long valid_offset (int fd, int offset) @@ -129,12 +258,13 @@ static long valid_offset (int fd, int offset) return 1; } -static int count_blocks (int fd) +static int +find_size (int fd) { - int high, low; + unsigned int high, low; low = 0; - for (high = 1; valid_offset (fd, high); high *= 2) + for (high = 1; high > 0 && valid_offset (fd, high); high *= 2) low = high; while (low < high - 1) { @@ -145,108 +275,194 @@ static int count_blocks (int fd) else high = mid; } - valid_offset (fd, 0); return (low + 1); } -static int get_size(const char *file) +/* return size in pages, to avoid integer overflow */ +static long +get_size(const char *file) { int fd; - int size; + long size; - fd = open(file, O_RDWR); + fd = open(file, O_RDONLY); if (fd < 0) { perror(file); exit(1); } if (ioctl(fd, BLKGETSIZE, &size) >= 0) { - close(fd); - return (size * 512); + int sectors_per_page = pagesize/512; + size /= sectors_per_page; + } else { + size = find_size(fd) / pagesize; } - - size = count_blocks(fd); close(fd); return size; } -int -mkswap(const char *device_name, int pages, int check) - { +int mkswap_main(int argc, char ** argv) +{ + char * tmp; struct stat statbuf; + int sz; + int maxpages; int goodpages; - int signature_page[PAGE_SIZE/sizeof(int)]; + int offset; + int force = 0; - PAGES = pages; - do_check = check; + if (argc && *argv) + program_name = *argv; - memset(signature_page,0,PAGE_SIZE); + init_signature_page(); /* get pagesize */ - if (device_name && !PAGES) { - PAGES = get_size(device_name) / PAGE_SIZE; + while (argc-- > 1) { + argv++; + if (argv[0][0] != '-') { + if (device_name) { + int blocks_per_page = pagesize/1024; + PAGES = strtol(argv[0],&tmp,0)/blocks_per_page; + if (*tmp) + usage( mkswap_usage); + } else + device_name = argv[0]; + } else { + switch (argv[0][1]) { + case 'c': + check=1; + break; + case 'f': + force=1; + break; + case 'v': + version=atoi(argv[0]+2); + break; + default: + usage( mkswap_usage); + } + } + } + if (!device_name) { + fprintf(stderr, + "%s: error: Nowhere to set up swap on?\n", + program_name); + usage( mkswap_usage); } - if (!device_name || PAGES<10) { + sz = get_size(device_name); + if (!PAGES) { + PAGES = sz; + } else if (PAGES > sz && !force) { + fprintf(stderr, + "%s: error: " + "size %ld is larger than device size %d\n", + program_name, + PAGES*(pagesize/1024), sz*(pagesize/1024)); + exit( FALSE); + } + + if (version == -1) { + if (PAGES <= V0_MAX_PAGES) + version = 0; + else if (linux_version_code() < MAKE_VERSION(2,1,117)) + version = 0; + else if (pagesize < 2048) + version = 0; + else + version = 1; + } + if (version != 0 && version != 1) { + fprintf(stderr, "%s: error: unknown version %d\n", + program_name, version); + usage( mkswap_usage); + } + if (PAGES < 10) { fprintf(stderr, "%s: error: swap area needs to be at least %ldkB\n", - program_name, 10 * PAGE_SIZE / 1024); - /* usage(mkswap_usage); */ - exit(1); + program_name, (long)(10 * pagesize / 1024)); + usage( mkswap_usage); + } +#if 0 + maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES); +#else + if (!version) + maxpages = V0_MAX_PAGES; + else if (linux_version_code() >= MAKE_VERSION(2,2,1)) + maxpages = V1_MAX_PAGES; + else { + maxpages = V1_OLD_MAX_PAGES; + if (maxpages > V1_MAX_PAGES) + maxpages = V1_MAX_PAGES; } - if (PAGES > 8 * (PAGE_SIZE - 10)) { - PAGES = 8 * (PAGE_SIZE - 10); +#endif + if (PAGES > maxpages) { + PAGES = maxpages; fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n", - program_name, PAGES * PAGE_SIZE / 1024); + program_name, PAGES * pagesize / 1024); } + DEV = open(device_name,O_RDWR); if (DEV < 0 || fstat(DEV, &statbuf) < 0) { perror(device_name); - exit(1); + exit( FALSE); } if (!S_ISBLK(statbuf.st_mode)) - do_check=0; + check=0; else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) die("Will not try to make swapdevice on '%s'"); - check_blocks(signature_page); - if (!bit_test_and_clear(signature_page,0)) + +#ifdef __sparc__ + if (!force && version == 0) { + /* Don't overwrite partition table unless forced */ + unsigned char *buffer = (unsigned char *)signature_page; + unsigned short *q, sum; + + if (read(DEV, buffer, 512) != 512) + die("fatal: first page unreadable"); + if (buffer[508] == 0xDA && buffer[509] == 0xBE) { + q = (unsigned short *)(buffer + 510); + for (sum = 0; q >= (unsigned short *) buffer;) + sum ^= *q--; + if (!sum) { + fprintf(stderr, "\ +%s: Device '%s' contains a valid Sun disklabel.\n\ +This probably means creating v0 swap would destroy your partition table\n\ +No swap created. If you really want to create swap v0 on that device, use\n\ +the -f option to force it.\n", + program_name, device_name); + exit( FALSE); + } + } + } +#endif + + if (version == 0 || check) + check_blocks(); + if (version == 0 && !bit_test_and_clear(signature_page,0)) die("fatal: first page unreadable"); + if (version == 1) { + p->version = version; + p->last_page = PAGES-1; + p->nr_badpages = badpages; + } + goodpages = PAGES - badpages - 1; if (goodpages <= 0) die("Unable to set up swap-space: unreadable"); - printf("Setting up swapspace, size = %ld bytes\n",goodpages*PAGE_SIZE); - strncpy((char*)signature_page+PAGE_SIZE-10,"SWAP-SPACE",10); - if (lseek(DEV, 0, SEEK_SET)) + printf("Setting up swapspace version %d, size = %ld bytes\n", + version, (long)(goodpages*pagesize)); + write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2"); + + offset = ((version == 0) ? 0 : 1024); + if (lseek(DEV, offset, SEEK_SET) != offset) die("unable to rewind swap-device"); - if (PAGE_SIZE != write(DEV, signature_page, PAGE_SIZE)) + if (write(DEV,(char*)signature_page+offset, pagesize-offset) + != pagesize-offset) die("unable to write signature page"); - close(DEV); - return (TRUE); -} - -int mkswap_main(int argc, char ** argv) -{ - char * tmp; - long int pages=0; - int check=0; - - if (argc && *argv) - program_name = *argv; - while (argc > 1) { - argv++; - argc--; - if (argv[0][0] != '-') - if (device_name) { - pages = strtol(argv[0],&tmp,0)>>(PAGE_SHIFT-10); - if (*tmp) { - usage (mkswap_usage); - } - } else - device_name = argv[0]; - else while (*++argv[0]) - switch (argv[0][0]) { - case 'c': check=1; break; - default: usage (mkswap_usage); - exit( TRUE); - } - } - exit( mkswap(device_name, pages, check)); + /* + * A subsequent swapon() will fail if the signature + * is not actually on disk. (This is a kernel bug.) + */ + if (fsync(DEV)) + die("fsync failed"); + exit ( TRUE); } @@ -39,7 +39,7 @@ #define BUFSIZE 100 -const char mnc_usage[] = +static const char mnc_usage[] = "mini-netcat 0.0.3 -- Open pipe to IP:port\n" "\tmnc [IP] [port]\n"; @@ -30,7 +30,7 @@ #include <signal.h> -const char more_usage[] = "[file ...]"; +static const char more_usage[] = "[file ...]"; #ifdef BB_MORE_TERM @@ -37,7 +37,7 @@ #include <ctype.h> #include <fstab.h> -const char mount_usage[] = "Usage:\tmount [flags]\n" +static const char mount_usage[] = "Usage:\tmount [flags]\n" "\tmount [flags] device directory [-o options,more-options]\n" "\n" "Flags:\n" @@ -3,7 +3,7 @@ #include <sys/mtio.h> #include <sys/fcntl.h> -const char mt_usage[] = "mt [-f device] opcode value\n"; +static const char mt_usage[] = "mt [-f device] opcode value\n"; struct mt_opcodes { char * name; @@ -136,7 +136,7 @@ static void verify __P ((char *s, char *end)); /* The value to return to the calling program. */ static int exit_status; -const char printf_usage[] = "printf format [argument...]\n"; +static const char printf_usage[] = "printf format [argument...]\n"; int printf_main(int argc, char** argv) diff --git a/procps/kill.c b/procps/kill.c index 00f10f9..e89f913 100644 --- a/procps/kill.c +++ b/procps/kill.c @@ -21,20 +21,20 @@ const struct signal_name signames[] = { #ifndef __alpha__ {"IOT", SIGIOT}, #endif -#if defined(sparc) || defined(__alpha__) +#if defined(__sparc__) || defined(__alpha__) {"EMT", SIGEMT}, #else {"BUS", SIGBUS}, #endif {"FPE", SIGFPE}, {"KILL", SIGKILL}, -#if defined(sparc) || defined(__alpha__) +#if defined(__sparc__) || defined(__alpha__) {"BUS", SIGBUS}, #else {"USR1", SIGUSR1}, #endif {"SEGV", SIGSEGV}, -#if defined(sparc) || defined(__alpha__) +#if defined(__sparc__) || defined(__alpha__) {"SYS", SIGSYS}, #else {"USR2", SIGUSR2}, @@ -42,7 +42,7 @@ const struct signal_name signames[] = { {"PIPE", SIGPIPE}, {"ALRM", SIGALRM}, {"TERM", SIGTERM}, -#if defined(sparc) || defined(__alpha__) +#if defined(__sparc__) || defined(__alpha__) {"URG", SIGURG}, {"STOP", SIGSTOP}, {"TSTP", SIGTSTP}, diff --git a/sfdisk.c b/sfdisk.c new file mode 100644 index 0000000..5b67e69 --- /dev/null +++ b/sfdisk.c @@ -0,0 +1,2880 @@ +/* + * 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 + * + * busyboxed by Erik Andersen <andersee@debian.org> -- I stipped out + * all the NLS, pulled in some includes, and made stuff smaller... + */ + +#define PROGNAME "sfdisk" +#define VERSION "3.07" +#define DATE "990908" + +#include "internal.h" +#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 <linux/unistd.h> /* _syscall */ +#include <linux/hdreg.h> /* HDIO_GETGEO */ +#include <linux/fs.h> /* BLKGETSIZE */ + + +static const char sfdisk_usage[] = +"Usage: sfdisk [options] device ...\n" +"device: something like /dev/hda or /dev/sda\n" +"useful options:\n" +" -s [or --show-size]: list size of a partition\n" +" -c [or --id]: print or change partition Id\n" +" -l [or --list]: list partitions of each device\n" +" -d [or --dump]: idem, but in a format suitable for later input\n" +" -i [or --increment]: number cylinders etc. from 1 instead of from 0\n" +" -uS, -uB, -uC, -uM: accept/report in units of sectors/blocks/cylinders/MB\n" +" -T [or --list-types]:list the known partition types\n" +" -D [or --DOS]: for DOS-compatibility: waste a little space\n" +" -R [or --re-read]: make kernel reread partition table\n" +" -N# : change only the partition with number #\n" +" -n : do not actually write to disk\n" +" -O file : save the sectors that will be overwritten to file\n" +" -I file : restore these sectors again\n" +" -v [or --version]: print version\n" +" -? [or --help]: print this message\n" +"dangerous options:\n" +" -g [or --show-geometry]: print the kernel's idea of the geometry\n" +" -x [or --show-extended]: also list extended partitions on output\n\n" +" or expect descriptors for them on input\n" +" -L [or --Linux]: do not complain about things irrelevant for Linux\n" +" -q [or --quiet]: suppress warning messages\n" +" You can override the detected geometry using:\n" +" -C# [or --cylinders #]:set the number of cylinders to use\n" +" -H# [or --heads #]: set the number of heads to use\n" +" -S# [or --sectors #]: set the number of sectors to use\n" +"You can disable all consistency checking with:\n" +" -f [or --force]: do what I say, even if it is stupid\n"; + + + +/* common stuff for fdisk, cfdisk, sfdisk */ +struct systypes { + unsigned char type; + char *name; +}; + +static struct systypes i386_sys_types[] = { + {0x00, "Empty"}, + {0x01, "FAT12"}, + {0x02, "XENIX root"}, + {0x03, "XENIX usr"}, + {0x04, "FAT16 <32M"}, + {0x05, "Extended"}, /* DOS 3.3+ extended partition */ + {0x06, "FAT16"}, /* DOS 16-bit >=32M */ + {0x07, "HPFS/NTFS"}, /* OS/2 IFS, eg, HPFS or NTFS or QNX */ + {0x08, "AIX"}, /* AIX boot (AIX -- PS/2 port or SplitDrive) */ + {0x09, "AIX bootable"}, /* AIX data or Coherent */ + {0x0a, "OS/2 Boot Manager"},/* OS/2 Boot Manager */ + {0x0b, "Win95 FAT32"}, + {0x0c, "Win95 FAT32 (LBA)"},/* LBA really is `Extended Int 13h' */ + {0x0e, "Win95 FAT16 (LBA)"}, + {0x0f, "Win95 Ext'd (LBA)"}, + {0x10, "OPUS"}, + {0x11, "Hidden FAT12"}, + {0x12, "Compaq diagnostics"}, + {0x14, "Hidden FAT16 <32M"}, + {0x16, "Hidden FAT16"}, + {0x17, "Hidden HPFS/NTFS"}, + {0x18, "AST Windows swapfile"}, + {0x1b, "Hidden Win95 FAT32"}, + {0x1c, "Hidden Win95 FAT32 (LBA)"}, + {0x1e, "Hidden Win95 FAT16 (LBA)"}, + {0x24, "NEC DOS"}, + {0x3c, "PartitionMagic recovery"}, + {0x40, "Venix 80286"}, + {0x41, "PPC PReP Boot"}, + {0x42, "SFS"}, + {0x4d, "QNX4.x"}, + {0x4e, "QNX4.x 2nd part"}, + {0x4f, "QNX4.x 3rd part"}, + {0x50, "OnTrack DM"}, + {0x51, "OnTrack DM6 Aux1"}, /* (or Novell) */ + {0x52, "CP/M"}, /* CP/M or Microport SysV/AT */ + {0x53, "OnTrack DM6 Aux3"}, + {0x54, "OnTrackDM6"}, + {0x55, "EZ-Drive"}, + {0x56, "Golden Bow"}, + {0x5c, "Priam Edisk"}, + {0x61, "SpeedStor"}, + {0x63, "GNU HURD or SysV"}, /* GNU HURD or Mach or Sys V/386 (such as ISC UNIX) */ + {0x64, "Novell Netware 286"}, + {0x65, "Novell Netware 386"}, + {0x70, "DiskSecure Multi-Boot"}, + {0x75, "PC/IX"}, + {0x80, "Old Minix"}, /* Minix 1.4a and earlier */ + {0x81, "Minix / old Linux"},/* Minix 1.4b and later */ + {0x82, "Linux swap"}, /* also Solaris */ + {0x83, "Linux"}, + {0x84, "OS/2 hidden C: drive"}, + {0x85, "Linux extended"}, + {0x86, "NTFS volume set"}, + {0x87, "NTFS volume set"}, + {0x93, "Amoeba"}, + {0x94, "Amoeba BBT"}, /* (bad block table) */ + {0xa0, "IBM Thinkpad hibernation"}, + {0xa5, "BSD/386"}, + {0xa6, "OpenBSD"}, + {0xa7, "NeXTSTEP"}, + {0xb7, "BSDI fs"}, + {0xb8, "BSDI swap"}, + {0xc1, "DRDOS/sec (FAT-12)"}, + {0xc4, "DRDOS/sec (FAT-16 < 32M)"}, + {0xc6, "DRDOS/sec (FAT-16)"}, + {0xc7, "Syrinx"}, + {0xdb, "CP/M / CTOS / ..."},/* CP/M or Concurrent CP/M or Concurrent DOS or CTOS */ + {0xe1, "DOS access"}, /* DOS access or SpeedStor 12-bit FAT extended partition */ + {0xe3, "DOS R/O"}, /* DOS R/O or SpeedStor */ + {0xe4, "SpeedStor"}, /* SpeedStor 16-bit FAT extended partition < 1024 cyl. */ + {0xeb, "BeOS fs"}, + {0xf1, "SpeedStor"}, + {0xf4, "SpeedStor"}, /* SpeedStor large partition */ + {0xf2, "DOS secondary"}, /* DOS 3.3+ secondary */ + {0xfd, "Linux raid autodetect"},/* New (2.2.x) raid partition with autodetect + using persistent superblock */ + {0xfe, "LANstep"}, /* SpeedStor >1024 cyl. or LANstep */ + {0xff, "BBT"}, /* Xenix Bad Block Table */ + { 0, 0 } +}; + +#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 + */ +static int exit_status = 0; + +static int force = 0; /* 1: do what I say, even if it is stupid ... */ +static int quiet = 0; /* 1: suppress all warnings */ +static int Linux = 0; /* 1: suppress warnings irrelevant for Linux */ +static int DOS = 0; /* 1: shift extended partitions by #sectors, not 1 */ +static int dump = 0; /* 1: list in a format suitable for later input */ +static int verify = 0; /* 1: check that listed partition is reasonable */ +static int no_write = 0; /* 1: do not actually write to disk */ +static int no_reread = 0; /* 1: skip the BLKRRPART ioctl test at startup */ +static int leave_last = 0; /* 1: don't allocate the last cylinder */ +static int opt_list = 0; +static char *save_sector_file = NULL; +static char *restore_sector_file = NULL; + +static void +warn(char *s, ...) { + va_list p; + + va_start(p, s); + fflush(stdout); + if (!quiet) + vfprintf (stderr, s, p); + va_end(p); +} + +static void +error(char *s, ...) { + va_list p; + + va_start(p, s); + fflush(stdout); + fprintf(stderr, "\n" PROGNAME ": "); + vfprintf(stderr, s, p); + va_end(p); +} + +static void +fatal(char *s, ...) { + va_list p; + + va_start(p, s); + fflush(stdout); + fprintf(stderr, "\n" PROGNAME ": "); + vfprintf(stderr, s, p); + va_end(p); + exit(1); +} + +/* + * 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. + */ +#ifndef __alpha__ +static +_syscall5(int, _llseek, uint, fd, ulong, hi, ulong, lo, + loff_t *, res, uint, wh); +#endif + +static int +sseek(char *dev, unsigned int fd, unsigned long s) { + loff_t in, out; + in = ((loff_t) s << 9); + out = 1; + +#ifndef __alpha__ + 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", + (uint)(in>>32), (uint)(in & 0xffffffff), + (uint)(out>>32), (uint)(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 void +free_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)) { + 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 int +msdos_signature (struct sector *s) { + if (*(unsigned short *) (s->data + 0x1fe) != 0xaa55) { + error("ERROR: sector %lu does not have an msdos signature\n", + s->sectornumber); + return 0; + } + return 1; +} + +static int +write_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 void +ulong_to_chars(unsigned long u, char *uu) { + int i; + + for(i=0; i<4; i++) { + uu[i] = (u & 0xff); + u >>= 8; + } +} + +static unsigned long +chars_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 int +save_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 int +restore_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; + * }; + */ + +/* + * 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 cylindersize; + unsigned long heads, sectors, cylinders; +} B, F, U; + +static void +get_cylindersize(char *dev, int fd, int silent) { + struct hd_geometry g; + int ioctl_ok = 0; + + B.heads = B.sectors = B.cylinders = 0; + + if (!ioctl(fd, HDIO_GETGEO, &g)) { + ioctl_ok = 1; + + B.heads = g.heads; + B.sectors = g.sectors; + B.cylinders = g.cylinders; + } + + if (U.heads) + B.heads = U.heads; + if (U.sectors) + B.sectors = U.sectors; + if (U.cylinders) + B.cylinders = U.cylinders; + + B.cylindersize = B.heads * B.sectors; + + if (ioctl_ok) { + if (g.start && !force) { + warn( + "Warning: start=%d - this looks like a partition rather than\n" + "the entire disk. Using fdisk on it is probably meaningless.\n" + "[Use the --force option if you really want this]\n", g.start); + exit(1); + } + if (B.heads != g.heads) + warn("Warning: HDIO_GETGEO says that there are %d heads\n", + g.heads); + if (B.sectors != g.sectors) + warn("Warning: HDIO_GETGEO says that there are %d sectors\n", + g.sectors); + if (B.cylinders != g.cylinders) + warn("Warning: HDIO_GETGEO says that there are %d cylinders\n", + g.cylinders); + } else if (!silent) + if (!B.heads || !B.sectors || !B.cylinders) + printf("Disk %s: cannot get geometry\n", dev); + if (B.sectors > 63) + warn("Warning: unlikely number of sectors (%d - usually at most 63\n" + "This will give problems with all software that uses C/H/S addressing.\n", + B.sectors); + if (!silent) + printf("\nDisk %s: %lu cylinders, %lu heads, %lu sectors/track\n", + dev, B.cylinders, B.heads, B.sectors); +} + +typedef struct { unsigned char h,s,c; } chs; /* has some c bits in s */ +static chs zero_chs = { 0,0,0 }; + +typedef struct { unsigned long h,s,c; } longchs; +static longchs zero_longchs; + +static chs +longchs_to_chs (longchs aa, struct geometry G) { + chs a; + + if (aa.h < 256 && aa.s < 64 && aa.c < 1024) { + a.h = aa.h; + a.s = aa.s | ((aa.c >> 2) & 0xc0); + a.c = (aa.c & 0xff); + } else if (G.heads && G.sectors) { + a.h = G.heads - 1; + a.s = G.sectors | 0xc0; + a.c = 0xff; + } else + a = zero_chs; + return a; +} + +static longchs +chs_to_longchs (chs a) { + longchs aa; + + aa.h = a.h; + aa.s = (a.s & 0x3f); + aa.c = (a.s & 0xc0); + aa.c = (aa.c << 2) + a.c; + return aa; +} + +static longchs +ulong_to_longchs (unsigned long sno, struct geometry G) { + longchs aa; + + if (G.heads && G.sectors && G.cylindersize) { + aa.s = 1 + sno % G.sectors; + aa.h = (sno / G.sectors) % G.heads; + aa.c = sno / G.cylindersize; + return aa; + } else { + return zero_longchs; + } +} + +//static unsigned long +//longchs_to_ulong (longchs aa, struct geometry G) { +// return (aa.c*G.cylindersize + aa.h*G.sectors + aa.s - 1); +//} + +static chs +ulong_to_chs (unsigned long sno, struct geometry G) { + return longchs_to_chs(ulong_to_longchs(sno, G), G); +} + +//static unsigned long +//chs_to_ulong (chs a, struct geometry G) { +// return longchs_to_ulong(chs_to_longchs(a), G); +//} + +static int +is_equal_chs (chs a, chs b) { + return (a.h == b.h && a.s == b.s && a.c == b.c); +} + +static int +chs_ok (chs a, char *v, char *w) { + longchs aa = chs_to_longchs(a); + int ret = 1; + + if (is_equal_chs(a, zero_chs)) + return 1; + if (B.heads && aa.h >= B.heads) { + warn("%s of partition %s has impossible value for head: " + "%d (should be in 0-%d)\n", w, v, aa.h, B.heads-1); + ret = 0; + } + if (B.sectors && (aa.s == 0 || aa.s > B.sectors)) { + warn("%s of partition %s has impossible value for sector: " + "%d (should be in 1-%d)\n", w, v, aa.s, B.sectors); + ret = 0; + } + if (B.cylinders && aa.c >= B.cylinders) { + warn("%s of partition %s has impossible value for cylinders: " + "%d (should be in 0-%d)\n", w, v, aa.c, B.cylinders-1); + ret = 0; + } + return ret; +} + +/* + * D. About system Ids + */ + +#define EMPTY_PARTITION 0 +#define EXTENDED_PARTITION 5 +#define WIN98_EXTENDED 0x0f +#define DM6_AUX1PARTITION 0x51 +#define DM6_AUX3PARTITION 0x53 +#define DM6_PARTITION 0x54 +#define EZD_PARTITION 0x55 +#define LINUX_SWAP 0x82 +#define LINUX_NATIVE 0x83 +#define LINUX_EXTENDED 0x85 +#define BSD_PARTITION 0xa5 + +/* List of partition types now in i386_sys_types.c */ + +static const char * +sysname(unsigned char type) { + struct systypes *s; + + for (s = i386_sys_types; s->name; s++) + if (s->type == type) + return s->name; + return "Unknown"; +} + +static void +list_types(void) { + struct systypes *s; + + printf("Id Name\n\n"); + for (s = i386_sys_types; s->name; s++) + printf("%2x %s\n", s->type, s->name); +} + +static int +is_extended(unsigned char type) { + return (type == EXTENDED_PARTITION + || type == LINUX_EXTENDED + || type == WIN98_EXTENDED); +} + +static int +is_bsd(unsigned char type) { + return (type == BSD_PARTITION); +} + +/* + * E. About partitions + */ + +/* MS/DOS partition */ + +struct partition { + unsigned char bootable; /* 0 or 0x80 */ + chs begin_chs; + unsigned char sys_type; + chs end_chs; + unsigned int start_sect; /* starting sector counting from 0 */ + unsigned int nr_sects; /* nr of sectors in partition */ +}; + +/* Unfortunately, partitions are not aligned, and non-Intel machines + are unhappy with non-aligned integers. So, we need a copy by hand. */ +static int +copy_to_int(unsigned char *cp) { + unsigned int m; + + m = *cp++; + m += (*cp++ << 8); + m += (*cp++ << 16); + m += (*cp++ << 24); + return m; +} + +static void +copy_from_int(int m, char *cp) { + *cp++ = (m & 0xff); m >>= 8; + *cp++ = (m & 0xff); m >>= 8; + *cp++ = (m & 0xff); m >>= 8; + *cp++ = (m & 0xff); +} + +static void +copy_to_part(char *cp, struct partition *p) { + p->bootable = *cp++; + p->begin_chs.h = *cp++; + p->begin_chs.s = *cp++; + p->begin_chs.c = *cp++; + p->sys_type = *cp++; + p->end_chs.h = *cp++; + p->end_chs.s = *cp++; + p->end_chs.c = *cp++; + p->start_sect = copy_to_int(cp); + p->nr_sects = copy_to_int(cp+4); +} + +static void +copy_from_part(struct partition *p, char *cp) { + *cp++ = p->bootable; + *cp++ = p->begin_chs.h; + *cp++ = p->begin_chs.s; + *cp++ = p->begin_chs.c; + *cp++ = p->sys_type; + *cp++ = p->end_chs.h; + *cp++ = p->end_chs.s; + *cp++ = p->end_chs.c; + copy_from_int(p->start_sect, cp); + copy_from_int(p->nr_sects, cp+4); +} + +/* Roughly speaking, Linux doesn't use any of the above fields except + for partition type, start sector and number of sectors. (However, + see also linux/drivers/scsi/fdomain.c.) + The only way partition type is used (in the kernel) is the comparison + for equality with EXTENDED_PARTITION (and these Disk Manager types). */ + +struct part_desc { + unsigned long start; + unsigned long size; + unsigned long sector, offset; /* disk location of this info */ + struct partition p; + struct part_desc *ep; /* extended partition containing this one */ + int ptype; +#define DOS_TYPE 0 +#define BSD_TYPE 1 +} zero_part_desc; + +struct part_desc * +outer_extended_partition(struct part_desc *p) { + while (p->ep) + p = p->ep; + return p; +} + +static int +is_parent(struct part_desc *pp, struct part_desc *p) { + while (p) { + if (pp == p) + return 1; + p = p->ep; + } + return 0; +} + +struct disk_desc { + struct part_desc partitions[128]; + int partno; +} oldp, newp; + +/* determine where on the disk this information goes */ +static void +add_sector_and_offset(struct disk_desc *z) { + int pno; + struct part_desc *p; + + for (pno = 0; pno < z->partno; pno++) { + p = &(z->partitions[pno]); + p->offset = 0x1be + (pno%4)*sizeof(struct partition); + p->sector = (p->ep ? p->ep->start : 0); + } +} + +/* tell the kernel to reread the partition tables */ +static int +reread_ioctl(int fd) { + if(ioctl(fd, BLKRRPART)) { + perror("BLKRRPART"); + return -1; + } + return 0; +} + +static int +is_blockdev(int fd) { + struct stat statbuf; + + return(fstat(fd, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)); +} + +/* reread after writing */ +static void +reread_disk_partition(char *dev, int fd) { + printf("Re-reading the partition table ...\n"); + fflush(stdout); + sync(); + sleep(3); /* superfluous since 1.3.20 */ + + if(reread_ioctl(fd) && is_blockdev(fd)) + printf("The command to re-read the partition table failed\n" + "Reboot your system now, before using mkfs\n"); + + if (close(fd)) { + perror(dev); + printf("Error closing %s\n", dev); + } + printf("\n"); +} + +/* find Linux name of this partition, assuming that it will have a name */ +static int +index_to_linux(int pno, struct disk_desc *z) { + int i, ct = 1; + struct part_desc *p = &(z->partitions[0]); + for (i=0; i<pno; i++,p++) + if(i < 4 || (p->size > 0 && !is_extended(p->p.sys_type))) + ct++; + return ct; +} + +static int +linux_to_index(int lpno, struct disk_desc *z) { + int i, ct = 0; + struct part_desc *p = &(z->partitions[0]); + for (i=0; i<z->partno && ct < lpno; i++,p++) + if((i < 4 || (p->size > 0 && !is_extended(p->p.sys_type))) + && ++ct == lpno) + return i; + return -1; +} + +static int +asc_to_index(char *pnam, struct disk_desc *z) { + int pnum, pno; + + if (*pnam == '#') { + pno = atoi(pnam+1); + } else { + pnum = atoi(pnam); + pno = linux_to_index(pnum, z); + } + if (!(pno >= 0 && pno < z->partno)) + fatal("%s: no such partition\n"), pnam; + return pno; +} + +/* + * List partitions - in terms of sectors, blocks or cylinders + */ +#define F_SECTOR 1 +#define F_BLOCK 2 +#define F_CYLINDER 3 +#define F_MEGABYTE 4 + +static int default_format = F_MEGABYTE; +static int specified_format = 0; +static int show_extended = 0; +static int one_only = 0; +static int one_only_pno; +static int increment = 0; + +static void +set_format(char c) { + switch(c) { + default: + printf("unrecognized format - using sectors\n"); + case 'S': specified_format = F_SECTOR; break; + case 'B': specified_format = F_BLOCK; break; + case 'C': specified_format = F_CYLINDER; break; + case 'M': specified_format = F_MEGABYTE; break; + } +} + +static unsigned long +unitsize(int format) { + default_format = (B.cylindersize ? F_CYLINDER : F_MEGABYTE); + if (!format && !(format = specified_format)) + format = default_format; + + switch(format) { + default: + case F_CYLINDER: + if(B.cylindersize) + return B.cylindersize; + case F_SECTOR: + return 1; + case F_BLOCK: + return 2; + case F_MEGABYTE: + return 2048; + } +} + +static unsigned long +get_disksize(int format) { + unsigned long cs = B.cylinders; + if (cs && leave_last) + cs--; + return (cs * B.cylindersize) / unitsize(format); +} + +static void +out_partition_header(char *dev, int format, struct geometry G) { + if (dump) { + printf("# partition table of %s\n", dev); + printf("unit: sectors\n\n"); + return; + } + + default_format = (G.cylindersize ? F_CYLINDER : F_MEGABYTE); + if (!format && !(format = specified_format)) + format = default_format; + + switch(format) { + default: + printf("unimplemented format - using %s\n", + G.cylindersize ? "cylinders" : "sectors"); + case F_CYLINDER: + if (G.cylindersize) { + printf("Units = cylinders of %lu bytes, blocks of 1024 bytes" + ", counting from %d\n\n", + G.cylindersize<<9, increment); + printf(" Device Boot Start End #cyls #blocks Id System\n"); + break; + } + /* fall through */ + case F_SECTOR: + printf("Units = sectors of 512 bytes, counting from %d\n\n", + increment); + printf(" Device Boot Start End #sectors Id System\n"); + break; + case F_BLOCK: + printf("Units = blocks of 1024 bytes, counting from %d\n\n", + increment); + printf(" Device Boot Start End #blocks Id System\n"); + break; + case F_MEGABYTE: + printf("Units = megabytes of 1048576 bytes, blocks of 1024 bytes" + ", counting from %d\n\n", increment); + printf(" Device Boot Start End MB #blocks Id System\n"); + break; + } +} + +static void +out_rounddown(int width, unsigned long n, unsigned long unit, int inc) { + printf("%*lu", width, inc + n/unit); + if (unit != 1) + putchar((n % unit) ? '+' : ' '); + putchar(' '); +} + +static void +out_roundup(int width, unsigned long n, unsigned long unit, int inc) { + if (n == (unsigned long)(-1)) + printf("%*s", width, "-"); + else + printf("%*lu", width, inc + n/unit); + if (unit != 1) + putchar(((n+1) % unit) ? '-' : ' '); + putchar(' '); +} + +static void +out_roundup_size(int width, unsigned long n, unsigned long unit) { + printf("%*lu", width, (n+unit-1)/unit); + if (unit != 1) + putchar((n % unit) ? '-' : ' '); + putchar(' '); +} + +static int +get_fdisk_geometry(struct part_desc *p) { + chs b = p->p.end_chs; + longchs bb = chs_to_longchs(b); + F.heads = bb.h+1; + F.sectors = bb.s; + F.cylindersize = F.heads*F.sectors; + return (F.sectors != B.sectors || F.heads != B.heads); +} + +static void +out_partition(char *dev, int format, struct part_desc *p, + struct disk_desc *z, struct geometry G) { + unsigned long start, end, size; + int pno, lpno; + + if (!format && !(format = specified_format)) + format = default_format; + + pno = p - &(z->partitions[0]); /* our index */ + lpno = index_to_linux(pno, z); /* name of next one that has a name */ + if(pno == linux_to_index(lpno, z)) /* was that us? */ + printf("%8s%-2u", dev, lpno); /* yes */ + else if(show_extended) + printf(" - "); + else + return; + putchar(dump ? ':' : ' '); + + start = p->start; + end = p->start + p->size - 1; + size = p->size; + + if (dump) { + printf(" start=%9lu", start); + printf(", size=%8lu", size); + if (p->ptype == DOS_TYPE) { + printf(", Id=%2x", p->p.sys_type); + if (p->p.bootable == 0x80) + printf(", bootable"); + } + printf("\n"); + return; + } + + if(p->ptype != DOS_TYPE || p->p.bootable == 0) + printf(" "); + else if(p->p.bootable == 0x80) + printf(" * "); + else + printf(" ? "); /* garbage */ + + switch(format) { + case F_CYLINDER: + if (G.cylindersize) { + out_rounddown(6, start, G.cylindersize, increment); + out_roundup(6, end, G.cylindersize, increment); + out_roundup_size(6, size, G.cylindersize); + out_rounddown(8, size, 2, 0); + break; + } + /* fall through */ + default: + case F_SECTOR: + out_rounddown(9, start, 1, increment); + out_roundup(9, end, 1, increment); + out_rounddown(9, size, 1, 0); + break; + case F_BLOCK: +#if 0 + printf("%8lu,%3lu ", + p->sector/2, ((p->sector & 1) ? 512 : 0) + p->offset); +#endif + out_rounddown(8, start, 2, increment); + out_roundup(8, end, 2, increment); + out_rounddown(8, size, 2, 0); + break; + case F_MEGABYTE: + out_rounddown(5, start, 2048, increment); + out_roundup(5, end, 2048, increment); + out_roundup_size(5, size, 2048); + out_rounddown(8, size, 2, 0); + break; + } + if (p->ptype == DOS_TYPE) { + printf(" %2x %s\n", + p->p.sys_type, sysname(p->p.sys_type)); + } else { + printf("\n"); + } + + /* Is chs as we expect? */ + if (!quiet && p->ptype == DOS_TYPE) { + chs a, b; + longchs aa, bb; + a = (size ? ulong_to_chs(start,G) : zero_chs); + b = p->p.begin_chs; + aa = chs_to_longchs(a); + bb = chs_to_longchs(b); + if(a.s && !is_equal_chs(a, b)) + printf("\t\tstart: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", + aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); + a = (size ? ulong_to_chs(end,G) : zero_chs); + b = p->p.end_chs; + aa = chs_to_longchs(a); + bb = chs_to_longchs(b); + if(a.s && !is_equal_chs(a, b)) + printf("\t\tend: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", + aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); + if(G.cylinders && G.cylinders < 1024 && bb.c > G.cylinders) + printf("partition ends on cylinder %ld, beyond the end of the disk\n", + bb.c); + } +} + +static void +out_partitions(char *dev, struct disk_desc *z) { + struct part_desc *p; + int pno, format = 0; + + if (z->partno == 0) + printf("No partitions found\n"); + else { + for (pno=0; pno < z->partno; pno++) { + p = &(z->partitions[pno]); + if (p->size != 0 && p->p.sys_type != 0) { + if (get_fdisk_geometry(p)) + printf( + "Warning: The first partition looks like it was made\n" + " for C/H/S=*/%ld/%ld (instead of %ld/%ld/%ld).\n" + "For this listing I'll assume that geometry.\n", + F.heads, F.sectors, B.cylinders, B.heads, B.sectors); + break; + } + } + out_partition_header(dev, format, F); + for(pno=0; pno < z->partno; pno++) { + out_partition(dev, format, &(z->partitions[pno]), z, F); + if(show_extended && pno%4==3) + printf("\n"); + } + } +} + +static int +disj(struct part_desc *p, struct part_desc *q) { + return + ((p->start + p->size <= q->start) + || (is_extended(p->p.sys_type) + && q->start + q->size <= p->start + p->size)); +} + +static char * +pnumber(struct part_desc *p, struct disk_desc *z) { + static char buf[20]; + int this, next; + struct part_desc *p0 = &(z->partitions[0]); + + this = index_to_linux(p-p0, z); + next = index_to_linux(p-p0+1, z); + + if (next > this) + sprintf(buf, "%d", this); + else + sprintf(buf, "[%d]", this); + return buf; +} + +static int +partitions_ok(struct disk_desc *z) { + struct part_desc *partitions = &(z->partitions[0]), *p, *q; + int partno = z->partno; + +#define PNO(p) pnumber(p, z) + + /* Have at least 4 partitions been defined? */ + if (partno < 4) { + if (!partno) + fatal("no partition table present.\n"); + else + fatal("strange, only %d partitions defined.\n"), partno; + return 0; + } + + /* Are the partitions of size 0 marked empty? + And do they have start = 0? And bootable = 0? */ + for (p = partitions; p - partitions < partno; p++) + if (p->size == 0) { + if(p->p.sys_type != EMPTY_PARTITION) + warn("Warning: partition %s has size 0 but is not marked Empty\n", + PNO(p)); + else if(p->p.bootable != 0) + warn("Warning: partition %s has size 0 and is bootable\n", + PNO(p)); + else if(p->p.start_sect != 0) + warn("Warning: partition %s has size 0 and nonzero start\n", + PNO(p)); + /* all this is probably harmless, no error return */ + } + + /* Are the logical partitions contained in their extended partitions? */ + for (p = partitions+4; p < partitions+partno; p++) + if (p->ptype == DOS_TYPE) + if (p->size && !is_extended(p->p.sys_type)) { + q = p->ep; + if (p->start < q->start || p->start + p->size > q->start + q->size) { + warn("Warning: partition %s "), PNO(p); + warn("is not contained in partition %s\n"), PNO(q); + return 0; + } + } + + /* Are the data partitions mutually disjoint? */ + for (p = partitions; p < partitions+partno; p++) + if (p->size && !is_extended(p->p.sys_type)) + for (q = p+1; q < partitions+partno; q++) + if (q->size && !is_extended(q->p.sys_type)) + if(!((p->start > q-> start) ? disj(q,p) : disj(p,q))) { + warn("Warning: partitions %s "), PNO(p); + warn("and %s overlap\n"), PNO(q); + return 0; + } + + /* Are the data partitions and the extended partition + table sectors disjoint? */ + for (p = partitions; p < partitions+partno; p++) + if (p->size && !is_extended(p->p.sys_type)) + for (q = partitions; q < partitions+partno; q++) + if (is_extended(q->p.sys_type)) + if (p->start <= q->start && p->start + p->size > q->start) { + warn("Warning: partition %s contains part of ", PNO(p)); + warn("the partition table (sector %lu),\n", q->start); + warn("and will destroy it when filled\n"); + return 0; + } + + /* Do they start past zero and end before end-of-disk? */ + { unsigned long ds = get_disksize(F_SECTOR); + for (p = partitions; p < partitions+partno; p++) + if (p->size) { + if(p->start == 0) { + warn("Warning: partition %s starts at sector 0\n", PNO(p)); + return 0; + } + if (p->size && p->start + p->size > ds) { + warn("Warning: partition %s extends past end of disk\n", PNO(p)); + return 0; + } + } + } + + /* At most one chain of DOS extended partitions ? */ + /* It seems that the OS/2 fdisk has the additional requirement + that the extended partition must be the fourth one */ + { int ect = 0; + for (p = partitions; p < partitions+4; p++) + if (p->p.sys_type == EXTENDED_PARTITION) + ect++; + if (ect > 1 && !Linux) { + warn("Among the primary partitions, at most one can be extended\n"); + warn(" (although this is not a problem under Linux)\n"); + return 0; + } + } + + /* + * Do all partitions start at a cylinder boundary ? + * (this is not required for Linux) + * The first partition starts after MBR. + * Logical partitions start slightly after the containing extended partn. + */ + if (B.cylindersize) { + for(p = partitions; p < partitions+partno; p++) + if (p->size) { + if(p->start % B.cylindersize != 0 + && (!p->ep || p->start / B.cylindersize != p->ep->start / B.cylindersize) + && (p->p.start_sect >= B.cylindersize)) { + warn("Warning: partition %s does not start " + "at a cylinder boundary\n", PNO(p)); + if (!Linux) + return 0; + } + if((p->start + p->size) % B.cylindersize) { + warn("Warning: partition %s does not end " + "at a cylinder boundary\n", PNO(p)); + if (!Linux) + return 0; + } + } + } + + /* Usually, one can boot only from primary partitions. */ + /* In fact, from a unique one only. */ + /* do not warn about bootable extended partitions - + often LILO is there */ + { int pno = -1; + for(p = partitions; p < partitions+partno; p++) + if (p->p.bootable) { + if (pno == -1) + pno = p - partitions; + else if (p - partitions < 4) { + warn("Warning: more than one primary partition is marked " + "bootable (active)\n" + "This does not matter for LILO, but the DOS MBR will " + "not boot this disk.\n"); + break; + } + if (p - partitions >= 4) { + warn("Warning: usually one can boot from primary partitions " + "only\nLILO disregards the `bootable' flag.\n"); + break; + } + } + if (pno == -1 || pno >= 4) + warn("Warning: no primary partition is marked bootable (active)\n" + "This does not matter for LILO, but the DOS MBR will " + "not boot this disk.\n"); + } + + /* Is chs as we expect? */ + for(p = partitions; p < partitions+partno; p++) + if(p->ptype == DOS_TYPE) { + chs a, b; + longchs aa, bb; + a = p->size ? ulong_to_chs(p->start,B) : zero_chs; + b = p->p.begin_chs; + aa = chs_to_longchs(a); + bb = chs_to_longchs(b); + if (!chs_ok(b, PNO(p), "start")) + return 0; + if(a.s && !is_equal_chs(a, b)) + warn("partition %s: start: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", + PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); + a = p->size ? ulong_to_chs(p->start + p->size - 1, B) : zero_chs; + b = p->p.end_chs; + aa = chs_to_longchs(a); + bb = chs_to_longchs(b); + if (!chs_ok(b, PNO(p), "end")) + return 0; + if(a.s && !is_equal_chs(a, b)) + warn("partition %s: end: (c,h,s) expected (%ld,%ld,%ld) found (%ld,%ld,%ld)\n", + PNO(p), aa.c, aa.h, aa.s, bb.c, bb.h, bb.s); + if(B.cylinders && B.cylinders < 1024 && bb.c > B.cylinders) + warn("partition %s ends on cylinder %ld, beyond the end of the disk\n", + PNO(p), bb.c); + } + + return 1; + +#undef PNO +} + +static void +extended_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) { + char *cp; + struct sector *s; + unsigned long start, here, next; + int i, moretodo = 1; + struct partition p; + struct part_desc *partitions = &(z->partitions[0]); + int pno = z->partno; + + here = start = ep->start; + + while (moretodo) { + moretodo = 0; + + if (!(s = get_sector(dev, fd, here))) + break; + + if (!msdos_signature(s)) + break; + + cp = s->data + 0x1be; + + if (pno+4 >= SIZE(z->partitions)) { + printf("too many partitions - ignoring those past nr (%d)\n", + pno-1); + break; + } + + next = 0; + + for (i=0; i<4; i++,cp += sizeof(struct partition)) { + partitions[pno].sector = here; + partitions[pno].offset = cp - s->data; + partitions[pno].ep = ep; + copy_to_part(cp,&p); + if (is_extended(p.sys_type)) { + partitions[pno].start = start + p.start_sect; + if (next) + printf("tree of partitions?\n"); + else + next = partitions[pno].start; /* follow `upper' branch */ + moretodo = 1; + } else { + partitions[pno].start = here + p.start_sect; + } + partitions[pno].size = p.nr_sects; + partitions[pno].ptype = DOS_TYPE; + partitions[pno].p = p; + pno++; + } + here = next; + } + + z->partno = pno; +} + +#define BSD_DISKMAGIC (0x82564557UL) +#define BSD_MAXPARTITIONS 8 +#define BSD_FS_UNUSED 0 +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +struct bsd_disklabel { + u32 d_magic; + char d_junk1[4]; + char d_typename[16]; + char d_packname[16]; + char d_junk2[92]; + u32 d_magic2; + char d_junk3[2]; + u16 d_npartitions; /* number of partitions in following */ + char d_junk4[8]; + struct bsd_partition { /* the partition table */ + u32 p_size; /* number of sectors in partition */ + u32 p_offset; /* starting sector */ + u32 p_fsize; /* filesystem basic fragment size */ + u8 p_fstype; /* filesystem type, see below */ + u8 p_frag; /* filesystem fragments per block */ + u16 p_cpg; /* filesystem cylinders per group */ + } d_partitions[BSD_MAXPARTITIONS]; /* actually may be more */ +}; + +static void +bsd_partition(char *dev, int fd, struct part_desc *ep, struct disk_desc *z) { + struct bsd_disklabel *l; + struct bsd_partition *bp, *bp0; + unsigned long start = ep->start; + struct sector *s; + struct part_desc *partitions = &(z->partitions[0]); + int pno = z->partno; + + if (!(s = get_sector(dev,fd,start+1))) + return; + l = (struct bsd_disklabel *) (s->data); + if (l->d_magic != BSD_DISKMAGIC) + return; + + bp = bp0 = &l->d_partitions[0]; + while (bp - bp0 <= BSD_MAXPARTITIONS) { + if (pno+1 >= SIZE(z->partitions)) { + printf("too many partitions - ignoring those " + "past nr (%d)\n", pno-1); + break; + } + if (bp->p_fstype != BSD_FS_UNUSED) { + partitions[pno].start = bp->p_offset; + partitions[pno].size = bp->p_size; + partitions[pno].sector = start+1; + partitions[pno].offset = (char *)bp - (char *)bp0; + partitions[pno].ep = 0; + partitions[pno].ptype = BSD_TYPE; + pno++; + } + bp++; + } + z->partno = pno; +} + +static int +msdos_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { + int i; + char *cp; + struct partition pt; + struct sector *s; + struct part_desc *partitions = &(z->partitions[0]); + int pno = z->partno; + + if (!(s = get_sector(dev, fd, start))) + return 0; + + if (!msdos_signature(s)) + return 0; + + cp = s->data + 0x1be; + copy_to_part(cp,&pt); + + /* If I am not mistaken, recent kernels will hide this from us, + so we will never actually see traces of a Disk Manager */ + if (pt.sys_type == DM6_PARTITION + || pt.sys_type == EZD_PARTITION + || pt.sys_type == DM6_AUX1PARTITION + || pt.sys_type == DM6_AUX3PARTITION) { + printf("detected Disk Manager - unable to handle that\n"); + return 0; + } + { unsigned int sig = *(unsigned short *)(s->data + 2); + if (sig <= 0x1ae + && *(unsigned short *)(s->data + sig) == 0x55aa + && (1 & *(unsigned char *)(s->data + sig + 2))) { + printf("DM6 signature found - giving up\n"); + return 0; + } + } + + for (pno=0; pno<4; pno++,cp += sizeof(struct partition)) { + partitions[pno].sector = start; + partitions[pno].offset = cp - s->data; + copy_to_part(cp,&pt); + partitions[pno].start = start + pt.start_sect; + partitions[pno].size = pt.nr_sects; + partitions[pno].ep = 0; + partitions[pno].p = pt; + } + + z->partno = pno; + + for (i=0; i<4; i++) { + if (is_extended(partitions[i].p.sys_type)) { + if (!partitions[i].size) { + printf("strange..., an extended partition of size 0?\n"); + continue; + } + extended_partition(dev, fd, &partitions[i], z); + } + if (is_bsd(partitions[i].p.sys_type)) { + if (!partitions[i].size) { + printf("strange..., a BSD partition of size 0?\n"); + continue; + } + bsd_partition(dev, fd, &partitions[i], z); + } + } + return 1; +} + +static int +osf_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { + return 0; +} + +static int +sun_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { + return 0; +} + +static int +amiga_partition(char *dev, int fd, unsigned long start, struct disk_desc *z) { + return 0; +} + +static void +get_partitions(char *dev, int fd, struct disk_desc *z) { + z->partno = 0; + + if (!msdos_partition(dev, fd, 0, z) + && !osf_partition(dev, fd, 0, z) + && !sun_partition(dev, fd, 0, z) + && !amiga_partition(dev, fd, 0, z)) { + printf(" %s: unrecognized partition\n", dev); + return; + } +} + +static int +write_partitions(char *dev, int fd, struct disk_desc *z) { + struct sector *s; + struct part_desc *partitions = &(z->partitions[0]), *p; + int pno = z->partno; + + if (no_write) { + printf("-n flag was given: Nothing changed\n"); + exit(0); + } + + for (p = partitions; p < partitions+pno; p++) { + s = get_sector(dev, fd, p->sector); + if (!s) return 0; + s->to_be_written = 1; + copy_from_part(&(p->p), s->data + p->offset); + *(unsigned short *)(&(s->data[0x1fe])) = 0xaa55; + } + if (save_sector_file) { + if (!save_sectors(dev, fd)) { + fatal("Failed saving the old sectors - aborting\n"); + return 0; + } + } + if (!write_sectors(dev, fd)) { + error("Failed writing the partition on %s\n"), dev; + return 0; + } + return 1; +} + +/* + * F. The standard input + */ + +/* + * Input format: + * <start> <size> <type> <bootable> <c,h,s> <c,h,s> + * Fields are separated by whitespace or comma or semicolon possibly + * followed by whitespace; initial and trailing whitespace is ignored. + * Numbers can be octal, decimal or hexadecimal, decimal is default + * The <c,h,s> parts can (and probably should) be omitted. + * Bootable is specified as [*|-], with as default not-bootable. + * Type is given in hex, without the 0x prefix, or is [E|S|L|X], where + * L (LINUX_NATIVE (83)) is the default, S is LINUX_SWAP (82), and E + * is EXTENDED_PARTITION (5), X is LINUX_EXTENDED (85). + * The default value of start is the first nonassigned sector/cylinder/... + * The default value of size is as much as possible (until next + * partition or end-of-disk). + * .: end of chain of extended partitions. + * + * On interactive input an empty line means: all defaults. + * Otherwise empty lines are ignored. + */ + +static int eof, eob; + +struct dumpfld { + int fldno; + char *fldname; + int is_bool; +} dumpflds[] = { + { 0, "start", 0 }, + { 1, "size", 0 }, + { 2, "Id", 0 }, + { 3, "bootable", 1 }, + { 4, "bh", 0 }, + { 5, "bs", 0 }, + { 6, "bc", 0 }, + { 7, "eh", 0 }, + { 8, "es", 0 }, + { 9, "ec", 0 } +}; + +/* + * Read a line, split it into fields + * + * (some primitive handwork, but a more elaborate parser seems + * unnecessary) + */ +#define RD_EOF (-1) +#define RD_CMD (-2) + +static int +read_stdin(unsigned char **fields, unsigned char *line, int fieldssize, int linesize) { + unsigned char *lp, *ip; + int c, fno; + + /* boolean true and empty string at start */ + line[0] = '*'; + line[1] = 0; + for (fno=0; fno < fieldssize; fno++) + fields[fno] = line + 1; + fno = 0; + + /* read a line from stdin */ + lp = fgets(line+2, linesize, stdin); + if (lp == NULL) { + eof = 1; + return RD_EOF; + } + if (!(lp = index(lp, '\n'))) + fatal("long or incomplete input line - quitting\n"); + *lp = 0; + + /* remove comments, if any */ + if ((lp = index(line+2, '#')) != 0) + *lp = 0; + + /* recognize a few commands - to be expanded */ + if (!strcmp(line+2, "unit: sectors")) { + specified_format = F_SECTOR; + return RD_CMD; + } + + /* dump style? - then bad input is fatal */ + if ((ip = index(line+2, ':')) != 0) { + struct dumpfld *d; + + nxtfld: + ip++; + while(isspace(*ip)) + ip++; + if (*ip == 0) + return fno; + for(d = dumpflds; d-dumpflds < SIZE(dumpflds); d++) { + if(!strncmp(ip, d->fldname, strlen(d->fldname))) { + ip += strlen(d->fldname); + while(isspace(*ip)) + ip++; + if (d->is_bool) + fields[d->fldno] = line; + else if (*ip == '=') { + while(isspace(*++ip)) ; + fields[d->fldno] = ip; + while(isalnum(*ip)) /* 0x07FF */ + ip++; + } else + fatal("input error: `=' expected after %s field\n", + d->fldname); + if (fno <= d->fldno) + fno = d->fldno + 1; + if(*ip == 0) + return fno; + if(*ip != ',' && *ip != ';') + fatal("input error: unexpected character %c after %s field\n", + *ip, d->fldname); + *ip = 0; + goto nxtfld; + } + } + fatal("unrecognized input: %s\n"), ip; + } + + /* split line into fields */ + lp = ip = line+2; + fields[fno++] = lp; + while((c = *ip++) != 0) { + if (!lp[-1] && (c == '\t' || c == ' ')) + ; + else if (c == '\t' || c == ' ' || c == ',' || c == ';') { + *lp++ = 0; + if (fno < fieldssize) + fields[fno++] = lp; + continue; + } else + *lp++ = c; + } + + if (lp == fields[fno-1]) + fno--; + return fno; +} + +/* read a number, use default if absent */ +static int +get_ul(char *u, unsigned long *up, unsigned long def, int base) { + char *nu; + + if (*u) { + errno = 0; + *up = strtoul(u, &nu, base); + if (errno == ERANGE) { + printf("number too big\n"); + return -1; + } + if (*nu) { + printf("trailing junk after number\n"); + return -1; + } + } else + *up = def; + return 0; +} + +/* There are two common ways to structure extended partitions: + as nested boxes, and as a chain. Sometimes the partitions + must be given in order. Sometimes all logical partitions + must lie inside the outermost extended partition. +NESTED: every partition is contained in the surrounding partitions + and is disjoint from all others. +CHAINED: every data partition is contained in the surrounding partitions + and disjoint from all others, but extended partitions may lie outside + (insofar as allowed by all_logicals_inside_outermost_extended). +ONESECTOR: all data partitions are mutually disjoint; extended partitions + each use one sector only (except perhaps for the outermost one). +*/ +static int partitions_in_order = 0; +static int all_logicals_inside_outermost_extended = 1; +static enum { NESTED, CHAINED, ONESECTOR } boxes = NESTED; + +/* find the default value for <start> - assuming entire units */ +static unsigned long +first_free(int pno, int is_extended, struct part_desc *ep, int format, + unsigned long mid, struct disk_desc *z) { + unsigned long ff, fff; + unsigned long unit = unitsize(format); + struct part_desc *partitions = &(z->partitions[0]), *pp = 0; + + /* if containing ep undefined, look at its container */ + if (ep && ep->p.sys_type == EMPTY_PARTITION) + ep = ep->ep; + + if (ep) { + if (boxes == NESTED || (boxes == CHAINED && !is_extended)) + pp = ep; + else if (all_logicals_inside_outermost_extended) + pp = outer_extended_partition(ep); + } +#if 0 + ff = pp ? (pp->start + unit - 1) / unit : 0; +#else + /* rounding up wastes almost an entire cylinder - round down + and leave it to compute_start_sect() to fix the difference */ + ff = pp ? pp->start / unit : 0; +#endif + /* MBR and 1st sector of an extended partition are never free */ + if (unit == 1) + ff++; + + again: + for(pp = partitions; pp < partitions+pno; pp++) { + if (!is_parent(pp, ep) && pp->size > 0) { + if ((partitions_in_order || pp->start / unit <= ff + || (mid && pp->start / unit <= mid)) + && (fff = (pp->start + pp->size + unit - 1) / unit) > ff) { + ff = fff; + goto again; + } + } + } + + return ff; +} + +/* find the default value for <size> - assuming entire units */ +static unsigned long +max_length(int pno, int is_extended, struct part_desc *ep, int format, + unsigned long start, struct disk_desc *z) { + unsigned long fu; + unsigned long unit = unitsize(format); + struct part_desc *partitions = &(z->partitions[0]), *pp = 0; + + /* if containing ep undefined, look at its container */ + if (ep && ep->p.sys_type == EMPTY_PARTITION) + ep = ep->ep; + + if (ep) { + if (boxes == NESTED || (boxes == CHAINED && !is_extended)) + pp = ep; + else if (all_logicals_inside_outermost_extended) + pp = outer_extended_partition(ep); + } + fu = pp ? (pp->start + pp->size) / unit : get_disksize(format); + + for(pp = partitions; pp < partitions+pno; pp++) + if (!is_parent(pp, ep) && pp->size > 0 + && pp->start / unit >= start && pp->start / unit < fu) + fu = pp->start / unit; + + return (fu > start) ? fu - start : 0; +} + +/* compute starting sector of a partition inside an extended one */ +/* ep is 0 or points to surrounding extended partition */ +static int +compute_start_sect(struct part_desc *p, struct part_desc *ep) { + unsigned long base; + int inc = (DOS && B.sectors) ? B.sectors : 1; + int delta; + + if (ep && p->start + p->size >= ep->start + 1) + delta = p->start - ep->start - inc; + else if (p->start == 0 && p->size > 0) + delta = -inc; + else + delta = 0; + if (delta < 0) { + p->start -= delta; + p->size += delta; + if (is_extended(p->p.sys_type) && boxes == ONESECTOR) + p->size = inc; + else if ((int)(p->size) <= 0) { + warn("no room for partition descriptor\n"); + return 0; + } + } + base = (!ep ? 0 + : (is_extended(p->p.sys_type) ? + outer_extended_partition(ep) : ep)->start); + p->ep = ep; + if (p->p.sys_type == EMPTY_PARTITION && p->size == 0) { + p->p.start_sect = 0; + p->p.begin_chs = zero_chs; + p->p.end_chs = zero_chs; + } else { + p->p.start_sect = p->start - base; + p->p.begin_chs = ulong_to_chs(p->start,B); + p->p.end_chs = ulong_to_chs(p->start + p->size - 1,B); + } + p->p.nr_sects = p->size; + return 1; +} + +/* build the extended partition surrounding a given logical partition */ +static int +build_surrounding_extended(struct part_desc *p, struct part_desc *ep, + struct disk_desc *z) { + int inc = (DOS && B.sectors) ? B.sectors : 1; + int format = F_SECTOR; + struct part_desc *p0 = &(z->partitions[0]), *eep = ep->ep; + + if (boxes == NESTED) { + ep->start = first_free(ep-p0, 1, eep, format, p->start, z); + ep->size = max_length(ep-p0, 1, eep, format, ep->start, z); + if (ep->start > p->start || ep->start + ep->size < p->start + p->size) { + warn("cannot build surrounding extended partition\n"); + return 0; + } + } else { + ep->start = p->start; + if(boxes == CHAINED) + ep->size = p->size; + else + ep->size = inc; + } + + ep->p.nr_sects = ep->size; + ep->p.bootable = 0; + ep->p.sys_type = EXTENDED_PARTITION; + if (!compute_start_sect(ep, eep) || !compute_start_sect(p, ep)) { + ep->p.sys_type = EMPTY_PARTITION; + ep->size = 0; + return 0; + } + + return 1; +} + +static int +read_line(int pno, struct part_desc *ep, char *dev, int interactive, + struct disk_desc *z) { + unsigned char line[1000]; + unsigned char *fields[11]; + int fno, pct = pno%4; + struct part_desc p, *orig; + unsigned long ff, ff1, ul, ml, ml1, def; + int format, lpno, is_extd; + + if (eof || eob) + return -1; + + lpno = index_to_linux(pno, z); + + if (interactive) { + if (pct == 0 && (show_extended || pno == 0)) + warn("\n"); + warn("%8s%d: ", dev, lpno); + } + + /* read input line - skip blank lines when reading from a file */ + do { + fno = read_stdin(fields, line, SIZE(fields), SIZE(line)); + } while(fno == RD_CMD || (fno == 0 && !interactive)); + if (fno == RD_EOF) { + return -1; + } else if (fno > 10 && *(fields[10]) != 0) { + printf("too many input fields\n"); + return 0; + } + + if (fno == 1 && !strcmp(fields[0], ".")) { + eob = 1; + return -1; + } + + /* use specified format, but round to cylinders if F_MEGABYTE specified */ + format = 0; + if (B.cylindersize && specified_format == F_MEGABYTE) + format = F_CYLINDER; + + orig = (one_only ? &(oldp.partitions[pno]) : 0); + + p = zero_part_desc; + p.ep = ep; + + /* first read the type - we need to know whether it is extended */ + /* stop reading when input blank (defaults) and all is full */ + is_extd = 0; + if (fno == 0) { /* empty line */ + if (orig && is_extended(orig->p.sys_type)) + is_extd = 1; + ff = first_free(pno, is_extd, ep, format, 0, z); + ml = max_length(pno, is_extd, ep, format, ff, z); + if (ml == 0 && is_extd == 0) { + is_extd = 1; + ff = first_free(pno, is_extd, ep, format, 0, z); + ml = max_length(pno, is_extd, ep, format, ff, z); + } + if (ml == 0 && pno >= 4) { + /* no free blocks left - don't read any further */ + warn("No room for more\n"); + return -1; + } + } + if (fno < 3 || !*(fields[2])) + ul = orig ? orig->p.sys_type : + (is_extd || (pno > 3 && pct == 1 && show_extended)) + ? EXTENDED_PARTITION : LINUX_NATIVE; + else if(!strcmp(fields[2], "L")) + ul = LINUX_NATIVE; + else if(!strcmp(fields[2], "S")) + ul = LINUX_SWAP; + else if(!strcmp(fields[2], "E")) + ul = EXTENDED_PARTITION; + else if(!strcmp(fields[2], "X")) + ul = LINUX_EXTENDED; + else if (get_ul(fields[2], &ul, LINUX_NATIVE, 16)) + return 0; + if (ul > 255) { + warn("Illegal type\n"); + return 0; + } + p.p.sys_type = ul; + is_extd = is_extended(ul); + + /* find start */ + ff = first_free(pno, is_extd, ep, format, 0, z); + ff1 = ff * unitsize(format); + def = orig ? orig->start : (pno > 4 && pct > 1) ? 0 : ff1; + if (fno < 1 || !*(fields[0])) + p.start = def; + else { + if (get_ul(fields[0], &ul, def / unitsize(0), 0)) + return 0; + p.start = ul * unitsize(0); + p.start -= (p.start % unitsize(format)); + } + + /* find length */ + ml = max_length(pno, is_extd, ep, format, p.start / unitsize(format), z); + ml1 = ml * unitsize(format); + def = orig ? orig->size : (pno > 4 && pct > 1) ? 0 : ml1; + if (fno < 2 || !*(fields[1])) + p.size = def; + else { + if (get_ul(fields[1], &ul, def / unitsize(0), 0)) + return 0; + p.size = ul * unitsize(0) + unitsize(format) - 1; + p.size -= (p.size % unitsize(format)); + } + if (p.size > ml1) { + warn("Warning: exceeds max allowable size (%lu)\n", ml1 / unitsize(0)); + if (!force) + return 0; + } + if (p.size == 0 && pno >= 4 && (fno < 2 || !*(fields[1]))) { + warn("Warning: empty partition\n"); + if (!force) + return 0; + } + p.p.nr_sects = p.size; + + if (p.size == 0 && !orig) { + if(fno < 1 || !*(fields[0])) + p.start = 0; + if(fno < 3 || !*(fields[2])) + p.p.sys_type = EMPTY_PARTITION; + } + + if (p.start < ff1 && p.size > 0) { + warn("Warning: bad partition start (earliest %lu)\n", + (ff1 + unitsize(0) - 1) / unitsize(0)); + if (!force) + return 0; + } + + if (fno < 4 || !*(fields[3])) + ul = (orig ? orig->p.bootable : 0); + else if (!strcmp(fields[3], "-")) + ul = 0; + else if (!strcmp(fields[3], "*") || !strcmp(fields[3], "+")) + ul = 0x80; + else { + warn("unrecognized bootable flag - choose - or *\n"); + return 0; + } + p.p.bootable = ul; + + if (ep && ep->p.sys_type == EMPTY_PARTITION) { + if(!build_surrounding_extended(&p, ep, z)) + return 0; + } else + if(!compute_start_sect(&p, ep)) + return 0; + + { longchs aa = chs_to_longchs(p.p.begin_chs), bb; + + if (fno < 5) { + bb = aa; + } else if (fno < 7) { + warn("partial c,h,s specification?\n"); + return 0; + } else if(get_ul(fields[4], &bb.c, aa.c, 0) || + get_ul(fields[5], &bb.h, aa.h, 0) || + get_ul(fields[6], &bb.s, aa.s, 0)) + return 0; + p.p.begin_chs = longchs_to_chs(bb,B); + } + { longchs aa = chs_to_longchs(p.p.end_chs), bb; + + if (fno < 8) { + bb = aa; + } else if (fno < 10) { + warn("partial c,h,s specification?\n"); + return 0; + } else if(get_ul(fields[7], &bb.c, aa.c, 0) || + get_ul(fields[8], &bb.h, aa.h, 0) || + get_ul(fields[9], &bb.s, aa.s, 0)) + return 0; + p.p.end_chs = longchs_to_chs(bb, B); + } + + if (pno > 3 && p.size && show_extended && p.p.sys_type != EMPTY_PARTITION + && (is_extended(p.p.sys_type) != (pct == 1))) { + warn("Extended partition not where expected\n"); + if (!force) + return 0; + } + + z->partitions[pno] = p; + if (pno >= z->partno) + z->partno += 4; /* reqd for out_partition() */ + + if (interactive) + out_partition(dev, 0, &(z->partitions[pno]), z, B); + + return 1; +} + +/* ep either points to the extended partition to contain this one, + or to the empty partition that may become extended or is 0 */ +static int +read_partition(char *dev, int interactive, int pno, struct part_desc *ep, + struct disk_desc *z) { + struct part_desc *p = &(z->partitions[pno]); + int i; + + if (one_only) { + *p = oldp.partitions[pno]; + if (one_only_pno != pno) + goto ret; + } else if (!show_extended && pno > 4 && pno%4) + goto ret; + + while (!(i = read_line(pno, ep, dev, interactive, z))) + if (!interactive) + fatal("bad input\n"); + if (i < 0) { + p->ep = ep; + return 0; + } + + ret: + p->ep = ep; + if (pno >= z->partno) + z->partno += 4; + return 1; +} + +static void +read_partition_chain(char *dev, int interactive, struct part_desc *ep, + struct disk_desc *z) { + int i, base; + + eob = 0; + while (1) { + base = z->partno; + if (base+4 > SIZE(z->partitions)) { + printf("too many partitions\n"); + break; + } + for (i=0; i<4; i++) + if (!read_partition(dev, interactive, base+i, ep, z)) + return; + for (i=0; i<4; i++) { + ep = &(z->partitions[base+i]); + if (is_extended(ep->p.sys_type) && ep->size) + break; + } + if (i == 4) { + /* nothing found - maybe an empty partition is going + to be extended */ + if (one_only || show_extended) + break; + ep = &(z->partitions[base+1]); + if (ep->size || ep->p.sys_type != EMPTY_PARTITION) + break; + } + } +} + +static void +read_input(char *dev, int interactive, struct disk_desc *z) { + int i; + struct part_desc *partitions = &(z->partitions[0]), *ep; + + for (i=0; i < SIZE(z->partitions); i++) + partitions[i] = zero_part_desc; + z->partno = 0; + + if (interactive) + warn("Input in the following format; absent fields get a default value.\n" + "<start> <size> <type [E,S,L,X,hex]> <bootable [-,*]> <c,h,s> <c,h,s>\n" + "Usually you only need to specify <start> and <size> (and perhaps <type>).\n"); + eof = 0; + + for (i=0; i<4; i++) + read_partition(dev, interactive, i, 0, z); + for (i=0; i<4; i++) { + ep = partitions+i; + if (is_extended(ep->p.sys_type) && ep->size) + read_partition_chain(dev, interactive, ep, z); + } + add_sector_and_offset(z); +} + +/* + * G. The command line + */ + +static void version(void) { + printf("%s %s %s (aeb@cwi.nl, %s)\n", PROGNAME, "version", VERSION, DATE); +} + +static char short_opts[] = "cdfgilnqsu:vx?1A::C:DH:I:LN:O:RS:TU::V"; + +#define PRINT_ID 0400 +#define CHANGE_ID 01000 + +static const struct option long_opts[] = { + { "change-id", no_argument, NULL, 'c' + CHANGE_ID }, + { "print-id", no_argument, NULL, 'c' + PRINT_ID }, + { "id", no_argument, NULL, 'c' }, + { "dump", no_argument, NULL, 'd' }, + { "force", no_argument, NULL, 'f' }, + { "show-geometry", no_argument, NULL, 'g' }, + { "increment", no_argument, NULL, 'i' }, + { "list", no_argument, NULL, 'l' }, + { "quiet", no_argument, NULL, 'q' }, + { "show-size", no_argument, NULL, 's' }, + { "unit", required_argument, NULL, 'u' }, + { "version", no_argument, NULL, 'v' }, + { "show-extended", no_argument, NULL, 'x' }, + { "help", no_argument, NULL, '?' }, + { "one-only", no_argument, NULL, '1' }, + { "cylinders", required_argument, NULL, 'C' }, + { "heads", required_argument, NULL, 'H' }, + { "sectors", required_argument, NULL, 'S' }, + { "activate", optional_argument, NULL, 'A' }, + { "DOS", no_argument, NULL, 'D' }, + { "Linux", no_argument, NULL, 'L' }, + { "re-read", no_argument, NULL, 'R' }, + { "list-types", no_argument, NULL, 'T' }, + { "unhide", optional_argument, NULL, 'U' }, + { "no-reread", no_argument, NULL, 160 }, + { "IBM", no_argument, NULL, 161 }, + { "leave-last", no_argument, NULL, 161 }, +/* undocumented flags - not all completely implemented */ + { "in-order", no_argument, NULL, 128 }, + { "not-in-order", no_argument, NULL, 129 }, + { "inside-outer", no_argument, NULL, 130 }, + { "not-inside-outer", no_argument, NULL, 131 }, + { "nested", no_argument, NULL, 132 }, + { "chained", no_argument, NULL, 133 }, + { "onesector", no_argument, NULL, 134 }, + { NULL, 0, NULL, 0 } +}; + +/* default devices to list */ +static struct devd { + char *pref, *letters; +} defdevs[] = { + { "hd", "abcdefgh" }, + { "sd", "abcde" }, + { "xd", "ab" }, + { "ed", "abcd" } +}; + +static int +is_ide_cdrom(char *device) { + /* No device was given explicitly, and we are trying some + likely things. But opening /dev/hdc may produce errors like + "hdc: tray open or drive not ready" + if it happens to be a CD-ROM drive. So try to be careful. + This only works since 2.1.73. */ + + FILE *procf; + char buf[100]; + struct stat statbuf; + + sprintf(buf, "/proc/ide/%s/media", device+5); + procf = fopen(buf, "r"); + if (procf != NULL && fgets(buf, sizeof(buf), procf)) + return !strncmp(buf, "cdrom", 5); + + /* Now when this proc file does not exist, skip the + device when it is read-only. */ + if (stat(device, &statbuf) == 0) + return (statbuf.st_mode & 0222) == 0; + + return 0; +} + +static void do_list(char *dev, int silent); +static void do_size(char *dev, int silent); +static void do_geom(char *dev, int silent); +static void do_fdisk(char *dev); +static void do_reread(char *dev); +static void do_change_id(char *dev, char *part, char *id); +static void do_unhide(char **av, int ac, char *arg); +static void do_activate(char **av, int ac, char *arg); + +static int total_size; + +extern int +sfdisk_main(int argc, char **argv) { + int c; + char *dev; + int opt_size = 0; + int opt_out_geom = 0; + int opt_reread = 0; + int activate = 0; + int do_id = 0; + int unhide = 0; + char *activatearg = 0; + char *unhidearg = 0; + + if (argc < 1) + usage( sfdisk_usage); + + while ((c = getopt_long (argc, argv, short_opts, long_opts, NULL)) != -1) { + switch (c) { + case 'f': + force = 1; break; /* does not imply quiet */ + case 'g': + opt_out_geom = 1; break; + case 'i': + increment = 1; break; + case 'c': + case 'c' + PRINT_ID: + case 'c' + CHANGE_ID: + do_id = c; break; + case 'd': + dump = 1; /* fall through */ + case 'l': + opt_list = 1; break; + case 'n': + no_write = 1; break; + case 'q': + quiet = 1; break; + case 's': + opt_size = 1; break; + case 'u': + set_format(*optarg); break; + case 'v': + version(); + exit(0); + case 'x': + show_extended = 1; break; + case 'A': + activatearg = optarg; + activate = 1; break; + case 'C': + U.cylinders = atoi(optarg); break; + case 'D': + DOS = 1; break; + case 'H': + U.heads = atoi(optarg); break; + case 'L': + Linux = 1; break; + case 'N': + one_only = atoi(optarg); break; + case 'I': + restore_sector_file = optarg; break; + case 'O': + save_sector_file = optarg; break; + case 'R': + opt_reread = 1; break; + case 'S': + U.sectors = atoi(optarg); break; + case 'T': + list_types(); + exit(0); + case 'U': + unhidearg = optarg; + unhide = 1; break; + case 'V': + verify = 1; break; + case '?': + default: + usage( sfdisk_usage); + + /* undocumented flags */ + case 128: + partitions_in_order = 1; break; + case 129: + partitions_in_order = 0; break; + case 130: + all_logicals_inside_outermost_extended = 1; break; + case 131: + all_logicals_inside_outermost_extended = 0; break; + case 132: + boxes = NESTED; break; + case 133: + boxes = CHAINED; break; + case 134: + boxes = ONESECTOR; break; + + /* more flags */ + case 160: + no_reread = 1; break; + case 161: + leave_last = 1; break; + } + } + + if (optind == argc && (opt_list || opt_out_geom || opt_size || verify)) { + struct devd *dp; + char *lp; + char device[10]; + + total_size = 0; + + for(dp = defdevs; dp-defdevs < SIZE(defdevs); dp++) { + lp = dp->letters; + while(*lp) { + sprintf(device, "/dev/%s%c", dp->pref, *lp++); + if (!strcmp(dp->pref, "hd") && is_ide_cdrom(device)) + continue; + if (opt_out_geom) + do_geom(device, 1); + if (opt_size) + do_size(device, 1); + if (opt_list || verify) + do_list(device, 1); + } + } + + if (opt_size) + printf("total: %d blocks\n", total_size); + + exit(exit_status); + } + + if (optind == argc) usage( sfdisk_usage); + + if (opt_list || opt_out_geom || opt_size || verify) { + while (optind < argc) { + if (opt_out_geom) + do_geom(argv[optind], 0); + if (opt_size) + do_size(argv[optind], 0); + if (opt_list || verify) + do_list(argv[optind], 0); + optind++; + } + exit(exit_status); + } + + if (activate) { + do_activate(argv+optind, argc-optind, activatearg); + exit(exit_status); + } + if (unhide) { + do_unhide(argv+optind, argc-optind, unhidearg); + exit(exit_status); + } + if (do_id) { + if ((do_id & PRINT_ID) != 0 && optind != argc-2) + fatal("usage: sfdisk --print-id device partition-number\n"); + else if ((do_id & CHANGE_ID) != 0 && optind != argc-3) + fatal("usage: sfdisk --change-id device partition-number Id\n"); + else if (optind != argc-3 && optind != argc-2) + fatal("usage: sfdisk --id device partition-number [Id]\n"); + do_change_id(argv[optind], argv[optind+1], + (optind == argc-2) ? 0 : argv[optind+2]); + exit(exit_status); + } + + if (optind != argc-1) + fatal("can specify only one device (except with -l or -s)\n"); + dev = argv[optind]; + + if (opt_reread) + do_reread(dev); + else if (restore_sector_file) + restore_sectors(dev); + else + do_fdisk(dev); + + return ( TRUE); +} + +/* + * H. Listing the current situation + */ + +static int +my_open (char *dev, int rw, int silent) { + int fd, mode; + + mode = (rw ? O_RDWR : O_RDONLY); + fd = open(dev, mode); + if (fd < 0 && !silent) { + perror(dev); + fatal("cannot open %s %s\n", dev, rw ? "read-write" : "for reading"); + } + return fd; +} + +static void +do_list (char *dev, int silent) { + int fd; + struct disk_desc *z; + + fd = my_open(dev, 0, silent); + if (fd < 0) + return; + + z = &oldp; + + free_sectors(); + get_cylindersize(dev, fd, dump ? 1 : opt_list ? 0 : 1); + get_partitions(dev, fd, z); + + if (opt_list) + out_partitions(dev, z); + + if (verify) { + if (partitions_ok(z)) + warn("%s: OK\n"), dev; + else + exit_status = 1; + } +} + +static void +do_geom (char *dev, int silent) { + int fd; + struct hd_geometry g; + + fd = my_open(dev, 0, silent); + if (fd < 0) + return; + + /* get_cylindersize(dev, fd, silent); */ + if (!ioctl(fd, HDIO_GETGEO, &g)) + printf("%s: %d cylinders, %d heads, %d sectors/track\n", + dev, g.cylinders, g.heads, g.sectors); + else + printf("%s: unknown geometry\n", dev); +} + +/* for compatibility with earlier fdisk: provide option -s */ +static void +do_size (char *dev, int silent) { + int fd; + long size; + + fd = my_open(dev, 0, silent); + if (fd < 0) + return; + + if(ioctl(fd, BLKGETSIZE, &size)) { + if(!silent) { + perror(dev); + fatal("BLKGETSIZE ioctl failed for %s\n"), dev; + } + return; + } + + size /= 2; /* convert sectors to blocks */ + + /* a CDROM drive without mounted CD yields MAXINT */ + if (silent && size == ((1<<30)-1)) + return; + + if (silent) + printf("%s: %9ld\n", dev, size); + else + printf("%ld\n", size); + + total_size += size; +} + +/* + * Activate: usually one wants to have a single primary partition + * to be active. OS/2 fdisk makes non-bootable logical partitions + * active - I don't know what that means to OS/2 Boot Manager. + * + * Call: activate /dev/hda 2 5 7 make these partitions active + * and the remaining ones inactive + * Or: sfdisk -A /dev/hda 2 5 7 + * + * If only a single partition must be active, one may also use the form + * sfdisk -A2 /dev/hda + * + * With "activate /dev/hda" or "sfdisk -A /dev/hda" the active partitions + * are listed but not changed. To get zero active partitions, use + * "activate /dev/hda none" or "sfdisk -A /dev/hda none". + * Use something like `echo ",,,*" | sfdisk -N2 /dev/hda' to only make + * /dev/hda2 active, without changing other partitions. + * + * A warning will be given if after the change not precisely one primary + * partition is active. + * + * The present syntax was chosen to be (somewhat) compatible with the + * activate from the LILO package. + */ +static void +set_active (struct disk_desc *z, char *pnam) { + int pno; + + pno = asc_to_index(pnam, z); + z->partitions[pno].p.bootable = 0x80; +} + +static void +do_activate (char **av, int ac, char *arg) { + char *dev = av[0]; + int fd; + int rw, i, pno, lpno; + struct disk_desc *z; + + z = &oldp; + + rw = (!no_write && (arg || ac > 1)); + fd = my_open(dev, rw, 0); + + free_sectors(); + get_cylindersize(dev, fd, 1); + get_partitions(dev, fd, z); + + if (!arg && ac == 1) { + /* list active partitions */ + for (pno=0; pno < z->partno; pno++) { + if (z->partitions[pno].p.bootable) { + lpno = index_to_linux(pno, z); + if (pno == linux_to_index(lpno, z)) + printf("%s%d\n", dev, lpno); + else + printf("%s#%d\n", dev, pno); + if (z->partitions[pno].p.bootable != 0x80) + warn("bad active byte: 0x%x instead of 0x80\n", + z->partitions[pno].p.bootable); + } + } + } else { + /* clear `active byte' everywhere */ + for (pno=0; pno < z->partno; pno++) + z->partitions[pno].p.bootable = 0; + + /* then set where desired */ + if (ac == 1) + set_active(z, arg); + else for(i=1; i<ac; i++) + set_active(z, av[i]); + + /* then write to disk */ + if(write_partitions(dev, fd, z)) + warn("Done\n\n"); + else + exit_status = 1; + } + i = 0; + for (pno=0; pno < z->partno && pno < 4; pno++) + if (z->partitions[pno].p.bootable) + i++; + if (i != 1) + warn("You have %d active primary partitions. This does not matter for LILO,\n" + "but the DOS MBR will only boot a disk with 1 active partition.\n", i); +} + +static void +set_unhidden (struct disk_desc *z, char *pnam) { + int pno; + unsigned char id; + + pno = asc_to_index(pnam, z); + id = z->partitions[pno].p.sys_type; + if (id == 0x11 || id == 0x14 || id == 0x16 || id == 0x17) + id -= 0x10; + else + fatal("partition %s has id %x and is not hidden\n", pnam, id); + z->partitions[pno].p.sys_type = id; +} + +/* + * maybe remove and make part of --change-id + */ +static void +do_unhide (char **av, int ac, char *arg) { + char *dev = av[0]; + int fd, rw, i; + struct disk_desc *z; + + z = &oldp; + + rw = !no_write; + fd = my_open(dev, rw, 0); + + free_sectors(); + get_cylindersize(dev, fd, 1); + get_partitions(dev, fd, z); + + /* unhide where desired */ + if (ac == 1) + set_unhidden(z, arg); + else for(i=1; i<ac; i++) + set_unhidden(z, av[i]); + + /* then write to disk */ + if(write_partitions(dev, fd, z)) + warn("Done\n\n"); + else + exit_status = 1; +} + +static void do_change_id(char *dev, char *pnam, char *id) { + int fd, rw, pno; + struct disk_desc *z; + unsigned long i; + + z = &oldp; + + rw = !no_write; + fd = my_open(dev, rw, 0); + + free_sectors(); + get_cylindersize(dev, fd, 1); + get_partitions(dev, fd, z); + + pno = asc_to_index(pnam, z); + if (id == 0) { + printf("%x\n", z->partitions[pno].p.sys_type); + return; + } + i = strtoul(id, NULL, 16); + if (i > 255) + fatal("Bad Id %x\n"), i; + z->partitions[pno].p.sys_type = i; + + if(write_partitions(dev, fd, z)) + warn("Done\n\n"); + else + exit_status = 1; +} + +static void +do_reread(char *dev) { + int fd; + + fd = my_open(dev, 0, 0); + if(reread_ioctl(fd)) + printf("This disk is currently in use.\n"); +} + +/* + * I. Writing the new situation + */ + +static void +do_fdisk(char *dev){ + int fd; + int c, answer; + struct stat statbuf; + int interactive = isatty(0); + struct disk_desc *z; + + if (stat(dev, &statbuf) < 0) { + perror(dev); + fatal("Fatal error: cannot find %s\n"), dev; + } + if (!S_ISBLK(statbuf.st_mode)) { + warn("Warning: %s is not a block device\n"), dev; + no_reread = 1; + } + fd = my_open(dev, !no_write, 0); + + if(!no_write && !no_reread) { + warn("Checking that no-one is using this disk right now ...\n"); + if(reread_ioctl(fd)) { + printf("\nThis disk is currently in use - repartitioning is probably a bad idea." + "Umount all file systems, and swapoff all swap partitions on this disk." + "Use the --no-reread flag to suppress this check.\n"); + if (!force) { + printf("Use the --force flag to overrule all checks.\n"); + exit(1); + } + } else + warn("OK"); + } + + z = &oldp; + + free_sectors(); + get_cylindersize(dev, fd, 0); + get_partitions(dev, fd, z); + + printf("Old situation:\n"); + out_partitions(dev, z); + + if (one_only && (one_only_pno = linux_to_index(one_only, z)) < 0) + fatal("Partition %d does not exist, cannot change it\n"), one_only; + + z = &newp; + + while(1) { + + read_input(dev, interactive, z); + + printf("New situation:\n"); + out_partitions(dev, z); + + if (!partitions_ok(z) && !force) { + if(!interactive) + fatal("I don't like these partitions - nothing changed.\n" + "(If you really want this, use the --force option.)\n"); + else + printf("I don't like this - probably you should answer No\n"); + } + ask: + if (interactive) { + if (no_write) + printf("Are you satisfied with this? [ynq] "); + else + printf("Do you want to write this to disk? [ynq] "); + answer = c = getchar(); + while (c != '\n' && c != EOF) + c = getchar(); + if (c == EOF) + printf("\nsfdisk: premature end of input\n"); + if (c == EOF || answer == 'q' || answer == 'Q') { + fatal("Quitting - nothing changed\n"); + } else if (answer == 'n' || answer == 'N') { + continue; + } else if (answer == 'y' || answer == 'Y') { + break; + } else { + printf("Please answer one of y,n,q\n"); + goto ask; + } + } else + break; + } + + if(write_partitions(dev, fd, z)) + printf("Successfully wrote the new partition table\n\n"); + else + exit_status = 1; + + reread_disk_partition(dev, fd); + + warn("If you created or changed a DOS partition, /dev/foo7, say, then use dd(1)\n" + "to zero the first 512 bytes: dd if=/dev/zero of=/dev/foo7 bs=512 count=1\n" + "(See fdisk(8).)\n"); + + sync(); /* superstition */ + sleep(3); + exit(exit_status); +} @@ -12,10 +12,15 @@ #include "internal.h" +#include <stdio.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <time.h> -#ifdef BB_TAR -const char tar_usage[] = +static const char tar_usage[] = "Create, extract, or list files from a TAR file\n\n" "usage: tar -[cxtvOf] [tarFileName] [FILE] ...\n" "\tc=create, x=extract, t=list contents, v=verbose,\n" @@ -23,13 +28,6 @@ const char tar_usage[] = -#include <stdio.h> -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <signal.h> -#include <time.h> - /* * Tar file constants. */ @@ -1151,5 +1149,4 @@ wantFileName (const char *fileName, int fileCount, char **fileTable) -#endif /* END CODE */ @@ -28,7 +28,7 @@ #include <errno.h> -const char touch_usage[] = "touch [-c] file [file ...]\n\n" +static const char touch_usage[] = "touch [-c] file [file ...]\n\n" "\tUpdate the last-modified date on the given file[s].\n"; @@ -26,7 +26,7 @@ #include <fstab.h> #include <errno.h> -const char umount_usage[] = +static const char umount_usage[] = "Usage: umount filesystem\n" " or: umount directory\n" " or: umount -a" diff --git a/util-linux/dmesg.c b/util-linux/dmesg.c index e5d403f..aa26f58 100644 --- a/util-linux/dmesg.c +++ b/util-linux/dmesg.c @@ -1,45 +1,49 @@ -#include "internal.h" -#include <stdlib.h> -#include <unistd.h> -#include <time.h> - /* dmesg.c -- Print out the contents of the kernel ring buffer * Created: Sat Oct 9 16:19:47 1993 * Revised: Thu Oct 28 21:52:17 1993 by faith@cs.unc.edu * Copyright 1993 Theodore Ts'o (tytso@athena.mit.edu) * This program comes with ABSOLUTELY NO WARRANTY. * Modifications by Rick Sladkey (jrs@world.std.com) - * from util-linux; adapted for busybox + * Larger buffersize 3 June 1998 by Nicolai Langfeldt, based on a patch + * by Peeter Joot. This was also suggested by John Hudson. + * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org> + * - added Native Language Support + * + * from util-linux -- adapted for busybox by + * Erik Andersen <andersee@debian.org>. I ripped out Native Language + * Support, replaced getopt, added some gotos for redundant stuff. */ +#include "internal.h" #include <linux/unistd.h> #include <stdio.h> +#include <getopt.h> +#include <stdlib.h> -#define __NR_klog __NR_syslog - -#if defined(__GLIBC__) -#include <sys/klog.h> -#define klog klogctl -#else -static inline _syscall3 (int, klog, int, type, char *, b, int, len) -#endif /* __GLIBC__ */ +#if __GNU_LIBRARY__ < 5 +#ifndef __alpha__ +# define __NR_klogctl __NR_syslog + static inline _syscall3(int, klogctl, int, type, char *, b, int, len); +#else /* __alpha__ */ +#define klogctl syslog +#endif +#else +# include <sys/klog.h> +#endif -static const char dmesg_usage[] = "dmesg [-c] [-n level]\n"; +static const char dmesg_usage[] = "dmesg [-c] [-n level] [-s bufsize]\n"; -int dmesg_main (int argc, char **argv) +int dmesg_main( int argc, char** argv ) { - - char buf[4096]; - int i; - int n; - int level = 0; - int lastc; - int cmd = 3; - - argc--; - argv++; + char *buf; + int bufsize=8196; + int i; + int n; + int level = 0; + int lastc; + int cmd = 3; /* Parse any options */ while (argc && **argv == '-') { @@ -56,43 +60,57 @@ int dmesg_main (int argc, char **argv) --argc; ++argv; break; + case 's': + if (--argc == 0) + goto end; + bufsize = atoi (*(++argv)); + --argc; + ++argv; + break; default: goto end; } } + + if (argc > 1) { + goto end; + } - if (cmd == 8) { - n = klog (cmd, NULL, level); - if (n < 0) { - perror ("klog"); - exit (FALSE); - } - exit (TRUE); - } + if (cmd == 8) { + n = klogctl( cmd, NULL, level ); + if (n < 0) { + goto klogctl_error; + } + exit( TRUE ); + } - n = klog (cmd, buf, sizeof (buf)); - if (n < 0) { - perror ("klog"); - exit (FALSE); - } + if (bufsize < 4096) bufsize = 4096; + buf = (char*)malloc(bufsize); + n = klogctl( cmd, buf, bufsize ); + if (n < 0) { + goto klogctl_error; + } - lastc = '\n'; - for (i = 0; i < n; i++) { - if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') { + lastc = '\n'; + for (i = 0; i < n; i++) { + if ((i == 0 || buf[i - 1] == '\n') && buf[i] == '<') { + i++; + while (buf[i] >= '0' && buf[i] <= '9') i++; - while (buf[i] >= '0' && buf[i] <= '9') - i++; - if (buf[i] == '>') - i++; - } - lastc = buf[i]; - putchar (lastc); - } - if (lastc != '\n') - putchar ('\n'); - exit (TRUE); - - end: + if (buf[i] == '>') + i++; + } + lastc = buf[i]; + putchar( lastc ); + } + if (lastc != '\n') + putchar( '\n' ); + exit( TRUE); +end: usage( dmesg_usage); exit (FALSE); +klogctl_error: + perror( "klogctl" ); + exit( FALSE ); + } diff --git a/util-linux/mkswap.c b/util-linux/mkswap.c index 8c0c4de..fceeb28 100644 --- a/util-linux/mkswap.c +++ b/util-linux/mkswap.c @@ -1,4 +1,3 @@ -#include "internal.h" /* * mkswap.c - set up a linux swap device * @@ -9,51 +8,170 @@ /* * 20.12.91 - time began. Got VM working yesterday by doing this by hand. * - * Usage: mkswap [-c] device [size-in-blocks] + * Usage: mkswap [-c] [-vN] [-f] device [size-in-blocks] * - * -c for readablility checking (use it unless you are SURE!) + * -c for readability checking. (Use it unless you are SURE!) + * -vN for swap areas version N. (Only N=0,1 known today.) + * -f for forcing swap creation even if it would smash partition table. * - * The device may be a block device or a image of one, but this isn't + * The device may be a block device or an image of one, but this isn't * enforced (but it's not much fun on a character device :-). * * Patches from jaggy@purplet.demon.co.uk (Mike Jagdis) to make the * size-in-blocks parameter optional added Wed Feb 8 10:33:43 1995. + * + * Version 1 swap area code (for kernel 2.1.117), aeb, 981010. + * + * Sparc fixes, jj@ultra.linux.cz (Jakub Jelinek), 981201 - mangled by aeb. + * V1_MAX_PAGES fixes, jj, 990325. + * + * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org> + * - added Native Language Support + * + * from util-linux -- adapted for busybox by + * Erik Andersen <andersee@debian.org>. I ripped out Native Language + * Support, made some stuff smaller, and fitted for life in busybox. + * */ +#include "internal.h" #include <stdio.h> #include <unistd.h> #include <string.h> #include <fcntl.h> #include <stdlib.h> +#include <sys/ioctl.h> /* for _IO */ +#include <sys/utsname.h> #include <sys/stat.h> -#include <sys/ioctl.h> +#include <asm/page.h> /* for PAGE_SIZE and PAGE_SHIFT */ + /* we also get PAGE_SIZE via getpagesize() */ -#include <asm/page.h> -#include <linux/fs.h> -#ifndef __linux__ -# define volatile -#endif +static const char mkswap_usage[] = "mkswap [-c] [-v0|-v1] device [block-count]\n" +"Prepare a disk partition to be used as a swap partition.\n\n" +"\t-c\tCheck for read-ability.\n" +"\t-v0\tMake version 0 swap [max 128 Megs].\n" +"\t-v1\tMake version 1 swap [big!] (default for kernels > 2.1.117).\n" +"\tblock-count\tNumber of block to use (default is entire partition).\n"; -#define TEST_BUFFER_PAGES 8 -const char mkswap_usage[] = "mkswap [-c] partition [block-count]\n" -"\n" -"\tPrepare a disk partition to be used as a swap partition.\n" -"\tThe default block count is the size of the entire partition.\n" -"\n" -"\t-c:\tCheck for read-ability.\n" -"\tblock-count\tUse only this many blocks.\n"; +#ifndef _IO +/* pre-1.3.45 */ +#define BLKGETSIZE 0x1260 +#else +/* same on i386, m68k, arm; different on alpha, mips, sparc, ppc */ +#define BLKGETSIZE _IO(0x12,96) +#endif -static const char * program_name = "mkswap"; -static const char * device_name = NULL; +static char * program_name = "mkswap"; +static char * device_name = NULL; static int DEV = -1; static long PAGES = 0; -static int do_check = 0; +static int check = 0; static int badpages = 0; +static int version = -1; + +#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r)) + +static int +linux_version_code(void) { + struct utsname my_utsname; + int p, q, r; + + if (uname(&my_utsname) == 0) { + p = atoi(strtok(my_utsname.release, ".")); + q = atoi(strtok(NULL, ".")); + r = atoi(strtok(NULL, ".")); + return MAKE_VERSION(p,q,r); + } + return 0; +} + +/* + * The definition of the union swap_header uses the constant PAGE_SIZE. + * Unfortunately, on some architectures this depends on the hardware model, + * and can only be found at run time -- we use getpagesize(). + */ + +static int pagesize; +static int *signature_page; + +struct swap_header_v1 { + char bootbits[1024]; /* Space for disklabel etc. */ + unsigned int version; + unsigned int last_page; + unsigned int nr_badpages; + unsigned int padding[125]; + unsigned int badpages[1]; +} *p; + +static void +init_signature_page() { + pagesize = getpagesize(); + +#ifdef PAGE_SIZE + if (pagesize != PAGE_SIZE) + fprintf(stderr, "Assuming pages of size %d\n", pagesize); +#endif + signature_page = (int *) malloc(pagesize); + memset(signature_page,0,pagesize); + p = (struct swap_header_v1 *) signature_page; +} +static void +write_signature(char *sig) { + char *sp = (char *) signature_page; -static long bit_test_and_set (unsigned int *addr, unsigned int nr) + strncpy(sp+pagesize-10, sig, 10); +} + +#define V0_MAX_PAGES (8 * (pagesize - 10)) +/* Before 2.2.0pre9 */ +#define V1_OLD_MAX_PAGES ((0x7fffffff / pagesize) - 1) +/* Since 2.2.0pre9: + error if nr of pages >= SWP_OFFSET(SWP_ENTRY(0,~0UL)) + with variations on + #define SWP_ENTRY(type,offset) (((type) << 1) | ((offset) << 8)) + #define SWP_OFFSET(entry) ((entry) >> 8) + on the various architectures. Below the result - yuk. + + Machine pagesize SWP_ENTRY SWP_OFFSET bound+1 oldbound+2 + i386 2^12 o<<8 e>>8 1<<24 1<<19 + mips 2^12 o<<15 e>>15 1<<17 1<<19 + alpha 2^13 o<<40 e>>40 1<<24 1<<18 + m68k 2^12 o<<12 e>>12 1<<20 1<<19 + sparc 2^{12,13} (o&0x3ffff)<<9 (e>>9)&0x3ffff 1<<18 1<<{19,18} + sparc64 2^13 o<<13 e>>13 1<<51 1<<18 + ppc 2^12 o<<8 e>>8 1<<24 1<<19 + armo 2^{13,14,15} o<<8 e>>8 1<<24 1<<{18,17,16} + armv 2^12 o<<9 e>>9 1<<23 1<<19 + + assuming that longs have 64 bits on alpha and sparc64 and 32 bits elsewhere. + + The bad part is that we need to know this since the kernel will + refuse a swap space if it is too large. +*/ +/* patch from jj - why does this differ from the above? */ +#if defined(__alpha__) +#define V1_MAX_PAGES ((1 << 24) - 1) +#elif defined(__mips__) +#define V1_MAX_PAGES ((1 << 17) - 1) +#elif defined(__sparc_v9__) +#define V1_MAX_PAGES ((3 << 29) - 1) +#elif defined(__sparc__) +#define V1_MAX_PAGES (pagesize == 8192 ? ((3 << 29) - 1) : ((1 << 18) - 1)) +#else +#define V1_MAX_PAGES V1_OLD_MAX_PAGES +#endif +/* man page now says: +The maximum useful size of a swap area now depends on the architecture. +It is roughly 2GB on i386, PPC, m68k, ARM, 1GB on sparc, 512MB on mips, +128GB on alpha and 3TB on sparc64. +*/ + +#define MAX_BADPAGES ((pagesize-1024-128*sizeof(int)-10)/sizeof(int)) + +static void bit_set (unsigned int *addr, unsigned int nr) { unsigned int r, m; @@ -61,7 +179,6 @@ static long bit_test_and_set (unsigned int *addr, unsigned int nr) r = *addr; m = 1 << (nr & (8 * sizeof(int) - 1)); *addr = r | m; - return (r & m) != 0; } static int bit_test_and_clear (unsigned int *addr, unsigned int nr) @@ -75,47 +192,59 @@ static int bit_test_and_clear (unsigned int *addr, unsigned int nr) return (r & m) != 0; } -/* - * Volatile to let gcc know that this doesn't return. When trying - * to compile this under minix, volatile gives a warning, as - * exit() isn't defined as volatile under minix. - */ -volatile void fatal_error(const char * fmt_string) -{ - fprintf(stderr,fmt_string,program_name,device_name); - exit(FALSE); + +void +die(const char *str) { + fprintf(stderr, "%s: %s\n", program_name, str); + exit( FALSE); } -#define die(str) fatal_error("%s: " str "\n") +void +page_ok(int page) { + if (version==0) + bit_set(signature_page, page); +} -static void check_blocks(int * signature_page) -{ +void +page_bad(int page) { + if (version == 0) + bit_test_and_clear(signature_page, page); + else { + if (badpages == MAX_BADPAGES) + die("too many bad pages"); + p->badpages[badpages] = page; + } + badpages++; +} + +void +check_blocks(void) { unsigned int current_page; int do_seek = 1; - char buffer[PAGE_SIZE]; + char *buffer; + buffer = malloc(pagesize); + if (!buffer) + die("Out of memory"); current_page = 0; while (current_page < PAGES) { - if (!do_check) { - bit_test_and_set(signature_page,current_page++); + if (!check) { + page_ok(current_page++); continue; - } else { - printf("\r%d", current_page); } - if (do_seek && lseek(DEV,current_page*PAGE_SIZE,SEEK_SET) != - current_page*PAGE_SIZE) + if (do_seek && lseek(DEV,current_page*pagesize,SEEK_SET) != + current_page*pagesize) die("seek failed in check_blocks"); - if ( (do_seek = (PAGE_SIZE != read(DEV, buffer, PAGE_SIZE))) ) { - bit_test_and_clear(signature_page,current_page++); - badpages++; + if ((do_seek = (pagesize != read(DEV, buffer, pagesize)))) { + page_bad(current_page++); continue; } - bit_test_and_set(signature_page,current_page++); + page_ok(current_page++); } - if (do_check) - printf("\n"); - if (badpages) - printf("%d bad page%s\n",badpages,(badpages>1)?"s":""); + if (badpages == 1) + printf("one bad page\n"); + else if (badpages > 1) + printf("%d bad pages\n", badpages); } static long valid_offset (int fd, int offset) @@ -129,12 +258,13 @@ static long valid_offset (int fd, int offset) return 1; } -static int count_blocks (int fd) +static int +find_size (int fd) { - int high, low; + unsigned int high, low; low = 0; - for (high = 1; valid_offset (fd, high); high *= 2) + for (high = 1; high > 0 && valid_offset (fd, high); high *= 2) low = high; while (low < high - 1) { @@ -145,108 +275,194 @@ static int count_blocks (int fd) else high = mid; } - valid_offset (fd, 0); return (low + 1); } -static int get_size(const char *file) +/* return size in pages, to avoid integer overflow */ +static long +get_size(const char *file) { int fd; - int size; + long size; - fd = open(file, O_RDWR); + fd = open(file, O_RDONLY); if (fd < 0) { perror(file); exit(1); } if (ioctl(fd, BLKGETSIZE, &size) >= 0) { - close(fd); - return (size * 512); + int sectors_per_page = pagesize/512; + size /= sectors_per_page; + } else { + size = find_size(fd) / pagesize; } - - size = count_blocks(fd); close(fd); return size; } -int -mkswap(const char *device_name, int pages, int check) - { +int mkswap_main(int argc, char ** argv) +{ + char * tmp; struct stat statbuf; + int sz; + int maxpages; int goodpages; - int signature_page[PAGE_SIZE/sizeof(int)]; + int offset; + int force = 0; - PAGES = pages; - do_check = check; + if (argc && *argv) + program_name = *argv; - memset(signature_page,0,PAGE_SIZE); + init_signature_page(); /* get pagesize */ - if (device_name && !PAGES) { - PAGES = get_size(device_name) / PAGE_SIZE; + while (argc-- > 1) { + argv++; + if (argv[0][0] != '-') { + if (device_name) { + int blocks_per_page = pagesize/1024; + PAGES = strtol(argv[0],&tmp,0)/blocks_per_page; + if (*tmp) + usage( mkswap_usage); + } else + device_name = argv[0]; + } else { + switch (argv[0][1]) { + case 'c': + check=1; + break; + case 'f': + force=1; + break; + case 'v': + version=atoi(argv[0]+2); + break; + default: + usage( mkswap_usage); + } + } + } + if (!device_name) { + fprintf(stderr, + "%s: error: Nowhere to set up swap on?\n", + program_name); + usage( mkswap_usage); } - if (!device_name || PAGES<10) { + sz = get_size(device_name); + if (!PAGES) { + PAGES = sz; + } else if (PAGES > sz && !force) { + fprintf(stderr, + "%s: error: " + "size %ld is larger than device size %d\n", + program_name, + PAGES*(pagesize/1024), sz*(pagesize/1024)); + exit( FALSE); + } + + if (version == -1) { + if (PAGES <= V0_MAX_PAGES) + version = 0; + else if (linux_version_code() < MAKE_VERSION(2,1,117)) + version = 0; + else if (pagesize < 2048) + version = 0; + else + version = 1; + } + if (version != 0 && version != 1) { + fprintf(stderr, "%s: error: unknown version %d\n", + program_name, version); + usage( mkswap_usage); + } + if (PAGES < 10) { fprintf(stderr, "%s: error: swap area needs to be at least %ldkB\n", - program_name, 10 * PAGE_SIZE / 1024); - /* usage(mkswap_usage); */ - exit(1); + program_name, (long)(10 * pagesize / 1024)); + usage( mkswap_usage); + } +#if 0 + maxpages = ((version == 0) ? V0_MAX_PAGES : V1_MAX_PAGES); +#else + if (!version) + maxpages = V0_MAX_PAGES; + else if (linux_version_code() >= MAKE_VERSION(2,2,1)) + maxpages = V1_MAX_PAGES; + else { + maxpages = V1_OLD_MAX_PAGES; + if (maxpages > V1_MAX_PAGES) + maxpages = V1_MAX_PAGES; } - if (PAGES > 8 * (PAGE_SIZE - 10)) { - PAGES = 8 * (PAGE_SIZE - 10); +#endif + if (PAGES > maxpages) { + PAGES = maxpages; fprintf(stderr, "%s: warning: truncating swap area to %ldkB\n", - program_name, PAGES * PAGE_SIZE / 1024); + program_name, PAGES * pagesize / 1024); } + DEV = open(device_name,O_RDWR); if (DEV < 0 || fstat(DEV, &statbuf) < 0) { perror(device_name); - exit(1); + exit( FALSE); } if (!S_ISBLK(statbuf.st_mode)) - do_check=0; + check=0; else if (statbuf.st_rdev == 0x0300 || statbuf.st_rdev == 0x0340) die("Will not try to make swapdevice on '%s'"); - check_blocks(signature_page); - if (!bit_test_and_clear(signature_page,0)) + +#ifdef __sparc__ + if (!force && version == 0) { + /* Don't overwrite partition table unless forced */ + unsigned char *buffer = (unsigned char *)signature_page; + unsigned short *q, sum; + + if (read(DEV, buffer, 512) != 512) + die("fatal: first page unreadable"); + if (buffer[508] == 0xDA && buffer[509] == 0xBE) { + q = (unsigned short *)(buffer + 510); + for (sum = 0; q >= (unsigned short *) buffer;) + sum ^= *q--; + if (!sum) { + fprintf(stderr, "\ +%s: Device '%s' contains a valid Sun disklabel.\n\ +This probably means creating v0 swap would destroy your partition table\n\ +No swap created. If you really want to create swap v0 on that device, use\n\ +the -f option to force it.\n", + program_name, device_name); + exit( FALSE); + } + } + } +#endif + + if (version == 0 || check) + check_blocks(); + if (version == 0 && !bit_test_and_clear(signature_page,0)) die("fatal: first page unreadable"); + if (version == 1) { + p->version = version; + p->last_page = PAGES-1; + p->nr_badpages = badpages; + } + goodpages = PAGES - badpages - 1; if (goodpages <= 0) die("Unable to set up swap-space: unreadable"); - printf("Setting up swapspace, size = %ld bytes\n",goodpages*PAGE_SIZE); - strncpy((char*)signature_page+PAGE_SIZE-10,"SWAP-SPACE",10); - if (lseek(DEV, 0, SEEK_SET)) + printf("Setting up swapspace version %d, size = %ld bytes\n", + version, (long)(goodpages*pagesize)); + write_signature((version == 0) ? "SWAP-SPACE" : "SWAPSPACE2"); + + offset = ((version == 0) ? 0 : 1024); + if (lseek(DEV, offset, SEEK_SET) != offset) die("unable to rewind swap-device"); - if (PAGE_SIZE != write(DEV, signature_page, PAGE_SIZE)) + if (write(DEV,(char*)signature_page+offset, pagesize-offset) + != pagesize-offset) die("unable to write signature page"); - close(DEV); - return (TRUE); -} - -int mkswap_main(int argc, char ** argv) -{ - char * tmp; - long int pages=0; - int check=0; - - if (argc && *argv) - program_name = *argv; - while (argc > 1) { - argv++; - argc--; - if (argv[0][0] != '-') - if (device_name) { - pages = strtol(argv[0],&tmp,0)>>(PAGE_SHIFT-10); - if (*tmp) { - usage (mkswap_usage); - } - } else - device_name = argv[0]; - else while (*++argv[0]) - switch (argv[0][0]) { - case 'c': check=1; break; - default: usage (mkswap_usage); - exit( TRUE); - } - } - exit( mkswap(device_name, pages, check)); + /* + * A subsequent swapon() will fail if the signature + * is not actually on disk. (This is a kernel bug.) + */ + if (fsync(DEV)) + die("fsync failed"); + exit ( TRUE); } diff --git a/util-linux/more.c b/util-linux/more.c index 53437ed..772d51b 100644 --- a/util-linux/more.c +++ b/util-linux/more.c @@ -30,7 +30,7 @@ #include <signal.h> -const char more_usage[] = "[file ...]"; +static const char more_usage[] = "[file ...]"; #ifdef BB_MORE_TERM diff --git a/util-linux/mount.c b/util-linux/mount.c index 26d4693..a7d5aed 100644 --- a/util-linux/mount.c +++ b/util-linux/mount.c @@ -37,7 +37,7 @@ #include <ctype.h> #include <fstab.h> -const char mount_usage[] = "Usage:\tmount [flags]\n" +static const char mount_usage[] = "Usage:\tmount [flags]\n" "\tmount [flags] device directory [-o options,more-options]\n" "\n" "Flags:\n" diff --git a/util-linux/umount.c b/util-linux/umount.c index 625fcfa..48efbd3 100644 --- a/util-linux/umount.c +++ b/util-linux/umount.c @@ -26,7 +26,7 @@ #include <fstab.h> #include <errno.h> -const char umount_usage[] = +static const char umount_usage[] = "Usage: umount filesystem\n" " or: umount directory\n" " or: umount -a" @@ -4,7 +4,7 @@ #include "internal.h" -const char zcat_usage[] = "zcat\n" +static const char zcat_usage[] = "zcat\n" "\n" "\tuncompress gzipped data from stdin to stdout\n"; @@ -59,7 +59,7 @@ static char *license_msg[] = { */ #ifdef RCSID -static char rcsid[] = "$Id: zcat.c,v 1.2 1999/10/06 20:25:32 andersen Exp $"; +static char rcsid[] = "$Id: zcat.c,v 1.3 1999/10/19 20:03:34 andersen Exp $"; #endif #include <ctype.h> @@ -80,7 +80,7 @@ static char rcsid[] = "$Id: zcat.c,v 1.2 1999/10/06 20:25:32 andersen Exp $"; * The target dependent functions should be defined in tailor.c. */ -/* $Id: zcat.c,v 1.2 1999/10/06 20:25:32 andersen Exp $ */ +/* $Id: zcat.c,v 1.3 1999/10/19 20:03:34 andersen Exp $ */ #define RECORD_IO 0 @@ -436,7 +436,7 @@ extern int unlzw OF((int in, int out)); # undef LZW #endif -/* $Id: zcat.c,v 1.2 1999/10/06 20:25:32 andersen Exp $ */ +/* $Id: zcat.c,v 1.3 1999/10/19 20:03:34 andersen Exp $ */ /* #include "getopt.h" */ @@ -895,7 +895,7 @@ RETSIGTYPE abort_gzip() */ #ifdef RCSID -static char rcsid[] = "$Id: zcat.c,v 1.2 1999/10/06 20:25:32 andersen Exp $"; +static char rcsid[] = "$Id: zcat.c,v 1.3 1999/10/19 20:03:34 andersen Exp $"; #endif /* #include "crypt.h" */ @@ -1021,7 +1021,7 @@ int unzip(in, out) */ #ifdef RCSID -static char rcsid[] = "$Id: zcat.c,v 1.2 1999/10/06 20:25:32 andersen Exp $"; +static char rcsid[] = "$Id: zcat.c,v 1.3 1999/10/19 20:03:34 andersen Exp $"; #endif #include <ctype.h> @@ -1408,7 +1408,7 @@ ulg crc_32_tab[] = { */ #ifdef RCSID -static char rcsid[] = "$Id: zcat.c,v 1.2 1999/10/06 20:25:32 andersen Exp $"; +static char rcsid[] = "$Id: zcat.c,v 1.3 1999/10/19 20:03:34 andersen Exp $"; #endif #include <sys/types.h> |